]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Mon, 15 Nov 2021 13:42:06 +0000 (08:42 -0500)
committerSasha Levin <sashal@kernel.org>
Mon, 15 Nov 2021 13:42:06 +0000 (08:42 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/net-neigh-enable-state-migration-between-nud_permane.patch [new file with mode: 0644]
queue-5.10/series

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 (file)
index 0000000..4004bde
--- /dev/null
@@ -0,0 +1,163 @@
+From 0fd6123746c3881f1ccf0c3449f77ea458673b13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Oct 2021 14:12:36 +0200
+Subject: net, neigh: Enable state migration between NUD_PERMANENT and NTF_USE
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+[ 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 <daniel@iogearbox.net>
+Acked-by: Roopa Prabhu <roopa@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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, &notify);
++      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
+
index a543f70ce7aff56c05abaf86df5d0b88183d07fa..e8f3174744f805a12eaa0029036231fad014d9eb 100644 (file)
@@ -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