ipv6: Clean up ipv6_select_ident() and ip6_fragment()
authorMartin KaFai Lau <kafai@fb.com>
Sat, 23 May 2015 03:55:56 +0000 (20:55 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 25 May 2015 17:25:32 +0000 (13:25 -0400)
This patch changes the ipv6_select_ident() signature to return a
fragment id instead of taking a whole frag_hdr as a param to
only set the frag_hdr->identification.

It also cleans up ip6_fragment() to obtain the fragment id at the
beginning instead of using multiple "if" later to check fragment id
has been generated or not.

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Julian Anastasov <ja@ssi.bg>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ipv6.h
net/ipv6/ip6_output.c
net/ipv6/output_core.c

index aab8190d16e8f33197a53e18be4783a2824700c5..8c4f881edbd2586c7aef0b5396fbf38b405cc57e 100644 (file)
@@ -671,8 +671,7 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
        return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
 }
 
-void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr,
-                      struct rt6_info *rt);
+u32 ipv6_select_ident(struct net *net, struct rt6_info *rt);
 void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb);
 
 int ip6_dst_hoplimit(struct dst_entry *dst);
index bc09cb97b8401011c112afe469fd231382387622..05e2cdf938bdce64627c92ad1a66a6ec96b7f489 100644 (file)
@@ -551,7 +551,7 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
        struct frag_hdr *fh;
        unsigned int mtu, hlen, left, len;
        int hroom, troom;
-       __be32 frag_id = 0;
+       __be32 frag_id;
        int ptr, offset = 0, err = 0;
        u8 *prevhdr, nexthdr = 0;
        struct net *net = dev_net(skb_dst(skb)->dev);
@@ -584,6 +584,8 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
        }
        mtu -= hlen + sizeof(struct frag_hdr);
 
+       frag_id = ipv6_select_ident(net, rt);
+
        if (skb_has_frag_list(skb)) {
                int first_len = skb_pagelen(skb);
                struct sk_buff *frag2;
@@ -632,11 +634,10 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
                skb_reset_network_header(skb);
                memcpy(skb_network_header(skb), tmp_hdr, hlen);
 
-               ipv6_select_ident(net, fh, rt);
                fh->nexthdr = nexthdr;
                fh->reserved = 0;
                fh->frag_off = htons(IP6_MF);
-               frag_id = fh->identification;
+               fh->identification = frag_id;
 
                first_len = skb_pagelen(skb);
                skb->data_len = first_len - skb_headlen(skb);
@@ -778,11 +779,7 @@ slow_path:
                 */
                fh->nexthdr = nexthdr;
                fh->reserved = 0;
-               if (!frag_id) {
-                       ipv6_select_ident(net, fh, rt);
-                       frag_id = fh->identification;
-               } else
-                       fh->identification = frag_id;
+               fh->identification = frag_id;
 
                /*
                 *      Copy a block of the IP datagram.
@@ -1064,7 +1061,6 @@ static inline int ip6_ufo_append_data(struct sock *sk,
 
 {
        struct sk_buff *skb;
-       struct frag_hdr fhdr;
        int err;
 
        /* There is support for UDP large send offload by network
@@ -1106,8 +1102,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
        skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
                                     sizeof(struct frag_hdr)) & ~7;
        skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
-       ipv6_select_ident(sock_net(sk), &fhdr, rt);
-       skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+       skb_shinfo(skb)->ip6_frag_id = ipv6_select_ident(sock_net(sk), rt);
 
 append:
        return skb_append_datato_frags(sk, skb, getfrag, from,
index 85892af5736491fef3978bb8b195045e8e6d2e2c..ef0e2326496b20db674d5ceb6960443ac6ef782d 100644 (file)
@@ -60,8 +60,7 @@ void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
 
-void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr,
-                      struct rt6_info *rt)
+u32 ipv6_select_ident(struct net *net, struct rt6_info *rt)
 {
        static u32 ip6_idents_hashrnd __read_mostly;
        u32 id;
@@ -70,7 +69,7 @@ void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr,
 
        id = __ipv6_select_ident(net, ip6_idents_hashrnd, &rt->rt6i_dst.addr,
                                 &rt->rt6i_src.addr);
-       fhdr->identification = htonl(id);
+       return htonl(id);
 }
 EXPORT_SYMBOL(ipv6_select_ident);