From 5b4c8cc3d22822475bd828ab212b22b4a11d1ab8 Mon Sep 17 00:00:00 2001 From: Paras Singh Jain Date: Wed, 2 Sep 2020 18:57:51 +0530 Subject: [PATCH 1/3] net: core: Send ARP probe and trigger RTM_NEWNEIGH Send ARP probe and generate RTM_NEWNEIGH if the neighbor state is not NUD_REACHABLE. Also featurize changes for sending neighbor probe. Change-Id: I633285b8e0cbcd49291d5e52136f11e20f2388bc Signed-off-by: Paras Singh Jain --- 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 8ec77bfdc1a4..202fc901cccc 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -64,6 +64,7 @@ enum { NEIGH_VAR_GC_THRESH1, NEIGH_VAR_GC_THRESH2, NEIGH_VAR_GC_THRESH3, + NEIGH_VAR_PROBE, NEIGH_VAR_MAX }; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 1d053a5db3b5..de1e2a8ac99e 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -58,6 +58,7 @@ static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid); static int pneigh_ifdown_and_unlock(struct neigh_table *tbl, struct net_device *dev); +static unsigned int neigh_probe_enable; #ifdef CONFIG_PROC_FS static const struct seq_operations neigh_stat_seq_ops; #endif @@ -1437,9 +1438,20 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl, { struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev, lladdr || !dev->addr_len); - if (neigh) - neigh_update(neigh, lladdr, NUD_STALE, - NEIGH_UPDATE_F_OVERRIDE, 0); + if (neigh) { + if (neigh_probe_enable) { + if (!(neigh->nud_state == NUD_REACHABLE)) { + neigh_update(neigh, lladdr, NUD_STALE, + NEIGH_UPDATE_F_OVERRIDE, 0); + write_lock(&neigh->lock); + neigh_probe(neigh); + neigh_update_notify(neigh, 0); + } + } else { + neigh_update(neigh, lladdr, NUD_STALE, + NEIGH_UPDATE_F_OVERRIDE, 0); + } + } return neigh; } EXPORT_SYMBOL(neigh_event_ns); @@ -3612,6 +3624,12 @@ static struct neigh_sysctl_table { .extra2 = SYSCTL_INT_MAX, .proc_handler = proc_dointvec_minmax, }, + [NEIGH_VAR_PROBE] = { + .procname = "neigh_probe", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, {}, }, }; @@ -3647,6 +3665,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1; t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2; t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3; + t->neigh_vars[NEIGH_VAR_PROBE].data = &neigh_probe_enable; } if (handler) { From 6df2a9aebc6e0c66f0a3904faa781380415b69d5 Mon Sep 17 00:00:00 2001 From: Paras Singh Jain Date: Wed, 9 Sep 2020 20:19:07 +0530 Subject: [PATCH 2/3] net: core: Release neigh lock when neigh_probe is enabled Release the neighbor lock when timer expires for a neighbor entry when neigh_probe flag is enabled. Change-Id: I25aa82bfbba32908b093b53fff85a52d1fd894b2 Signed-off-by: Paras Singh Jain --- net/core/neighbour.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index de1e2a8ac99e..b4b7d0ace5eb 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1087,11 +1087,19 @@ static void neigh_timer_handler(struct timer_list *t) if (!mod_timer(&neigh->timer, next)) neigh_hold(neigh); } - if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) { - neigh_probe(neigh); + + if (neigh_probe_enable) { + if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE | NUD_STALE)) + neigh_probe(neigh); + else + write_unlock(&neigh->lock); } else { + if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) { + neigh_probe(neigh); + } else { out: - write_unlock(&neigh->lock); + write_unlock(&neigh->lock); + } } if (notify) From b9f06c10b80ec9ec71c5a61f38cdaf537c9c2199 Mon Sep 17 00:00:00 2001 From: Paras Singh Jain Date: Fri, 18 Sep 2020 11:02:13 +0530 Subject: [PATCH 3/3] net: core: Dont send ARP probes for NUD_PERMANENET Whenever a new neighbour is added with the state NUD_PERMANENT, the ARP probing is removed since it is not needed. Change-Id: Id92b24d1b99b8deff91a8e105f7310efc2f21b39 Signed-off-by: Paras Singh Jain --- net/core/neighbour.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b4b7d0ace5eb..897fdc066014 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1448,9 +1448,10 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl, lladdr || !dev->addr_len); if (neigh) { if (neigh_probe_enable) { - if (!(neigh->nud_state == NUD_REACHABLE)) { + if (neigh->nud_state != NUD_REACHABLE && + neigh->nud_state != NUD_PERMANENT) { neigh_update(neigh, lladdr, NUD_STALE, - NEIGH_UPDATE_F_OVERRIDE, 0); + NEIGH_UPDATE_F_OVERRIDE, 0); write_lock(&neigh->lock); neigh_probe(neigh); neigh_update_notify(neigh, 0);