summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/if_netlink.c4
-rw-r--r--zebra/interface.c5
-rw-r--r--zebra/interface.h2
-rw-r--r--zebra/ioctl.c8
-rw-r--r--zebra/kernel_netlink.c12
-rw-r--r--zebra/kernel_socket.c35
-rw-r--r--zebra/zapi_msg.c2
-rw-r--r--zebra/zebra_evpn_mac.c13
-rw-r--r--zebra/zebra_evpn_mac.h4
-rw-r--r--zebra/zebra_netns_notify.c2
-rw-r--r--zebra/zebra_rnh.c27
-rw-r--r--zebra/zebra_rnh.h8
-rw-r--r--zebra/zebra_vty.c12
-rw-r--r--zebra/zebra_vxlan.c169
14 files changed, 199 insertions, 104 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index fca03e55bf..873aea236d 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -103,7 +103,7 @@ static void set_ifindex(struct interface *ifp, ifindex_t ifi_index,
EC_LIB_INTERFACE,
"interface rename detected on up interface: index %d was renamed from %s to %s, results are uncertain!",
ifi_index, oifp->name, ifp->name);
- if_delete_update(oifp);
+ if_delete_update(&oifp);
}
}
if_set_index(ifp, ifi_index);
@@ -2144,7 +2144,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
else if (IS_ZEBRA_IF_VXLAN(ifp))
zebra_l2_vxlanif_del(ifp);
- if_delete_update(ifp);
+ if_delete_update(&ifp);
/* If VRF, delete the VRF structure itself. */
if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns())
diff --git a/zebra/interface.c b/zebra/interface.c
index 69d611e583..a70326ebb3 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -806,9 +806,10 @@ static void if_delete_connected(struct interface *ifp)
}
/* Handle an interface delete event */
-void if_delete_update(struct interface *ifp)
+void if_delete_update(struct interface **pifp)
{
struct zebra_if *zif;
+ struct interface *ifp = *pifp;
if (if_is_up(ifp)) {
flog_err(
@@ -871,7 +872,7 @@ void if_delete_update(struct interface *ifp)
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("interface %s is being deleted from the system",
ifp->name);
- if_delete(&ifp);
+ if_delete(pifp);
}
}
diff --git a/zebra/interface.h b/zebra/interface.h
index 4b06603e7f..c6930ce816 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -492,7 +492,7 @@ extern void if_nbr_ipv6ll_to_ipv4ll_neigh_update(struct interface *ifp,
struct in6_addr *address,
int add);
extern void if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(struct interface *ifp);
-extern void if_delete_update(struct interface *ifp);
+extern void if_delete_update(struct interface **ifp);
extern void if_add_update(struct interface *ifp);
extern void if_up(struct interface *ifp, bool install_connected);
extern void if_down(struct interface *);
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index 9b6aaf1d85..a895ed9410 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -136,7 +136,7 @@ static int if_ioctl_ipv6(unsigned long request, caddr_t buffer)
void if_get_metric(struct interface *ifp)
{
#ifdef SIOCGIFMETRIC
- struct ifreq ifreq;
+ struct ifreq ifreq = {};
ifreq_set_name(&ifreq, ifp);
@@ -153,7 +153,7 @@ void if_get_metric(struct interface *ifp)
/* get interface MTU */
void if_get_mtu(struct interface *ifp)
{
- struct ifreq ifreq;
+ struct ifreq ifreq = {};
ifreq_set_name(&ifreq, ifp);
@@ -410,8 +410,8 @@ int if_unset_prefix_ctx(const struct zebra_dplane_ctx *ctx)
void if_get_flags(struct interface *ifp)
{
int ret;
- struct ifreq ifreqflags;
- struct ifreq ifreqdata;
+ struct ifreq ifreqflags = {};
+ struct ifreq ifreqdata = {};
ifreq_set_name(&ifreqflags, ifp);
ifreq_set_name(&ifreqdata, ifp);
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 0dd76e3253..35f3274c65 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -1016,6 +1016,18 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
return err;
}
+ /*
+ * What is the right thing to do? The kernel
+ * is telling us that the dump request was interrupted
+ * and we more than likely are out of luck and have
+ * missed data from the kernel. At this point in time
+ * lets just note that this is happening.
+ */
+ if (h->nlmsg_flags & NLM_F_DUMP_INTR)
+ flog_err(
+ EC_ZEBRA_NETLINK_BAD_SEQUENCE,
+ "netlink recvmsg: The Dump request was interrupted");
+
/* OK we got netlink message. */
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 6583af0a54..d6ca92f54e 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -159,6 +159,9 @@ const struct message rtm_type_str[] = {{RTM_ADD, "RTM_ADD"},
#ifdef RTM_IFANNOUNCE
{RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
#endif /* RTM_IFANNOUNCE */
+#ifdef RTM_IEEE80211
+ {RTM_IEEE80211, "RTM_IEEE80211"},
+#endif
{0}};
static const struct message rtm_flag_str[] = {{RTF_UP, "UP"},
@@ -450,12 +453,13 @@ static int ifan_read(struct if_announcemsghdr *ifan)
if_get_metric(ifp);
if_add_update(ifp);
} else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
- if_delete_update(ifp);
-
- if_get_flags(ifp);
- if_get_mtu(ifp);
- if_get_metric(ifp);
+ if_delete_update(&ifp);
+ if (ifp) {
+ if_get_flags(ifp);
+ if_get_mtu(ifp);
+ if_get_metric(ifp);
+ }
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: interface %s index %d", __func__,
ifan->ifan_name, ifan->ifan_index);
@@ -722,10 +726,10 @@ int ifm_read(struct if_msghdr *ifm)
* will still behave correctly if run on a platform
* without
*/
- if_delete_update(ifp);
+ if_delete_update(&ifp);
}
#endif /* RTM_IFANNOUNCE */
- if (if_is_up(ifp)) {
+ if (ifp && if_is_up(ifp)) {
#if defined(__bsdi__)
if_kvm_get_mtu(ifp);
#else
@@ -735,14 +739,16 @@ int ifm_read(struct if_msghdr *ifm)
}
}
+ if (ifp) {
#ifdef HAVE_NET_RT_IFLIST
- ifp->stats = ifm->ifm_data;
+ ifp->stats = ifm->ifm_data;
#endif /* HAVE_NET_RT_IFLIST */
- ifp->speed = ifm->ifm_data.ifi_baudrate / 1000000;
+ ifp->speed = ifm->ifm_data.ifi_baudrate / 1000000;
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s: interface %s index %d", __func__, ifp->name,
- ifp->ifindex);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: interface %s index %d", __func__,
+ ifp->name, ifp->ifindex);
+ }
return 0;
}
@@ -1405,7 +1411,10 @@ static void kernel_read(struct thread *thread)
#endif /* RTM_IFANNOUNCE */
default:
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type);
+ zlog_debug(
+ "Unprocessed RTM_type: %s(%d)",
+ lookup_msg(rtm_type_str, rtm->rtm_type, NULL),
+ rtm->rtm_type);
break;
}
}
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index e94aee5c1a..fd475e4cee 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1215,7 +1215,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
p.family);
return;
}
- rnh = zebra_add_rnh(&p, zvrf_id(zvrf), &exist);
+ rnh = zebra_add_rnh(&p, zvrf_id(zvrf), safi, &exist);
if (!rnh)
return;
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 1a1cbaa948..46d789bc34 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -2479,9 +2479,13 @@ void zebra_evpn_mac_gw_macip_add(struct interface *ifp,
if (zvrf && zvrf->zns)
local_ns_id = zvrf->zns->ns_id;
- mac = zebra_evpn_mac_lookup(zevpn, macaddr);
- if (!mac)
- mac = zebra_evpn_mac_add(zevpn, macaddr);
+ if (!*macp) {
+ mac = zebra_evpn_mac_lookup(zevpn, macaddr);
+ if (!mac)
+ mac = zebra_evpn_mac_add(zevpn, macaddr);
+ *macp = mac;
+ } else
+ mac = *macp;
/* Set "local" forwarding info. */
zebra_evpn_mac_clear_fwd_info(mac);
@@ -2494,8 +2498,6 @@ void zebra_evpn_mac_gw_macip_add(struct interface *ifp,
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
mac->fwd_info.local.vid = vlan_id;
-
- *macp = mac;
}
void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn)
@@ -2548,7 +2550,6 @@ void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn)
? true
: false;
- mac = NULL;
zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
diff --git a/zebra/zebra_evpn_mac.h b/zebra/zebra_evpn_mac.h
index 6a8ec1d2e1..b727ac1f98 100644
--- a/zebra/zebra_evpn_mac.h
+++ b/zebra/zebra_evpn_mac.h
@@ -124,8 +124,8 @@ struct zebra_mac {
/* List of neigh associated with this mac */
struct list *neigh_list;
- /* list of hosts pointing to this remote RMAC */
- struct host_rb_tree_entry host_rb;
+ /* List of nexthop associated with this RMAC */
+ struct list *nh_list;
/* Duplicate mac detection */
uint32_t dad_count;
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 7cb1906895..af6046c9ad 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -179,7 +179,7 @@ static int zebra_ns_delete(char *name)
}
UNSET_FLAG(ifp->flags, IFF_UP);
- if_delete_update(ifp);
+ if_delete_update(&ifp);
}
ns = (struct ns *)vrf->ns_ctxt;
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 4d5336120d..7934a9d206 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -132,13 +132,13 @@ static void zebra_rnh_store_in_routing_table(struct rnh *rnh)
route_unlock_node(rn);
}
-struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, bool *exists)
+struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, safi_t safi,
+ bool *exists)
{
struct route_table *table;
struct route_node *rn;
struct rnh *rnh = NULL;
afi_t afi = family2afi(p->family);
- safi_t safi = SAFI_UNICAST;
if (IS_ZEBRA_DEBUG_NHT) {
struct vrf *vrf = vrf_lookup_by_id(vrfid);
@@ -345,7 +345,7 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw,
return;
addr2hostprefix(pw->af, &pw->nexthop, &nh);
- rnh = zebra_add_rnh(&nh, vrf_id, &exists);
+ rnh = zebra_add_rnh(&nh, vrf_id, SAFI_UNICAST, &exists);
if (!rnh)
return;
@@ -768,7 +768,7 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi,
* of a particular VRF and address-family or a specific prefix.
*/
void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
- struct prefix *p, safi_t safi)
+ const struct prefix *p, safi_t safi)
{
struct route_table *rnh_table;
struct route_node *nrn;
@@ -802,13 +802,13 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
}
}
-void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
- struct prefix *p)
+void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, safi_t safi,
+ struct vty *vty, const struct prefix *p)
{
struct route_table *table;
struct route_node *rn;
- table = get_rnh_table(vrfid, afi, SAFI_UNICAST);
+ table = get_rnh_table(vrfid, afi, safi);
if (!table) {
if (IS_ZEBRA_DEBUG_NHT)
zlog_debug("print_rnhs: rnh table not found");
@@ -1337,7 +1337,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty)
vty_out(vty, "\n");
}
-static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
+static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, safi_t safi,
struct zserv *client)
{
struct route_table *ntable;
@@ -1352,7 +1352,7 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
zebra_route_string(client->proto), afi2str(afi));
}
- ntable = get_rnh_table(vrf_id, afi, SAFI_UNICAST);
+ ntable = get_rnh_table(vrf_id, afi, safi);
if (!ntable) {
zlog_debug("cleanup_rnh_client: rnh table not found");
return -1;
@@ -1377,9 +1377,14 @@ static int zebra_client_cleanup_rnh(struct zserv *client)
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
zvrf = vrf->info;
if (zvrf) {
- zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client);
+ zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP,
+ SAFI_UNICAST, client);
+ zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP,
+ SAFI_MULTICAST, client);
+ zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6,
+ SAFI_UNICAST, client);
zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6,
- client);
+ SAFI_MULTICAST, client);
}
}
diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h
index 27c016ebe6..70eda725c4 100644
--- a/zebra/zebra_rnh.h
+++ b/zebra/zebra_rnh.h
@@ -31,7 +31,7 @@ extern "C" {
extern void zebra_rnh_init(void);
-extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
+extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, safi_t safi,
bool *exists);
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
safi_t safi);
@@ -44,9 +44,9 @@ extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *, bool *);
extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client);
extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
- struct prefix *p, safi_t safi);
-extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
- struct prefix *p);
+ const struct prefix *p, safi_t safi);
+extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, safi_t safi,
+ struct vty *vty, const struct prefix *p);
extern int rnh_resolve_via_default(struct zebra_vrf *zvrf, int family);
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 32bbfd6654..22c65e3c0c 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -1361,7 +1361,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
DEFPY (show_ip_nht,
show_ip_nht_cmd,
- "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all]",
+ "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib]",
SHOW_STR
IP_STR
IP6_STR
@@ -1372,11 +1372,13 @@ DEFPY (show_ip_nht,
VRF_CMD_HELP_STR
"IPv4 Address\n"
"IPv6 Address\n"
- VRF_ALL_CMD_HELP_STR)
+ VRF_ALL_CMD_HELP_STR
+ "Show Multicast (MRIB) NHT state\n")
{
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
vrf_id_t vrf_id = VRF_DEFAULT;
struct prefix prefix, *p = NULL;
+ safi_t safi = mrib ? SAFI_MULTICAST : SAFI_UNICAST;
if (vrf_all) {
struct vrf *vrf;
@@ -1385,8 +1387,8 @@ DEFPY (show_ip_nht,
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
if ((zvrf = vrf->info) != NULL) {
vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
- zebra_print_rnh_table(zvrf_id(zvrf), afi, vty,
- NULL);
+ zebra_print_rnh_table(zvrf_id(zvrf), afi, safi,
+ vty, NULL);
}
return CMD_SUCCESS;
}
@@ -1400,7 +1402,7 @@ DEFPY (show_ip_nht,
return CMD_WARNING;
}
- zebra_print_rnh_table(vrf_id, afi, vty, p);
+ zebra_print_rnh_table(vrf_id, afi, safi, vty, p);
return CMD_SUCCESS;
}
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 6a3b1bfbe3..13e1f63457 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -62,6 +62,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash");
DEFINE_MTYPE_STATIC(ZEBRA, L3VNI_MAC, "EVPN L3VNI MAC");
DEFINE_MTYPE_STATIC(ZEBRA, L3NEIGH, "EVPN Neighbor");
DEFINE_MTYPE_STATIC(ZEBRA, ZVXLAN_SG, "zebra VxLAN multicast group");
+DEFINE_MTYPE_STATIC(ZEBRA, EVPN_VTEP, "zebra VxLAN VTEP IP");
DEFINE_HOOK(zebra_rmac_update,
(struct zebra_mac * rmac, struct zebra_l3vni *zl3vni, bool delete,
@@ -198,6 +199,37 @@ static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe)
return count;
}
+static int l3vni_rmac_nh_list_cmp(void *p1, void *p2)
+{
+ const struct ipaddr *vtep_ip1 = p1;
+ const struct ipaddr *vtep_ip2 = p2;
+
+ return !ipaddr_cmp(vtep_ip1, vtep_ip2);
+}
+
+static void l3vni_rmac_nh_free(struct ipaddr *vtep_ip)
+{
+ XFREE(MTYPE_EVPN_VTEP, vtep_ip);
+}
+
+static void l3vni_rmac_nh_list_nh_delete(struct zebra_l3vni *zl3vni,
+ struct zebra_mac *zrmac,
+ struct ipaddr *vtep_ip)
+{
+ struct listnode *node = NULL, *nnode = NULL;
+ struct ipaddr *vtep = NULL;
+
+ for (ALL_LIST_ELEMENTS(zrmac->nh_list, node, nnode, vtep)) {
+ if (ipaddr_cmp(vtep, vtep_ip) == 0)
+ break;
+ }
+
+ if (node) {
+ l3vni_rmac_nh_free(vtep);
+ list_delete_node(zrmac->nh_list, node);
+ }
+}
+
/*
* Print neighbors for all EVPN.
*/
@@ -366,35 +398,25 @@ static void zl3vni_print_nh(struct zebra_neigh *n, struct vty *vty,
static void zl3vni_print_rmac(struct zebra_mac *zrmac, struct vty *vty,
json_object *json)
{
- char buf1[ETHER_ADDR_STRLEN];
- char buf2[PREFIX_STRLEN];
- json_object *json_hosts = NULL;
- struct host_rb_entry *hle;
+ struct listnode *node = NULL;
+ struct ipaddr *vtep = NULL;
+ json_object *json_nhs = NULL;
if (!json) {
- vty_out(vty, "MAC: %s\n",
- prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
+ vty_out(vty, "MAC: %pEA\n", &zrmac->macaddr);
vty_out(vty, " Remote VTEP: %pI4\n",
&zrmac->fwd_info.r_vtep_ip);
- vty_out(vty, " Refcount: %d\n", rb_host_count(&zrmac->host_rb));
- vty_out(vty, " Prefixes:\n");
- RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
- vty_out(vty, " %pFX\n", &hle->p);
} else {
- json_hosts = json_object_new_array();
- json_object_string_add(
- json, "routerMac",
- prefix_mac2str(&zrmac->macaddr, buf1, sizeof(buf1)));
+ json_nhs = json_object_new_array();
+ json_object_string_addf(json, "routerMac", "%pEA",
+ &zrmac->macaddr);
json_object_string_addf(json, "vtepIp", "%pI4",
&zrmac->fwd_info.r_vtep_ip);
- json_object_int_add(json, "refCount",
- rb_host_count(&zrmac->host_rb));
- RB_FOREACH (hle, host_rb_tree_entry, &zrmac->host_rb)
- json_object_array_add(
- json_hosts,
- json_object_new_string(prefix2str(
- &hle->p, buf2, sizeof(buf2))));
- json_object_object_add(json, "prefixList", json_hosts);
+ for (ALL_LIST_ELEMENTS_RO(zrmac->nh_list, node, vtep)) {
+ json_object_array_add(json_nhs, json_object_new_stringf(
+ "%pIA", vtep));
+ }
+ json_object_object_add(json, "nexthops", json_nhs);
}
}
@@ -1169,7 +1191,9 @@ static struct zebra_mac *zl3vni_rmac_add(struct zebra_l3vni *zl3vni,
zrmac = hash_get(zl3vni->rmac_table, &tmp_rmac, zl3vni_rmac_alloc);
assert(zrmac);
- RB_INIT(host_rb_tree_entry, &zrmac->host_rb);
+ zrmac->nh_list = list_new();
+ zrmac->nh_list->cmp = (int (*)(void *, void *))l3vni_rmac_nh_list_cmp;
+ zrmac->nh_list->del = (void (*)(void *))l3vni_rmac_nh_free;
SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE);
SET_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC);
@@ -1183,14 +1207,9 @@ static struct zebra_mac *zl3vni_rmac_add(struct zebra_l3vni *zl3vni,
static int zl3vni_rmac_del(struct zebra_l3vni *zl3vni, struct zebra_mac *zrmac)
{
struct zebra_mac *tmp_rmac;
- struct host_rb_entry *hle;
- while (!RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
- hle = RB_ROOT(host_rb_tree_entry, &zrmac->host_rb);
-
- RB_REMOVE(host_rb_tree_entry, &zrmac->host_rb, hle);
- XFREE(MTYPE_HOST_PREFIX, hle);
- }
+ /* free the list of nh list*/
+ list_delete(&zrmac->nh_list);
tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
XFREE(MTYPE_L3VNI_MAC, tmp_rmac);
@@ -1291,10 +1310,10 @@ static int zl3vni_rmac_uninstall(struct zebra_l3vni *zl3vni,
/* handle rmac add */
static int zl3vni_remote_rmac_add(struct zebra_l3vni *zl3vni,
const struct ethaddr *rmac,
- const struct ipaddr *vtep_ip,
- const struct prefix *host_prefix)
+ const struct ipaddr *vtep_ip)
{
struct zebra_mac *zrmac = NULL;
+ struct ipaddr *vtep = NULL;
zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
if (!zrmac) {
@@ -1303,13 +1322,18 @@ static int zl3vni_remote_rmac_add(struct zebra_l3vni *zl3vni,
zrmac = zl3vni_rmac_add(zl3vni, rmac);
if (!zrmac) {
zlog_debug(
- "Failed to add RMAC %pEA L3VNI %u Remote VTEP %pIA, prefix %pFX",
- rmac, zl3vni->vni, vtep_ip, host_prefix);
+ "Failed to add RMAC %pEA L3VNI %u Remote VTEP %pIA",
+ rmac, zl3vni->vni, vtep_ip);
return -1;
}
memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
+ vtep = XCALLOC(MTYPE_EVPN_VTEP, sizeof(struct ipaddr));
+ memcpy(vtep, vtep_ip, sizeof(struct ipaddr));
+ if (!listnode_add_sort_nodup(zrmac->nh_list, (void *)vtep))
+ XFREE(MTYPE_EVPN_VTEP, vtep);
+
/* Send RMAC for FPM processing */
hook_call(zebra_rmac_update, zrmac, zl3vni, false,
"new RMAC added");
@@ -1320,18 +1344,21 @@ static int zl3vni_remote_rmac_add(struct zebra_l3vni *zl3vni,
&vtep_ip->ipaddr_v4)) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA, prefix %pFX",
+ "L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA",
zl3vni->vni, &zrmac->fwd_info.r_vtep_ip,
- vtep_ip, rmac, host_prefix);
+ vtep_ip, rmac);
zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
+ vtep = XCALLOC(MTYPE_EVPN_VTEP, sizeof(struct ipaddr));
+ memcpy(vtep, vtep_ip, sizeof(struct ipaddr));
+ if (!listnode_add_sort_nodup(zrmac->nh_list, (void *)vtep))
+ XFREE(MTYPE_EVPN_VTEP, vtep);
+
/* install rmac in kernel */
zl3vni_rmac_install(zl3vni, zrmac);
}
- rb_find_or_add_host(&zrmac->host_rb, host_prefix);
-
return 0;
}
@@ -1339,20 +1366,59 @@ static int zl3vni_remote_rmac_add(struct zebra_l3vni *zl3vni,
/* handle rmac delete */
static void zl3vni_remote_rmac_del(struct zebra_l3vni *zl3vni,
struct zebra_mac *zrmac,
- struct prefix *host_prefix)
+ struct ipaddr *vtep_ip)
{
- rb_delete_host(&zrmac->host_rb, host_prefix);
+ struct ipaddr ipv4_vtep;
- if (RB_EMPTY(host_rb_tree_entry, &zrmac->host_rb)) {
- /* uninstall from kernel */
- zl3vni_rmac_uninstall(zl3vni, zrmac);
+ if (!zl3vni_nh_lookup(zl3vni, vtep_ip)) {
+ memset(&ipv4_vtep, 0, sizeof(struct ipaddr));
+ ipv4_vtep.ipa_type = IPADDR_V4;
+ if (vtep_ip->ipa_type == IPADDR_V6)
+ ipv4_mapped_ipv6_to_ipv4(&vtep_ip->ipaddr_v6,
+ &ipv4_vtep.ipaddr_v4);
+ else
+ memcpy(&(ipv4_vtep.ipaddr_v4), &vtep_ip->ipaddr_v4,
+ sizeof(struct in_addr));
- /* Send RMAC for FPM processing */
- hook_call(zebra_rmac_update, zrmac, zl3vni, true,
- "RMAC deleted");
+ /* remove nh from rmac's list */
+ l3vni_rmac_nh_list_nh_delete(zl3vni, zrmac, &ipv4_vtep);
+ /* delete nh is same as current selected, fall back to
+ * one present in the list
+ */
+ if (IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip,
+ &ipv4_vtep.ipaddr_v4) &&
+ listcount(zrmac->nh_list)) {
+ struct ipaddr *vtep;
+
+ vtep = listgetdata(listhead(zrmac->nh_list));
+ zrmac->fwd_info.r_vtep_ip = vtep->ipaddr_v4;
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "L3VNI %u Remote VTEP nh change(%pIA -> %pI4) for RMAC %pEA",
+ zl3vni->vni, &ipv4_vtep,
+ &zrmac->fwd_info.r_vtep_ip,
+ &zrmac->macaddr);
+
+ /* install rmac in kernel */
+ zl3vni_rmac_install(zl3vni, zrmac);
+ }
+
+ if (!listcount(zrmac->nh_list)) {
+ /* uninstall from kernel */
+ zl3vni_rmac_uninstall(zl3vni, zrmac);
- /* del the rmac entry */
- zl3vni_rmac_del(zl3vni, zrmac);
+ /* Send RMAC for FPM processing */
+ hook_call(zebra_rmac_update, zrmac, zl3vni, true,
+ "RMAC deleted");
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "L3VNI %u RMAC %pEA vtep_ip %pIA delete",
+ zl3vni->vni, &zrmac->macaddr, vtep_ip);
+
+ /* del the rmac entry */
+ zl3vni_rmac_del(zl3vni, zrmac);
+ }
}
}
@@ -2235,7 +2301,7 @@ void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
* add the rmac - remote rmac to be installed is against the ipv4
* nexthop address
*/
- zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep, host_prefix);
+ zl3vni_remote_rmac_add(zl3vni, rmac, &ipv4_vtep);
}
/* handle evpn vrf route delete */
@@ -2262,8 +2328,7 @@ void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
/* delete the rmac entry */
if (zrmac)
- zl3vni_remote_rmac_del(zl3vni, zrmac, host_prefix);
-
+ zl3vni_remote_rmac_del(zl3vni, zrmac, vtep_ip);
}
void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
@@ -2297,7 +2362,7 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,
vty_out(vty, "{}\n");
else
vty_out(vty,
- "%% Requested RMAC doesn't exist in L3-VNI %u",
+ "%% Requested RMAC doesn't exist in L3-VNI %u\n",
l3vni);
return;
}