From 6c5dabd69c17c5b2ec40212bfb47493cb8dd978b Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 15 Nov 2021 08:42:06 -0500 Subject: [PATCH] Fixes for 5.10 Signed-off-by: Sasha Levin --- ...-state-migration-between-nud_permane.patch | 163 ++++++++++++++++++ queue-5.10/series | 1 + 2 files changed, 164 insertions(+) create mode 100644 queue-5.10/net-neigh-enable-state-migration-between-nud_permane.patch diff --git a/queue-5.10/net-neigh-enable-state-migration-between-nud_permane.patch b/queue-5.10/net-neigh-enable-state-migration-between-nud_permane.patch new file mode 100644 index 00000000000..4004bde1132 --- /dev/null +++ b/queue-5.10/net-neigh-enable-state-migration-between-nud_permane.patch @@ -0,0 +1,163 @@ +From 0fd6123746c3881f1ccf0c3449f77ea458673b13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Oct 2021 14:12:36 +0200 +Subject: net, neigh: Enable state migration between NUD_PERMANENT and NTF_USE + +From: Daniel Borkmann + +[ Upstream commit 3dc20f4762c62d3b3f0940644881ed818aa7b2f5 ] + +Currently, it is not possible to migrate a neighbor entry between NUD_PERMANENT +state and NTF_USE flag with a dynamic NUD state from a user space control plane. +Similarly, it is not possible to add/remove NTF_EXT_LEARNED flag from an existing +neighbor entry in combination with NTF_USE flag. + +This is due to the latter directly calling into neigh_event_send() without any +meta data updates as happening in __neigh_update(). Thus, to enable this use +case, extend the latter with a NEIGH_UPDATE_F_USE flag where we break the +NUD_PERMANENT state in particular so that a latter neigh_event_send() is able +to re-resolve a neighbor entry. + +Before fix, NUD_PERMANENT -> NUD_* & NTF_USE: + + # ./ip/ip n replace 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a PERMANENT + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a PERMANENT + [...] + +As can be seen, despite the admin-triggered replace, the entry remains in the +NUD_PERMANENT state. + +After fix, NUD_PERMANENT -> NUD_* & NTF_USE: + + # ./ip/ip n replace 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a PERMANENT + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a extern_learn REACHABLE + [...] + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a extern_learn STALE + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a PERMANENT + [...] + +After the fix, the admin-triggered replace switches to a dynamic state from +the NTF_USE flag which triggered a new neighbor resolution. Likewise, we can +transition back from there, if needed, into NUD_PERMANENT. + +Similar before/after behavior can be observed for below transitions: + +Before fix, NTF_USE -> NTF_USE | NTF_EXT_LEARNED -> NTF_USE: + + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE + [...] + +After fix, NTF_USE -> NTF_USE | NTF_EXT_LEARNED -> NTF_USE: + + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a extern_learn REACHABLE + [...] + # ./ip/ip n replace 192.168.178.30 dev enp5s0 use + # ./ip/ip n + 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE + [..] + +Signed-off-by: Daniel Borkmann +Acked-by: Roopa Prabhu +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/net/neighbour.h | 1 + + net/core/neighbour.c | 22 +++++++++++++--------- + 2 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/include/net/neighbour.h b/include/net/neighbour.h +index 990f9b1d17092..d5767e25509cc 100644 +--- a/include/net/neighbour.h ++++ b/include/net/neighbour.h +@@ -253,6 +253,7 @@ static inline void *neighbour_priv(const struct neighbour *n) + #define NEIGH_UPDATE_F_OVERRIDE 0x00000001 + #define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002 + #define NEIGH_UPDATE_F_OVERRIDE_ISROUTER 0x00000004 ++#define NEIGH_UPDATE_F_USE 0x10000000 + #define NEIGH_UPDATE_F_EXT_LEARNED 0x20000000 + #define NEIGH_UPDATE_F_ISROUTER 0x40000000 + #define NEIGH_UPDATE_F_ADMIN 0x80000000 +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 01e243a578e9c..8eec7667aa761 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -1222,7 +1222,7 @@ static void neigh_update_hhs(struct neighbour *neigh) + lladdr instead of overriding it + if it is different. + NEIGH_UPDATE_F_ADMIN means that the change is administrative. +- ++ NEIGH_UPDATE_F_USE means that the entry is user triggered. + NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing + NTF_ROUTER flag. + NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as +@@ -1260,6 +1260,12 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, + goto out; + + ext_learn_change = neigh_update_ext_learned(neigh, flags, ¬ify); ++ if (flags & NEIGH_UPDATE_F_USE) { ++ new = old & ~NUD_PERMANENT; ++ neigh->nud_state = new; ++ err = 0; ++ goto out; ++ } + + if (!(new & NUD_VALID)) { + neigh_del_timer(neigh); +@@ -1971,22 +1977,20 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, + + if (protocol) + neigh->protocol = protocol; +- + if (ndm->ndm_flags & NTF_EXT_LEARNED) + flags |= NEIGH_UPDATE_F_EXT_LEARNED; +- + if (ndm->ndm_flags & NTF_ROUTER) + flags |= NEIGH_UPDATE_F_ISROUTER; ++ if (ndm->ndm_flags & NTF_USE) ++ flags |= NEIGH_UPDATE_F_USE; + +- if (ndm->ndm_flags & NTF_USE) { ++ err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags, ++ NETLINK_CB(skb).portid, extack); ++ if (!err && ndm->ndm_flags & NTF_USE) { + neigh_event_send(neigh, NULL); + err = 0; +- } else +- err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags, +- NETLINK_CB(skb).portid, extack); +- ++ } + neigh_release(neigh); +- + out: + return err; + } +-- +2.33.0 + diff --git a/queue-5.10/series b/queue-5.10/series index a543f70ce7a..e8f3174744f 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -541,3 +541,4 @@ arm-9156-1-drop-cc-option-fallbacks-for-architecture-selection.patch parisc-fix-backtrace-to-always-include-init-funtion-names.patch mips-fix-assembly-error-from-mipsr2-code-used-within-mips_isa_arch_level.patch x86-mce-add-errata-workaround-for-skylake-skx37.patch +net-neigh-enable-state-migration-between-nud_permane.patch -- 2.47.2