From: Don Slice Date: Wed, 28 Nov 2018 15:57:01 +0000 (+0000) Subject: zebra: handle neighbor delete from kernel for ipv4 link-local X-Git-Tag: frr-7.1-dev~145 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=f17b99ed1709c8e6cc940d3dbad737d3be21ddc4;p=mirror%2Ffrr.git zebra: handle neighbor delete from kernel for ipv4 link-local 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 --- diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index da74a757bf..cb9ef8e36f 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -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.