Skip to content

Commit 0ff4eb3

Browse files
mihalicyndavem330
authored andcommitted
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" <[email protected]> Cc: Eric Dumazet <[email protected]> Cc: Jakub Kicinski <[email protected]> Cc: Paolo Abeni <[email protected]> Cc: Daniel Borkmann <[email protected]> Cc: David Ahern <[email protected]> Cc: Yajun Deng <[email protected]> Cc: Roopa Prabhu <[email protected]> Cc: Christian Brauner <[email protected]> Cc: [email protected] Cc: [email protected] Cc: Alexey Kuznetsov <[email protected]> Cc: Alexander Mikhalitsyn <[email protected]> Cc: Konstantin Khorenko <[email protected]> Cc: [email protected] Cc: [email protected] Suggested-by: Denis V. Lunev <[email protected]> Signed-off-by: Alexander Mikhalitsyn <[email protected]> Reviewed-by: Denis V. Lunev <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 66ba215 commit 0ff4eb3

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

include/net/neighbour.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ struct neigh_parms {
8383
struct rcu_head rcu_head;
8484

8585
int reachable_time;
86+
int qlen;
8687
int data[NEIGH_VAR_DATA_MAX];
8788
DECLARE_BITMAP(data_state, NEIGH_VAR_DATA_MAX);
8889
};

net/core/neighbour.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,18 @@ static void pneigh_queue_purge(struct sk_buff_head *list, struct net *net)
316316
skb = skb_peek(list);
317317
while (skb != NULL) {
318318
struct sk_buff *skb_next = skb_peek_next(skb, list);
319-
if (net == NULL || net_eq(dev_net(skb->dev), net)) {
319+
struct net_device *dev = skb->dev;
320+
if (net == NULL || net_eq(dev_net(dev), net)) {
321+
struct in_device *in_dev;
322+
323+
rcu_read_lock();
324+
in_dev = __in_dev_get_rcu(dev);
325+
if (in_dev)
326+
in_dev->arp_parms->qlen--;
327+
rcu_read_unlock();
320328
__skb_unlink(skb, list);
321-
dev_put(skb->dev);
329+
330+
dev_put(dev);
322331
kfree_skb(skb);
323332
}
324333
skb = skb_next;
@@ -1606,8 +1615,15 @@ static void neigh_proxy_process(struct timer_list *t)
16061615

16071616
if (tdif <= 0) {
16081617
struct net_device *dev = skb->dev;
1618+
struct in_device *in_dev;
16091619

1620+
rcu_read_lock();
1621+
in_dev = __in_dev_get_rcu(dev);
1622+
if (in_dev)
1623+
in_dev->arp_parms->qlen--;
1624+
rcu_read_unlock();
16101625
__skb_unlink(skb, &tbl->proxy_queue);
1626+
16111627
if (tbl->proxy_redo && netif_running(dev)) {
16121628
rcu_read_lock();
16131629
tbl->proxy_redo(skb);
@@ -1632,7 +1648,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
16321648
unsigned long sched_next = jiffies +
16331649
prandom_u32_max(NEIGH_VAR(p, PROXY_DELAY));
16341650

1635-
if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
1651+
if (p->qlen > NEIGH_VAR(p, PROXY_QLEN)) {
16361652
kfree_skb(skb);
16371653
return;
16381654
}
@@ -1648,6 +1664,7 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
16481664
skb_dst_drop(skb);
16491665
dev_hold(skb->dev);
16501666
__skb_queue_tail(&tbl->proxy_queue, skb);
1667+
p->qlen++;
16511668
mod_timer(&tbl->proxy_timer, sched_next);
16521669
spin_unlock(&tbl->proxy_queue.lock);
16531670
}
@@ -1680,6 +1697,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
16801697
refcount_set(&p->refcnt, 1);
16811698
p->reachable_time =
16821699
neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
1700+
p->qlen = 0;
16831701
netdev_hold(dev, &p->dev_tracker, GFP_KERNEL);
16841702
p->dev = dev;
16851703
write_pnet(&p->net, net);
@@ -1745,6 +1763,7 @@ void neigh_table_init(int index, struct neigh_table *tbl)
17451763
refcount_set(&tbl->parms.refcnt, 1);
17461764
tbl->parms.reachable_time =
17471765
neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
1766+
tbl->parms.qlen = 0;
17481767

17491768
tbl->stats = alloc_percpu(struct neigh_statistics);
17501769
if (!tbl->stats)

0 commit comments

Comments
 (0)