mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-03 07:38:10 +00:00
netdev: Add netdev->select_queue() method.
Devices or device layers can set this to control the queue selection performed by dev_pick_tx(). This function runs under RCU protection, which allows overriding functions to have some way of synchronizing with things like dynamic ->real_num_tx_queues adjustments. This makes the spinlock prefetch in dev_queue_xmit() a little bit less effective, but that's the price right now for correctness. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e3c50d5d25
commit
eae792b722
2 changed files with 9 additions and 3 deletions
|
@ -724,6 +724,9 @@ struct net_device
|
||||||
void (*poll_controller)(struct net_device *dev);
|
void (*poll_controller)(struct net_device *dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
u16 (*select_queue)(struct net_device *dev,
|
||||||
|
struct sk_buff *skb);
|
||||||
|
|
||||||
#ifdef CONFIG_NET_NS
|
#ifdef CONFIG_NET_NS
|
||||||
/* Network namespace this network device is inside */
|
/* Network namespace this network device is inside */
|
||||||
struct net *nd_net;
|
struct net *nd_net;
|
||||||
|
|
|
@ -1670,6 +1670,9 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
|
||||||
{
|
{
|
||||||
u16 queue_index = 0;
|
u16 queue_index = 0;
|
||||||
|
|
||||||
|
if (dev->select_queue)
|
||||||
|
queue_index = dev->select_queue(dev, skb);
|
||||||
|
|
||||||
skb_set_queue_mapping(skb, queue_index);
|
skb_set_queue_mapping(skb, queue_index);
|
||||||
return netdev_get_tx_queue(dev, queue_index);
|
return netdev_get_tx_queue(dev, queue_index);
|
||||||
}
|
}
|
||||||
|
@ -1710,14 +1713,14 @@ int dev_queue_xmit(struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
|
|
||||||
gso:
|
gso:
|
||||||
txq = dev_pick_tx(dev, skb);
|
|
||||||
spin_lock_prefetch(&txq->lock);
|
|
||||||
|
|
||||||
/* Disable soft irqs for various locks below. Also
|
/* Disable soft irqs for various locks below. Also
|
||||||
* stops preemption for RCU.
|
* stops preemption for RCU.
|
||||||
*/
|
*/
|
||||||
rcu_read_lock_bh();
|
rcu_read_lock_bh();
|
||||||
|
|
||||||
|
txq = dev_pick_tx(dev, skb);
|
||||||
|
spin_lock_prefetch(&txq->lock);
|
||||||
|
|
||||||
/* Updates of qdisc are serialized by queue->lock.
|
/* Updates of qdisc are serialized by queue->lock.
|
||||||
* The struct Qdisc which is pointed to by qdisc is now a
|
* The struct Qdisc which is pointed to by qdisc is now a
|
||||||
* rcu structure - it may be accessed without acquiring
|
* rcu structure - it may be accessed without acquiring
|
||||||
|
|
Loading…
Reference in a new issue