Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: Add utility functions to clear rxhash

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>

authored by

Tom Herbert and committed by
David S. Miller
7539fadc 3958afa1

+22 -12
+12
include/linux/skbuff.h
··· 712 712 return skb->rxhash; 713 713 } 714 714 715 + static inline void skb_clear_hash(struct sk_buff *skb) 716 + { 717 + skb->rxhash = 0; 718 + skb->l4_rxhash = 0; 719 + } 720 + 721 + static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb) 722 + { 723 + if (!skb->l4_rxhash) 724 + skb_clear_hash(skb); 725 + } 726 + 715 727 #ifdef NET_SKBUFF_DATA_USES_OFFSET 716 728 static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) 717 729 {
+2 -3
include/net/dst.h
··· 322 322 skb->dev = dev; 323 323 324 324 /* 325 - * Clear rxhash so that we can recalulate the hash for the 325 + * Clear hash so that we can recalulate the hash for the 326 326 * encapsulated packet, unless we have already determine the hash 327 327 * over the L4 4-tuple. 328 328 */ 329 - if (!skb->l4_rxhash) 330 - skb->rxhash = 0; 329 + skb_clear_hash_if_not_l4(skb); 331 330 skb_set_queue_mapping(skb, 0); 332 331 skb_scrub_packet(skb, !net_eq(net, dev_net(dev))); 333 332 }
+1 -1
net/ipv4/ip_fragment.c
··· 704 704 memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); 705 705 if (ip_defrag(skb, user)) 706 706 return NULL; 707 - skb->rxhash = 0; 707 + skb_clear_hash(skb); 708 708 } 709 709 } 710 710 return skb;
+2 -3
net/ipv4/ip_tunnel_core.c
··· 56 56 57 57 skb_scrub_packet(skb, xnet); 58 58 59 - skb->rxhash = 0; 59 + skb_clear_hash(skb); 60 60 skb_dst_set(skb, &rt->dst); 61 61 memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 62 62 ··· 107 107 108 108 nf_reset(skb); 109 109 secpath_reset(skb); 110 - if (!skb->l4_rxhash) 111 - skb->rxhash = 0; 110 + skb_clear_hash_if_not_l4(skb); 112 111 skb_dst_drop(skb); 113 112 skb->vlan_tci = 0; 114 113 skb_set_queue_mapping(skb, 0);
+5 -5
net/openvswitch/actions.c
··· 165 165 } 166 166 167 167 csum_replace4(&nh->check, *addr, new_addr); 168 - skb->rxhash = 0; 168 + skb_clear_hash(skb); 169 169 *addr = new_addr; 170 170 } 171 171 ··· 199 199 if (recalculate_csum) 200 200 update_ipv6_checksum(skb, l4_proto, addr, new_addr); 201 201 202 - skb->rxhash = 0; 202 + skb_clear_hash(skb); 203 203 memcpy(addr, new_addr, sizeof(__be32[4])); 204 204 } 205 205 ··· 296 296 { 297 297 inet_proto_csum_replace2(check, skb, *port, new_port, 0); 298 298 *port = new_port; 299 - skb->rxhash = 0; 299 + skb_clear_hash(skb); 300 300 } 301 301 302 302 static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port) ··· 310 310 uh->check = CSUM_MANGLED_0; 311 311 } else { 312 312 *port = new_port; 313 - skb->rxhash = 0; 313 + skb_clear_hash(skb); 314 314 } 315 315 } 316 316 ··· 381 381 /* Carry any checksum errors through. */ 382 382 sh->checksum = old_csum ^ old_correct_csum ^ new_csum; 383 383 384 - skb->rxhash = 0; 384 + skb_clear_hash(skb); 385 385 } 386 386 387 387 return 0;