diff options
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 38 | 
1 files changed, 31 insertions, 7 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 2b3bf53bc687..0ea10f849be8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1553,6 +1553,24 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)  	rcu_read_unlock();  } +/* + * Routine to help set real_num_tx_queues. To avoid skbs mapped to queues + * greater then real_num_tx_queues stale skbs on the qdisc must be flushed. + */ +void netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) +{ +	unsigned int real_num = dev->real_num_tx_queues; + +	if (unlikely(txq > dev->num_tx_queues)) +		; +	else if (txq > real_num) +		dev->real_num_tx_queues = txq; +	else if (txq < real_num) { +		dev->real_num_tx_queues = txq; +		qdisc_reset_all_tx_gt(dev, txq); +	} +} +EXPORT_SYMBOL(netif_set_real_num_tx_queues);  static inline void __netif_reschedule(struct Qdisc *q)  { @@ -1893,8 +1911,16 @@ static int dev_gso_segment(struct sk_buff *skb)   */  static inline void skb_orphan_try(struct sk_buff *skb)  { -	if (!skb_tx(skb)->flags) +	struct sock *sk = skb->sk; + +	if (sk && !skb_tx(skb)->flags) { +		/* skb_tx_hash() wont be able to get sk. +		 * We copy sk_hash into skb->rxhash +		 */ +		if (!skb->rxhash) +			skb->rxhash = sk->sk_hash;  		skb_orphan(skb); +	}  }  int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, @@ -1980,8 +2006,7 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb)  	if (skb->sk && skb->sk->sk_hash)  		hash = skb->sk->sk_hash;  	else -		hash = (__force u16) skb->protocol; - +		hash = (__force u16) skb->protocol ^ skb->rxhash;  	hash = jhash_1word(hash, hashrnd);  	return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); @@ -2004,12 +2029,11 @@ static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)  static struct netdev_queue *dev_pick_tx(struct net_device *dev,  					struct sk_buff *skb)  { -	u16 queue_index; +	int queue_index;  	struct sock *sk = skb->sk; -	if (sk_tx_queue_recorded(sk)) { -		queue_index = sk_tx_queue_get(sk); -	} else { +	queue_index = sk_tx_queue_get(sk); +	if (queue_index < 0) {  		const struct net_device_ops *ops = dev->netdev_ops;  		if (ops->ndo_select_queue) {  | 
