diff options
author | Vlad Yasevich <vyasevich@gmail.com> | 2015-02-03 16:36:15 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-02-03 23:06:43 -0800 |
commit | 0508c07f5e0c94f38afd5434e8b2a55b84553077 (patch) | |
tree | 268267ccdf554b7872644c5d5b52d4fccb2757ed /net/ipv6/udp_offload.c | |
parent | 42b5212fee4f57907e9415b18fe19c13e65574bc (diff) | |
download | linux-0508c07f5e0c94f38afd5434e8b2a55b84553077.tar.gz linux-0508c07f5e0c94f38afd5434e8b2a55b84553077.tar.bz2 linux-0508c07f5e0c94f38afd5434e8b2a55b84553077.zip |
ipv6: Select fragment id during UFO segmentation if not set.
If the IPv6 fragment id has not been set and we perform
fragmentation due to UFO, select a new fragment id.
We now consider a fragment id of 0 as unset and if id selection
process returns 0 (after all the pertrubations), we set it to
0x80000000, thus giving us ample space not to create collisions
with the next packet we may have to fragment.
When doing UFO integrity checking, we also select the
fragment id if it has not be set yet. This is stored into
the skb_shinfo() thus allowing UFO to function correclty.
This patch also removes duplicate fragment id generation code
and moves ipv6_select_ident() into the header as it may be
used during GSO.
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/udp_offload.c')
-rw-r--r-- | net/ipv6/udp_offload.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index b6aa8ed18257..a56276996b72 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -52,6 +52,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); + /* Set the IPv6 fragment id if not set yet */ + if (!skb_shinfo(skb)->ip6_frag_id) + ipv6_proxy_select_ident(skb); + segs = NULL; goto out; } @@ -108,7 +112,11 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen); fptr->nexthdr = nexthdr; fptr->reserved = 0; - fptr->identification = skb_shinfo(skb)->ip6_frag_id; + if (skb_shinfo(skb)->ip6_frag_id) + fptr->identification = skb_shinfo(skb)->ip6_frag_id; + else + ipv6_select_ident(fptr, + (struct rt6_info *)skb_dst(skb)); /* Fragment the skb. ipv6 header and the remaining fields of the * fragment header are updated in ipv6_gso_segment() |