Skip to content
Permalink
Browse files
Exempt multicast address from five-second neighbor lifetime
Commit 5895631 guarantees arp table entries a five-second lifetime.  We have some apps which make heavy use of multicast, and these can cause the table to overflow by filling it with multicast addresses which can't be GC-ed until their five seconds are up.
This patch allows multicast addresses to be thrown out before they've lived out their five seconds.

Signed-off-by: Jeff Dike <jdike@akamai.com>
  • Loading branch information
jdike authored and intel-lab-lkp committed Oct 16, 2020
1 parent 48d072c commit 3afd4b26a439959c7e9250ea6ede30645bb4f2ff
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 0 deletions.
@@ -204,6 +204,7 @@ struct neigh_table {
int (*pconstructor)(struct pneigh_entry *);
void (*pdestructor)(struct pneigh_entry *);
void (*proxy_redo)(struct sk_buff *skb);
int (*is_multicast)(const void *pkey);
bool (*allow_add)(const struct net_device *dev,
struct netlink_ext_ack *extack);
char *id;
@@ -235,6 +235,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)

write_lock(&n->lock);
if ((n->nud_state == NUD_FAILED) ||
(tbl->is_multicast &&
tbl->is_multicast(n->primary_key)) ||
time_after(tref, n->updated))
remove = true;
write_unlock(&n->lock);
@@ -79,6 +79,7 @@
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/errno.h>
#define __UAPI_DEF_IN_CLASS 1
#include <linux/in.h>
#include <linux/mm.h>
#include <linux/inet.h>
@@ -125,6 +126,7 @@ static int arp_constructor(struct neighbour *neigh);
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
static void parp_redo(struct sk_buff *skb);
static int arp_is_multicast(const void *pkey);

static const struct neigh_ops arp_generic_ops = {
.family = AF_INET,
@@ -156,6 +158,7 @@ struct neigh_table arp_tbl = {
.key_eq = arp_key_eq,
.constructor = arp_constructor,
.proxy_redo = parp_redo,
.is_multicast = arp_is_multicast,
.id = "arp_cache",
.parms = {
.tbl = &arp_tbl,
@@ -928,6 +931,10 @@ static void parp_redo(struct sk_buff *skb)
arp_process(dev_net(skb->dev), NULL, skb);
}

static int arp_is_multicast(const void *pkey)
{
return IN_MULTICAST(htonl(*((u32 *) pkey)));
}

/*
* Receive an arp request from the device layer.
@@ -81,6 +81,7 @@ static void ndisc_error_report(struct neighbour *neigh, struct sk_buff *skb);
static int pndisc_constructor(struct pneigh_entry *n);
static void pndisc_destructor(struct pneigh_entry *n);
static void pndisc_redo(struct sk_buff *skb);
static int ndisc_is_multicast(const void *pkey);

static const struct neigh_ops ndisc_generic_ops = {
.family = AF_INET6,
@@ -115,6 +116,7 @@ struct neigh_table nd_tbl = {
.pconstructor = pndisc_constructor,
.pdestructor = pndisc_destructor,
.proxy_redo = pndisc_redo,
.is_multicast = ndisc_is_multicast,
.allow_add = ndisc_allow_add,
.id = "ndisc_cache",
.parms = {
@@ -1706,6 +1708,11 @@ static void pndisc_redo(struct sk_buff *skb)
kfree_skb(skb);
}

static int ndisc_is_multicast(const void *pkey)
{
return (((struct in6_addr *) pkey)->in6_u.u6_addr8[0] & 0xf0) == 0xf0;
}

static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
{
struct inet6_dev *idev = __in6_dev_get(skb->dev);

0 comments on commit 3afd4b2

Please sign in to comment.