aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/skbuff.h
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-02-04 02:48:24 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-04 16:02:54 -0500
commit2bd82484bb4c5db1d5dc983ac7c409b2782e0154 (patch)
tree747ea7398b64904505419a0c6843c16c1452b5c9 /include/linux/skbuff.h
parent7e8acbb69ee2b855288afc61e3794a30e3582977 (diff)
xps: fix xps for stacked devices
A typical qdisc setup is the following : bond0 : bonding device, using HTB hierarchy eth1/eth2 : slaves, multiqueue NIC, using MQ + FQ qdisc XPS allows to spread packets on specific tx queues, based on the cpu doing the send. Problem is that dequeues from bond0 qdisc can happen on random cpus, due to the fact that qdisc_run() can dequeue a batch of packets. CPUA -> queue packet P1 on bond0 qdisc, P1->ooo_okay=1 CPUA -> queue packet P2 on bond0 qdisc, P2->ooo_okay=0 CPUB -> dequeue packet P1 from bond0 enqueue packet on eth1/eth2 CPUC -> dequeue packet P2 from bond0 enqueue packet on eth1/eth2 using sk cache (ooo_okay is 0) get_xps_queue() then might select wrong queue for P1, since current cpu might be different than CPUA. P2 might be sent on the old queue (stored in sk->sk_tx_queue_mapping), if CPUC runs a bit faster (or CPUB spins a bit on qdisc lock) Effect of this bug is TCP reorders, and more generally not optimal TX queue placement. (A victim bulk flow can be migrated to the wrong TX queue for a while) To fix this, we have to record sender cpu number the first time dev_queue_xmit() is called for one tx skb. We can union napi_id (used on receive path) and sender_cpu, granted we clear sender_cpu in skb_scrub_packet() (credit to Willem for this union idea) Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Willem de Bruijn <willemb@google.com> Cc: Nandita Dukkipati <nanditad@google.com> Cc: Yuchung Cheng <ycheng@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/skbuff.h')
-rw-r--r--include/linux/skbuff.h7
1 files changed, 5 insertions, 2 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 85ab7d72b54c..2748ff639144 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -626,8 +626,11 @@ struct sk_buff {
626 __u32 hash; 626 __u32 hash;
627 __be16 vlan_proto; 627 __be16 vlan_proto;
628 __u16 vlan_tci; 628 __u16 vlan_tci;
629#ifdef CONFIG_NET_RX_BUSY_POLL 629#if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS)
630 unsigned int napi_id; 630 union {
631 unsigned int napi_id;
632 unsigned int sender_cpu;
633 };
631#endif 634#endif
632#ifdef CONFIG_NETWORK_SECMARK 635#ifdef CONFIG_NETWORK_SECMARK
633 __u32 secmark; 636 __u32 secmark;