diff options
author | Iván Briano <ivan.briano@intel.com> | 2017-07-13 12:46:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-07-14 11:20:28 -0400 |
commit | ccd4eb49f3392ebf989d58bd013a7bf44cdca4d6 (patch) | |
tree | 11a5591bb0e15a09f49ce46d24b7161aaed750be /net | |
parent | 31a4562d7408493c6377933ff2f7d7302dbdea80 (diff) |
net/packet: Fix Tx queue selection for AF_PACKET
When PACKET_QDISC_BYPASS is not used, Tx queue selection will be done
before the packet is enqueued, taking into account any mappings set by
a queuing discipline such as mqprio without hardware offloading. This
selection may be affected by a previously saved queue_mapping, either on
the Rx path, or done before the packet reaches the device, as it's
currently the case for AF_PACKET.
In order for queue selection to work as expected when using traffic
control, there can't be another selection done before that point is
reached, so move the call to packet_pick_tx_queue to
packet_direct_xmit, leaving the default xmit path as it was before
PACKET_QDISC_BYPASS was introduced.
A forward declaration of packet_pick_tx_queue() is introduced to avoid
the need to reorder the functions within the file.
Fixes: d346a3fae3ff ("packet: introduce PACKET_QDISC_BYPASS socket option")
Signed-off-by: Iván Briano <ivan.briano@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/packet/af_packet.c | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index e3beb28203eb..008bb34ee324 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -214,6 +214,7 @@ static void prb_clear_rxhash(struct tpacket_kbdq_core *, | |||
214 | static void prb_fill_vlan_info(struct tpacket_kbdq_core *, | 214 | static void prb_fill_vlan_info(struct tpacket_kbdq_core *, |
215 | struct tpacket3_hdr *); | 215 | struct tpacket3_hdr *); |
216 | static void packet_flush_mclist(struct sock *sk); | 216 | static void packet_flush_mclist(struct sock *sk); |
217 | static void packet_pick_tx_queue(struct net_device *dev, struct sk_buff *skb); | ||
217 | 218 | ||
218 | struct packet_skb_cb { | 219 | struct packet_skb_cb { |
219 | union { | 220 | union { |
@@ -260,6 +261,7 @@ static int packet_direct_xmit(struct sk_buff *skb) | |||
260 | if (skb != orig_skb) | 261 | if (skb != orig_skb) |
261 | goto drop; | 262 | goto drop; |
262 | 263 | ||
264 | packet_pick_tx_queue(dev, skb); | ||
263 | txq = skb_get_tx_queue(dev, skb); | 265 | txq = skb_get_tx_queue(dev, skb); |
264 | 266 | ||
265 | local_bh_disable(); | 267 | local_bh_disable(); |
@@ -2747,8 +2749,6 @@ tpacket_error: | |||
2747 | goto tpacket_error; | 2749 | goto tpacket_error; |
2748 | } | 2750 | } |
2749 | 2751 | ||
2750 | packet_pick_tx_queue(dev, skb); | ||
2751 | |||
2752 | skb->destructor = tpacket_destruct_skb; | 2752 | skb->destructor = tpacket_destruct_skb; |
2753 | __packet_set_status(po, ph, TP_STATUS_SENDING); | 2753 | __packet_set_status(po, ph, TP_STATUS_SENDING); |
2754 | packet_inc_pending(&po->tx_ring); | 2754 | packet_inc_pending(&po->tx_ring); |
@@ -2931,8 +2931,6 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
2931 | skb->priority = sk->sk_priority; | 2931 | skb->priority = sk->sk_priority; |
2932 | skb->mark = sockc.mark; | 2932 | skb->mark = sockc.mark; |
2933 | 2933 | ||
2934 | packet_pick_tx_queue(dev, skb); | ||
2935 | |||
2936 | if (po->has_vnet_hdr) { | 2934 | if (po->has_vnet_hdr) { |
2937 | err = virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le()); | 2935 | err = virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le()); |
2938 | if (err) | 2936 | if (err) |