OSDN Git Service

neighbour: support for NTF_EXT_LEARNED flag
authorRoopa Prabhu <roopa@cumulusnetworks.com>
Tue, 24 Apr 2018 20:49:34 +0000 (13:49 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 25 Apr 2018 17:19:59 +0000 (13:19 -0400)
This patch extends NTF_EXT_LEARNED support to the neighbour system.
Example use-case: An Ethernet VPN implementation (eg in FRR routing suite)
can use this flag to add dynamic reachable external neigh entires
learned via control plane. The use of neigh NTF_EXT_LEARNED in this
patch is consistent with its use with bridge and vxlan fdb entries.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/neighbour.h
net/core/neighbour.c

index e421f86..6c1eecd 100644 (file)
@@ -246,6 +246,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_EXT_LEARNED             0x20000000
 #define NEIGH_UPDATE_F_ISROUTER                        0x40000000
 #define NEIGH_UPDATE_F_ADMIN                   0x80000000
 
@@ -526,5 +527,21 @@ static inline void neigh_ha_snapshot(char *dst, const struct neighbour *n,
        } while (read_seqretry(&n->ha_lock, seq));
 }
 
-
+static inline void neigh_update_ext_learned(struct neighbour *neigh, u32 flags,
+                                           int *notify)
+{
+       u8 ndm_flags = 0;
+
+       if (!(flags & NEIGH_UPDATE_F_ADMIN))
+               return;
+
+       ndm_flags |= (flags & NEIGH_UPDATE_F_EXT_LEARNED) ? NTF_EXT_LEARNED : 0;
+       if ((neigh->flags ^ ndm_flags) & NTF_EXT_LEARNED) {
+               if (ndm_flags & NTF_EXT_LEARNED)
+                       neigh->flags |= NTF_EXT_LEARNED;
+               else
+                       neigh->flags &= ~NTF_EXT_LEARNED;
+               *notify = 1;
+       }
+}
 #endif
index ce51986..5afae29 100644 (file)
@@ -820,7 +820,8 @@ static void neigh_periodic_work(struct work_struct *work)
                        write_lock(&n->lock);
 
                        state = n->nud_state;
-                       if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
+                       if ((state & (NUD_PERMANENT | NUD_IN_TIMER)) ||
+                           (n->flags & NTF_EXT_LEARNED)) {
                                write_unlock(&n->lock);
                                goto next_elt;
                        }
@@ -1136,6 +1137,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
        if (neigh->dead)
                goto out;
 
+       neigh_update_ext_learned(neigh, flags, &notify);
+
        if (!(new & NUD_VALID)) {
                neigh_del_timer(neigh);
                if (old & NUD_CONNECTED)
@@ -1781,6 +1784,9 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
                        flags &= ~NEIGH_UPDATE_F_OVERRIDE;
        }
 
+       if (ndm->ndm_flags & NTF_EXT_LEARNED)
+               flags |= NEIGH_UPDATE_F_EXT_LEARNED;
+
        if (ndm->ndm_flags & NTF_USE) {
                neigh_event_send(neigh, NULL);
                err = 0;