lkml.org 
[lkml]   [2021]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 339/355] net, neigh: Enable state migration between NUD_PERMANENT and NTF_USE
    Date
    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 4232bc8ce3d7d..b6494e87c897c 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 3a4cf53e38416..02e55041a8813 100644
    --- a/net/core/neighbour.c
    +++ b/net/core/neighbour.c
    @@ -1221,7 +1221,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
    @@ -1259,6 +1259,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);
    @@ -1966,22 +1972,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


    \
     
     \ /
      Last update: 2021-11-15 19:35    [W:2.111 / U:0.068 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site