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. https://jira.sw.ru/browse/PSBM-140896 Cc: "David S. Miller" <da...@davemloft.net> Cc: Eric Dumazet <eduma...@google.com> Cc: Jakub Kicinski <k...@kernel.org> Cc: Paolo Abeni <pab...@redhat.com> Cc: Daniel Borkmann <dan...@iogearbox.net> Cc: David Ahern <dsah...@kernel.org> Cc: Yajun Deng <yajun.d...@linux.dev> Cc: Roopa Prabhu <ro...@nvidia.com> Cc: Christian Brauner <brau...@kernel.org> Cc: net...@vger.kernel.org Cc: linux-ker...@vger.kernel.org Cc: Alexey Kuznetsov <kuz...@ms2.inr.ac.ru> Cc: Alexander Mikhalitsyn <alexander.mikhalit...@virtuozzo.com> Cc: Konstantin Khorenko <khore...@virtuozzo.com> Cc: ker...@openvz.org Cc: devel@openvz.org Suggested-by: Denis V. Lunev <d...@openvz.org> Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalit...@virtuozzo.com> Reviewed-by: Denis V. Lunev <d...@openvz.org> --- include/net/neighbour.h | 1 + net/core/neighbour.c | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 22ced1381ede..8c8b8605bf98 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -81,6 +81,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); }; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f33e01a0ed5e..4f7edf22c2fd 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -292,9 +292,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; @@ -1589,8 +1598,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); @@ -1615,7 +1631,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; } @@ -1631,6 +1647,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); } @@ -1663,6 +1680,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; dev_hold(dev); p->dev = dev; write_pnet(&p->net, net); @@ -1726,6 +1744,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) -- 2.36.1 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel