]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: handle neighbor delete from kernel for ipv4 link-local
authorDon Slice <dslice@cumulusnetworks.com>
Wed, 28 Nov 2018 15:57:01 +0000 (15:57 +0000)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 29 Nov 2018 21:01:47 +0000 (22:01 +0100)
Problem reported that kernel neighbor entries could end up in "FAILED"
state when the neighbor entry was deleted.  This fix handles the
notification of the event from netlink messages and re-inserts the
deleted entry.

Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
zebra/rt_netlink.c

index da74a757bfd1cb0cfd59d3d24f14d3f195bed504..cb9ef8e36f8dc0ac0cb7c1782bc03bb233592a70 100644 (file)
@@ -2274,6 +2274,25 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
                            0);
 }
 
+/*
+ * In the event the kernel deletes ipv4 link-local neighbor entries created for
+ * 5549 support, re-install them.
+ */
+static void netlink_handle_5549(struct ndmsg *ndm, struct zebra_if *zif,
+                               struct interface *ifp, struct ipaddr *ip)
+{
+       if (ndm->ndm_family != AF_INET)
+               return;
+
+       if (!zif->v6_2_v4_ll_neigh_entry)
+               return;
+
+       if (ipv4_ll.s_addr != ip->ip._v4_addr.s_addr)
+               return;
+
+       if_nbr_ipv6ll_to_ipv4ll_neigh_update(ifp, &zif->v6_2_v4_ll_addr6, true);
+}
+
 #define NUD_VALID                                                              \
        (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE     \
         | NUD_DELAY)
@@ -2319,29 +2338,16 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
        ip.ipa_type = (ndm->ndm_family == AF_INET) ? IPADDR_V4 : IPADDR_V6;
        memcpy(&ip.ip.addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
 
-       /* Drop some "permanent" entries. */
-       if (ndm->ndm_state & NUD_PERMANENT) {
-               char b[16] = "169.254.0.1";
-               struct in_addr ipv4_ll;
-
-               if (ndm->ndm_family != AF_INET)
-                       return 0;
-
-               if (!zif->v6_2_v4_ll_neigh_entry)
-                       return 0;
-
-               if (h->nlmsg_type != RTM_DELNEIGH)
-                       return 0;
-
-               inet_pton(AF_INET, b, &ipv4_ll);
-               if (ipv4_ll.s_addr != ip.ip._v4_addr.s_addr)
-                       return 0;
-
-               if_nbr_ipv6ll_to_ipv4ll_neigh_update(
-                       ifp, &zif->v6_2_v4_ll_addr6, true);
+       /* if kernel deletes our rfc5549 neighbor entry, re-install it */
+       if (h->nlmsg_type == RTM_DELNEIGH && (ndm->ndm_state & NUD_PERMANENT)) {
+               netlink_handle_5549(ndm, zif, ifp, &ip);
                return 0;
        }
 
+       /* if kernel marks our rfc5549 neighbor entry invalid, re-install it */
+       if (h->nlmsg_type == RTM_NEWNEIGH && !(ndm->ndm_state & NUD_VALID))
+               netlink_handle_5549(ndm, zif, ifp, &ip);
+
        /* The neighbor is present on an SVI. From this, we locate the
         * underlying
         * bridge because we're only interested in neighbors on a VxLAN bridge.