Skip to content

Commit a805d50

Browse files
jdikeksacilotto
authored andcommitted
Exempt multicast addresses from five-second neighbor lifetime
BugLink: https://bugs.launchpad.net/bugs/1908561 [ Upstream commit 8cf8821 ] Commit 5895631 ("neighbor: Improve garbage collection") guarantees neighbour table entries a five-second lifetime. Processes which make heavy use of multicast can fill the neighour table with multicast addresses in five seconds. At that point, neighbour entries can't be GC-ed because they aren't five seconds old yet, the kernel log starts to fill up with "neighbor table overflow!" messages, and sends start to fail. This patch allows multicast addresses to be thrown out before they've lived out their five seconds. This makes room for non-multicast addresses and makes messages to all addresses more reliable in these circumstances. Fixes: 5895631 ("neighbor: Improve garbage collection") Signed-off-by: Jeff Dike <jdike@akamai.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://lore.kernel.org/r/20201113015815.31397-1-jdike@akamai.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Ian May <ian.may@canonical.com>
1 parent a6636ae commit a805d50

File tree

4 files changed

+16
-0
lines changed

4 files changed

+16
-0
lines changed

include/net/neighbour.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ struct neigh_table {
204204
int (*pconstructor)(struct pneigh_entry *);
205205
void (*pdestructor)(struct pneigh_entry *);
206206
void (*proxy_redo)(struct sk_buff *skb);
207+
int (*is_multicast)(const void *pkey);
207208
bool (*allow_add)(const struct net_device *dev,
208209
struct netlink_ext_ack *extack);
209210
char *id;

net/core/neighbour.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)
235235

236236
write_lock(&n->lock);
237237
if ((n->nud_state == NUD_FAILED) ||
238+
(tbl->is_multicast &&
239+
tbl->is_multicast(n->primary_key)) ||
238240
time_after(tref, n->updated))
239241
remove = true;
240242
write_unlock(&n->lock);

net/ipv4/arp.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ static int arp_constructor(struct neighbour *neigh);
125125
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
126126
static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
127127
static void parp_redo(struct sk_buff *skb);
128+
static int arp_is_multicast(const void *pkey);
128129

129130
static const struct neigh_ops arp_generic_ops = {
130131
.family = AF_INET,
@@ -156,6 +157,7 @@ struct neigh_table arp_tbl = {
156157
.key_eq = arp_key_eq,
157158
.constructor = arp_constructor,
158159
.proxy_redo = parp_redo,
160+
.is_multicast = arp_is_multicast,
159161
.id = "arp_cache",
160162
.parms = {
161163
.tbl = &arp_tbl,
@@ -928,6 +930,10 @@ static void parp_redo(struct sk_buff *skb)
928930
arp_process(dev_net(skb->dev), NULL, skb);
929931
}
930932

933+
static int arp_is_multicast(const void *pkey)
934+
{
935+
return ipv4_is_multicast(*((__be32 *)pkey));
936+
}
931937

932938
/*
933939
* Receive an arp request from the device layer.

net/ipv6/ndisc.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
8181
static int pndisc_constructor(struct pneigh_entry *n);
8282
static void pndisc_destructor(struct pneigh_entry *n);
8383
static void pndisc_redo(struct sk_buff *skb);
84+
static int ndisc_is_multicast(const void *pkey);
8485

8586
static const struct neigh_ops ndisc_generic_ops = {
8687
.family = AF_INET6,
@@ -115,6 +116,7 @@ struct neigh_table nd_tbl = {
115116
.pconstructor = pndisc_constructor,
116117
.pdestructor = pndisc_destructor,
117118
.proxy_redo = pndisc_redo,
119+
.is_multicast = ndisc_is_multicast,
118120
.allow_add = ndisc_allow_add,
119121
.id = "ndisc_cache",
120122
.parms = {
@@ -1705,6 +1707,11 @@ static void pndisc_redo(struct sk_buff *skb)
17051707
kfree_skb(skb);
17061708
}
17071709

1710+
static int ndisc_is_multicast(const void *pkey)
1711+
{
1712+
return ipv6_addr_is_multicast((struct in6_addr *)pkey);
1713+
}
1714+
17081715
static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
17091716
{
17101717
struct inet6_dev *idev = __in6_dev_get(skb->dev);

0 commit comments

Comments
 (0)