mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	neighbour: make proxy_queue.qlen limit per-device
Right now we have a neigh_param PROXY_QLEN which specifies maximum length of neigh_table->proxy_queue. But in fact, this limitation doesn't work well because check condition looks like: tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN) The problem is that p (struct neigh_parms) is a per-device thing, but tbl (struct neigh_table) is a system-wide global thing. It seems reasonable to make proxy_queue limit per-device based. v2: - nothing changed in this patch v3: - rebase to net tree Cc: "David S. Miller" <davem@davemloft.net> Cc: Eric Dumazet <edumazet@google.com> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Paolo Abeni <pabeni@redhat.com> Cc: Daniel Borkmann <daniel@iogearbox.net> Cc: David Ahern <dsahern@kernel.org> Cc: Yajun Deng <yajun.deng@linux.dev> Cc: Roopa Prabhu <roopa@nvidia.com> Cc: Christian Brauner <brauner@kernel.org> Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> Cc: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com> Cc: Konstantin Khorenko <khorenko@virtuozzo.com> Cc: kernel@openvz.org Cc: devel@openvz.org Suggested-by: Denis V. Lunev <den@openvz.org> Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com> Reviewed-by: Denis V. Lunev <den@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									66ba215cb5
								
							
						
					
					
						commit
						0ff4eb3d5e
					
				
					 2 changed files with 23 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -83,6 +83,7 @@ struct neigh_parms {
 | 
			
		|||
	struct rcu_head rcu_head;
 | 
			
		||||
 | 
			
		||||
	int	reachable_time;
 | 
			
		||||
	int	qlen;
 | 
			
		||||
	int	data[NEIGH_VAR_DATA_MAX];
 | 
			
		||||
	DECLARE_BITMAP(data_state, NEIGH_VAR_DATA_MAX);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -316,9 +316,18 @@ static void pneigh_queue_purge(struct sk_buff_head *list, struct net *net)
 | 
			
		|||
	skb = skb_peek(list);
 | 
			
		||||
	while (skb != NULL) {
 | 
			
		||||
		struct sk_buff *skb_next = skb_peek_next(skb, list);
 | 
			
		||||
		if (net == NULL || net_eq(dev_net(skb->dev), net)) {
 | 
			
		||||
		struct net_device *dev = skb->dev;
 | 
			
		||||
		if (net == NULL || net_eq(dev_net(dev), net)) {
 | 
			
		||||
			struct in_device *in_dev;
 | 
			
		||||
 | 
			
		||||
			rcu_read_lock();
 | 
			
		||||
			in_dev = __in_dev_get_rcu(dev);
 | 
			
		||||
			if (in_dev)
 | 
			
		||||
				in_dev->arp_parms->qlen--;
 | 
			
		||||
			rcu_read_unlock();
 | 
			
		||||
			__skb_unlink(skb, list);
 | 
			
		||||
			dev_put(skb->dev);
 | 
			
		||||
 | 
			
		||||
			dev_put(dev);
 | 
			
		||||
			kfree_skb(skb);
 | 
			
		||||
		}
 | 
			
		||||
		skb = skb_next;
 | 
			
		||||
| 
						 | 
				
			
			@ -1606,8 +1615,15 @@ static void neigh_proxy_process(struct timer_list *t)
 | 
			
		|||
 | 
			
		||||
		if (tdif <= 0) {
 | 
			
		||||
			struct net_device *dev = skb->dev;
 | 
			
		||||
			struct in_device *in_dev;
 | 
			
		||||
 | 
			
		||||
			rcu_read_lock();
 | 
			
		||||
			in_dev = __in_dev_get_rcu(dev);
 | 
			
		||||
			if (in_dev)
 | 
			
		||||
				in_dev->arp_parms->qlen--;
 | 
			
		||||
			rcu_read_unlock();
 | 
			
		||||
			__skb_unlink(skb, &tbl->proxy_queue);
 | 
			
		||||
 | 
			
		||||
			if (tbl->proxy_redo && netif_running(dev)) {
 | 
			
		||||
				rcu_read_lock();
 | 
			
		||||
				tbl->proxy_redo(skb);
 | 
			
		||||
| 
						 | 
				
			
			@ -1632,7 +1648,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
 | 
			
		|||
	unsigned long sched_next = jiffies +
 | 
			
		||||
			prandom_u32_max(NEIGH_VAR(p, PROXY_DELAY));
 | 
			
		||||
 | 
			
		||||
	if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
 | 
			
		||||
	if (p->qlen > NEIGH_VAR(p, PROXY_QLEN)) {
 | 
			
		||||
		kfree_skb(skb);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1648,6 +1664,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
 | 
			
		|||
	skb_dst_drop(skb);
 | 
			
		||||
	dev_hold(skb->dev);
 | 
			
		||||
	__skb_queue_tail(&tbl->proxy_queue, skb);
 | 
			
		||||
	p->qlen++;
 | 
			
		||||
	mod_timer(&tbl->proxy_timer, sched_next);
 | 
			
		||||
	spin_unlock(&tbl->proxy_queue.lock);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1680,6 +1697,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
 | 
			
		|||
		refcount_set(&p->refcnt, 1);
 | 
			
		||||
		p->reachable_time =
 | 
			
		||||
				neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
 | 
			
		||||
		p->qlen = 0;
 | 
			
		||||
		netdev_hold(dev, &p->dev_tracker, GFP_KERNEL);
 | 
			
		||||
		p->dev = dev;
 | 
			
		||||
		write_pnet(&p->net, net);
 | 
			
		||||
| 
						 | 
				
			
			@ -1745,6 +1763,7 @@ void neigh_table_init(int index, struct neigh_table *tbl)
 | 
			
		|||
	refcount_set(&tbl->parms.refcnt, 1);
 | 
			
		||||
	tbl->parms.reachable_time =
 | 
			
		||||
			  neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
 | 
			
		||||
	tbl->parms.qlen = 0;
 | 
			
		||||
 | 
			
		||||
	tbl->stats = alloc_percpu(struct neigh_statistics);
 | 
			
		||||
	if (!tbl->stats)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue