DESC_ENTRY(ZEBRA_NHG_DEL),
DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER),
DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST),
- DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY)};
+ DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY),
+ DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_ADD),
+ DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL)};
#undef DESC_ENTRY
static const struct zebra_desc_table unknown = {0, "unknown", '?'};
[ZEBRA_NHG_ADD] = zread_nhg_add,
[ZEBRA_NHG_DEL] = zread_nhg_del,
[ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request,
+ [ZEBRA_EVPN_REMOTE_NH_ADD] = zebra_evpn_proc_remote_nh,
+ [ZEBRA_EVPN_REMOTE_NH_DEL] = zebra_evpn_proc_remote_nh,
};
/*
}
}
+/*****************************************************************************
+ * Nexthop management: nexthops associated with Type-2 routes that have
+ * an ES as destination are consolidated by BGP into a per-VRF nh->rmac
+ * mapping which is the installed as a remote neigh/fdb entry with a
+ * dummy (type-1) prefix referencing it.
+ * This handling is needed because Type-2 routes with ES as dest use NHG
+ * that are setup using EAD routes (i.e. such NHGs do not include the
+ * RMAC info).
+ ****************************************************************************/
+void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS)
+{
+ struct stream *s;
+ vrf_id_t vrf_id;
+ struct ipaddr nh;
+ struct ethaddr rmac;
+ struct prefix_evpn dummy_prefix;
+
+ s = msg;
+ vrf_id = stream_getl(s);
+ stream_get(&nh, s, sizeof(nh));
+
+ memset(&dummy_prefix, 0, sizeof(dummy_prefix));
+ dummy_prefix.family = AF_EVPN;
+ dummy_prefix.prefixlen = (sizeof(struct evpn_addr) * 8);
+ dummy_prefix.prefix.route_type = 1; /* XXX - fixup to type-1 def */
+
+ if (hdr->command == ZEBRA_EVPN_REMOTE_NH_ADD) {
+ stream_get(&rmac, s, sizeof(rmac));
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("evpn remote nh %d %pIA rmac %pEA add",
+ vrf_id, &nh, &rmac);
+ zebra_vxlan_evpn_vrf_route_add(vrf_id, &rmac, &nh,
+ (struct prefix *)&dummy_prefix);
+ } else {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("evpn remote nh %d %pIA del", vrf_id, &nh);
+ zebra_vxlan_evpn_vrf_route_del(vrf_id, &nh,
+ (struct prefix *)&dummy_prefix);
+ }
+}
+
/*****************************************************************************/
void zebra_evpn_mh_config_write(struct vty *vty)
{
} else if (hle1->p.family == AF_INET6) {
return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6,
IPV6_MAX_BYTELEN);
+ } else if (hle1->p.family == AF_EVPN) {
+ /* a single dummy prefix of route_type BGP_EVPN_AD_ROUTE is
+ * used for all nexthops associated with a non-zero ESI
+ */
+ return 0;
} else {
zlog_debug("%s: Unexpected family type: %d", __func__,
hle1->p.family);