aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-12-17 16:36:33 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-17 16:36:33 -0500
commitf66fd2dd7e29eecc4db82baa0cc96d77124b6049 (patch)
tree5d5e556692e3c945517319e812520286905a4af6
parent1aee6cc2a5193aa9963ea49b0d452723c1d493d8 (diff)
parent3df7a74e797aa2d8be9b7c649cfd56a8517dcf6e (diff)
Merge branch 'skb_hash'
Tom Herbert says: ==================== net: Add rxhash utility hash functions v3: There's really nothing specific about rxhash that constrains it to be a value just for these receive path. Drop the 'rx' part in utility functions, including skb_get_rxhash. In subsequent patches, we can change the rxhash and l4_rxhash names also, as well as abstracting out the interface to the hash. Added comments about hash types per feedback. In this version I'm omitting the changes to drivers to make the patch set manageable. Will add those changes in followup pathes. ----- This patch series introduce skb_set_rxhash and skb_clear_rxhash which are called to set the rxhash (from network drivers) and to clear the rxhash. This API should be used instead of updating fields in the skbuff directly. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/macvtap.c2
-rw-r--r--drivers/net/tun.c4
-rw-r--r--drivers/net/vxlan.c2
-rw-r--r--include/linux/skbuff.h64
-rw-r--r--include/net/dst.h5
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/flow_dissector.c6
-rw-r--r--net/core/skbuff.c3
-rw-r--r--net/ipv4/ip_fragment.c2
-rw-r--r--net/ipv4/ip_tunnel_core.c5
-rw-r--r--net/openvswitch/actions.c10
-rw-r--r--net/packet/af_packet.c4
-rw-r--r--net/sched/cls_flow.c2
-rw-r--r--net/sched/em_meta.c2
-rw-r--r--net/sched/sch_fq.c2
15 files changed, 86 insertions, 31 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 64409af0da31..431f58cb2ceb 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -224,7 +224,7 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev,
224 goto out; 224 goto out;
225 225
226 /* Check if we can use flow to select a queue */ 226 /* Check if we can use flow to select a queue */
227 rxq = skb_get_rxhash(skb); 227 rxq = skb_get_hash(skb);
228 if (rxq) { 228 if (rxq) {
229 tap = rcu_dereference(vlan->taps[rxq % numvtaps]); 229 tap = rcu_dereference(vlan->taps[rxq % numvtaps]);
230 goto out; 230 goto out;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 3c5a8d8cde50..8569da248336 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -358,7 +358,7 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
358 rcu_read_lock(); 358 rcu_read_lock();
359 numqueues = ACCESS_ONCE(tun->numqueues); 359 numqueues = ACCESS_ONCE(tun->numqueues);
360 360
361 txq = skb_get_rxhash(skb); 361 txq = skb_get_hash(skb);
362 if (txq) { 362 if (txq) {
363 e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq); 363 e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
364 if (e) 364 if (e)
@@ -1146,7 +1146,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
1146 skb_reset_network_header(skb); 1146 skb_reset_network_header(skb);
1147 skb_probe_transport_header(skb, 0); 1147 skb_probe_transport_header(skb, 0);
1148 1148
1149 rxhash = skb_get_rxhash(skb); 1149 rxhash = skb_get_hash(skb);
1150 netif_rx_ni(skb); 1150 netif_rx_ni(skb);
1151 1151
1152 tun->dev->stats.rx_packets++; 1152 tun->dev->stats.rx_packets++;
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 58f6a0c02b17..b247a7a29366 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1405,7 +1405,7 @@ __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb)
1405 unsigned int range = (port_max - port_min) + 1; 1405 unsigned int range = (port_max - port_min) + 1;
1406 u32 hash; 1406 u32 hash;
1407 1407
1408 hash = skb_get_rxhash(skb); 1408 hash = skb_get_hash(skb);
1409 if (!hash) 1409 if (!hash)
1410 hash = jhash(skb->data, 2 * ETH_ALEN, 1410 hash = jhash(skb->data, 2 * ETH_ALEN,
1411 (__force u32) skb->protocol); 1411 (__force u32) skb->protocol);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 77c7aae1c6b2..06bedeb0d49e 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -703,15 +703,73 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
703 unsigned int to, struct ts_config *config, 703 unsigned int to, struct ts_config *config,
704 struct ts_state *state); 704 struct ts_state *state);
705 705
706void __skb_get_rxhash(struct sk_buff *skb); 706/*
707static inline __u32 skb_get_rxhash(struct sk_buff *skb) 707 * Packet hash types specify the type of hash in skb_set_hash.
708 *
709 * Hash types refer to the protocol layer addresses which are used to
710 * construct a packet's hash. The hashes are used to differentiate or identify
711 * flows of the protocol layer for the hash type. Hash types are either
712 * layer-2 (L2), layer-3 (L3), or layer-4 (L4).
713 *
714 * Properties of hashes:
715 *
716 * 1) Two packets in different flows have different hash values
717 * 2) Two packets in the same flow should have the same hash value
718 *
719 * A hash at a higher layer is considered to be more specific. A driver should
720 * set the most specific hash possible.
721 *
722 * A driver cannot indicate a more specific hash than the layer at which a hash
723 * was computed. For instance an L3 hash cannot be set as an L4 hash.
724 *
725 * A driver may indicate a hash level which is less specific than the
726 * actual layer the hash was computed on. For instance, a hash computed
727 * at L4 may be considered an L3 hash. This should only be done if the
728 * driver can't unambiguously determine that the HW computed the hash at
729 * the higher layer. Note that the "should" in the second property above
730 * permits this.
731 */
732enum pkt_hash_types {
733 PKT_HASH_TYPE_NONE, /* Undefined type */
734 PKT_HASH_TYPE_L2, /* Input: src_MAC, dest_MAC */
735 PKT_HASH_TYPE_L3, /* Input: src_IP, dst_IP */
736 PKT_HASH_TYPE_L4, /* Input: src_IP, dst_IP, src_port, dst_port */
737};
738
739static inline void
740skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type)
741{
742 skb->l4_rxhash = (type == PKT_HASH_TYPE_L4);
743 skb->rxhash = hash;
744}
745
746void __skb_get_hash(struct sk_buff *skb);
747static inline __u32 skb_get_hash(struct sk_buff *skb)
708{ 748{
709 if (!skb->l4_rxhash) 749 if (!skb->l4_rxhash)
710 __skb_get_rxhash(skb); 750 __skb_get_hash(skb);
711 751
712 return skb->rxhash; 752 return skb->rxhash;
713} 753}
714 754
755static inline void skb_clear_hash(struct sk_buff *skb)
756{
757 skb->rxhash = 0;
758 skb->l4_rxhash = 0;
759}
760
761static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb)
762{
763 if (!skb->l4_rxhash)
764 skb_clear_hash(skb);
765}
766
767static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
768{
769 to->rxhash = from->rxhash;
770 to->l4_rxhash = from->l4_rxhash;
771};
772
715#ifdef NET_SKBUFF_DATA_USES_OFFSET 773#ifdef NET_SKBUFF_DATA_USES_OFFSET
716static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) 774static inline unsigned char *skb_end_pointer(const struct sk_buff *skb)
717{ 775{
diff --git a/include/net/dst.h b/include/net/dst.h
index 44995c13e941..77eb53fabfb0 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -322,12 +322,11 @@ static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev,
322 skb->dev = dev; 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 * encapsulated packet, unless we have already determine the hash 326 * encapsulated packet, unless we have already determine the hash
327 * over the L4 4-tuple. 327 * over the L4 4-tuple.
328 */ 328 */
329 if (!skb->l4_rxhash) 329 skb_clear_hash_if_not_l4(skb);
330 skb->rxhash = 0;
331 skb_set_queue_mapping(skb, 0); 330 skb_set_queue_mapping(skb, 0);
332 skb_scrub_packet(skb, !net_eq(net, dev_net(dev))); 331 skb_scrub_packet(skb, !net_eq(net, dev_net(dev)));
333} 332}
diff --git a/net/core/dev.c b/net/core/dev.c
index 9d4369ece679..c482fe8abf87 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3006,7 +3006,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
3006 } 3006 }
3007 3007
3008 skb_reset_network_header(skb); 3008 skb_reset_network_header(skb);
3009 if (!skb_get_rxhash(skb)) 3009 if (!skb_get_hash(skb))
3010 goto done; 3010 goto done;
3011 3011
3012 flow_table = rcu_dereference(rxqueue->rps_flow_table); 3012 flow_table = rcu_dereference(rxqueue->rps_flow_table);
@@ -3151,7 +3151,7 @@ static bool skb_flow_limit(struct sk_buff *skb, unsigned int qlen)
3151 rcu_read_lock(); 3151 rcu_read_lock();
3152 fl = rcu_dereference(sd->flow_limit); 3152 fl = rcu_dereference(sd->flow_limit);
3153 if (fl) { 3153 if (fl) {
3154 new_flow = skb_get_rxhash(skb) & (fl->num_buckets - 1); 3154 new_flow = skb_get_hash(skb) & (fl->num_buckets - 1);
3155 old_flow = fl->history[fl->history_head]; 3155 old_flow = fl->history[fl->history_head];
3156 fl->history[fl->history_head] = new_flow; 3156 fl->history[fl->history_head] = new_flow;
3157 3157
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index d6ef17322500..b324bfa3485c 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -202,12 +202,12 @@ static __always_inline u32 __flow_hash_1word(u32 a)
202} 202}
203 203
204/* 204/*
205 * __skb_get_rxhash: calculate a flow hash based on src/dst addresses 205 * __skb_get_hash: calculate a flow hash based on src/dst addresses
206 * and src/dst port numbers. Sets rxhash in skb to non-zero hash value 206 * and src/dst port numbers. Sets rxhash in skb to non-zero hash value
207 * on success, zero indicates no valid hash. Also, sets l4_rxhash in skb 207 * on success, zero indicates no valid hash. Also, sets l4_rxhash in skb
208 * if hash is a canonical 4-tuple hash over transport ports. 208 * if hash is a canonical 4-tuple hash over transport ports.
209 */ 209 */
210void __skb_get_rxhash(struct sk_buff *skb) 210void __skb_get_hash(struct sk_buff *skb)
211{ 211{
212 struct flow_keys keys; 212 struct flow_keys keys;
213 u32 hash; 213 u32 hash;
@@ -234,7 +234,7 @@ void __skb_get_rxhash(struct sk_buff *skb)
234 234
235 skb->rxhash = hash; 235 skb->rxhash = hash;
236} 236}
237EXPORT_SYMBOL(__skb_get_rxhash); 237EXPORT_SYMBOL(__skb_get_hash);
238 238
239/* 239/*
240 * Returns a Tx hash based on the given packet descriptor a Tx queues' number 240 * Returns a Tx hash based on the given packet descriptor a Tx queues' number
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 06e72d3cdf60..2b6b863f51f2 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -712,9 +712,8 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
712 new->inner_network_header = old->inner_network_header; 712 new->inner_network_header = old->inner_network_header;
713 new->inner_mac_header = old->inner_mac_header; 713 new->inner_mac_header = old->inner_mac_header;
714 skb_dst_copy(new, old); 714 skb_dst_copy(new, old);
715 new->rxhash = old->rxhash; 715 skb_copy_hash(new, old);
716 new->ooo_okay = old->ooo_okay; 716 new->ooo_okay = old->ooo_okay;
717 new->l4_rxhash = old->l4_rxhash;
718 new->no_fcs = old->no_fcs; 717 new->no_fcs = old->no_fcs;
719 new->encapsulation = old->encapsulation; 718 new->encapsulation = old->encapsulation;
720#ifdef CONFIG_XFRM 719#ifdef CONFIG_XFRM
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 2481993a4970..c10a3ce5cbff 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -704,7 +704,7 @@ struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
704 memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); 704 memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
705 if (ip_defrag(skb, user)) 705 if (ip_defrag(skb, user))
706 return NULL; 706 return NULL;
707 skb->rxhash = 0; 707 skb_clear_hash(skb);
708 } 708 }
709 } 709 }
710 return skb; 710 return skb;
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 42ffbc8d65c6..6156f4ef5e91 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -56,7 +56,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
56 56
57 skb_scrub_packet(skb, xnet); 57 skb_scrub_packet(skb, xnet);
58 58
59 skb->rxhash = 0; 59 skb_clear_hash(skb);
60 skb_dst_set(skb, &rt->dst); 60 skb_dst_set(skb, &rt->dst);
61 memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 61 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
62 62
@@ -107,8 +107,7 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
107 107
108 nf_reset(skb); 108 nf_reset(skb);
109 secpath_reset(skb); 109 secpath_reset(skb);
110 if (!skb->l4_rxhash) 110 skb_clear_hash_if_not_l4(skb);
111 skb->rxhash = 0;
112 skb_dst_drop(skb); 111 skb_dst_drop(skb);
113 skb->vlan_tci = 0; 112 skb->vlan_tci = 0;
114 skb_set_queue_mapping(skb, 0); 113 skb_set_queue_mapping(skb, 0);
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 65cfaa816075..716b7eebfe70 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -165,7 +165,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
165 } 165 }
166 166
167 csum_replace4(&nh->check, *addr, new_addr); 167 csum_replace4(&nh->check, *addr, new_addr);
168 skb->rxhash = 0; 168 skb_clear_hash(skb);
169 *addr = new_addr; 169 *addr = new_addr;
170} 170}
171 171
@@ -199,7 +199,7 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
199 if (recalculate_csum) 199 if (recalculate_csum)
200 update_ipv6_checksum(skb, l4_proto, addr, new_addr); 200 update_ipv6_checksum(skb, l4_proto, addr, new_addr);
201 201
202 skb->rxhash = 0; 202 skb_clear_hash(skb);
203 memcpy(addr, new_addr, sizeof(__be32[4])); 203 memcpy(addr, new_addr, sizeof(__be32[4]));
204} 204}
205 205
@@ -296,7 +296,7 @@ static void set_tp_port(struct sk_buff *skb, __be16 *port,
296{ 296{
297 inet_proto_csum_replace2(check, skb, *port, new_port, 0); 297 inet_proto_csum_replace2(check, skb, *port, new_port, 0);
298 *port = new_port; 298 *port = new_port;
299 skb->rxhash = 0; 299 skb_clear_hash(skb);
300} 300}
301 301
302static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port) 302static 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)
310 uh->check = CSUM_MANGLED_0; 310 uh->check = CSUM_MANGLED_0;
311 } else { 311 } else {
312 *port = new_port; 312 *port = new_port;
313 skb->rxhash = 0; 313 skb_clear_hash(skb);
314 } 314 }
315} 315}
316 316
@@ -381,7 +381,7 @@ static int set_sctp(struct sk_buff *skb,
381 /* Carry any checksum errors through. */ 381 /* Carry any checksum errors through. */
382 sh->checksum = old_csum ^ old_correct_csum ^ new_csum; 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 return 0; 387 return 0;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index cc803c63059a..24675f06f4fd 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -963,7 +963,7 @@ static void prb_clear_blk_fill_status(struct packet_ring_buffer *rb)
963static void prb_fill_rxhash(struct tpacket_kbdq_core *pkc, 963static void prb_fill_rxhash(struct tpacket_kbdq_core *pkc,
964 struct tpacket3_hdr *ppd) 964 struct tpacket3_hdr *ppd)
965{ 965{
966 ppd->hv1.tp_rxhash = skb_get_rxhash(pkc->skb); 966 ppd->hv1.tp_rxhash = skb_get_hash(pkc->skb);
967} 967}
968 968
969static void prb_clear_rxhash(struct tpacket_kbdq_core *pkc, 969static void prb_clear_rxhash(struct tpacket_kbdq_core *pkc,
@@ -1295,7 +1295,7 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
1295 if (!skb) 1295 if (!skb)
1296 return 0; 1296 return 0;
1297 } 1297 }
1298 skb_get_rxhash(skb); 1298 skb_get_hash(skb);
1299 idx = fanout_demux_hash(f, skb, num); 1299 idx = fanout_demux_hash(f, skb, num);
1300 break; 1300 break;
1301 case PACKET_FANOUT_LB: 1301 case PACKET_FANOUT_LB:
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 7881e2fccbc2..83a6322b7751 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -220,7 +220,7 @@ static u32 flow_get_vlan_tag(const struct sk_buff *skb)
220 220
221static u32 flow_get_rxhash(struct sk_buff *skb) 221static u32 flow_get_rxhash(struct sk_buff *skb)
222{ 222{
223 return skb_get_rxhash(skb); 223 return skb_get_hash(skb);
224} 224}
225 225
226static u32 flow_key_get(struct sk_buff *skb, int key, struct flow_keys *flow) 226static u32 flow_key_get(struct sk_buff *skb, int key, struct flow_keys *flow)
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 382519a5d7f9..9b8c0b0e60d7 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -222,7 +222,7 @@ META_COLLECTOR(int_maclen)
222 222
223META_COLLECTOR(int_rxhash) 223META_COLLECTOR(int_rxhash)
224{ 224{
225 dst->value = skb_get_rxhash(skb); 225 dst->value = skb_get_hash(skb);
226} 226}
227 227
228/************************************************************************** 228/**************************************************************************
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index f2fb92dd970d..08ef7a42c0e4 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -226,7 +226,7 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
226 /* By forcing low order bit to 1, we make sure to not 226 /* By forcing low order bit to 1, we make sure to not
227 * collide with a local flow (socket pointers are word aligned) 227 * collide with a local flow (socket pointers are word aligned)
228 */ 228 */
229 sk = (struct sock *)(skb_get_rxhash(skb) | 1L); 229 sk = (struct sock *)(skb_get_hash(skb) | 1L);
230 } 230 }
231 231
232 root = &q->fq_root[hash_32((u32)(long)sk, q->fq_trees_log)]; 232 root = &q->fq_root[hash_32((u32)(long)sk, q->fq_trees_log)];