diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2018-04-09 14:04:39 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2018-04-09 14:04:39 +0200 |
commit | 20089ae2e41621e3e63aab67170d71bdf8605641 (patch) | |
tree | e96a774f74fc3e3cc60acc4d24d15a64afdebce9 | |
parent | zebra: Notice when our route is deleted and re-install. (diff) | |
download | frr-20089ae2e41621e3e63aab67170d71bdf8605641.tar.xz frr-20089ae2e41621e3e63aab67170d71bdf8605641.zip |
zebra: Notice when our neighbor entry is removed and fight back
Notice when someone deletes a neighbor entry we've put in for
rfc-5549 gets deleted by some evil evil person. When this happens
notice and push it back in, immediately.
Ticket: CM-18612
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
-rw-r--r-- | zebra/interface.c | 11 | ||||
-rw-r--r-- | zebra/interface.h | 7 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 61 |
3 files changed, 57 insertions, 22 deletions
diff --git a/zebra/interface.c b/zebra/interface.c index 4f761a5e9..6f59a2d39 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -825,6 +825,7 @@ void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp, struct in6_addr *address, int add) { struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + struct zebra_if *zif = ifp->info; char buf[16] = "169.254.0.1"; struct in_addr ipv4_ll; char mac[6]; @@ -845,6 +846,16 @@ void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp, /* Add arp record */ kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id); + + /* + * We need to note whether or not we originated a v6 + * neighbor entry for this interface. So that when + * someone unwisely accidently deletes this entry + * we can shove it back in. + */ + zif->v6_2_v4_ll_neigh_entry = !!add; + memcpy(&zif->v6_2_v4_ll_addr6, address, sizeof(*address)); + zvrf->neigh_updates++; } diff --git a/zebra/interface.h b/zebra/interface.h index fba3201c5..9634bfdb3 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -272,6 +272,13 @@ struct zebra_if { struct interface *link; struct thread *speed_update; + + /* + * Does this interface have a v6 to v4 ll neighbor entry + * for bgp unnumbered? + */ + bool v6_2_v4_ll_neigh_entry; + struct in6_addr v6_2_v4_ll_addr6; }; DECLARE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp), diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 3053c56d1..d1edea804 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -2112,21 +2112,53 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, ndm = NLMSG_DATA(h); - /* We only process neigh notifications if EVPN is enabled */ - if (!is_evpn_enabled()) - return 0; - /* The interface should exist. */ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ndm->ndm_ifindex); if (!ifp || !ifp->info) return 0; - /* Drop "permanent" entries. */ - if (ndm->ndm_state & NUD_PERMANENT) + zif = (struct zebra_if *)ifp->info; + + /* Parse attributes and extract fields of interest. */ + memset(tb, 0, sizeof tb); + netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + + if (!tb[NDA_DST]) { + zlog_warn("%s family %s IF %s(%u) - no DST", + nl_msg_type_to_str(h->nlmsg_type), + nl_family_to_str(ndm->ndm_family), ifp->name, + ndm->ndm_ifindex); return 0; + } + + memset(&ip, 0, sizeof(struct ipaddr)); + 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 buf[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, buf, &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); + return 0; + } - zif = (struct zebra_if *)ifp->info; /* 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. @@ -2148,22 +2180,7 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h, else return 0; - /* Parse attributes and extract fields of interest. */ - memset(tb, 0, sizeof tb); - netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); - - if (!tb[NDA_DST]) { - zlog_warn("%s family %s IF %s(%u) - no DST", - nl_msg_type_to_str(h->nlmsg_type), - nl_family_to_str(ndm->ndm_family), ifp->name, - ndm->ndm_ifindex); - return 0; - } memset(&mac, 0, sizeof(struct ethaddr)); - memset(&ip, 0, sizeof(struct ipaddr)); - 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])); - if (h->nlmsg_type == RTM_NEWNEIGH) { if (tb[NDA_LLADDR]) { if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) { |