net: Add utility functions to clear rxhash
authorTom Herbert <therbert@google.com>
Mon, 16 Dec 2013 06:12:18 +0000 (22:12 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 Dec 2013 21:36:21 +0000 (16:36 -0500)
In several places 'skb->rxhash = 0' is being done to clear the
rxhash value in an skb.  This does not clear l4_rxhash which could
still be set so that the rxhash wouldn't be recalculated on subsequent
call to skb_get_rxhash.  This patch adds an explict function to clear
all the rxhash related information in the skb properly.

skb_clear_hash_if_not_l4 clears the rxhash only if it is not marked as
l4_rxhash.

Fixed up places where 'skb->rxhash = 0' was being called.

Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/skbuff.h
include/net/dst.h
net/ipv4/ip_fragment.c
net/ipv4/ip_tunnel_core.c
net/openvswitch/actions.c

index 4725b953e00d0cee125591a5902476cc94a2f234..7deb7ad65914f6353e2007190223a845d1bed322 100644 (file)
@@ -712,6 +712,18 @@ static inline __u32 skb_get_hash(struct sk_buff *skb)
        return skb->rxhash;
 }
 
+static inline void skb_clear_hash(struct sk_buff *skb)
+{
+       skb->rxhash = 0;
+       skb->l4_rxhash = 0;
+}
+
+static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb)
+{
+       if (!skb->l4_rxhash)
+               skb_clear_hash(skb);
+}
+
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
 static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
 {
index 44995c13e941df814db2433819d2934869df4d0f..77eb53fabfb00d6e446d89066937621b22c68e44 100644 (file)
@@ -322,12 +322,11 @@ static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
        skb->dev = dev;
 
        /*
-        * Clear rxhash so that we can recalulate the hash for the
+        * Clear hash so that we can recalulate the hash for the
         * encapsulated packet, unless we have already determine the hash
         * over the L4 4-tuple.
         */
-       if (!skb->l4_rxhash)
-               skb->rxhash = 0;
+       skb_clear_hash_if_not_l4(skb);
        skb_set_queue_mapping(skb, 0);
        skb_scrub_packet(skb, !net_eq(net, dev_net(dev)));
 }
index 2481993a49708337af890fad97c70f8d6c85f43d..c10a3ce5cbff0fc0bd0f23ac72188fd9e39fa83f 100644 (file)
@@ -704,7 +704,7 @@ struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
                        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
                        if (ip_defrag(skb, user))
                                return NULL;
-                       skb->rxhash = 0;
+                       skb_clear_hash(skb);
                }
        }
        return skb;
index 42ffbc8d65c65fda2b288008b4aed7670b43ee3f..6156f4ef5e919ccdc470f8cdb5a27593dedbe2c3 100644 (file)
@@ -56,7 +56,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
 
        skb_scrub_packet(skb, xnet);
 
-       skb->rxhash = 0;
+       skb_clear_hash(skb);
        skb_dst_set(skb, &rt->dst);
        memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 
@@ -107,8 +107,7 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
 
        nf_reset(skb);
        secpath_reset(skb);
-       if (!skb->l4_rxhash)
-               skb->rxhash = 0;
+       skb_clear_hash_if_not_l4(skb);
        skb_dst_drop(skb);
        skb->vlan_tci = 0;
        skb_set_queue_mapping(skb, 0);
index 65cfaa816075c93d933d4c6e17d13eaf6e92546f..716b7eebfe70dd46e52dc933c770db9c9133cb6f 100644 (file)
@@ -165,7 +165,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
        }
 
        csum_replace4(&nh->check, *addr, new_addr);
-       skb->rxhash = 0;
+       skb_clear_hash(skb);
        *addr = new_addr;
 }
 
@@ -199,7 +199,7 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
        if (recalculate_csum)
                update_ipv6_checksum(skb, l4_proto, addr, new_addr);
 
-       skb->rxhash = 0;
+       skb_clear_hash(skb);
        memcpy(addr, new_addr, sizeof(__be32[4]));
 }
 
@@ -296,7 +296,7 @@ static void set_tp_port(struct sk_buff *skb, __be16 *port,
 {
        inet_proto_csum_replace2(check, skb, *port, new_port, 0);
        *port = new_port;
-       skb->rxhash = 0;
+       skb_clear_hash(skb);
 }
 
 static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port)
@@ -310,7 +310,7 @@ static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port)
                        uh->check = CSUM_MANGLED_0;
        } else {
                *port = new_port;
-               skb->rxhash = 0;
+               skb_clear_hash(skb);
        }
 }
 
@@ -381,7 +381,7 @@ static int set_sctp(struct sk_buff *skb,
                /* Carry any checksum errors through. */
                sh->checksum = old_csum ^ old_correct_csum ^ new_csum;
 
-               skb->rxhash = 0;
+               skb_clear_hash(skb);
        }
 
        return 0;