summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLou Berger <lberger@labn.net>2018-04-10 11:57:13 -0400
committerGitHub <noreply@github.com>2018-04-10 11:57:13 -0400
commitebf58e2e481e3be7d9649b9923a8dc2f015a4b11 (patch)
tree7ade500ad3876b2cf6993faba792be45fbed66ac
parentaa2fc55b2096ee9704ddb74f200672ae999d9ab9 (diff)
parent20089ae2e41621e3e63aab67170d71bdf8605641 (diff)
Merge pull request #2009 from donaldsharp/self_originate
zebra: Notice when our route is deleted and re-install.
-rw-r--r--zebra/interface.c11
-rw-r--r--zebra/interface.h7
-rw-r--r--zebra/rt_netlink.c61
-rw-r--r--zebra/zebra_rib.c3
4 files changed, 58 insertions, 24 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 4f761a5e99..6f59a2d399 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 fba3201c5c..9634bfdb3f 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 3053c56d1e..d1edea804a 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) {
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index effe672a9d..48969e87f2 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -2491,8 +2491,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
* If we can show that this code path is
* dead then we can remove it.
*/
- if (fib && type == ZEBRA_ROUTE_KERNEL
- && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) {
+ if (fib && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) {
if (IS_ZEBRA_DEBUG_RIB) {
rnode_debug(
rn, vrf_id,