diff options
Diffstat (limited to 'zebra/zebra_vxlan.c')
| -rw-r--r-- | zebra/zebra_vxlan.c | 5948 |
1 files changed, 689 insertions, 5259 deletions
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 998c035656..13a58bc34a 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -49,75 +49,31 @@ #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_vxlan.h" +#include "zebra/zebra_evpn.h" +#include "zebra/zebra_evpn_mac.h" +#include "zebra/zebra_evpn_neigh.h" #include "zebra/zebra_vxlan_private.h" +#include "zebra/zebra_evpn_mh.h" +#include "zebra/zebra_evpn_vxlan.h" #include "zebra/zebra_router.h" DEFINE_MTYPE_STATIC(ZEBRA, HOST_PREFIX, "host prefix"); -DEFINE_MTYPE_STATIC(ZEBRA, ZVNI, "VNI hash"); DEFINE_MTYPE_STATIC(ZEBRA, ZL3VNI, "L3 VNI hash"); -DEFINE_MTYPE_STATIC(ZEBRA, ZVNI_VTEP, "VNI remote VTEP"); -DEFINE_MTYPE_STATIC(ZEBRA, MAC, "VNI MAC"); -DEFINE_MTYPE_STATIC(ZEBRA, NEIGH, "VNI Neighbor"); +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_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni, bool delete, const char *reason), (rmac, zl3vni, delete, reason)) -/* definitions */ -/* PMSI strings. */ -#define VXLAN_FLOOD_STR_NO_INFO "-" -#define VXLAN_FLOOD_STR_DEFAULT VXLAN_FLOOD_STR_NO_INFO -static const struct message zvtep_flood_str[] = { - {VXLAN_FLOOD_DISABLED, VXLAN_FLOOD_STR_NO_INFO}, - {VXLAN_FLOOD_PIM_SM, "PIM-SM"}, - {VXLAN_FLOOD_HEAD_END_REPL, "HER"}, - {0} -}; - - /* static function declarations */ -static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, - uint16_t cmd); -static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json); -static void zvni_print_neigh_hash(struct hash_bucket *bucket, void *ctxt); -static void zvni_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt); -static void zvni_print_neigh_hash_all_vni(struct hash_bucket *bucket, - void **args); +static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket, + void **args); static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty, json_object *json); static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty, json_object *json); -static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json); -static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt); -static void zvni_print_mac_hash_all_vni(struct hash_bucket *bucket, void *ctxt); -static void zvni_print(zebra_vni_t *zvni, void **ctxt); -static void zvni_print_hash(struct hash_bucket *bucket, void *ctxt[]); - -static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, - struct ipaddr *ip, uint8_t flags, - uint32_t seq, int state, uint16_t cmd); -static unsigned int neigh_hash_keymake(const void *p); -static void *zvni_neigh_alloc(void *p); -static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip, - struct ethaddr *mac); -static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n); -static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client, - uint32_t flags); -static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip); -static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, - struct ethaddr *macaddr, - uint8_t flags, uint32_t seq); -static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip, - struct ethaddr *macaddr, - uint8_t flags, int state); -static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n); -static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n); -static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n); -static zebra_vni_t *zvni_from_svi(struct interface *ifp, - struct interface *br_if); -static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if); -static struct interface *zvni_map_to_macvlan(struct interface *br_if, - struct interface *svi_if); +static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt); /* l3-vni next-hop neigh related APIs */ static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni, @@ -142,75 +98,13 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac); static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac); /* l3-vni related APIs*/ -static zebra_l3vni_t *zl3vni_lookup(vni_t vni); static void *zl3vni_alloc(void *p); static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id); static int zl3vni_del(zebra_l3vni_t *zl3vni); static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni); static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni); -static unsigned int mac_hash_keymake(const void *p); -static bool mac_cmp(const void *p1, const void *p2); -static void *zvni_mac_alloc(void *p); -static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr); -static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac); -static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client, - uint32_t flags); -static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *macaddr); -static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, - uint8_t flags, uint32_t seq); -static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr); -static zebra_vni_t *zvni_map_vlan(struct interface *ifp, - struct interface *br_if, vlanid_t vid); -static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac); -static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac); -static void zvni_install_mac_hash(struct hash_bucket *bucket, void *ctxt); - -static unsigned int vni_hash_keymake(const void *p); -static void *zvni_alloc(void *p); -static zebra_vni_t *zvni_lookup(vni_t vni); -static zebra_vni_t *zvni_add(vni_t vni); -static int zvni_del(zebra_vni_t *zvni); -static int zvni_send_add_to_client(zebra_vni_t *zvni); -static int zvni_send_del_to_client(vni_t vni); -static void zvni_build_hash_table(void); -static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep); -static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip); -static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip, - int flood_control); -static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep); -static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall); -static int zvni_vtep_install(zebra_vni_t *zvni, zebra_vtep_t *zvtep); -static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip); -static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni); -static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni); -static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, - struct ethaddr *macaddr, struct ipaddr *ip); -static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni, - struct ipaddr *ip); -struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp); -static int advertise_gw_macip_enabled(zebra_vni_t *zvni); -static int advertise_svi_macip_enabled(zebra_vni_t *zvni); -static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, - zebra_mac_t *old_zmac, - zebra_mac_t *new_zmac, - zebra_neigh_t *nbr); -static int remote_neigh_count(zebra_mac_t *zmac); -static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac); -static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t); -static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t); -static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, - zebra_neigh_t *nbr, - struct in_addr vtep_ip, - bool do_dad, - bool *is_dup_detect, - bool is_local); -static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, - zebra_mac_t *mac, - struct in_addr vtep_ip, - bool do_dad, - bool *is_dup_detect, - bool is_local); +static void zevpn_build_hash_table(void); static unsigned int zebra_vxlan_sg_hash_key_make(const void *p); static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2); static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf, @@ -223,9 +117,6 @@ static void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip, struct in_addr mcast_grp); static void zebra_vxlan_sg_cleanup(struct hash_bucket *bucket, void *arg); -static void zvni_send_mac_to_client(zebra_vni_t *zvn); -static void zvni_send_neigh_to_client(zebra_vni_t *zvni); - /* Private functions */ static int host_rb_entry_compare(const struct host_rb_entry *hle1, const struct host_rb_entry *hle2) @@ -273,677 +164,14 @@ static uint32_t rb_host_count(struct host_rb_tree_entry *hrbe) } /* - * Return number of valid MACs in a VNI's MAC hash table - all - * remote MACs and non-internal (auto) local MACs count. - */ -static uint32_t num_valid_macs(zebra_vni_t *zvni) -{ - unsigned int i; - uint32_t num_macs = 0; - struct hash *hash; - struct hash_bucket *hb; - zebra_mac_t *mac; - - hash = zvni->mac_table; - if (!hash) - return num_macs; - for (i = 0; i < hash->size; i++) { - for (hb = hash->index[i]; hb; hb = hb->next) { - mac = (zebra_mac_t *)hb->data; - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) - || CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) - || !CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) - num_macs++; - } - } - - return num_macs; -} - -static uint32_t num_dup_detected_macs(zebra_vni_t *zvni) -{ - unsigned int i; - uint32_t num_macs = 0; - struct hash *hash; - struct hash_bucket *hb; - zebra_mac_t *mac; - - hash = zvni->mac_table; - if (!hash) - return num_macs; - for (i = 0; i < hash->size; i++) { - for (hb = hash->index[i]; hb; hb = hb->next) { - mac = (zebra_mac_t *)hb->data; - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - num_macs++; - } - } - - return num_macs; -} - -static uint32_t num_dup_detected_neighs(zebra_vni_t *zvni) -{ - unsigned int i; - uint32_t num_neighs = 0; - struct hash *hash; - struct hash_bucket *hb; - zebra_neigh_t *nbr; - - hash = zvni->neigh_table; - if (!hash) - return num_neighs; - for (i = 0; i < hash->size; i++) { - for (hb = hash->index[i]; hb; hb = hb->next) { - nbr = (zebra_neigh_t *)hb->data; - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) - num_neighs++; - } - } - - return num_neighs; -} - -static int advertise_gw_macip_enabled(zebra_vni_t *zvni) -{ - struct zebra_vrf *zvrf; - - zvrf = zebra_vrf_get_evpn(); - if (zvrf && zvrf->advertise_gw_macip) - return 1; - - if (zvni && zvni->advertise_gw_macip) - return 1; - - return 0; -} - -static int advertise_svi_macip_enabled(zebra_vni_t *zvni) -{ - struct zebra_vrf *zvrf; - - zvrf = zebra_vrf_get_evpn(); - if (zvrf && zvrf->advertise_svi_macip) - return 1; - - if (zvni && zvni->advertise_svi_macip) - return 1; - - return 0; -} - -/* As part Duplicate Address Detection (DAD) for IP mobility - * MAC binding changes, ensure to inherit duplicate flag - * from MAC. + * Print neighbors for all EVPN. */ -static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, - zebra_mac_t *old_zmac, - zebra_mac_t *new_zmac, - zebra_neigh_t *nbr) -{ - bool is_old_mac_dup = false; - bool is_new_mac_dup = false; - - if (!zvrf->dup_addr_detect) - return 0; - /* Check old or new MAC is detected as duplicate - * mark this neigh as duplicate - */ - if (old_zmac) - is_old_mac_dup = CHECK_FLAG(old_zmac->flags, - ZEBRA_MAC_DUPLICATE); - if (new_zmac) - is_new_mac_dup = CHECK_FLAG(new_zmac->flags, - ZEBRA_MAC_DUPLICATE); - /* Old and/or new MAC can be in duplicate state, - * based on that IP/Neigh Inherits the flag. - * If New MAC is marked duplicate, inherit to the IP. - * If old MAC is duplicate but new MAC is not, clear - * duplicate flag for IP and reset detection params - * and let IP DAD retrigger. - */ - if (is_new_mac_dup && !CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) { - SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); - /* Capture Duplicate detection time */ - nbr->dad_dup_detect_time = monotime(NULL); - /* Mark neigh inactive */ - ZEBRA_NEIGH_SET_INACTIVE(nbr); - - return 1; - } else if (is_old_mac_dup && !is_new_mac_dup) { - UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); - nbr->dad_count = 0; - nbr->detect_start_time.tv_sec = 0; - nbr->detect_start_time.tv_usec = 0; - } - return 0; -} - -static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, - zebra_mac_t *mac, - struct in_addr vtep_ip, - bool do_dad, - bool *is_dup_detect, - bool is_local) -{ - zebra_neigh_t *nbr; - struct listnode *node = NULL; - struct timeval elapsed = {0, 0}; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - bool reset_params = false; - - if (!(zvrf->dup_addr_detect && do_dad)) - return; - - /* MAC is detected as duplicate, - * Local MAC event -> hold on advertising to BGP. - * Remote MAC event -> hold on installing it. - */ - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u", - __func__, - prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags, mac->dad_count, - zvrf->dad_freeze_time); - - /* For duplicate MAC do not update - * client but update neigh due to - * this MAC update. - */ - if (zvrf->dad_freeze) - *is_dup_detect = true; - - return; - } - - /* Check if detection time (M-secs) expired. - * Reset learn count and detection start time. - */ - monotime_since(&mac->detect_start_time, &elapsed); - reset_params = (elapsed.tv_sec > zvrf->dad_time); - if (is_local && !reset_params) { - /* RFC-7432: A PE/VTEP that detects a MAC mobility - * event via LOCAL learning starts an M-second timer. - * - * NOTE: This is the START of the probe with count is - * 0 during LOCAL learn event. - * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time) - */ - reset_params = !mac->dad_count; - } - - if (reset_params) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u", - __func__, - prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags, mac->dad_count); - - mac->dad_count = 0; - /* Start dup. addr detection (DAD) start time, - * ONLY during LOCAL learn. - */ - if (is_local) - monotime(&mac->detect_start_time); - - } else if (!is_local) { - /* For REMOTE MAC, increment detection count - * ONLY while in probe window, once window passed, - * next local learn event should trigger DAD. - */ - mac->dad_count++; - } - - /* For LOCAL MAC learn event, once count is reset above via either - * initial/start detection time or passed the probe time, the count - * needs to be incremented. - */ - if (is_local) - mac->dad_count++; - - if (mac->dad_count >= zvrf->dad_max_moves) { - flog_warn(EC_ZEBRA_DUP_MAC_DETECTED, - "VNI %u: MAC %s detected as duplicate during %s VTEP %s", - mac->zvni->vni, - prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - is_local ? "local update, last" : - "remote update, from", inet_ntoa(vtep_ip)); - - SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE); - - /* Capture Duplicate detection time */ - mac->dad_dup_detect_time = monotime(NULL); - - /* Mark all IPs/Neighs as duplicate - * associcated with this MAC - */ - for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) { - - /* Ony Mark IPs which are Local */ - if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) - continue; - - SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); - - nbr->dad_dup_detect_time = monotime(NULL); - - flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED, - "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC", - mac->zvni->vni, - prefix_mac2str(&mac->macaddr, - buf, sizeof(buf)), - ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), - is_local ? "local" : "remote"); - } - - /* Start auto recovery timer for this MAC */ - THREAD_OFF(mac->dad_mac_auto_recovery_timer); - if (zvrf->dad_freeze && zvrf->dad_freeze_time) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start", - __func__, - prefix_mac2str(&mac->macaddr, buf, - sizeof(buf)), - mac->flags, zvrf->dad_freeze_time); - - thread_add_timer(zrouter.master, - zebra_vxlan_dad_mac_auto_recovery_exp, - mac, zvrf->dad_freeze_time, - &mac->dad_mac_auto_recovery_timer); - } - - /* In case of local update, do not inform to client (BGPd), - * upd_neigh for neigh sequence change. - */ - if (zvrf->dad_freeze) - *is_dup_detect = true; - } -} - -static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, - zebra_neigh_t *nbr, - struct in_addr vtep_ip, - bool do_dad, - bool *is_dup_detect, - bool is_local) -{ - - struct timeval elapsed = {0, 0}; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - bool reset_params = false; - - if (!zvrf->dup_addr_detect) - return; - - /* IP is detected as duplicate or inherit dup - * state, hold on to install as remote entry - * only if freeze is enabled. - */ - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u", - __func__, - prefix_mac2str(&nbr->emac, buf, sizeof(buf)), - ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), - nbr->flags, nbr->dad_count, - zvrf->dad_freeze_time); - - if (zvrf->dad_freeze) - *is_dup_detect = true; - - /* warn-only action, neigh will be installed. - * freeze action, it wil not be installed. - */ - return; - } - - if (!do_dad) - return; - - /* Check if detection time (M-secs) expired. - * Reset learn count and detection start time. - * During remote mac add, count should already be 1 - * via local learning. - */ - monotime_since(&nbr->detect_start_time, &elapsed); - reset_params = (elapsed.tv_sec > zvrf->dad_time); - - if (is_local && !reset_params) { - /* RFC-7432: A PE/VTEP that detects a MAC mobility - * event via LOCAL learning starts an M-second timer. - * - * NOTE: This is the START of the probe with count is - * 0 during LOCAL learn event. - */ - reset_params = !nbr->dad_count; - } - - if (reset_params) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u", - __func__, - prefix_mac2str(&nbr->emac, buf, sizeof(buf)), - ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), - nbr->flags, nbr->dad_count); - /* Reset learn count but do not start detection - * during REMOTE learn event. - */ - nbr->dad_count = 0; - /* Start dup. addr detection (DAD) start time, - * ONLY during LOCAL learn. - */ - if (is_local) - monotime(&nbr->detect_start_time); - - } else if (!is_local) { - /* For REMOTE IP/Neigh, increment detection count - * ONLY while in probe window, once window passed, - * next local learn event should trigger DAD. - */ - nbr->dad_count++; - } - - /* For LOCAL IP/Neigh learn event, once count is reset above via either - * initial/start detection time or passed the probe time, the count - * needs to be incremented. - */ - if (is_local) - nbr->dad_count++; - - if (nbr->dad_count >= zvrf->dad_max_moves) { - flog_warn(EC_ZEBRA_DUP_IP_DETECTED, - "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %s", - nbr->zvni->vni, - prefix_mac2str(&nbr->emac, buf, sizeof(buf)), - ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), - is_local ? "local update, last" : - "remote update, from", - inet_ntoa(vtep_ip)); - - SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); - - /* Capture Duplicate detection time */ - nbr->dad_dup_detect_time = monotime(NULL); - - /* Start auto recovery timer for this IP */ - THREAD_OFF(nbr->dad_ip_auto_recovery_timer); - if (zvrf->dad_freeze && zvrf->dad_freeze_time) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start", - __func__, - prefix_mac2str(&nbr->emac, buf, - sizeof(buf)), - ipaddr2str(&nbr->ip, buf1, - sizeof(buf1)), - nbr->flags, zvrf->dad_freeze_time); - - thread_add_timer(zrouter.master, - zebra_vxlan_dad_ip_auto_recovery_exp, - nbr, zvrf->dad_freeze_time, - &nbr->dad_ip_auto_recovery_timer); - } - if (zvrf->dad_freeze) - *is_dup_detect = true; - } -} - -/* - * Helper function to determine maximum width of neighbor IP address for - * display - just because we're dealing with IPv6 addresses that can - * widely vary. - */ -static void zvni_find_neigh_addr_width(struct hash_bucket *bucket, void *ctxt) -{ - zebra_neigh_t *n; - char buf[INET6_ADDRSTRLEN]; - struct neigh_walk_ctx *wctx = ctxt; - int width; - - n = (zebra_neigh_t *)bucket->data; - - ipaddr2str(&n->ip, buf, sizeof(buf)); - width = strlen(buf); - if (width > wctx->addr_width) - wctx->addr_width = width; - -} - -/* - * Print a specific neighbor entry. - */ -static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json) -{ - struct vty *vty; - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - const char *type_str; - const char *state_str; - bool flags_present = false; - struct zebra_vrf *zvrf = NULL; - struct timeval detect_start_time = {0, 0}; - char timebuf[MONOTIME_STRLEN]; - - zvrf = zebra_vrf_get_evpn(); - if (!zvrf) - return; - - ipaddr2str(&n->ip, buf2, sizeof(buf2)); - prefix_mac2str(&n->emac, buf1, sizeof(buf1)); - type_str = CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) ? - "local" : "remote"; - state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive"; - vty = (struct vty *)ctxt; - if (json == NULL) { - vty_out(vty, "IP: %s\n", - ipaddr2str(&n->ip, buf2, sizeof(buf2))); - vty_out(vty, " Type: %s\n", type_str); - vty_out(vty, " State: %s\n", state_str); - vty_out(vty, " MAC: %s\n", - prefix_mac2str(&n->emac, buf1, sizeof(buf1))); - } else { - json_object_string_add(json, "ip", buf2); - json_object_string_add(json, "type", type_str); - json_object_string_add(json, "state", state_str); - json_object_string_add(json, "mac", buf1); - } - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { - if (json == NULL) { - vty_out(vty, " Remote VTEP: %s\n", - inet_ntoa(n->r_vtep_ip)); - } else - json_object_string_add(json, "remoteVtep", - inet_ntoa(n->r_vtep_ip)); - } - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) { - if (!json) { - vty_out(vty, " Flags: Default-gateway"); - flags_present = true; - } else - json_object_boolean_true_add(json, "defaultGateway"); - } - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG)) { - if (!json) { - vty_out(vty, - flags_present ? " ,Router" : " Flags: Router"); - flags_present = true; - } - } - if (json == NULL) { - if (flags_present) - vty_out(vty, "\n"); - vty_out(vty, " Local Seq: %u Remote Seq: %u\n", - n->loc_seq, n->rem_seq); - - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) { - vty_out(vty, " Duplicate, detected at %s", - time_to_string(n->dad_dup_detect_time, - timebuf)); - } else if (n->dad_count) { - monotime_since(&n->detect_start_time, - &detect_start_time); - if (detect_start_time.tv_sec <= zvrf->dad_time) { - time_to_string(n->detect_start_time.tv_sec, - timebuf); - vty_out(vty, - " Duplicate detection started at %s, detection count %u\n", - timebuf, n->dad_count); - } - } - } else { - json_object_int_add(json, "localSequence", n->loc_seq); - json_object_int_add(json, "remoteSequence", n->rem_seq); - json_object_int_add(json, "detectionCount", - n->dad_count); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) - json_object_boolean_true_add(json, "isDuplicate"); - else - json_object_boolean_false_add(json, "isDuplicate"); - - - } -} - -/* - * Print neighbor hash entry - called for display of all neighbors. - */ -static void zvni_print_neigh_hash(struct hash_bucket *bucket, void *ctxt) -{ - struct vty *vty; - json_object *json_vni = NULL, *json_row = NULL; - zebra_neigh_t *n; - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - struct neigh_walk_ctx *wctx = ctxt; - const char *state_str; - - vty = wctx->vty; - json_vni = wctx->json; - n = (zebra_neigh_t *)bucket->data; - - if (json_vni) - json_row = json_object_new_object(); - - prefix_mac2str(&n->emac, buf1, sizeof(buf1)); - ipaddr2str(&n->ip, buf2, sizeof(buf2)); - state_str = IS_ZEBRA_NEIGH_ACTIVE(n) ? "active" : "inactive"; - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - if (wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) - return; - - if (json_vni == NULL) { - vty_out(vty, "%*s %-6s %-8s %-17s %u/%u\n", - -wctx->addr_width, buf2, "local", - state_str, buf1, n->loc_seq, n->rem_seq); - } else { - json_object_string_add(json_row, "type", "local"); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "mac", buf1); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) - json_object_boolean_true_add( - json_row, "defaultGateway"); - json_object_int_add(json_row, "localSequence", - n->loc_seq); - json_object_int_add(json_row, "remoteSequence", - n->rem_seq); - json_object_int_add(json_row, "detectionCount", - n->dad_count); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) - json_object_boolean_true_add(json_row, - "isDuplicate"); - else - json_object_boolean_false_add(json_row, - "isDuplicate"); - } - wctx->count++; - } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { - if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) && - !IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip)) - return; - - if (json_vni == NULL) { - if ((wctx->flags & SHOW_REMOTE_NEIGH_FROM_VTEP) && - (wctx->count == 0)) - vty_out(vty, "%*s %-6s %-8s %-17s %-21s %s\n", - -wctx->addr_width, "Neighbor", "Type", - "State", "MAC", "Remote VTEP", - "Seq #'s"); - vty_out(vty, "%*s %-6s %-8s %-17s %-21s %u/%u\n", - -wctx->addr_width, buf2, "remote", state_str, - buf1, inet_ntoa(n->r_vtep_ip), n->loc_seq, n->rem_seq); - } else { - json_object_string_add(json_row, "type", "remote"); - json_object_string_add(json_row, "state", state_str); - json_object_string_add(json_row, "mac", buf1); - json_object_string_add(json_row, "remoteVtep", - inet_ntoa(n->r_vtep_ip)); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW)) - json_object_boolean_true_add(json_row, - "defaultGateway"); - json_object_int_add(json_row, "localSequence", - n->loc_seq); - json_object_int_add(json_row, "remoteSequence", - n->rem_seq); - json_object_int_add(json_row, "detectionCount", - n->dad_count); - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) - json_object_boolean_true_add(json_row, - "isDuplicate"); - else - json_object_boolean_false_add(json_row, - "isDuplicate"); - } - wctx->count++; - } - - if (json_vni) - json_object_object_add(json_vni, buf2, json_row); -} - -/* - * Print neighbor hash entry in detail - called for display of all neighbors. - */ -static void zvni_print_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt) -{ - struct vty *vty; - json_object *json_vni = NULL, *json_row = NULL; - zebra_neigh_t *n; - char buf[INET6_ADDRSTRLEN]; - struct neigh_walk_ctx *wctx = ctxt; - - vty = wctx->vty; - json_vni = wctx->json; - n = (zebra_neigh_t *)bucket->data; - if (!n) - return; - - ipaddr2str(&n->ip, buf, sizeof(buf)); - if (json_vni) - json_row = json_object_new_object(); - - zvni_print_neigh(n, vty, json_row); - - if (json_vni) - json_object_object_add(json_vni, buf, json_row); -} - -/* - * Print neighbors for all VNI. - */ -static void zvni_print_neigh_hash_all_vni(struct hash_bucket *bucket, +static void zevpn_print_neigh_hash_all_evpn(struct hash_bucket *bucket, void **args) { struct vty *vty; - json_object *json = NULL, *json_vni = NULL; - zebra_vni_t *zvni; + json_object *json = NULL, *json_evpn = NULL; + zebra_evpn_t *zevpn; uint32_t num_neigh; struct neigh_walk_ctx wctx; char vni_str[VNI_STR_LEN]; @@ -953,26 +181,26 @@ static void zvni_print_neigh_hash_all_vni(struct hash_bucket *bucket, json = (json_object *)args[1]; print_dup = (uint32_t)(uintptr_t)args[2]; - zvni = (zebra_vni_t *)bucket->data; + zevpn = (zebra_evpn_t *)bucket->data; - num_neigh = hashcount(zvni->neigh_table); + num_neigh = hashcount(zevpn->neigh_table); if (print_dup) - num_neigh = num_dup_detected_neighs(zvni); + num_neigh = num_dup_detected_neighs(zevpn); if (json == NULL) { vty_out(vty, "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", - zvni->vni, num_neigh); + zevpn->vni, num_neigh); } else { - json_vni = json_object_new_object(); - json_object_int_add(json_vni, "numArpNd", num_neigh); - snprintf(vni_str, sizeof(vni_str), "%u", zvni->vni); + json_evpn = json_object_new_object(); + json_object_int_add(json_evpn, "numArpNd", num_neigh); + snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); } if (!num_neigh) { if (json) - json_object_object_add(json, vni_str, json_vni); + json_object_object_add(json, vni_str, json_evpn); return; } @@ -981,61 +209,36 @@ static void zvni_print_neigh_hash_all_vni(struct hash_bucket *bucket, * the maximum width. */ memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); - wctx.zvni = zvni; + wctx.zevpn = zevpn; wctx.vty = vty; wctx.addr_width = 15; - wctx.json = json_vni; - hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); + wctx.json = json_evpn; + hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width, + &wctx); + + if (json == NULL) + zebra_evpn_print_neigh_hdr(vty, &wctx); - if (json == NULL) { - vty_out(vty, "%*s %-6s %-8s %-17s %-21s %s\n", - -wctx.addr_width, "IP", "Type", - "State", "MAC", "Remote VTEP", "Seq #'s"); - } if (print_dup) - hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash, - &wctx); + hash_iterate(zevpn->neigh_table, + zebra_evpn_print_dad_neigh_hash, &wctx); else - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); + hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, + &wctx); if (json) - json_object_object_add(json, vni_str, json_vni); -} - -static void zvni_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt) -{ - zebra_neigh_t *nbr; - - nbr = (zebra_neigh_t *)bucket->data; - if (!nbr) - return; - - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) - zvni_print_neigh_hash(bucket, ctxt); -} - -static void zvni_print_dad_neigh_hash_detail(struct hash_bucket *bucket, - void *ctxt) -{ - zebra_neigh_t *nbr; - - nbr = (zebra_neigh_t *)bucket->data; - if (!nbr) - return; - - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) - zvni_print_neigh_hash_detail(bucket, ctxt); + json_object_object_add(json, vni_str, json_evpn); } /* - * Print neighbors for all VNIs in detail. + * Print neighbors for all EVPNs in detail. */ -static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket *bucket, +static void zevpn_print_neigh_hash_all_evpn_detail(struct hash_bucket *bucket, void **args) { struct vty *vty; - json_object *json = NULL, *json_vni = NULL; - zebra_vni_t *zvni; + json_object *json = NULL, *json_evpn = NULL; + zebra_evpn_t *zevpn; uint32_t num_neigh; struct neigh_walk_ctx wctx; char vni_str[VNI_STR_LEN]; @@ -1045,47 +248,47 @@ static void zvni_print_neigh_hash_all_vni_detail(struct hash_bucket *bucket, json = (json_object *)args[1]; print_dup = (uint32_t)(uintptr_t)args[2]; - zvni = (zebra_vni_t *)bucket->data; - if (!zvni) { + zevpn = (zebra_evpn_t *)bucket->data; + if (!zevpn) { if (json) vty_out(vty, "{}\n"); return; } - num_neigh = hashcount(zvni->neigh_table); + num_neigh = hashcount(zevpn->neigh_table); - if (print_dup && num_dup_detected_neighs(zvni) == 0) + if (print_dup && num_dup_detected_neighs(zevpn) == 0) return; if (json == NULL) { vty_out(vty, "\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n", - zvni->vni, num_neigh); + zevpn->vni, num_neigh); } else { - json_vni = json_object_new_object(); - json_object_int_add(json_vni, "numArpNd", num_neigh); - snprintf(vni_str, sizeof(vni_str), "%u", zvni->vni); + json_evpn = json_object_new_object(); + json_object_int_add(json_evpn, "numArpNd", num_neigh); + snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); } if (!num_neigh) { if (json) - json_object_object_add(json, vni_str, json_vni); + json_object_object_add(json, vni_str, json_evpn); return; } memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); - wctx.zvni = zvni; + wctx.zevpn = zevpn; wctx.vty = vty; wctx.addr_width = 15; - wctx.json = json_vni; + wctx.json = json_evpn; if (print_dup) - hash_iterate(zvni->neigh_table, - zvni_print_dad_neigh_hash_detail, &wctx); + hash_iterate(zevpn->neigh_table, + zebra_evpn_print_dad_neigh_hash_detail, &wctx); else - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash_detail, - &wctx); + hash_iterate(zevpn->neigh_table, + zebra_evpn_print_neigh_hash_detail, &wctx); if (json) - json_object_object_add(json, vni_str, json_vni); + json_object_object_add(json, vni_str, json_evpn); } /* print a specific next hop for an l3vni */ @@ -1165,352 +368,14 @@ static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty, } /* - * Print a specific MAC entry. - */ -static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json) -{ - struct vty *vty; - zebra_neigh_t *n = NULL; - struct listnode *node = NULL; - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - struct zebra_vrf *zvrf; - struct timeval detect_start_time = {0, 0}; - char timebuf[MONOTIME_STRLEN]; - - zvrf = zebra_vrf_get_evpn(); - if (!zvrf) - return; - - vty = (struct vty *)ctxt; - prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); - - if (json) { - json_object *json_mac = json_object_new_object(); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { - struct zebra_ns *zns; - struct interface *ifp; - ifindex_t ifindex; - - ifindex = mac->fwd_info.local.ifindex; - zns = zebra_ns_lookup(mac->fwd_info.local.ns_id); - ifp = if_lookup_by_index_per_ns(zns, ifindex); - if (!ifp) - return; - json_object_string_add(json_mac, "type", "local"); - json_object_string_add(json_mac, "intf", ifp->name); - json_object_int_add(json_mac, "ifindex", ifindex); - if (mac->fwd_info.local.vid) - json_object_int_add(json_mac, "vlan", - mac->fwd_info.local.vid); - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - json_object_string_add(json_mac, "type", "remote"); - json_object_string_add( - json_mac, "remoteVtep", - inet_ntoa(mac->fwd_info.r_vtep_ip)); - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) - json_object_string_add(json_mac, "type", "auto"); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) - json_object_boolean_true_add(json_mac, "stickyMac"); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) - json_object_boolean_true_add(json_mac, - "defaultGateway"); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)) - json_object_boolean_true_add(json_mac, - "remoteGatewayMac"); - - json_object_int_add(json_mac, "localSequence", mac->loc_seq); - json_object_int_add(json_mac, "remoteSequence", mac->rem_seq); - - json_object_int_add(json_mac, "detectionCount", mac->dad_count); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - json_object_boolean_true_add(json_mac, "isDuplicate"); - else - json_object_boolean_false_add(json_mac, "isDuplicate"); - - /* print all the associated neigh */ - if (!listcount(mac->neigh_list)) - json_object_string_add(json_mac, "neighbors", "none"); - else { - json_object *json_active_nbrs = json_object_new_array(); - json_object *json_inactive_nbrs = - json_object_new_array(); - json_object *json_nbrs = json_object_new_object(); - - for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) { - if (IS_ZEBRA_NEIGH_ACTIVE(n)) - json_object_array_add( - json_active_nbrs, - json_object_new_string( - ipaddr2str( - &n->ip, buf2, - sizeof(buf2)))); - else - json_object_array_add( - json_inactive_nbrs, - json_object_new_string( - ipaddr2str( - &n->ip, buf2, - sizeof(buf2)))); - } - - json_object_object_add(json_nbrs, "active", - json_active_nbrs); - json_object_object_add(json_nbrs, "inactive", - json_inactive_nbrs); - json_object_object_add(json_mac, "neighbors", - json_nbrs); - } - - json_object_object_add(json, buf1, json_mac); - } else { - vty_out(vty, "MAC: %s\n", buf1); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { - struct zebra_ns *zns; - struct interface *ifp; - ifindex_t ifindex; - - ifindex = mac->fwd_info.local.ifindex; - zns = zebra_ns_lookup(mac->fwd_info.local.ns_id); - ifp = if_lookup_by_index_per_ns(zns, ifindex); - if (!ifp) - return; - vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex); - if (mac->fwd_info.local.vid) - vty_out(vty, " VLAN: %u", - mac->fwd_info.local.vid); - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - vty_out(vty, " Remote VTEP: %s", - inet_ntoa(mac->fwd_info.r_vtep_ip)); - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) { - vty_out(vty, " Auto Mac "); - } - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) - vty_out(vty, " Sticky Mac "); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) - vty_out(vty, " Default-gateway Mac "); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)) - vty_out(vty, " Remote-gateway Mac "); - - vty_out(vty, "\n"); - vty_out(vty, " Local Seq: %u Remote Seq: %u", mac->loc_seq, - mac->rem_seq); - vty_out(vty, "\n"); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { - vty_out(vty, " Duplicate, detected at %s", - time_to_string(mac->dad_dup_detect_time, - timebuf)); - } else if (mac->dad_count) { - monotime_since(&mac->detect_start_time, - &detect_start_time); - if (detect_start_time.tv_sec <= zvrf->dad_time) { - time_to_string(mac->detect_start_time.tv_sec, - timebuf); - vty_out(vty, - " Duplicate detection started at %s, detection count %u\n", - timebuf, mac->dad_count); - } - } - - /* print all the associated neigh */ - vty_out(vty, " Neighbors:\n"); - if (!listcount(mac->neigh_list)) - vty_out(vty, " No Neighbors\n"); - else { - for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) { - vty_out(vty, " %s %s\n", - ipaddr2str(&n->ip, buf2, sizeof(buf2)), - (IS_ZEBRA_NEIGH_ACTIVE(n) - ? "Active" - : "Inactive")); - } - } - - vty_out(vty, "\n"); - } -} - -/* - * Print MAC hash entry - called for display of all MACs. + * Print MACs for all EVPNs. */ -static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt) +static void zevpn_print_mac_hash_all_evpn(struct hash_bucket *bucket, void *ctxt) { struct vty *vty; - json_object *json_mac_hdr = NULL, *json_mac = NULL; - zebra_mac_t *mac; - char buf1[ETHER_ADDR_STRLEN]; - struct mac_walk_ctx *wctx = ctxt; - - vty = wctx->vty; - json_mac_hdr = wctx->json; - mac = (zebra_mac_t *)bucket->data; - - prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); - - if (json_mac_hdr) - json_mac = json_object_new_object(); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { - struct zebra_ns *zns; - ifindex_t ifindex; - struct interface *ifp; - vlanid_t vid; - - if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) - return; - - zns = zebra_ns_lookup(mac->fwd_info.local.ns_id); - ifindex = mac->fwd_info.local.ifindex; - ifp = if_lookup_by_index_per_ns(zns, ifindex); - if (!ifp) // unexpected - return; - vid = mac->fwd_info.local.vid; - if (json_mac_hdr == NULL) - vty_out(vty, "%-17s %-6s %-21s", buf1, "local", - ifp->name); - else { - json_object_string_add(json_mac, "type", "local"); - json_object_string_add(json_mac, "intf", ifp->name); - } - if (vid) { - if (json_mac_hdr == NULL) - vty_out(vty, " %-5u", vid); - else - json_object_int_add(json_mac, "vlan", vid); - } else /* No vid? fill out the space */ - if (json_mac_hdr == NULL) - vty_out(vty, " %-5s", ""); - if (json_mac_hdr == NULL) { - vty_out(vty, " %u/%u", mac->loc_seq, mac->rem_seq); - vty_out(vty, "\n"); - } else { - json_object_int_add(json_mac, "localSequence", - mac->loc_seq); - json_object_int_add(json_mac, "remoteSequence", - mac->rem_seq); - json_object_int_add(json_mac, "detectionCount", - mac->dad_count); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - json_object_boolean_true_add(json_mac, - "isDuplicate"); - else - json_object_boolean_false_add(json_mac, - "isDuplicate"); - json_object_object_add(json_mac_hdr, buf1, json_mac); - } - - wctx->count++; - - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - - if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) && - !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, - &wctx->r_vtep_ip)) - return; - - if (json_mac_hdr == NULL) { - if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) && - (wctx->count == 0)) { - vty_out(vty, "\nVNI %u\n\n", wctx->zvni->vni); - vty_out(vty, "%-17s %-6s %-21s %-5s %s\n", - "MAC", "Type", "Intf/Remote VTEP", - "VLAN", "Seq #'s"); - } - vty_out(vty, "%-17s %-6s %-21s %-5s %u/%u\n", buf1, - "remote", inet_ntoa(mac->fwd_info.r_vtep_ip), - "", mac->loc_seq, mac->rem_seq); - } else { - json_object_string_add(json_mac, "type", "remote"); - json_object_string_add(json_mac, "remoteVtep", - inet_ntoa(mac->fwd_info.r_vtep_ip)); - json_object_object_add(json_mac_hdr, buf1, json_mac); - json_object_int_add(json_mac, "localSequence", - mac->loc_seq); - json_object_int_add(json_mac, "remoteSequence", - mac->rem_seq); - json_object_int_add(json_mac, "detectionCount", - mac->dad_count); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - json_object_boolean_true_add(json_mac, - "isDuplicate"); - else - json_object_boolean_false_add(json_mac, - "isDuplicate"); - - } - - wctx->count++; - } -} - -/* Print Duplicate MAC */ -static void zvni_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt) -{ - zebra_mac_t *mac; - - mac = (zebra_mac_t *)bucket->data; - if (!mac) - return; - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - zvni_print_mac_hash(bucket, ctxt); -} - -/* - * Print MAC hash entry in detail - called for display of all MACs. - */ -static void zvni_print_mac_hash_detail(struct hash_bucket *bucket, void *ctxt) -{ - struct vty *vty; - json_object *json_mac_hdr = NULL; - zebra_mac_t *mac; - struct mac_walk_ctx *wctx = ctxt; - char buf1[ETHER_ADDR_STRLEN]; - - vty = wctx->vty; - json_mac_hdr = wctx->json; - mac = (zebra_mac_t *)bucket->data; - if (!mac) - return; - - wctx->count++; - prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); - - zvni_print_mac(mac, vty, json_mac_hdr); -} - -/* Print Duplicate MAC in detail */ -static void zvni_print_dad_mac_hash_detail(struct hash_bucket *bucket, - void *ctxt) -{ - zebra_mac_t *mac; - - mac = (zebra_mac_t *)bucket->data; - if (!mac) - return; - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - zvni_print_mac_hash_detail(bucket, ctxt); -} - -/* - * Print MACs for all VNI. - */ -static void zvni_print_mac_hash_all_vni(struct hash_bucket *bucket, void *ctxt) -{ - struct vty *vty; - json_object *json = NULL, *json_vni = NULL; + json_object *json = NULL, *json_evpn = NULL; json_object *json_mac = NULL; - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; uint32_t num_macs; struct mac_walk_ctx *wctx = ctxt; char vni_str[VNI_STR_LEN]; @@ -1518,70 +383,74 @@ static void zvni_print_mac_hash_all_vni(struct hash_bucket *bucket, void *ctxt) vty = wctx->vty; json = wctx->json; - zvni = (zebra_vni_t *)bucket->data; - wctx->zvni = zvni; + zevpn = (zebra_evpn_t *)bucket->data; + wctx->zevpn = zevpn; /*We are iterating over a new VNI, set the count to 0*/ wctx->count = 0; - num_macs = num_valid_macs(zvni); + num_macs = num_valid_macs(zevpn); if (!num_macs) return; if (wctx->print_dup) - num_macs = num_dup_detected_macs(zvni); + num_macs = num_dup_detected_macs(zevpn); if (json) { - json_vni = json_object_new_object(); + json_evpn = json_object_new_object(); json_mac = json_object_new_object(); - snprintf(vni_str, sizeof(vni_str), "%u", zvni->vni); + snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); } if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) { if (json == NULL) { vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", - zvni->vni, num_macs); - vty_out(vty, "%-17s %-6s %-21s %-5s %s\n", "MAC", - "Type", "Intf/Remote VTEP", "VLAN", "Seq #'s"); + zevpn->vni, num_macs); + vty_out(vty, + "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n"); + vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC", + "Type", "Flags", "Intf/Remote ES/VTEP", + "VLAN", "Seq #'s"); } else - json_object_int_add(json_vni, "numMacs", num_macs); + json_object_int_add(json_evpn, "numMacs", num_macs); } if (!num_macs) { if (json) { - json_object_int_add(json_vni, "numMacs", num_macs); - json_object_object_add(json, vni_str, json_vni); + json_object_int_add(json_evpn, "numMacs", num_macs); + json_object_object_add(json, vni_str, json_evpn); } return; } - /* assign per-vni to wctx->json object to fill macs - * under the vni. Re-assign primary json object to fill - * next vni information. + /* assign per-evpn to wctx->json object to fill macs + * under the evpn. Re-assign primary json object to fill + * next evpn information. */ wctx->json = json_mac; if (wctx->print_dup) - hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, wctx); + hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash, + wctx); else - hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx); + hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, wctx); wctx->json = json; if (json) { if (wctx->count) - json_object_object_add(json_vni, "macs", json_mac); - json_object_object_add(json, vni_str, json_vni); + json_object_object_add(json_evpn, "macs", json_mac); + json_object_object_add(json, vni_str, json_evpn); } } /* - * Print MACs in detail for all VNI. + * Print MACs in detail for all EVPNs. */ -static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket *bucket, +static void zevpn_print_mac_hash_all_evpn_detail(struct hash_bucket *bucket, void *ctxt) { struct vty *vty; - json_object *json = NULL, *json_vni = NULL; + json_object *json = NULL, *json_evpn = NULL; json_object *json_mac = NULL; - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; uint32_t num_macs; struct mac_walk_ctx *wctx = ctxt; char vni_str[VNI_STR_LEN]; @@ -1589,52 +458,53 @@ static void zvni_print_mac_hash_all_vni_detail(struct hash_bucket *bucket, vty = wctx->vty; json = wctx->json; - zvni = (zebra_vni_t *)bucket->data; - if (!zvni) { + zevpn = (zebra_evpn_t *)bucket->data; + if (!zevpn) { if (json) vty_out(vty, "{}\n"); return; } - wctx->zvni = zvni; + wctx->zevpn = zevpn; - /*We are iterating over a new VNI, set the count to 0*/ + /*We are iterating over a new EVPN, set the count to 0*/ wctx->count = 0; - num_macs = num_valid_macs(zvni); + num_macs = num_valid_macs(zevpn); if (!num_macs) return; - if (wctx->print_dup && (num_dup_detected_macs(zvni) == 0)) + if (wctx->print_dup && (num_dup_detected_macs(zevpn) == 0)) return; if (json) { - json_vni = json_object_new_object(); + json_evpn = json_object_new_object(); json_mac = json_object_new_object(); - snprintf(vni_str, sizeof(vni_str), "%u", zvni->vni); + snprintf(vni_str, VNI_STR_LEN, "%u", zevpn->vni); } if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) { if (json == NULL) { vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", - zvni->vni, num_macs); + zevpn->vni, num_macs); } else - json_object_int_add(json_vni, "numMacs", num_macs); + json_object_int_add(json_evpn, "numMacs", num_macs); } - /* assign per-vni to wctx->json object to fill macs - * under the vni. Re-assign primary json object to fill - * next vni information. + /* assign per-evpn to wctx->json object to fill macs + * under the evpn. Re-assign primary json object to fill + * next evpn information. */ wctx->json = json_mac; if (wctx->print_dup) - hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash_detail, - wctx); + hash_iterate(zevpn->mac_table, + zebra_evpn_print_dad_mac_hash_detail, wctx); else - hash_iterate(zvni->mac_table, zvni_print_mac_hash_detail, wctx); + hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash_detail, + wctx); wctx->json = json; if (json) { if (wctx->count) - json_object_object_add(json_vni, "macs", json_mac); - json_object_object_add(json, vni_str, json_vni); + json_object_object_add(json_evpn, "macs", json_mac); + json_object_object_add(json, vni_str, json_evpn); } } @@ -1642,7 +512,7 @@ static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx) { struct nh_walk_ctx *wctx = NULL; struct vty *vty = NULL; - struct json_object *json_vni = NULL; + struct json_object *json_evpn = NULL; struct json_object *json_nh = NULL; zebra_neigh_t *n = NULL; char buf1[ETHER_ADDR_STRLEN]; @@ -1650,12 +520,12 @@ static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx) wctx = (struct nh_walk_ctx *)ctx; vty = wctx->vty; - json_vni = wctx->json; - if (json_vni) + json_evpn = wctx->json; + if (json_evpn) json_nh = json_object_new_object(); n = (zebra_neigh_t *)bucket->data; - if (!json_vni) { + if (!json_evpn) { vty_out(vty, "%-15s %-17s\n", ipaddr2str(&(n->ip), buf2, sizeof(buf2)), prefix_mac2str(&n->emac, buf1, sizeof(buf1))); @@ -1665,7 +535,7 @@ static void zl3vni_print_nh_hash(struct hash_bucket *bucket, void *ctx) json_object_string_add( json_nh, "routerMac", prefix_mac2str(&n->emac, buf1, sizeof(buf1))); - json_object_object_add(json_vni, + json_object_object_add(json_evpn, ipaddr2str(&(n->ip), buf2, sizeof(buf2)), json_nh); } @@ -1676,7 +546,7 @@ static void zl3vni_print_nh_hash_all_vni(struct hash_bucket *bucket, { struct vty *vty = NULL; json_object *json = NULL; - json_object *json_vni = NULL; + json_object *json_evpn = NULL; zebra_l3vni_t *zl3vni = NULL; uint32_t num_nh = 0; struct nh_walk_ctx wctx; @@ -1692,22 +562,22 @@ static void zl3vni_print_nh_hash_all_vni(struct hash_bucket *bucket, return; if (json) { - json_vni = json_object_new_object(); - snprintf(vni_str, sizeof(vni_str), "%u", zl3vni->vni); + json_evpn = json_object_new_object(); + snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni); } if (json == NULL) { vty_out(vty, "\nVNI %u #Next-Hops %u\n\n", zl3vni->vni, num_nh); vty_out(vty, "%-15s %-17s\n", "IP", "RMAC"); } else - json_object_int_add(json_vni, "numNextHops", num_nh); + json_object_int_add(json_evpn, "numNextHops", num_nh); memset(&wctx, 0, sizeof(struct nh_walk_ctx)); wctx.vty = vty; - wctx.json = json_vni; + wctx.json = json_evpn; hash_iterate(zl3vni->nh_table, zl3vni_print_nh_hash, &wctx); if (json) - json_object_object_add(json, vni_str, json_vni); + json_object_object_add(json, vni_str, json_evpn); } static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket, @@ -1715,7 +585,7 @@ static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket, { struct vty *vty = NULL; json_object *json = NULL; - json_object *json_vni = NULL; + json_object *json_evpn = NULL; zebra_l3vni_t *zl3vni = NULL; uint32_t num_rmacs; struct rmac_walk_ctx wctx; @@ -1731,15 +601,15 @@ static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket, return; if (json) { - json_vni = json_object_new_object(); - snprintf(vni_str, sizeof(vni_str), "%u", zl3vni->vni); + json_evpn = json_object_new_object(); + snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni); } if (json == NULL) { vty_out(vty, "\nVNI %u #RMACs %u\n\n", zl3vni->vni, num_rmacs); vty_out(vty, "%-17s %-21s\n", "RMAC", "Remote VTEP"); } else - json_object_int_add(json_vni, "numRmacs", num_rmacs); + json_object_int_add(json_evpn, "numRmacs", num_rmacs); /* assign per-vni to wctx->json object to fill macs * under the vni. Re-assign primary json object to fill @@ -1747,10 +617,10 @@ static void zl3vni_print_rmac_hash_all_vni(struct hash_bucket *bucket, */ memset(&wctx, 0, sizeof(struct rmac_walk_ctx)); wctx.vty = vty; - wctx.json = json_vni; + wctx.json = json_evpn; hash_iterate(zl3vni->rmac_table, zl3vni_print_rmac_hash, &wctx); if (json) - json_object_object_add(json, vni_str, json_vni); + json_object_object_add(json, vni_str, json_evpn); } static void zl3vni_print_rmac_hash(struct hash_bucket *bucket, void *ctx) @@ -1791,8 +661,8 @@ static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx) char buf[ETHER_ADDR_STRLEN]; struct vty *vty = NULL; json_object *json = NULL; - zebra_vni_t *zvni = NULL; - json_object *json_vni_list = NULL; + zebra_evpn_t *zevpn = NULL; + json_object *json_evpn_list = NULL; struct listnode *node = NULL, *nnode = NULL; vty = ctx[0]; @@ -1817,11 +687,11 @@ static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx) vty_out(vty, " Router MAC: %s\n", zl3vni_rmac2str(zl3vni, buf, sizeof(buf))); vty_out(vty, " L2 VNIs: "); - for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni)) - vty_out(vty, "%u ", zvni->vni); + for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn)) + vty_out(vty, "%u ", zevpn->vni); vty_out(vty, "\n"); } else { - json_vni_list = json_object_new_array(); + json_evpn_list = json_object_new_array(); json_object_int_add(json, "vni", zl3vni->vni); json_object_string_add(json, "type", "L3"); json_object_string_add(json, "localVtepIp", @@ -1843,106 +713,11 @@ static void zl3vni_print(zebra_l3vni_t *zl3vni, void **ctx) CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY) ? "prefix-routes-only" : "none"); - for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zvni)) { - json_object_array_add(json_vni_list, - json_object_new_int(zvni->vni)); + for (ALL_LIST_ELEMENTS(zl3vni->l2vnis, node, nnode, zevpn)) { + json_object_array_add(json_evpn_list, + json_object_new_int(zevpn->vni)); } - json_object_object_add(json, "l2Vnis", json_vni_list); - } -} - -/* - * Print a specific VNI entry. - */ -static void zvni_print(zebra_vni_t *zvni, void **ctxt) -{ - struct vty *vty; - zebra_vtep_t *zvtep; - uint32_t num_macs; - uint32_t num_neigh; - json_object *json = NULL; - json_object *json_vtep_list = NULL; - json_object *json_ip_str = NULL; - - vty = ctxt[0]; - json = ctxt[1]; - - if (json == NULL) { - vty_out(vty, "VNI: %u\n", zvni->vni); - vty_out(vty, " Type: %s\n", "L2"); - vty_out(vty, " Tenant VRF: %s\n", vrf_id_to_name(zvni->vrf_id)); - } else { - json_object_int_add(json, "vni", zvni->vni); - json_object_string_add(json, "type", "L2"); - json_object_string_add(json, "vrf", - vrf_id_to_name(zvni->vrf_id)); - } - - if (!zvni->vxlan_if) { // unexpected - if (json == NULL) - vty_out(vty, " VxLAN interface: unknown\n"); - return; - } - num_macs = num_valid_macs(zvni); - num_neigh = hashcount(zvni->neigh_table); - if (json == NULL) { - vty_out(vty, " VxLAN interface: %s\n", zvni->vxlan_if->name); - vty_out(vty, " VxLAN ifIndex: %u\n", zvni->vxlan_if->ifindex); - vty_out(vty, " Local VTEP IP: %s\n", - inet_ntoa(zvni->local_vtep_ip)); - vty_out(vty, " Mcast group: %s\n", - inet_ntoa(zvni->mcast_grp)); - } else { - json_object_string_add(json, "vxlanInterface", - zvni->vxlan_if->name); - json_object_int_add(json, "ifindex", zvni->vxlan_if->ifindex); - json_object_string_add(json, "vtepIp", - inet_ntoa(zvni->local_vtep_ip)); - json_object_string_add(json, "mcastGroup", - inet_ntoa(zvni->mcast_grp)); - json_object_string_add(json, "advertiseGatewayMacip", - zvni->advertise_gw_macip ? "Yes" : "No"); - json_object_int_add(json, "numMacs", num_macs); - json_object_int_add(json, "numArpNd", num_neigh); - } - if (!zvni->vteps) { - if (json == NULL) - vty_out(vty, " No remote VTEPs known for this VNI\n"); - } else { - if (json == NULL) - vty_out(vty, " Remote VTEPs for this VNI:\n"); - else - json_vtep_list = json_object_new_array(); - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) { - const char *flood_str = lookup_msg(zvtep_flood_str, - zvtep->flood_control, - VXLAN_FLOOD_STR_DEFAULT); - - if (json == NULL) { - vty_out(vty, " %s flood: %s\n", - inet_ntoa(zvtep->vtep_ip), - flood_str); - } else { - json_ip_str = json_object_new_string( - inet_ntoa(zvtep->vtep_ip)); - json_object_array_add(json_vtep_list, - json_ip_str); - } - } - if (json) - json_object_object_add(json, "numRemoteVteps", - json_vtep_list); - } - if (json == NULL) { - vty_out(vty, - " Number of MACs (local and remote) known for this VNI: %u\n", - num_macs); - vty_out(vty, - " Number of ARPs (IPv4 and IPv6, local and remote) " - "known for this VNI: %u\n", - num_neigh); - vty_out(vty, " Advertise-gw-macip: %s\n", - zvni->advertise_gw_macip ? "Yes" : "No"); + json_object_object_add(json, "l2Vnis", json_evpn_list); } } @@ -1951,7 +726,7 @@ static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[]) { struct vty *vty = NULL; json_object *json = NULL; - json_object *json_vni = NULL; + json_object *json_evpn = NULL; zebra_l3vni_t *zl3vni = NULL; vty = (struct vty *)ctx[0]; @@ -1968,31 +743,23 @@ static void zl3vni_print_hash(struct hash_bucket *bucket, void *ctx[]) } else { char vni_str[VNI_STR_LEN]; - snprintf(vni_str, sizeof(vni_str), "%u", zl3vni->vni); - json_vni = json_object_new_object(); - json_object_int_add(json_vni, "vni", zl3vni->vni); - json_object_string_add(json_vni, "vxlanIf", + snprintf(vni_str, VNI_STR_LEN, "%u", zl3vni->vni); + json_evpn = json_object_new_object(); + json_object_int_add(json_evpn, "vni", zl3vni->vni); + json_object_string_add(json_evpn, "vxlanIf", zl3vni_vxlan_if_name(zl3vni)); - json_object_int_add(json_vni, "numMacs", + json_object_int_add(json_evpn, "numMacs", hashcount(zl3vni->rmac_table)); - json_object_int_add(json_vni, "numArpNd", + json_object_int_add(json_evpn, "numArpNd", hashcount(zl3vni->nh_table)); - json_object_string_add(json_vni, "numRemoteVteps", "n/a"); - json_object_string_add(json_vni, "type", "L3"); - json_object_string_add(json_vni, "tenantVrf", + json_object_string_add(json_evpn, "numRemoteVteps", "n/a"); + json_object_string_add(json_evpn, "type", "L3"); + json_object_string_add(json_evpn, "tenantVrf", zl3vni_vrf_name(zl3vni)); - json_object_object_add(json, vni_str, json_vni); + json_object_object_add(json, vni_str, json_evpn); } } -/* Private Structure to pass callback data for hash iterator */ -struct zvni_evpn_show { - struct vty *vty; - json_object *json; - struct zebra_vrf *zvrf; - bool use_json; -}; - /* print a L3 VNI hash entry in detail*/ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data) { @@ -2000,7 +767,7 @@ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data) zebra_l3vni_t *zl3vni = NULL; json_object *json_array = NULL; bool use_json = false; - struct zvni_evpn_show *zes = data; + struct zebra_evpn_show *zes = data; vty = zes->vty; json_array = zes->json; @@ -2015,1749 +782,6 @@ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data) vty_out(vty, "\n"); } - -/* - * Print a VNI hash entry - called for display of all VNIs. - */ -static void zvni_print_hash(struct hash_bucket *bucket, void *ctxt[]) -{ - struct vty *vty; - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - uint32_t num_vteps = 0; - uint32_t num_macs = 0; - uint32_t num_neigh = 0; - json_object *json = NULL; - json_object *json_vni = NULL; - json_object *json_ip_str = NULL; - json_object *json_vtep_list = NULL; - - vty = ctxt[0]; - json = ctxt[1]; - - zvni = (zebra_vni_t *)bucket->data; - - zvtep = zvni->vteps; - while (zvtep) { - num_vteps++; - zvtep = zvtep->next; - } - - num_macs = num_valid_macs(zvni); - num_neigh = hashcount(zvni->neigh_table); - if (json == NULL) - vty_out(vty, "%-10u %-4s %-21s %-8u %-8u %-15u %-37s\n", - zvni->vni, "L2", - zvni->vxlan_if ? zvni->vxlan_if->name : "unknown", - num_macs, num_neigh, num_vteps, - vrf_id_to_name(zvni->vrf_id)); - else { - char vni_str[VNI_STR_LEN]; - snprintf(vni_str, sizeof(vni_str), "%u", zvni->vni); - json_vni = json_object_new_object(); - json_object_int_add(json_vni, "vni", zvni->vni); - json_object_string_add(json_vni, "type", "L2"); - json_object_string_add(json_vni, "vxlanIf", - zvni->vxlan_if ? zvni->vxlan_if->name - : "unknown"); - json_object_int_add(json_vni, "numMacs", num_macs); - json_object_int_add(json_vni, "numArpNd", num_neigh); - json_object_int_add(json_vni, "numRemoteVteps", num_vteps); - json_object_string_add(json_vni, "tenantVrf", - vrf_id_to_name(zvni->vrf_id)); - if (num_vteps) { - json_vtep_list = json_object_new_array(); - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) { - json_ip_str = json_object_new_string( - inet_ntoa(zvtep->vtep_ip)); - json_object_array_add(json_vtep_list, - json_ip_str); - } - json_object_object_add(json_vni, "remoteVteps", - json_vtep_list); - } - json_object_object_add(json, vni_str, json_vni); - } -} - -/* - * Print a VNI hash entry in detail - called for display of all VNIs. - */ -static void zvni_print_hash_detail(struct hash_bucket *bucket, void *data) -{ - struct vty *vty; - zebra_vni_t *zvni; - json_object *json_array = NULL; - bool use_json = false; - struct zvni_evpn_show *zes = data; - - vty = zes->vty; - json_array = zes->json; - use_json = zes->use_json; - - zvni = (zebra_vni_t *)bucket->data; - - zebra_vxlan_print_vni(vty, zes->zvrf, zvni->vni, use_json, json_array); - - if (!use_json) - vty_out(vty, "\n"); -} - -/* - * Inform BGP about local MACIP. - */ -static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, - struct ipaddr *ip, uint8_t flags, - uint32_t seq, int state, uint16_t cmd) -{ - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - int ipa_len; - struct zserv *client = NULL; - struct stream *s = NULL; - - client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); - /* BGP may not be running. */ - if (!client) - return 0; - - s = stream_new(ZEBRA_MAX_PACKET_SIZ); - - zclient_create_header(s, cmd, zebra_vrf_get_evpn_id()); - stream_putl(s, vni); - stream_put(s, macaddr->octet, ETH_ALEN); - if (ip) { - ipa_len = 0; - if (IS_IPADDR_V4(ip)) - ipa_len = IPV4_MAX_BYTELEN; - else if (IS_IPADDR_V6(ip)) - ipa_len = IPV6_MAX_BYTELEN; - - stream_putl(s, ipa_len); /* IP address length */ - if (ipa_len) - stream_put(s, &ip->ip.addr, ipa_len); /* IP address */ - } else - stream_putl(s, 0); /* Just MAC. */ - - if (cmd == ZEBRA_MACIP_ADD) { - stream_putc(s, flags); /* sticky mac/gateway mac */ - stream_putl(s, seq); /* sequence number */ - } else { - stream_putl(s, state); /* state - active/inactive */ - } - - - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "Send MACIP %s flags 0x%x MAC %s IP %s seq %u L2-VNI %u to %s", - (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags, - prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(ip, buf2, sizeof(buf2)), seq, vni, - zebra_route_string(client->proto)); - - if (cmd == ZEBRA_MACIP_ADD) - client->macipadd_cnt++; - else - client->macipdel_cnt++; - - return zserv_send_message(client, s); -} - -/* - * Make hash key for neighbors. - */ -static unsigned int neigh_hash_keymake(const void *p) -{ - const zebra_neigh_t *n = p; - const struct ipaddr *ip = &n->ip; - - if (IS_IPADDR_V4(ip)) - return jhash_1word(ip->ipaddr_v4.s_addr, 0); - - return jhash2(ip->ipaddr_v6.s6_addr32, - array_size(ip->ipaddr_v6.s6_addr32), 0); -} - -/* - * Compare two neighbor hash structures. - */ -static bool neigh_cmp(const void *p1, const void *p2) -{ - const zebra_neigh_t *n1 = p1; - const zebra_neigh_t *n2 = p2; - - if (n1 == NULL && n2 == NULL) - return true; - - if (n1 == NULL || n2 == NULL) - return false; - - return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0); -} - -static int neigh_list_cmp(void *p1, void *p2) -{ - const zebra_neigh_t *n1 = p1; - const zebra_neigh_t *n2 = p2; - - return memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)); -} - -/* - * Callback to allocate neighbor hash entry. - */ -static void *zvni_neigh_alloc(void *p) -{ - const zebra_neigh_t *tmp_n = p; - zebra_neigh_t *n; - - n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t)); - *n = *tmp_n; - - return ((void *)n); -} - -/* - * Add neighbor entry. - */ -static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip, - struct ethaddr *mac) -{ - zebra_neigh_t tmp_n; - zebra_neigh_t *n = NULL; - zebra_mac_t *zmac = NULL; - - memset(&tmp_n, 0, sizeof(zebra_neigh_t)); - memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr)); - n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc); - assert(n); - - memcpy(&n->emac, mac, ETH_ALEN); - n->state = ZEBRA_NEIGH_INACTIVE; - n->zvni = zvni; - n->dad_ip_auto_recovery_timer = NULL; - - /* Associate the neigh to mac */ - zmac = zvni_mac_lookup(zvni, mac); - if (zmac) - listnode_add_sort(zmac->neigh_list, n); - - return n; -} - -/* - * Delete neighbor entry. - */ -static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n) -{ - zebra_neigh_t *tmp_n; - zebra_mac_t *zmac = NULL; - - zmac = zvni_mac_lookup(zvni, &n->emac); - if (zmac) - listnode_delete(zmac->neigh_list, n); - - /* Cancel auto recovery */ - THREAD_OFF(n->dad_ip_auto_recovery_timer); - - /* Free the VNI hash entry and allocated memory. */ - tmp_n = hash_release(zvni->neigh_table, n); - XFREE(MTYPE_NEIGH, tmp_n); - - return 0; -} - -/* - * Free neighbor hash entry (callback) - */ -static void zvni_neigh_del_hash_entry(struct hash_bucket *bucket, void *arg) -{ - struct neigh_walk_ctx *wctx = arg; - zebra_neigh_t *n = bucket->data; - - if (((wctx->flags & DEL_LOCAL_NEIGH) && (n->flags & ZEBRA_NEIGH_LOCAL)) - || ((wctx->flags & DEL_REMOTE_NEIGH) - && (n->flags & ZEBRA_NEIGH_REMOTE)) - || ((wctx->flags & DEL_REMOTE_NEIGH_FROM_VTEP) - && (n->flags & ZEBRA_NEIGH_REMOTE) - && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) { - if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL)) - zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip, - &n->emac, 0, n->state); - - if (wctx->uninstall) - zvni_neigh_uninstall(wctx->zvni, n); - - zvni_neigh_del(wctx->zvni, n); - } - - return; -} - -/* - * Delete all neighbor entries for this VNI. - */ -static void zvni_neigh_del_all(zebra_vni_t *zvni, int uninstall, int upd_client, - uint32_t flags) -{ - struct neigh_walk_ctx wctx; - - if (!zvni->neigh_table) - return; - - memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); - wctx.zvni = zvni; - wctx.uninstall = uninstall; - wctx.upd_client = upd_client; - wctx.flags = flags; - - hash_iterate(zvni->neigh_table, zvni_neigh_del_hash_entry, &wctx); -} - -/* - * Look up neighbor hash entry. - */ -static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip) -{ - zebra_neigh_t tmp; - zebra_neigh_t *n; - - memset(&tmp, 0, sizeof(tmp)); - memcpy(&tmp.ip, ip, sizeof(struct ipaddr)); - n = hash_lookup(zvni->neigh_table, &tmp); - - return n; -} - -/* - * Process all neighbors associated with a MAC upon the MAC being learnt - * locally or undergoing any other change (such as sequence number). - */ -static void zvni_process_neigh_on_local_mac_change(zebra_vni_t *zvni, - zebra_mac_t *zmac, - bool seq_change) -{ - zebra_neigh_t *n = NULL; - struct listnode *node = NULL; - struct zebra_vrf *zvrf = NULL; - char buf[ETHER_ADDR_STRLEN]; - - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Processing neighbors on local MAC %s %s, VNI %u", - prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)), - seq_change ? "CHANGE" : "ADD", zvni->vni); - - /* Walk all neighbors and mark any inactive local neighbors as - * active and/or update sequence number upon a move, and inform BGP. - * The action for remote neighbors is TBD. - * NOTE: We can't simply uninstall remote neighbors as the kernel may - * accidentally end up deleting a just-learnt local neighbor. - */ - for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - if (IS_ZEBRA_NEIGH_INACTIVE(n) || seq_change) { - ZEBRA_NEIGH_SET_ACTIVE(n); - n->loc_seq = zmac->loc_seq; - if (!(zvrf->dup_addr_detect && - zvrf->dad_freeze && !!CHECK_FLAG(n->flags, - ZEBRA_NEIGH_DUPLICATE))) - zvni_neigh_send_add_to_client( - zvni->vni, &n->ip, &n->emac, - n->flags, n->loc_seq); - } - } - } -} - -/* - * Process all neighbors associated with a local MAC upon the MAC being - * deleted. - */ -static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni, - zebra_mac_t *zmac) -{ - zebra_neigh_t *n = NULL; - struct listnode *node = NULL; - char buf[ETHER_ADDR_STRLEN]; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u", - prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)), - zvni->vni); - - /* Walk all local neighbors and mark as inactive and inform - * BGP, if needed. - * TBD: There is currently no handling for remote neighbors. We - * don't expect them to exist, if they do, do we install the MAC - * as a remote MAC and the neighbor as remote? - */ - for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - if (IS_ZEBRA_NEIGH_ACTIVE(n)) { - ZEBRA_NEIGH_SET_INACTIVE(n); - n->loc_seq = 0; - zvni_neigh_send_del_to_client(zvni->vni, &n->ip, - &n->emac, 0, ZEBRA_NEIGH_ACTIVE); - } - } - } -} - -/* - * Process all neighbors associated with a MAC upon the MAC being remotely - * learnt. - */ -static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni, - zebra_mac_t *zmac) -{ - zebra_neigh_t *n = NULL; - struct listnode *node = NULL; - char buf[ETHER_ADDR_STRLEN]; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u", - prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)), - zvni->vni); - - /* Walk all local neighbors and mark as inactive and inform - * BGP, if needed. - */ - for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - if (IS_ZEBRA_NEIGH_ACTIVE(n)) { - ZEBRA_NEIGH_SET_INACTIVE(n); - n->loc_seq = 0; - zvni_neigh_send_del_to_client(zvni->vni, &n->ip, - &n->emac, 0, ZEBRA_NEIGH_ACTIVE); - } - } - } -} - -/* - * Process all neighbors associated with a remote MAC upon the MAC being - * deleted. - */ -static void zvni_process_neigh_on_remote_mac_del(zebra_vni_t *zvni, - zebra_mac_t *zmac) -{ - /* NOTE: Currently a NO-OP. */ -} - -static void zvni_probe_neigh_on_mac_add(zebra_vni_t *zvni, zebra_mac_t *zmac) -{ - zebra_neigh_t *nbr = NULL; - struct listnode *node = NULL; - - for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, nbr)) { - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL) && - IS_ZEBRA_NEIGH_INACTIVE(nbr)) - zvni_neigh_probe(zvni, nbr); - } -} - -/* - * Inform BGP about local neighbor addition. - */ -static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, - struct ethaddr *macaddr, - uint8_t neigh_flags, - uint32_t seq) -{ - uint8_t flags = 0; - - if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_DEF_GW)) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - /* Set router flag (R-bit) based on local neigh entry add */ - if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_ROUTER_FLAG)) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); - if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_SVI_IP)) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP); - - return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, - seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD); -} - -/* - * Inform BGP about local neighbor deletion. - */ -static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip, - struct ethaddr *macaddr, uint8_t flags, - int state) -{ - return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, - 0, state, ZEBRA_MACIP_DEL); -} - -/* - * Install remote neighbor into the kernel. - */ -static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) -{ - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct interface *vlan_if; - int flags; - int ret = 0; - - if (!(n->flags & ZEBRA_NEIGH_REMOTE)) - return 0; - - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; - - vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); - if (!vlan_if) - return -1; - - flags = DPLANE_NTF_EXT_LEARNED; - if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) - flags |= DPLANE_NTF_ROUTER; - ZEBRA_NEIGH_SET_ACTIVE(n); - - dplane_neigh_add(vlan_if, &n->ip, &n->emac, flags); - - return ret; -} - -/* - * Uninstall remote neighbor from the kernel. - */ -static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n) -{ - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct interface *vlan_if; - - if (!(n->flags & ZEBRA_NEIGH_REMOTE)) - return 0; - - if (!zvni->vxlan_if) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } - - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; - vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); - if (!vlan_if) - return -1; - - ZEBRA_NEIGH_SET_INACTIVE(n); - n->loc_seq = 0; - - dplane_neigh_delete(vlan_if, &n->ip); - - return 0; -} - -/* - * Probe neighbor from the kernel. - */ -static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n) -{ - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl; - struct interface *vlan_if; - - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - vxl = &zif->l2info.vxl; - - vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); - if (!vlan_if) - return -1; - - dplane_neigh_update(vlan_if, &n->ip, &n->emac); - - return 0; -} - -/* - * Install neighbor hash entry - called upon access VLAN change. - */ -static void zvni_install_neigh_hash(struct hash_bucket *bucket, void *ctxt) -{ - zebra_neigh_t *n; - struct neigh_walk_ctx *wctx = ctxt; - - n = (zebra_neigh_t *)bucket->data; - - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) - zvni_neigh_install(wctx->zvni, n); -} - -/* Get the VRR interface for SVI if any */ -struct interface *zebra_get_vrr_intf_for_svi(struct interface *ifp) -{ - struct zebra_vrf *zvrf = NULL; - struct interface *tmp_if = NULL; - struct zebra_if *zif = NULL; - - zvrf = vrf_info_lookup(ifp->vrf_id); - assert(zvrf); - - FOR_ALL_INTERFACES (zvrf->vrf, tmp_if) { - zif = tmp_if->info; - if (!zif) - continue; - - if (!IS_ZEBRA_IF_MACVLAN(tmp_if)) - continue; - - if (zif->link == ifp) - return tmp_if; - } - - return NULL; -} - -static int zvni_del_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni) -{ - struct listnode *cnode = NULL, *cnnode = NULL; - struct connected *c = NULL; - struct ethaddr macaddr; - - memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN); - - for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { - struct ipaddr ip; - - memset(&ip, 0, sizeof(struct ipaddr)); - if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL)) - continue; - - if (c->address->family == AF_INET) { - ip.ipa_type = IPADDR_V4; - memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4), - sizeof(struct in_addr)); - } else if (c->address->family == AF_INET6) { - ip.ipa_type = IPADDR_V6; - memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6), - sizeof(struct in6_addr)); - } else { - continue; - } - - zvni_gw_macip_del(ifp, zvni, &ip); - } - - return 0; -} - -static int zvni_add_macip_for_intf(struct interface *ifp, zebra_vni_t *zvni) -{ - struct listnode *cnode = NULL, *cnnode = NULL; - struct connected *c = NULL; - struct ethaddr macaddr; - - memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN); - - for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { - struct ipaddr ip; - - memset(&ip, 0, sizeof(struct ipaddr)); - if (!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL)) - continue; - - if (c->address->family == AF_INET) { - ip.ipa_type = IPADDR_V4; - memcpy(&(ip.ipaddr_v4), &(c->address->u.prefix4), - sizeof(struct in_addr)); - } else if (c->address->family == AF_INET6) { - ip.ipa_type = IPADDR_V6; - memcpy(&(ip.ipaddr_v6), &(c->address->u.prefix6), - sizeof(struct in6_addr)); - } else { - continue; - } - - zvni_gw_macip_add(ifp, zvni, &macaddr, &ip); - } - return 0; -} - - -static int zvni_advertise_subnet(zebra_vni_t *zvni, struct interface *ifp, - int advertise) -{ - struct listnode *cnode = NULL, *cnnode = NULL; - struct connected *c = NULL; - struct ethaddr macaddr; - - memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN); - - for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, c)) { - struct prefix p; - - memcpy(&p, c->address, sizeof(struct prefix)); - - /* skip link local address */ - if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) - continue; - - apply_mask(&p); - if (advertise) - ip_prefix_send_to_client(ifp->vrf_id, &p, - ZEBRA_IP_PREFIX_ROUTE_ADD); - else - ip_prefix_send_to_client(ifp->vrf_id, &p, - ZEBRA_IP_PREFIX_ROUTE_DEL); - } - return 0; -} - -/* - * zvni_gw_macip_add_to_client - */ -static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, - struct ethaddr *macaddr, struct ipaddr *ip) -{ - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - zebra_neigh_t *n = NULL; - zebra_mac_t *mac = NULL; - struct zebra_if *zif = NULL; - struct zebra_l2info_vxlan *vxl = NULL; - struct zebra_vrf *zvrf; - ns_id_t local_ns_id = NS_DEFAULT; - - zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); - if (zvrf && zvrf->zns) - local_ns_id = zvrf->zns->ns_id; - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - - vxl = &zif->l2info.vxl; - - mac = zvni_mac_lookup(zvni, macaddr); - if (!mac) { - mac = zvni_mac_add(zvni, macaddr); - if (!mac) { - flog_err(EC_ZEBRA_MAC_ADD_FAILED, - "Failed to add MAC %s intf %s(%u) VID %u", - prefix_mac2str(macaddr, buf, sizeof(buf)), - ifp->name, ifp->ifindex, vxl->access_vlan); - return -1; - } - } - - /* Set "local" forwarding info. */ - SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); - SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW); - memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); - mac->fwd_info.local.ifindex = ifp->ifindex; - mac->fwd_info.local.ns_id = local_ns_id; - mac->fwd_info.local.vid = vxl->access_vlan; - - n = zvni_neigh_lookup(zvni, ip); - if (!n) { - n = zvni_neigh_add(zvni, ip, macaddr); - if (!n) { - flog_err( - EC_ZEBRA_MAC_ADD_FAILED, - "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", - ipaddr2str(ip, buf2, sizeof(buf2)), - prefix_mac2str(macaddr, buf, sizeof(buf)), - ifp->name, ifp->ifindex, zvni->vni); - return -1; - } - } - - /* Set "local" forwarding info. */ - SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); - ZEBRA_NEIGH_SET_ACTIVE(n); - memcpy(&n->emac, macaddr, ETH_ALEN); - n->ifindex = ifp->ifindex; - - /* Only advertise in BGP if the knob is enabled */ - if (advertise_gw_macip_enabled(zvni)) { - - SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW); - SET_FLAG(n->flags, ZEBRA_NEIGH_DEF_GW); - /* Set Router flag (R-bit) */ - if (ip->ipa_type == IPADDR_V6) - SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x", - ifp->name, ifp->ifindex, zvni->vni, - prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(ip, buf2, sizeof(buf2)), n->flags); - - zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, - n->flags, n->loc_seq); - } else if (advertise_svi_macip_enabled(zvni)) { - - SET_FLAG(n->flags, ZEBRA_NEIGH_SVI_IP); - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "SVI %s(%u) L2-VNI %u, sending SVI MAC %s IP %s add to BGP with flags 0x%x", - ifp->name, ifp->ifindex, zvni->vni, - prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(ip, buf2, sizeof(buf2)), n->flags); - - zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, - n->flags, n->loc_seq); - } - - return 0; -} - -/* - * zvni_gw_macip_del_from_client - */ -static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni, - struct ipaddr *ip) -{ - char buf1[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - zebra_neigh_t *n = NULL; - zebra_mac_t *mac = NULL; - - /* If the neigh entry is not present nothing to do*/ - n = zvni_neigh_lookup(zvni, ip); - if (!n) - return 0; - - /* mac entry should be present */ - mac = zvni_mac_lookup(zvni, &n->emac); - if (!mac) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u", - prefix_mac2str(&n->emac, - buf1, sizeof(buf1)), - ipaddr2str(ip, buf2, sizeof(buf2)), - zvni->vni); - return -1; - } - - /* If the entry is not local nothing to do*/ - if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) - return -1; - - /* only need to delete the entry from bgp if we sent it before */ - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP", - ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni, - prefix_mac2str(&(n->emac), buf1, sizeof(buf1)), - ipaddr2str(ip, buf2, sizeof(buf2))); - - /* Remove neighbor from BGP. */ - zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, - ZEBRA_MACIP_TYPE_GW, ZEBRA_NEIGH_ACTIVE); - - /* Delete this neighbor entry. */ - zvni_neigh_del(zvni, n); - - /* see if the mac needs to be deleted as well*/ - if (mac) - zvni_deref_ip2mac(zvni, mac); - - return 0; -} - -static void zvni_gw_macip_del_for_vni_hash(struct hash_bucket *bucket, - void *ctxt) -{ - zebra_vni_t *zvni = NULL; - struct zebra_if *zif = NULL; - struct zebra_l2info_vxlan zl2_info; - struct interface *vlan_if = NULL; - struct interface *vrr_if = NULL; - struct interface *ifp; - - /* Add primary SVI MAC*/ - zvni = (zebra_vni_t *)bucket->data; - - /* Global (Zvrf) advertise-default-gw is disabled, - * but zvni advertise-default-gw is enabled - */ - if (zvni->advertise_gw_macip) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip", - zvni->vni); - return; - } - - ifp = zvni->vxlan_if; - if (!ifp) - return; - zif = ifp->info; - - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative(ifp) || !zif->brslave_info.br_if) - return; - - zl2_info = zif->l2info.vxl; - - vlan_if = - zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); - if (!vlan_if) - return; - - /* Del primary MAC-IP */ - zvni_del_macip_for_intf(vlan_if, zvni); - - /* Del VRR MAC-IP - if any*/ - vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); - if (vrr_if) - zvni_del_macip_for_intf(vrr_if, zvni); - - return; -} - -static void zvni_gw_macip_add_for_vni_hash(struct hash_bucket *bucket, - void *ctxt) -{ - zebra_vni_t *zvni = NULL; - struct zebra_if *zif = NULL; - struct zebra_l2info_vxlan zl2_info; - struct interface *vlan_if = NULL; - struct interface *vrr_if = NULL; - struct interface *ifp = NULL; - - zvni = (zebra_vni_t *)bucket->data; - - ifp = zvni->vxlan_if; - if (!ifp) - return; - zif = ifp->info; - - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative(ifp) || !zif->brslave_info.br_if) - return; - zl2_info = zif->l2info.vxl; - - vlan_if = - zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); - if (!vlan_if) - return; - - /* Add primary SVI MAC-IP */ - zvni_add_macip_for_intf(vlan_if, zvni); - - if (advertise_gw_macip_enabled(zvni)) { - /* Add VRR MAC-IP - if any*/ - vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); - if (vrr_if) - zvni_add_macip_for_intf(vrr_if, zvni); - } - - return; -} - -static void zvni_svi_macip_del_for_vni_hash(struct hash_bucket *bucket, - void *ctxt) -{ - zebra_vni_t *zvni = NULL; - struct zebra_if *zif = NULL; - struct zebra_l2info_vxlan zl2_info; - struct interface *vlan_if = NULL; - struct interface *ifp; - - /* Add primary SVI MAC*/ - zvni = (zebra_vni_t *)bucket->data; - if (!zvni) - return; - - /* Global(vrf) advertise-svi-ip disabled, but zvni advertise-svi-ip - * enabled - */ - if (zvni->advertise_svi_macip) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("VNI: %u SVI-MACIP enabled, retain svi-macip", - zvni->vni); - return; - } - - ifp = zvni->vxlan_if; - if (!ifp) - return; - zif = ifp->info; - - /* If down or not mapped to a bridge, we're done. */ - if (!if_is_operative(ifp) || !zif->brslave_info.br_if) - return; - - zl2_info = zif->l2info.vxl; - - vlan_if = zvni_map_to_svi(zl2_info.access_vlan, - zif->brslave_info.br_if); - if (!vlan_if) - return; - - /* Del primary MAC-IP */ - zvni_del_macip_for_intf(vlan_if, zvni); - - return; -} - -static int zvni_local_neigh_update(zebra_vni_t *zvni, - struct interface *ifp, - struct ipaddr *ip, - struct ethaddr *macaddr, - bool is_router) -{ - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - struct zebra_vrf *zvrf; - zebra_neigh_t *n = NULL; - zebra_mac_t *zmac = NULL, *old_zmac = NULL; - uint32_t old_mac_seq = 0, mac_new_seq = 0; - bool upd_mac_seq = false; - bool neigh_mac_change = false; - bool neigh_on_hold = false; - bool neigh_was_remote = false; - bool do_dad = false; - struct in_addr vtep_ip = {.s_addr = 0}; - - /* Check if the MAC exists. */ - zmac = zvni_mac_lookup(zvni, macaddr); - if (!zmac) { - /* create a dummy MAC if the MAC is not already present */ - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "AUTO MAC %s created for neigh %s on VNI %u", - prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni); - - zmac = zvni_mac_add(zvni, macaddr); - if (!zmac) { - zlog_debug("Failed to add MAC %s VNI %u", - prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni); - return -1; - } - - memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info)); - memset(&zmac->flags, 0, sizeof(uint32_t)); - SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO); - } else { - if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) { - /* - * We don't change the MAC to local upon a neighbor - * learn event, we wait for the explicit local MAC - * learn. However, we have to compute its sequence - * number in preparation for when it actually turns - * local. - */ - upd_mac_seq = true; - } - } - - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - if (!zvrf) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug(" Unable to find vrf for: %d", - zvni->vxlan_if->vrf_id); - return -1; - } - - /* Check if the neighbor exists. */ - n = zvni_neigh_lookup(zvni, ip); - if (!n) { - /* New neighbor - create */ - n = zvni_neigh_add(zvni, ip, macaddr); - if (!n) { - flog_err( - EC_ZEBRA_MAC_ADD_FAILED, - "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", - ipaddr2str(ip, buf2, sizeof(buf2)), - prefix_mac2str(macaddr, buf, sizeof(buf)), - ifp->name, ifp->ifindex, zvni->vni); - return -1; - } - /* Set "local" forwarding info. */ - SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); - n->ifindex = ifp->ifindex; - } else { - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - bool mac_different; - bool cur_is_router; - - /* Note any changes and see if of interest to BGP. */ - mac_different = (memcmp(n->emac.octet, - macaddr->octet, ETH_ALEN) != 0) ? 1 : 0; - cur_is_router = !!CHECK_FLAG(n->flags, - ZEBRA_NEIGH_ROUTER_FLAG); - if (!mac_different && is_router == cur_is_router) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - " Ignoring entry mac is the same and is_router == cur_is_router"); - n->ifindex = ifp->ifindex; - return 0; - } - - if (!mac_different) { - bool is_neigh_freezed = false; - - /* Only the router flag has changed. */ - if (is_router) - SET_FLAG(n->flags, - ZEBRA_NEIGH_ROUTER_FLAG); - else - UNSET_FLAG(n->flags, - ZEBRA_NEIGH_ROUTER_FLAG); - - /* Neigh is in freeze state and freeze action - * is enabled, do not send update to client. - */ - is_neigh_freezed = (zvrf->dup_addr_detect && - zvrf->dad_freeze && - CHECK_FLAG(n->flags, - ZEBRA_NEIGH_DUPLICATE)); - - if (IS_ZEBRA_NEIGH_ACTIVE(n) && - !is_neigh_freezed) - return zvni_neigh_send_add_to_client( - zvni->vni, ip, macaddr, - n->flags, n->loc_seq); - else { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - " Neighbor active and frozen"); - } - return 0; - } - - /* The MAC has changed, need to issue a delete - * first as this means a different MACIP route. - * Also, need to do some unlinking/relinking. - * We also need to update the MAC's sequence number - * in different situations. - */ - if (IS_ZEBRA_NEIGH_ACTIVE(n)) - zvni_neigh_send_del_to_client(zvni->vni, &n->ip, - &n->emac, 0, n->state); - old_zmac = zvni_mac_lookup(zvni, &n->emac); - if (old_zmac) { - old_mac_seq = CHECK_FLAG(old_zmac->flags, - ZEBRA_MAC_REMOTE) ? - old_zmac->rem_seq : old_zmac->loc_seq; - neigh_mac_change = upd_mac_seq = true; - listnode_delete(old_zmac->neigh_list, n); - zvni_deref_ip2mac(zvni, old_zmac); - } - - /* Update the forwarding info. */ - n->ifindex = ifp->ifindex; - memcpy(&n->emac, macaddr, ETH_ALEN); - - /* Link to new MAC */ - listnode_add_sort(zmac->neigh_list, n); - } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { - /* - * Neighbor has moved from remote to local. Its - * MAC could have also changed as part of the move. - */ - if (memcmp(n->emac.octet, macaddr->octet, - ETH_ALEN) != 0) { - old_zmac = zvni_mac_lookup(zvni, &n->emac); - if (old_zmac) { - old_mac_seq = CHECK_FLAG( - old_zmac->flags, - ZEBRA_MAC_REMOTE) ? - old_zmac->rem_seq : - old_zmac->loc_seq; - neigh_mac_change = upd_mac_seq = true; - listnode_delete(old_zmac->neigh_list, - n); - zvni_deref_ip2mac(zvni, old_zmac); - } - - /* Link to new MAC */ - memcpy(&n->emac, macaddr, ETH_ALEN); - listnode_add_sort(zmac->neigh_list, n); - } - /* Based on Mobility event Scenario-B from the - * draft, neigh's previous state was remote treat this - * event for DAD. - */ - neigh_was_remote = true; - vtep_ip = n->r_vtep_ip; - /* Mark appropriately */ - UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); - n->r_vtep_ip.s_addr = INADDR_ANY; - SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); - n->ifindex = ifp->ifindex; - } - } - - /* If MAC was previously remote, or the neighbor had a different - * MAC earlier, recompute the sequence number. - */ - if (upd_mac_seq) { - uint32_t seq1, seq2; - - seq1 = CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE) ? - zmac->rem_seq + 1 : zmac->loc_seq; - seq2 = neigh_mac_change ? old_mac_seq + 1 : 0; - mac_new_seq = zmac->loc_seq < MAX(seq1, seq2) ? - MAX(seq1, seq2) : zmac->loc_seq; - } - - /* Mark Router flag (R-bit) */ - if (is_router) - SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - else - UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - - /* Check old and/or new MAC detected as duplicate mark - * the neigh as duplicate - */ - if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf, old_zmac, zmac, n)) { - flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED, - "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC", - zvni->vni, - prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(&n->ip, buf2, sizeof(buf2))); - } - - /* For IP Duplicate Address Detection (DAD) is trigger, - * when the event is extended mobility based on scenario-B - * from the draft, IP/Neigh's MAC binding changed and - * neigh's previous state was remote. - */ - if (neigh_mac_change && neigh_was_remote) - do_dad = true; - - zebra_vxlan_dup_addr_detect_for_neigh(zvrf, n, vtep_ip, do_dad, - &neigh_on_hold, true); - - /* Before we program this in BGP, we need to check if MAC is locally - * learnt. If not, force neighbor to be inactive and reset its seq. - */ - if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) { - ZEBRA_NEIGH_SET_INACTIVE(n); - n->loc_seq = 0; - zmac->loc_seq = mac_new_seq; - return 0; - } - - /* If the MAC's sequence number has changed, inform the MAC and all - * neighbors associated with the MAC to BGP, else just inform this - * neighbor. - */ - if (upd_mac_seq && zmac->loc_seq != mac_new_seq) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Seq changed for MAC %s VNI %u - old %u new %u", - prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni, zmac->loc_seq, mac_new_seq); - zmac->loc_seq = mac_new_seq; - if (zvni_mac_send_add_to_client(zvni->vni, macaddr, - zmac->flags, zmac->loc_seq)) - return -1; - zvni_process_neigh_on_local_mac_change(zvni, zmac, 1); - return 0; - } - - n->loc_seq = zmac->loc_seq; - - if (!neigh_on_hold) { - ZEBRA_NEIGH_SET_ACTIVE(n); - - return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, - n->flags, n->loc_seq); - } else { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug(" Neighbor on hold not sending"); - } - return 0; -} - -static int zvni_remote_neigh_update(zebra_vni_t *zvni, - struct interface *ifp, - struct ipaddr *ip, - struct ethaddr *macaddr, - uint16_t state) -{ - char buf[ETHER_ADDR_STRLEN]; - char buf2[INET6_ADDRSTRLEN]; - zebra_neigh_t *n = NULL; - zebra_mac_t *zmac = NULL; - - /* If the neighbor is unknown, there is no further action. */ - n = zvni_neigh_lookup(zvni, ip); - if (!n) - return 0; - - /* If a remote entry, see if it needs to be refreshed */ - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { -#ifdef GNU_LINUX - if (state & NUD_STALE) - zvni_neigh_install(zvni, n); -#endif - } else { - /* We got a "remote" neighbor notification for an entry - * we think is local. This can happen in a multihoming - * scenario - but only if the MAC is already "remote". - * Just mark our entry as "remote". - */ - zmac = zvni_mac_lookup(zvni, macaddr); - if (!zmac || !CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) { - zlog_debug( - "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local", - ipaddr2str(&n->ip, buf2, sizeof(buf2)), - prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni); - return -1; - } - - UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); - SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); - ZEBRA_NEIGH_SET_ACTIVE(n); - n->r_vtep_ip = zmac->fwd_info.r_vtep_ip; - } - - return 0; -} - -/* - * Make hash key for MAC. - */ -static unsigned int mac_hash_keymake(const void *p) -{ - const zebra_mac_t *pmac = p; - const void *pnt = (void *)pmac->macaddr.octet; - - return jhash(pnt, ETH_ALEN, 0xa5a5a55a); -} - -/* - * Compare two MAC addresses. - */ -static bool mac_cmp(const void *p1, const void *p2) -{ - const zebra_mac_t *pmac1 = p1; - const zebra_mac_t *pmac2 = p2; - - if (pmac1 == NULL && pmac2 == NULL) - return true; - - if (pmac1 == NULL || pmac2 == NULL) - return false; - - return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN) - == 0); -} - -/* - * Callback to allocate MAC hash entry. - */ -static void *zvni_mac_alloc(void *p) -{ - const zebra_mac_t *tmp_mac = p; - zebra_mac_t *mac; - - mac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t)); - *mac = *tmp_mac; - - return ((void *)mac); -} - -/* - * Add MAC entry. - */ -static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr) -{ - zebra_mac_t tmp_mac; - zebra_mac_t *mac = NULL; - - memset(&tmp_mac, 0, sizeof(zebra_mac_t)); - memcpy(&tmp_mac.macaddr, macaddr, ETH_ALEN); - mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc); - assert(mac); - - mac->zvni = zvni; - mac->dad_mac_auto_recovery_timer = NULL; - - mac->neigh_list = list_new(); - mac->neigh_list->cmp = neigh_list_cmp; - - return mac; -} - -/* - * Delete MAC entry. - */ -static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac) -{ - zebra_mac_t *tmp_mac; - - /* Cancel auto recovery */ - THREAD_OFF(mac->dad_mac_auto_recovery_timer); - - list_delete(&mac->neigh_list); - - /* Free the VNI hash entry and allocated memory. */ - tmp_mac = hash_release(zvni->mac_table, mac); - XFREE(MTYPE_MAC, tmp_mac); - - return 0; -} - -static bool zvni_check_mac_del_from_db(struct mac_walk_ctx *wctx, - zebra_mac_t *mac) -{ - if ((wctx->flags & DEL_LOCAL_MAC) && - (mac->flags & ZEBRA_MAC_LOCAL)) - return true; - else if ((wctx->flags & DEL_REMOTE_MAC) && - (mac->flags & ZEBRA_MAC_REMOTE)) - return true; - else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP) && - (mac->flags & ZEBRA_MAC_REMOTE) && - IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip)) - return true; - else if ((wctx->flags & DEL_LOCAL_MAC) && - (mac->flags & ZEBRA_MAC_AUTO) && - !listcount(mac->neigh_list)) { - if (IS_ZEBRA_DEBUG_VXLAN) { - char buf[ETHER_ADDR_STRLEN]; - - zlog_debug( - "%s: Del MAC %s flags 0x%x", __func__, - prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags); - } - wctx->uninstall = 0; - - return true; - } - - return false; -} - -/* - * Free MAC hash entry (callback) - */ -static void zvni_mac_del_hash_entry(struct hash_bucket *bucket, void *arg) -{ - struct mac_walk_ctx *wctx = arg; - zebra_mac_t *mac = bucket->data; - - if (zvni_check_mac_del_from_db(wctx, mac)) { - if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) { - zvni_mac_send_del_to_client(wctx->zvni->vni, - &mac->macaddr); - } - if (wctx->uninstall) - zvni_mac_uninstall(wctx->zvni, mac); - - zvni_mac_del(wctx->zvni, mac); - } - - return; -} - -/* - * Delete all MAC entries for this VNI. - */ -static void zvni_mac_del_all(zebra_vni_t *zvni, int uninstall, int upd_client, - uint32_t flags) -{ - struct mac_walk_ctx wctx; - - if (!zvni->mac_table) - return; - - memset(&wctx, 0, sizeof(struct mac_walk_ctx)); - wctx.zvni = zvni; - wctx.uninstall = uninstall; - wctx.upd_client = upd_client; - wctx.flags = flags; - - hash_iterate(zvni->mac_table, zvni_mac_del_hash_entry, &wctx); -} - -/* - * Look up MAC hash entry. - */ -static zebra_mac_t *zvni_mac_lookup(zebra_vni_t *zvni, struct ethaddr *mac) -{ - zebra_mac_t tmp; - zebra_mac_t *pmac; - - memset(&tmp, 0, sizeof(tmp)); - memcpy(&tmp.macaddr, mac, ETH_ALEN); - pmac = hash_lookup(zvni->mac_table, &tmp); - - return pmac; -} - -/* - * Inform BGP about local MAC addition. - */ -static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, - uint8_t mac_flags, uint32_t seq) -{ - uint8_t flags = 0; - - if (CHECK_FLAG(mac_flags, ZEBRA_MAC_STICKY)) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); - if (CHECK_FLAG(mac_flags, ZEBRA_MAC_DEF_GW)) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - - return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags, - seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD); -} - -/* - * Inform BGP about local MAC deletion. - */ -static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr) -{ - return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */, - 0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL); -} - -struct zvni_from_svi_param { - struct interface *br_if; - struct interface *svi_if; - struct zebra_if *zif; - uint8_t bridge_vlan_aware; - vlanid_t vid; -}; - -static int zvni_map_vlan_ns(struct ns *ns, - void *_in_param, - void **_p_zvni) -{ - struct zebra_ns *zns = ns->info; - struct route_node *rn; - struct interface *br_if; - zebra_vni_t **p_zvni = (zebra_vni_t **)_p_zvni; - zebra_vni_t *zvni; - struct interface *tmp_if = NULL; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl = NULL; - struct zvni_from_svi_param *in_param = - (struct zvni_from_svi_param *)_in_param; - int found = 0; - - if (!in_param) - return NS_WALK_STOP; - br_if = in_param->br_if; - zif = in_param->zif; - assert(zif); - assert(br_if); - - /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ - /* TODO: Optimize with a hash. */ - for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { - tmp_if = (struct interface *)rn->info; - if (!tmp_if) - continue; - zif = tmp_if->info; - if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) - continue; - if (!if_is_operative(tmp_if)) - continue; - vxl = &zif->l2info.vxl; - - if (zif->brslave_info.br_if != br_if) - continue; - - if (!in_param->bridge_vlan_aware - || vxl->access_vlan == in_param->vid) { - found = 1; - break; - } - } - if (!found) - return NS_WALK_CONTINUE; - - zvni = zvni_lookup(vxl->vni); - if (p_zvni) - *p_zvni = zvni; - return NS_WALK_STOP; -} - -/* - * Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC - * notifications, to see if they are of interest. - */ -static zebra_vni_t *zvni_map_vlan(struct interface *ifp, - struct interface *br_if, vlanid_t vid) -{ - struct zebra_if *zif; - struct zebra_l2info_bridge *br; - zebra_vni_t **p_zvni; - zebra_vni_t *zvni = NULL; - struct zvni_from_svi_param in_param; - - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert(zif); - br = &zif->l2info.br; - in_param.bridge_vlan_aware = br->vlan_aware; - in_param.vid = vid; - in_param.br_if = br_if; - in_param.zif = zif; - p_zvni = &zvni; - - ns_walk_func(zvni_map_vlan_ns, - (void *)&in_param, - (void **)p_zvni); - return zvni; -} - -static int zvni_from_svi_ns(struct ns *ns, - void *_in_param, - void **_p_zvni) -{ - struct zebra_ns *zns = ns->info; - struct route_node *rn; - struct interface *br_if; - zebra_vni_t **p_zvni = (zebra_vni_t **)_p_zvni; - zebra_vni_t *zvni; - struct interface *tmp_if = NULL; - struct zebra_if *zif; - struct zebra_l2info_vxlan *vxl = NULL; - struct zvni_from_svi_param *in_param = - (struct zvni_from_svi_param *)_in_param; - int found = 0; - - if (!in_param) - return NS_WALK_STOP; - br_if = in_param->br_if; - zif = in_param->zif; - assert(zif); - - /* TODO: Optimize with a hash. */ - for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { - tmp_if = (struct interface *)rn->info; - if (!tmp_if) - continue; - zif = tmp_if->info; - if (!zif || zif->zif_type != ZEBRA_IF_VXLAN) - continue; - if (!if_is_operative(tmp_if)) - continue; - vxl = &zif->l2info.vxl; - - if (zif->brslave_info.br_if != br_if) - continue; - - if (!in_param->bridge_vlan_aware - || vxl->access_vlan == !in_param->vid) { - found = 1; - break; - } - } - - if (!found) - return NS_WALK_CONTINUE; - - zvni = zvni_lookup(vxl->vni); - if (p_zvni) - *p_zvni = zvni; - return NS_WALK_STOP; -} - -/* - * Map SVI and associated bridge to a VNI. This is invoked upon getting - * neighbor notifications, to see if they are of interest. - */ -static zebra_vni_t *zvni_from_svi(struct interface *ifp, - struct interface *br_if) -{ - struct zebra_l2info_bridge *br; - zebra_vni_t *zvni = NULL; - zebra_vni_t **p_zvni; - struct zebra_if *zif; - struct zvni_from_svi_param in_param; - - if (!br_if) - return NULL; - - /* Make sure the linked interface is a bridge. */ - if (!IS_ZEBRA_IF_BRIDGE(br_if)) - return NULL; - - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert(zif); - br = &zif->l2info.br; - in_param.bridge_vlan_aware = br->vlan_aware; - in_param.vid = 0; - - if (in_param.bridge_vlan_aware) { - struct zebra_l2info_vlan *vl; - - if (!IS_ZEBRA_IF_VLAN(ifp)) - return NULL; - - zif = ifp->info; - assert(zif); - vl = &zif->l2info.vl; - in_param.vid = vl->vid; - } - - in_param.br_if = br_if; - in_param.zif = zif; - p_zvni = &zvni; - /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ - ns_walk_func(zvni_from_svi_ns, - (void *)&in_param, - (void **)p_zvni); - return zvni; -} - -static int zvni_map_to_svi_ns(struct ns *ns, - void *_in_param, - void **_p_ifp) -{ - struct zebra_ns *zns = ns->info; - struct route_node *rn; - struct zvni_from_svi_param *in_param = - (struct zvni_from_svi_param *)_in_param; - struct zebra_l2info_vlan *vl; - struct interface *tmp_if = NULL; - struct interface **p_ifp = (struct interface **)_p_ifp; - struct zebra_if *zif; - - if (!in_param) - return NS_WALK_STOP; - - /* TODO: Optimize with a hash. */ - for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { - tmp_if = (struct interface *)rn->info; - /* Check oper status of the SVI. */ - if (!tmp_if || !if_is_operative(tmp_if)) - continue; - zif = tmp_if->info; - if (!zif || zif->zif_type != ZEBRA_IF_VLAN - || zif->link != in_param->br_if) - continue; - vl = (struct zebra_l2info_vlan *)&zif->l2info.vl; - - if (vl->vid == in_param->vid) { - if (p_ifp) - *p_ifp = tmp_if; - return NS_WALK_STOP; - } - } - return NS_WALK_CONTINUE; -} - /* Map to SVI on bridge corresponding to specified VLAN. This can be one * of two cases: * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface @@ -3765,13 +789,17 @@ static int zvni_map_to_svi_ns(struct ns *ns, * (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface * itself */ -static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if) +struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if) { + struct zebra_ns *zns; + struct route_node *rn; struct interface *tmp_if = NULL; struct zebra_if *zif; struct zebra_l2info_bridge *br; - struct zvni_from_svi_param in_param; - struct interface **p_ifp; + struct zebra_l2info_vlan *vl; + uint8_t bridge_vlan_aware; + int found = 0; + /* Defensive check, caller expected to invoke only with valid bridge. */ if (!br_if) return NULL; @@ -3780,483 +808,59 @@ static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if) zif = br_if->info; assert(zif); br = &zif->l2info.br; - in_param.bridge_vlan_aware = br->vlan_aware; + bridge_vlan_aware = br->vlan_aware; + /* Check oper status of the SVI. */ - if (!in_param.bridge_vlan_aware) + if (!bridge_vlan_aware) return if_is_operative(br_if) ? br_if : NULL; - in_param.vid = vid; - in_param.br_if = br_if; - in_param.zif = NULL; - p_ifp = &tmp_if; - /* Identify corresponding VLAN interface. */ - ns_walk_func(zvni_map_to_svi_ns, - (void *)&in_param, - (void **)p_ifp); - return tmp_if; -} - -static int zvni_map_to_macvlan_ns(struct ns *ns, - void *_in_param, - void **_p_ifp) -{ - struct zebra_ns *zns = ns->info; - struct zvni_from_svi_param *in_param = - (struct zvni_from_svi_param *)_in_param; - struct interface **p_ifp = (struct interface **)_p_ifp; - struct route_node *rn; - struct interface *tmp_if = NULL; - struct zebra_if *zif; - - if (!in_param) - return NS_WALK_STOP; - /* Identify corresponding VLAN interface. */ + /* TODO: Optimize with a hash. */ + zns = zebra_ns_lookup(NS_DEFAULT); for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { tmp_if = (struct interface *)rn->info; /* Check oper status of the SVI. */ if (!tmp_if || !if_is_operative(tmp_if)) continue; zif = tmp_if->info; - - if (!zif || zif->zif_type != ZEBRA_IF_MACVLAN) + if (!zif || zif->zif_type != ZEBRA_IF_VLAN + || zif->link != br_if) continue; + vl = &zif->l2info.vl; - if (zif->link == in_param->svi_if) { - if (p_ifp) - *p_ifp = tmp_if; - return NS_WALK_STOP; + if (vl->vid == vid) { + found = 1; + break; } } - return NS_WALK_CONTINUE; + return found ? tmp_if : NULL; } -/* Map to MAC-VLAN interface corresponding to specified SVI interface. - */ -static struct interface *zvni_map_to_macvlan(struct interface *br_if, - struct interface *svi_if) +static int zebra_evpn_vxlan_del(zebra_evpn_t *zevpn) { - struct interface *tmp_if = NULL; - struct zebra_if *zif; - struct interface **p_ifp; - struct zvni_from_svi_param in_param; - - /* Defensive check, caller expected to invoke only with valid bridge. */ - if (!br_if) - return NULL; - - if (!svi_if) { - zlog_debug("svi_if is not passed."); - return NULL; - } - - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; - assert(zif); - - in_param.vid = 0; - in_param.br_if = br_if; - in_param.zif = NULL; - in_param.svi_if = svi_if; - p_ifp = &tmp_if; - - /* Identify corresponding VLAN interface. */ - ns_walk_func(zvni_map_to_macvlan_ns, - (void *)&in_param, - (void **)p_ifp); - return tmp_if; -} - -/* - * Install remote MAC into the forwarding plane. - */ -static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) -{ - const struct zebra_if *zif, *br_zif; - const struct zebra_l2info_vxlan *vxl; - bool sticky; - enum zebra_dplane_result res; - const struct interface *br_ifp; - vlanid_t vid; - - if (!(mac->flags & ZEBRA_MAC_REMOTE)) - return 0; - - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - - br_ifp = zif->brslave_info.br_if; - if (br_ifp == NULL) - return -1; - - vxl = &zif->l2info.vxl; - - sticky = !!CHECK_FLAG(mac->flags, - (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)); - - br_zif = (const struct zebra_if *)(br_ifp->info); - - if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) - vid = vxl->access_vlan; - else - vid = 0; - - res = dplane_mac_add(zvni->vxlan_if, br_ifp, vid, - &mac->macaddr, mac->fwd_info.r_vtep_ip, sticky); - if (res != ZEBRA_DPLANE_REQUEST_FAILURE) - return 0; - else - return -1; -} - -/* - * Uninstall remote MAC from the forwarding plane. - */ -static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac) -{ - const struct zebra_if *zif, *br_zif; - const struct zebra_l2info_vxlan *vxl; - struct in_addr vtep_ip; - const struct interface *ifp, *br_ifp; - vlanid_t vid; - enum zebra_dplane_result res; - - if (!(mac->flags & ZEBRA_MAC_REMOTE)) - return 0; - - if (!zvni->vxlan_if) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } - - zif = zvni->vxlan_if->info; - if (!zif) - return -1; - - br_ifp = zif->brslave_info.br_if; - if (br_ifp == NULL) - return -1; - - vxl = &zif->l2info.vxl; - - br_zif = (const struct zebra_if *)br_ifp->info; - - if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif)) - vid = vxl->access_vlan; - else - vid = 0; - - ifp = zvni->vxlan_if; - vtep_ip = mac->fwd_info.r_vtep_ip; - - res = dplane_mac_del(ifp, br_ifp, vid, &mac->macaddr, vtep_ip); - if (res != ZEBRA_DPLANE_REQUEST_FAILURE) - return 0; - else - return -1; -} - -/* - * Install MAC hash entry - called upon access VLAN change. - */ -static void zvni_install_mac_hash(struct hash_bucket *bucket, void *ctxt) -{ - zebra_mac_t *mac; - struct mac_walk_ctx *wctx = ctxt; - - mac = (zebra_mac_t *)bucket->data; - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) - zvni_mac_install(wctx->zvni, mac); -} - -/* - * Count of remote neighbors referencing this MAC. - */ -static int remote_neigh_count(zebra_mac_t *zmac) -{ - zebra_neigh_t *n = NULL; - struct listnode *node = NULL; - int count = 0; - - for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) - count++; - } - - return count; -} - -/* - * Decrement neighbor refcount of MAC; uninstall and free it if - * appropriate. - */ -static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac) -{ - if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) - return; - - /* If all remote neighbors referencing a remote MAC go away, - * we need to uninstall the MAC. - */ - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) && - remote_neigh_count(mac) == 0) { - zvni_mac_uninstall(zvni, mac); - UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); - } - - /* If no neighbors, delete the MAC. */ - if (list_isempty(mac->neigh_list)) - zvni_mac_del(zvni, mac); -} - -/* - * Read and populate local MACs and neighbors corresponding to this VNI. - */ -static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp) -{ - struct zebra_ns *zns; - struct zebra_vrf *zvrf; - struct zebra_if *zif; - struct interface *vlan_if; - struct zebra_l2info_vxlan *vxl; - struct interface *vrr_if; - - zif = ifp->info; - vxl = &zif->l2info.vxl; - zvrf = zebra_vrf_lookup_by_id(zvni->vrf_id); - if (!zvrf || !zvrf->zns) - return; - zns = zvrf->zns; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "Reading MAC FDB and Neighbors for intf %s(%u) VNI %u master %u", - ifp->name, ifp->ifindex, zvni->vni, - zif->brslave_info.bridge_ifindex); - - macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if); - vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); - if (vlan_if) { - - /* Add SVI MAC-IP */ - zvni_add_macip_for_intf(vlan_if, zvni); - - /* Add VRR MAC-IP - if any*/ - vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); - if (vrr_if) - zvni_add_macip_for_intf(vrr_if, zvni); - - neigh_read_for_vlan(zns, vlan_if); - } -} - -/* - * Hash function for VNI. - */ -static unsigned int vni_hash_keymake(const void *p) -{ - const zebra_vni_t *zvni = p; - - return (jhash_1word(zvni->vni, 0)); -} - -/* - * Compare 2 VNI hash entries. - */ -static bool vni_hash_cmp(const void *p1, const void *p2) -{ - const zebra_vni_t *zvni1 = p1; - const zebra_vni_t *zvni2 = p2; - - return (zvni1->vni == zvni2->vni); -} - -static int vni_list_cmp(void *p1, void *p2) -{ - const zebra_vni_t *zvni1 = p1; - const zebra_vni_t *zvni2 = p2; - - if (zvni1->vni == zvni2->vni) - return 0; - return (zvni1->vni < zvni2->vni) ? -1 : 1; -} - -/* - * Callback to allocate VNI hash entry. - */ -static void *zvni_alloc(void *p) -{ - const zebra_vni_t *tmp_vni = p; - zebra_vni_t *zvni; - - zvni = XCALLOC(MTYPE_ZVNI, sizeof(zebra_vni_t)); - zvni->vni = tmp_vni->vni; - return ((void *)zvni); -} - -/* - * Look up VNI hash entry. - */ -static zebra_vni_t *zvni_lookup(vni_t vni) -{ - struct zebra_vrf *zvrf; - zebra_vni_t tmp_vni; - zebra_vni_t *zvni = NULL; - - zvrf = zebra_vrf_get_evpn(); - assert(zvrf); - memset(&tmp_vni, 0, sizeof(zebra_vni_t)); - tmp_vni.vni = vni; - zvni = hash_lookup(zvrf->vni_table, &tmp_vni); - - return zvni; -} - -/* - * Add VNI hash entry. - */ -static zebra_vni_t *zvni_add(vni_t vni) -{ - struct zebra_vrf *zvrf; - zebra_vni_t tmp_zvni; - zebra_vni_t *zvni = NULL; - - zvrf = zebra_vrf_get_evpn(); - assert(zvrf); - memset(&tmp_zvni, 0, sizeof(zebra_vni_t)); - tmp_zvni.vni = vni; - zvni = hash_get(zvrf->vni_table, &tmp_zvni, zvni_alloc); - assert(zvni); - - /* Create hash table for MAC */ - zvni->mac_table = - hash_create(mac_hash_keymake, mac_cmp, "Zebra VNI MAC Table"); - - /* Create hash table for neighbors */ - zvni->neigh_table = hash_create(neigh_hash_keymake, neigh_cmp, - "Zebra VNI Neighbor Table"); - - return zvni; -} - -/* - * Delete VNI hash entry. - */ -static int zvni_del(zebra_vni_t *zvni) -{ - struct zebra_vrf *zvrf; - zebra_vni_t *tmp_zvni; - - zvrf = zebra_vrf_get_evpn(); - assert(zvrf); - - zvni->vxlan_if = NULL; + zevpn_vxlan_if_set(zevpn, zevpn->vxlan_if, false /* set */); /* Remove references to the BUM mcast grp */ - zebra_vxlan_sg_deref(zvni->local_vtep_ip, zvni->mcast_grp); - - /* Free the neighbor hash table. */ - hash_free(zvni->neigh_table); - zvni->neigh_table = NULL; - - /* Free the MAC hash table. */ - hash_free(zvni->mac_table); - zvni->mac_table = NULL; - - /* Free the VNI hash entry and allocated memory. */ - tmp_zvni = hash_release(zvrf->vni_table, zvni); - XFREE(MTYPE_ZVNI, tmp_zvni); - - return 0; -} - -/* - * Inform BGP about local VNI addition. - */ -static int zvni_send_add_to_client(zebra_vni_t *zvni) -{ - struct zserv *client; - struct stream *s; - - client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); - /* BGP may not be running. */ - if (!client) - return 0; - - s = stream_new(ZEBRA_MAX_PACKET_SIZ); - - zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id()); - stream_putl(s, zvni->vni); - stream_put_in_addr(s, &zvni->local_vtep_ip); - stream_put(s, &zvni->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */ - stream_put_in_addr(s, &zvni->mcast_grp); + zebra_vxlan_sg_deref(zevpn->local_vtep_ip, zevpn->mcast_grp); - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Send VNI_ADD %u %s tenant vrf %s to %s", zvni->vni, - inet_ntoa(zvni->local_vtep_ip), - vrf_id_to_name(zvni->vrf_id), - zebra_route_string(client->proto)); - - client->vniadd_cnt++; - return zserv_send_message(client, s); + return zebra_evpn_del(zevpn); } - /* - * Inform BGP about local VNI deletion. + * Build the VNI hash table by going over the VxLAN interfaces. This + * is called when EVPN (advertise-all-vni) is enabled. */ -static int zvni_send_del_to_client(vni_t vni) -{ - struct zserv *client; - struct stream *s; - - client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); - /* BGP may not be running. */ - if (!client) - return 0; - - s = stream_new(ZEBRA_MAX_PACKET_SIZ); - stream_reset(s); - - zclient_create_header(s, ZEBRA_VNI_DEL, zebra_vrf_get_evpn_id()); - stream_putl(s, vni); - - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Send VNI_DEL %u to %s", vni, - zebra_route_string(client->proto)); - - client->vnidel_cnt++; - return zserv_send_message(client, s); -} - -static int zvni_build_hash_table_ns(struct ns *ns, - void *param_in __attribute__((unused)), - void **param_out __attribute__((unused))) +static void zevpn_build_hash_table(void) { - struct zebra_ns *zns = ns->info; + struct zebra_ns *zns; struct route_node *rn; struct interface *ifp; - struct zebra_vrf *zvrf; - - zvrf = zebra_vrf_get_evpn(); - if (!zvrf) - return NS_WALK_STOP; - - /* Walk VxLAN interfaces and create VNI hash. */ + /* Walk VxLAN interfaces and create EVPN hash. */ + zns = zebra_ns_lookup(NS_DEFAULT); for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { vni_t vni; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; struct zebra_if *zif; struct zebra_l2info_vxlan *vxl; @@ -4270,15 +874,7 @@ static int zvni_build_hash_table_ns(struct ns *ns, vxl = &zif->l2info.vxl; vni = vxl->vni; - /* link of VXLAN interface should be in zebra_evpn_vrf */ - if (zvrf->zns->ns_id != vxl->link_nsid) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "Intf %s(%u) VNI %u, link not in same " - "namespace than BGP EVPN core instance ", - ifp->name, ifp->ifindex, vni); - continue; - } + /* L3-VNI and L2-VNI are handled seperately */ zl3vni = zl3vni_lookup(vni); if (zl3vni) { @@ -4321,11 +917,11 @@ static int zvni_build_hash_table_ns(struct ns *ns, ifp->name, ifp->ifindex, vni, inet_ntoa(vxl->vtep_ip)); - /* VNI hash entry is expected to exist, if the BGP process is killed */ - zvni = zvni_lookup(vni); - if (zvni) { + /* EVPN hash entry is expected to exist, if the BGP process is killed */ + zevpn = zebra_evpn_lookup(vni); + if (zevpn) { zlog_debug( - "VNI hash already present for IF %s(%u) L2-VNI %u", + "EVPN hash already present for IF %s(%u) L2-VNI %u", ifp->name, ifp->ifindex, vni); /* @@ -4334,44 +930,49 @@ static int zvni_build_hash_table_ns(struct ns *ns, */ if (if_is_operative(ifp) && zif->brslave_info.br_if) - zvni_send_add_to_client(zvni); + zebra_evpn_send_add_to_client(zevpn); /* Send Local MAC-entries to client */ - zvni_send_mac_to_client(zvni); + zebra_evpn_send_mac_list_to_client(zevpn); /* Send Loval Neighbor entries to client */ - zvni_send_neigh_to_client(zvni); + zebra_evpn_send_neigh_to_client(zevpn); } else { - zvni = zvni_add(vni); - if (!zvni) { + zevpn = zebra_evpn_add(vni); + if (!zevpn) { zlog_debug( - "Failed to add VNI hash, IF %s(%u) L2-VNI %u", + "Failed to add EVPN hash, IF %s(%u) L2-VNI %u", ifp->name, ifp->ifindex, vni); - return NS_WALK_CONTINUE; + return; } - if (zvni->local_vtep_ip.s_addr != + if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr || - zvni->mcast_grp.s_addr != + zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) { zebra_vxlan_sg_deref( - zvni->local_vtep_ip, - zvni->mcast_grp); + zevpn->local_vtep_ip, + zevpn->mcast_grp); zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp); - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->mcast_grp = vxl->mcast_grp; + zevpn->local_vtep_ip = vxl->vtep_ip; + zevpn->mcast_grp = vxl->mcast_grp; + /* on local vtep-ip check if ES + * orig-ip needs to be updated + */ + zebra_evpn_es_set_base_evpn(zevpn); } - zvni->vxlan_if = ifp; - vlan_if = zvni_map_to_svi(vxl->access_vlan, - zif->brslave_info.br_if); + zevpn_vxlan_if_set(zevpn, ifp, true /* set */); + vlan_if = zvni_map_to_svi( + vxl->access_vlan, + zif->brslave_info.br_if); if (vlan_if) { - zvni->vrf_id = vlan_if->vrf_id; + zevpn->vrf_id = vlan_if->vrf_id; zl3vni = zl3vni_from_vrf( vlan_if->vrf_id); if (zl3vni) listnode_add_sort( - zl3vni->l2vnis, zvni); + zl3vni->l2vnis, zevpn); } /* @@ -4380,195 +981,30 @@ static int zvni_build_hash_table_ns(struct ns *ns, */ if (if_is_operative(ifp) && zif->brslave_info.br_if) - zvni_send_add_to_client(zvni); + zebra_evpn_send_add_to_client(zevpn); } } } - return NS_WALK_CONTINUE; -} - -/* - * Build the VNI hash table by going over the VxLAN interfaces. This - * is called when EVPN (advertise-all-vni) is enabled. - */ - -static void zvni_build_hash_table(void) -{ - ns_walk_func(zvni_build_hash_table_ns, - (void *)NULL, - (void **)NULL); -} - -/* - * See if remote VTEP matches with prefix. - */ -static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep) -{ - return (IPV4_ADDR_SAME(vtep_ip, &zvtep->vtep_ip)); -} - -/* - * Locate remote VTEP in VNI hash table. - */ -static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip) -{ - zebra_vtep_t *zvtep; - - if (!zvni) - return NULL; - - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) { - if (zvni_vtep_match(vtep_ip, zvtep)) - break; - } - - return zvtep; -} - -/* - * Add remote VTEP to VNI hash table. - */ -static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip, - int flood_control) - -{ - zebra_vtep_t *zvtep; - - zvtep = XCALLOC(MTYPE_ZVNI_VTEP, sizeof(zebra_vtep_t)); - - zvtep->vtep_ip = *vtep_ip; - zvtep->flood_control = flood_control; - - if (zvni->vteps) - zvni->vteps->prev = zvtep; - zvtep->next = zvni->vteps; - zvni->vteps = zvtep; - - return zvtep; -} - -/* - * Remove remote VTEP from VNI hash table. - */ -static int zvni_vtep_del(zebra_vni_t *zvni, zebra_vtep_t *zvtep) -{ - if (zvtep->next) - zvtep->next->prev = zvtep->prev; - if (zvtep->prev) - zvtep->prev->next = zvtep->next; - else - zvni->vteps = zvtep->next; - - zvtep->prev = zvtep->next = NULL; - XFREE(MTYPE_ZVNI_VTEP, zvtep); - - return 0; -} - -/* - * Delete all remote VTEPs for this VNI (upon VNI delete). Also - * uninstall from kernel if asked to. - */ -static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall) -{ - zebra_vtep_t *zvtep, *zvtep_next; - - if (!zvni) - return -1; - - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep_next) { - zvtep_next = zvtep->next; - if (uninstall) - zvni_vtep_uninstall(zvni, &zvtep->vtep_ip); - zvni_vtep_del(zvni, zvtep); - } - - return 0; -} - -/* - * Install remote VTEP into the kernel if the remote VTEP has asked - * for head-end-replication. - */ -static int zvni_vtep_install(zebra_vni_t *zvni, zebra_vtep_t *zvtep) -{ - if (is_vxlan_flooding_head_end() && - (zvtep->flood_control == VXLAN_FLOOD_HEAD_END_REPL)) { - if (ZEBRA_DPLANE_REQUEST_FAILURE == - dplane_vtep_add(zvni->vxlan_if, - &zvtep->vtep_ip, zvni->vni)) - return -1; - } - - return 0; -} - -/* - * Uninstall remote VTEP from the kernel. - */ -static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip) -{ - if (!zvni->vxlan_if) { - zlog_debug("VNI %u hash %p couldn't be uninstalled - no intf", - zvni->vni, zvni); - return -1; - } - - if (ZEBRA_DPLANE_REQUEST_FAILURE == - dplane_vtep_delete(zvni->vxlan_if, vtep_ip, zvni->vni)) - return -1; - - return 0; -} - -/* - * Install or uninstall flood entries in the kernel corresponding to - * remote VTEPs. This is invoked upon change to BUM handling. - */ -static void zvni_handle_flooding_remote_vteps(struct hash_bucket *bucket, - void *zvrf) -{ - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - - zvni = (zebra_vni_t *)bucket->data; - if (!zvni) - return; - - for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) { - if (is_vxlan_flooding_head_end()) - zvni_vtep_install(zvni, zvtep); - else - zvni_vtep_uninstall(zvni, &zvtep->vtep_ip); - } } /* - * Cleanup VNI/VTEP and update kernel + * Cleanup EVPN/VTEP and update kernel */ -static void zvni_cleanup_all(struct hash_bucket *bucket, void *arg) +static void zebra_evpn_vxlan_cleanup_all(struct hash_bucket *bucket, void *arg) { - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; struct zebra_vrf *zvrf = (struct zebra_vrf *)arg; - zvni = (zebra_vni_t *)bucket->data; + zevpn = (zebra_evpn_t *)bucket->data; /* remove from l3-vni list */ if (zvrf->l3vni) zl3vni = zl3vni_lookup(zvrf->l3vni); if (zl3vni) - listnode_delete(zl3vni->l2vnis, zvni); - - /* Free up all neighbors and MACs, if any. */ - zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC); + listnode_delete(zl3vni->l2vnis, zevpn); - /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all(zvni, 1); - - /* Delete the hash entry. */ - zvni_del(zvni); + zebra_evpn_cleanup_all(bucket, arg); } /* cleanup L3VNI */ @@ -4641,7 +1077,7 @@ static void *zl3vni_rmac_alloc(void *p) const zebra_mac_t *tmp_rmac = p; zebra_mac_t *zrmac; - zrmac = XCALLOC(MTYPE_MAC, sizeof(zebra_mac_t)); + zrmac = XCALLOC(MTYPE_L3VNI_MAC, sizeof(zebra_mac_t)); *zrmac = *tmp_rmac; return ((void *)zrmac); @@ -4685,7 +1121,7 @@ static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) } tmp_rmac = hash_release(zl3vni->rmac_table, zrmac); - XFREE(MTYPE_MAC, tmp_rmac); + XFREE(MTYPE_L3VNI_MAC, tmp_rmac); return 0; } @@ -4722,8 +1158,9 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) else vid = 0; - res = dplane_mac_add(zl3vni->vxlan_if, br_ifp, vid, - &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0); + res = dplane_rem_mac_add(zl3vni->vxlan_if, br_ifp, vid, + &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0, 0, + false /*was_static*/); if (res != ZEBRA_DPLANE_REQUEST_FAILURE) return 0; else @@ -4772,7 +1209,7 @@ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) else vid = 0; - res = dplane_mac_del(zl3vni->vxlan_if, br_ifp, vid, + res = dplane_rem_mac_del(zl3vni->vxlan_if, br_ifp, vid, &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip); if (res != ZEBRA_DPLANE_REQUEST_FAILURE) return 0; @@ -4881,7 +1318,7 @@ static void *zl3vni_nh_alloc(void *p) const zebra_neigh_t *tmp_n = p; zebra_neigh_t *n; - n = XCALLOC(MTYPE_NEIGH, sizeof(zebra_neigh_t)); + n = XCALLOC(MTYPE_L3NEIGH, sizeof(zebra_neigh_t)); *n = *tmp_n; return ((void *)n); @@ -4927,7 +1364,7 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) } tmp_n = hash_release(zl3vni->nh_table, n); - XFREE(MTYPE_NEIGH, tmp_n); + XFREE(MTYPE_L3NEIGH, tmp_n); return 0; } @@ -4951,7 +1388,8 @@ static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) flags |= DPLANE_NTF_ROUTER; - dplane_neigh_add(zl3vni->svi_if, &n->ip, &n->emac, flags); + dplane_rem_neigh_add(zl3vni->svi_if, &n->ip, &n->emac, flags, + false /*was_static*/); return ret; } @@ -4968,7 +1406,7 @@ static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if)) return 0; - dplane_neigh_delete(zl3vni->svi_if, &n->ip); + dplane_rem_neigh_delete(zl3vni->svi_if, &n->ip); return 0; } @@ -5112,7 +1550,7 @@ static void *zl3vni_alloc(void *p) /* * Look up L3 VNI hash entry. */ -static zebra_l3vni_t *zl3vni_lookup(vni_t vni) +zebra_l3vni_t *zl3vni_lookup(vni_t vni) { zebra_l3vni_t tmp_l3vni; zebra_l3vni_t *zl3vni = NULL; @@ -5142,15 +1580,13 @@ static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id) zl3vni->svi_if = NULL; zl3vni->vxlan_if = NULL; zl3vni->l2vnis = list_new(); - zl3vni->l2vnis->cmp = vni_list_cmp; + zl3vni->l2vnis->cmp = zebra_evpn_list_cmp; /* Create hash table for remote RMAC */ - zl3vni->rmac_table = hash_create(mac_hash_keymake, mac_cmp, - "Zebra L3-VNI RMAC-Table"); + zl3vni->rmac_table = zebra_mac_db_create("Zebra L3-VNI RMAC-Table"); /* Create hash table for neighbors */ - zl3vni->nh_table = hash_create(neigh_hash_keymake, neigh_cmp, - "Zebra L3-VNI next-hop table"); + zl3vni->nh_table = zebra_neigh_db_create("Zebra L3-VNI next-hop table"); return zl3vni; } @@ -5181,22 +1617,14 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni) return 0; } -static int zl3vni_map_to_vxlan_if_ns(struct ns *ns, - void *_zl3vni, - void **_pifp) +struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni) { - struct zebra_ns *zns = ns->info; - zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)_zl3vni; + struct zebra_ns *zns = NULL; struct route_node *rn = NULL; struct interface *ifp = NULL; - struct zebra_vrf *zvrf; - - zvrf = zebra_vrf_get_evpn(); - - if (!zvrf) - return NS_WALK_STOP; /* loop through all vxlan-interface */ + zns = zebra_ns_lookup(NS_DEFAULT); for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { struct zebra_if *zif = NULL; @@ -5211,39 +1639,13 @@ static int zl3vni_map_to_vxlan_if_ns(struct ns *ns, continue; vxl = &zif->l2info.vxl; - if (vxl->vni != zl3vni->vni) - continue; - - /* link of VXLAN interface should be in zebra_evpn_vrf */ - if (zvrf->zns->ns_id != vxl->link_nsid) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "Intf %s(%u) VNI %u, link not in same " - "namespace than BGP EVPN core instance ", - ifp->name, ifp->ifindex, vxl->vni); - continue; + if (vxl->vni == zl3vni->vni) { + zl3vni->local_vtep_ip = vxl->vtep_ip; + return ifp; } - - - zl3vni->local_vtep_ip = vxl->vtep_ip; - if (_pifp) - *_pifp = (void *)ifp; - return NS_WALK_STOP; } - return NS_WALK_CONTINUE; -} - -struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni) -{ - struct interface **p_ifp; - struct interface *ifp = NULL; - - p_ifp = &ifp; - - ns_walk_func(zl3vni_map_to_vxlan_if_ns, - (void *)zl3vni, (void **)p_ifp); - return ifp; + return NULL; } struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni) @@ -5280,7 +1682,8 @@ struct interface *zl3vni_map_to_mac_vlan_if(zebra_l3vni_t *zl3vni) if (!zif) return NULL; - return zvni_map_to_macvlan(zif->brslave_info.br_if, zl3vni->svi_if); + return zebra_evpn_map_to_macvlan(zif->brslave_info.br_if, + zl3vni->svi_if); } @@ -5493,13 +1896,13 @@ static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni) zl3vni_send_del_to_client(zl3vni); } -static void zvni_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt) +static void zevpn_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt) { - zebra_vni_t *zvni = (zebra_vni_t *)bucket->data; + zebra_evpn_t *zevpn = (zebra_evpn_t *)bucket->data; zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)ctxt; - if (zvni->vrf_id == zl3vni_vrf_id(zl3vni)) - listnode_add_sort(zl3vni->l2vnis, zvni); + if (zevpn->vrf_id == zl3vni_vrf_id(zl3vni)) + listnode_add_sort(zl3vni->l2vnis, zevpn); } /* @@ -5508,7 +1911,7 @@ static void zvni_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt) static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni, int add) { - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; /* There is a possibility that VNI notification was already received * from kernel and we programmed it as L2-VNI @@ -5520,28 +1923,27 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni, */ if (add) { /* Locate hash entry */ - zvni = zvni_lookup(vni); - if (!zvni) + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) return 0; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("Del L2-VNI %u - transition to L3-VNI", vni); - /* Delete VNI from BGP. */ - zvni_send_del_to_client(zvni->vni); + /* Delete EVPN from BGP. */ + zebra_evpn_send_del_to_client(zevpn); - /* Free up all neighbors and MAC, if any. */ - zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH); - zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC); + zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH); + zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC); /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all(zvni, 0); + zebra_evpn_vtep_del_all(zevpn, 0); /* Delete the hash entry. */ - if (zvni_del(zvni)) { + if (zebra_evpn_vxlan_del(zevpn)) { flog_err(EC_ZEBRA_VNI_DEL_FAILED, - "Failed to del VNI hash %p, VNI %u", zvni, - zvni->vni); + "Failed to del EVPN hash %p, VNI %u", zevpn, + zevpn->vni); return -1; } } else { @@ -5583,40 +1985,6 @@ static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx) zl3vni_nh_del(zl3vni, n); } -static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, - uint16_t cmd) -{ - struct zserv *client = NULL; - struct stream *s = NULL; - char buf[PREFIX_STRLEN]; - - client = zserv_find_client(ZEBRA_ROUTE_BGP, 0); - /* BGP may not be running. */ - if (!client) - return 0; - - s = stream_new(ZEBRA_MAX_PACKET_SIZ); - - zclient_create_header(s, cmd, vrf_id); - stream_put(s, p, sizeof(struct prefix)); - - /* Write packet size. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Send ip prefix %s %s on vrf %s", - prefix2str(p, buf, sizeof(buf)), - (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) ? "ADD" : "DEL", - vrf_id_to_name(vrf_id)); - - if (cmd == ZEBRA_IP_PREFIX_ROUTE_ADD) - client->prefixadd_cnt++; - else - client->prefixdel_cnt++; - - return zserv_send_message(client, s); -} - /* re-add remote rmac if needed */ static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni, struct ethaddr *rmac) @@ -5636,503 +2004,6 @@ static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni, return 0; } -/* Process a remote MACIP add from BGP. */ -static void process_remote_macip_add(vni_t vni, - struct ethaddr *macaddr, - uint16_t ipa_len, - struct ipaddr *ipaddr, - uint8_t flags, - uint32_t seq, - struct in_addr vtep_ip) -{ - zebra_vni_t *zvni; - zebra_vtep_t *zvtep; - zebra_mac_t *mac = NULL, *old_mac = NULL; - zebra_neigh_t *n = NULL; - int update_mac = 0, update_neigh = 0; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - struct interface *ifp = NULL; - struct zebra_if *zif = NULL; - struct zebra_vrf *zvrf; - uint32_t tmp_seq; - bool sticky; - bool remote_gw; - bool is_router; - bool do_dad = false; - bool is_dup_detect = false; - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { - zlog_warn("Unknown VNI %u upon remote MACIP ADD", vni); - return; - } - - ifp = zvni->vxlan_if; - if (ifp) - zif = ifp->info; - if (!ifp || - !if_is_operative(ifp) || - !zif || - !zif->brslave_info.br_if) { - zlog_warn("Ignoring remote MACIP ADD VNI %u, invalid interface state or info", - vni); - return; - } - - /* The remote VTEP specified should normally exist, but it is - * possible that when peering comes up, peer may advertise MACIP - * routes before advertising type-3 routes. - */ - zvtep = zvni_vtep_find(zvni, &vtep_ip); - if (!zvtep) { - zvtep = zvni_vtep_add(zvni, &vtep_ip, VXLAN_FLOOD_DISABLED); - if (!zvtep) { - flog_err( - EC_ZEBRA_VTEP_ADD_FAILED, - "Failed to add remote VTEP, VNI %u zvni %p upon remote MACIP ADD", - vni, zvni); - return; - } - - zvni_vtep_install(zvni, zvtep); - } - - sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); - remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); - - mac = zvni_mac_lookup(zvni, macaddr); - - /* Ignore if the mac is already present as a gateway mac */ - if (mac && - CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) && - CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC", - vni, - prefix_mac2str(macaddr, buf, sizeof(buf)), - ipa_len ? " IP " : "", - ipa_len ? - ipaddr2str(ipaddr, buf1, sizeof(buf1)) : ""); - return; - } - - zvrf = zebra_vrf_get_evpn(); - if (!zvrf) - return; - - /* check if the remote MAC is unknown or has a change. - * If so, that needs to be updated first. Note that client could - * install MAC and MACIP separately or just install the latter. - */ - if (!mac - || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) - || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) - || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) - || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip) - || seq != mac->rem_seq) - update_mac = 1; - - if (update_mac) { - if (!mac) { - mac = zvni_mac_add(zvni, macaddr); - if (!mac) { - zlog_warn( - "Failed to add MAC %s VNI %u Remote VTEP %s", - prefix_mac2str(macaddr, buf, - sizeof(buf)), - vni, inet_ntoa(vtep_ip)); - return; - } - - /* Is this MAC created for a MACIP? */ - if (ipa_len) - SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - } else { - /* When host moves but changes its (MAC,IP) - * binding, BGP may install a MACIP entry that - * corresponds to "older" location of the host - * in transient situations (because {IP1,M1} - * is a different route from {IP1,M2}). Check - * the sequence number and ignore this update - * if appropriate. - */ - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) - tmp_seq = mac->loc_seq; - else - tmp_seq = mac->rem_seq; - - if (seq < tmp_seq) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing MAC has higher seq %u flags 0x%x", - vni, - prefix_mac2str(macaddr, - buf, sizeof(buf)), - ipa_len ? " IP " : "", - ipa_len ? - ipaddr2str(ipaddr, - buf1, sizeof(buf1)) : "", - tmp_seq, mac->flags); - return; - } - } - - /* Check MAC's curent state is local (this is the case - * where MAC has moved from L->R) and check previous - * detection started via local learning. - * RFC-7432: A PE/VTEP that detects a MAC mobility - * event via local learning starts an M-second timer. - * - * VTEP-IP or seq. change alone is not considered - * for dup. detection. - * - * MAC is already marked duplicate set dad, then - * is_dup_detect will be set to not install the entry. - */ - if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) && - mac->dad_count) || - CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - do_dad = true; - - /* Remove local MAC from BGP. */ - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) - zvni_mac_send_del_to_client(zvni->vni, macaddr); - - /* Set "auto" and "remote" forwarding info. */ - UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); - memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); - SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); - mac->fwd_info.r_vtep_ip = vtep_ip; - - if (sticky) - SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - else - UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - - if (remote_gw) - SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); - else - UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); - - zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac, - mac->fwd_info.r_vtep_ip, - do_dad, &is_dup_detect, - false); - - if (!is_dup_detect) { - zvni_process_neigh_on_remote_mac_add(zvni, mac); - /* Install the entry. */ - zvni_mac_install(zvni, mac); - } - } - - /* Update seq number. */ - mac->rem_seq = seq; - - /* If there is no IP, return after clearing AUTO flag of MAC. */ - if (!ipa_len) { - UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - return; - } - - /* Reset flag */ - do_dad = false; - - /* Check if the remote neighbor itself is unknown or has a - * change. If so, create or update and then install the entry. - */ - n = zvni_neigh_lookup(zvni, ipaddr); - if (!n - || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) - || is_router != !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) - || (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) - || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip) - || seq != n->rem_seq) - update_neigh = 1; - - if (update_neigh) { - if (!n) { - n = zvni_neigh_add(zvni, ipaddr, macaddr); - if (!n) { - zlog_warn( - "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", - ipaddr2str(ipaddr, buf1, - sizeof(buf1)), - prefix_mac2str(macaddr, buf, - sizeof(buf)), - vni, inet_ntoa(vtep_ip)); - return; - } - - } else { - const char *n_type; - - /* When host moves but changes its (MAC,IP) - * binding, BGP may install a MACIP entry that - * corresponds to "older" location of the host - * in transient situations (because {IP1,M1} - * is a different route from {IP1,M2}). Check - * the sequence number and ignore this update - * if appropriate. - */ - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - tmp_seq = n->loc_seq; - n_type = "local"; - } else { - tmp_seq = n->rem_seq; - n_type = "remote"; - } - if (seq < tmp_seq) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u", - vni, - prefix_mac2str(macaddr, - buf, sizeof(buf)), - " IP ", - ipaddr2str(ipaddr, buf1, sizeof(buf1)), - n_type, - tmp_seq); - return; - } - if (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) { - /* MAC change, send a delete for old - * neigh if learnt locally. - */ - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL) && - IS_ZEBRA_NEIGH_ACTIVE(n)) - zvni_neigh_send_del_to_client( - zvni->vni, &n->ip, - &n->emac, 0, n->state); - - /* update neigh list for macs */ - old_mac = zvni_mac_lookup(zvni, &n->emac); - if (old_mac) { - listnode_delete(old_mac->neigh_list, n); - zvni_deref_ip2mac(zvni, old_mac); - } - listnode_add_sort(mac->neigh_list, n); - memcpy(&n->emac, macaddr, ETH_ALEN); - - /* Check Neigh's curent state is local - * (this is the case where neigh/host has moved - * from L->R) and check previous detction - * started via local learning. - * - * RFC-7432: A PE/VTEP that detects a MAC - * mobilit event via local learning starts - * an M-second timer. - * VTEP-IP or seq. change along is not - * considered for dup. detection. - * - * Mobilty event scenario-B IP-MAC binding - * changed. - */ - if ((!CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) - && n->dad_count) - do_dad = true; - - } - } - - /* Set "remote" forwarding info. */ - UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); - n->r_vtep_ip = vtep_ip; - SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); - - /* Set router flag (R-bit) to this Neighbor entry */ - if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) - SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - else - UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - - /* Check old or new MAC detected as duplicate, - * inherit duplicate flag to this neigh. - */ - if (zebra_vxlan_ip_inherit_dad_from_mac(zvrf, old_mac, - mac, n)) { - flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED, - "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC", - zvni->vni, - prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - ipaddr2str(&n->ip, buf1, sizeof(buf1))); - } - - /* Check duplicate address detection for IP */ - zebra_vxlan_dup_addr_detect_for_neigh(zvrf, n, - n->r_vtep_ip, - do_dad, - &is_dup_detect, - false); - /* Install the entry. */ - if (!is_dup_detect) - zvni_neigh_install(zvni, n); - } - - zvni_probe_neigh_on_mac_add(zvni, mac); - - /* Update seq number. */ - n->rem_seq = seq; -} - -/* Process a remote MACIP delete from BGP. */ -static void process_remote_macip_del(vni_t vni, - struct ethaddr *macaddr, - uint16_t ipa_len, - struct ipaddr *ipaddr, - struct in_addr vtep_ip) -{ - zebra_vni_t *zvni; - zebra_mac_t *mac = NULL; - zebra_neigh_t *n = NULL; - struct interface *ifp = NULL; - struct zebra_if *zif = NULL; - struct zebra_ns *zns; - struct zebra_l2info_vxlan *vxl; - struct zebra_vrf *zvrf; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; - - /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Unknown VNI %u upon remote MACIP DEL", vni); - return; - } - - ifp = zvni->vxlan_if; - if (ifp) - zif = ifp->info; - if (!ifp || - !if_is_operative(ifp) || - !zif || - !zif->brslave_info.br_if) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("Ignoring remote MACIP DEL VNI %u, invalid interface state or info", - vni); - return; - } - zns = zebra_ns_lookup(NS_DEFAULT); - vxl = &zif->l2info.vxl; - - /* It is possible remote vtep del request is processed prior to - * remote macip route delete. remote_vtep_del does not clean up - * the macip route delete. Explicite withdraw of the macip route - * is expected to recieve. This handler removes the remote route. - */ - mac = zvni_mac_lookup(zvni, macaddr); - if (ipa_len) - n = zvni_neigh_lookup(zvni, ipaddr); - - if (n && !mac) { - zlog_warn("Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL", - prefix_mac2str(macaddr, buf, sizeof(buf)), - ipaddr2str(ipaddr, buf1, sizeof(buf1)), vni); - return; - } - - /* If the remote mac or neighbor doesn't exist there is nothing - * more to do. Otherwise, uninstall the entry and then remove it. - */ - if (!mac && !n) - return; - - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - - /* Ignore the delete if this mac is a gateway mac-ip */ - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) - && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) { - zlog_warn( - "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC", - vni, - prefix_mac2str(macaddr, buf, sizeof(buf)), - ipa_len ? " IP " : "", - ipa_len ? - ipaddr2str(ipaddr, buf1, sizeof(buf1)) : ""); - return; - } - - /* Uninstall remote neighbor or MAC. */ - if (n) { - if (zvrf->dad_freeze && - CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE) && - CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) && - (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) { - struct interface *vlan_if; - - vlan_if = zvni_map_to_svi(vxl->access_vlan, - zif->brslave_info.br_if); - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry", - __func__, - ipaddr2str(ipaddr, buf1, sizeof(buf1)), - n->flags, - vlan_if ? vlan_if->name : "Unknown"); - if (vlan_if) - neigh_read_specific_ip(ipaddr, vlan_if); - } - - /* When the MAC changes for an IP, it is possible the - * client may update the new MAC before trying to delete the - * "old" neighbor (as these are two different MACIP routes). - * Do the delete only if the MAC matches. - */ - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) - && (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) { - zvni_neigh_uninstall(zvni, n); - zvni_neigh_del(zvni, n); - zvni_deref_ip2mac(zvni, mac); - } - } else { - /* DAD: when MAC is freeze state as remote learn event, - * remote mac-ip delete event is received will result in freeze - * entry removal, first fetch kernel for the same entry present - * as LOCAL and reachable, avoid deleting this entry instead - * use kerenel local entry to update during unfreeze time. - */ - if (zvrf->dad_freeze && - CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) && - CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry", - __func__, - prefix_mac2str(macaddr, buf, - sizeof(buf)), - mac->flags); - macfdb_read_specific_mac(zns, zif->brslave_info.br_if, - macaddr, vxl->access_vlan); - } - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - zvni_process_neigh_on_remote_mac_del(zvni, mac); - /* - * the remote sequence number in the auto mac entry - * needs to be reset to 0 as the mac entry may have - * been removed on all VTEPs (including - * the originating one) - */ - mac->rem_seq = 0; - - /* If all remote neighbors referencing a remote MAC - * go away, we need to uninstall the MAC. - */ - if (remote_neigh_count(mac) == 0) { - zvni_mac_uninstall(zvni, mac); - UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); - } - if (list_isempty(mac->neigh_list)) - zvni_mac_del(zvni, mac); - else - SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - } - } -} - - /* Public functions */ int is_l3vni_for_prefix_routes_only(vni_t vni) @@ -6526,22 +2397,22 @@ void zebra_vxlan_print_vrf_vni(struct vty *vty, struct zebra_vrf *zvrf, void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, bool use_json) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; uint32_t num_neigh; struct neigh_walk_ctx wctx; json_object *json = NULL; if (!is_evpn_enabled()) return; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { if (use_json) vty_out(vty, "{}\n"); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - num_neigh = hashcount(zvni->neigh_table); + num_neigh = hashcount(zevpn->neigh_table); if (!num_neigh) return; @@ -6553,22 +2424,22 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, * the maximum width. */ memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); - wctx.zvni = zvni; + wctx.zevpn = zevpn; wctx.vty = vty; wctx.addr_width = 15; wctx.json = json; - hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); + hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width, + &wctx); if (!use_json) { vty_out(vty, "Number of ARPs (local and remote) known for this VNI: %u\n", num_neigh); - vty_out(vty, "%*s %-6s %-8s %-17s %-21s %s\n", -wctx.addr_width, - "IP", "Type", "State", "MAC", "Remote VTEP", "Seq #'s"); + zebra_evpn_print_neigh_hdr(vty, &wctx); } else json_object_int_add(json, "numArpNd", num_neigh); - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); + hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( json, JSON_C_TO_STRING_PRETTY)); @@ -6595,9 +2466,9 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf, args[1] = json; args[2] = (void *)(ptrdiff_t)print_dup; - hash_iterate(zvrf->vni_table, + hash_iterate(zvrf->evpn_table, (void (*)(struct hash_bucket *, - void *))zvni_print_neigh_hash_all_vni, + void *))zevpn_print_neigh_hash_all_evpn, args); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -6626,9 +2497,9 @@ void zebra_vxlan_print_neigh_all_vni_detail(struct vty *vty, args[1] = json; args[2] = (void *)(ptrdiff_t)print_dup; - hash_iterate(zvrf->vni_table, + hash_iterate(zvrf->evpn_table, (void (*)(struct hash_bucket *, - void *))zvni_print_neigh_hash_all_vni_detail, + void *))zevpn_print_neigh_hash_all_evpn_detail, args); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -6644,21 +2515,21 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct ipaddr *ip, bool use_json) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; zebra_neigh_t *n; json_object *json = NULL; if (!is_evpn_enabled()) return; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { if (use_json) vty_out(vty, "{}\n"); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - n = zvni_neigh_lookup(zvni, ip); + n = zebra_evpn_neigh_lookup(zevpn, ip); if (!n) { if (!use_json) vty_out(vty, @@ -6669,7 +2540,7 @@ void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, if (use_json) json = json_object_new_object(); - zvni_print_neigh(n, vty, json); + zebra_evpn_print_neigh(n, vty, json); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -6686,22 +2557,22 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip, bool use_json) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; uint32_t num_neigh; struct neigh_walk_ctx wctx; json_object *json = NULL; if (!is_evpn_enabled()) return; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { if (use_json) vty_out(vty, "{}\n"); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - num_neigh = hashcount(zvni->neigh_table); + num_neigh = hashcount(zevpn->neigh_table); if (!num_neigh) return; @@ -6709,14 +2580,15 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, json = json_object_new_object(); memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); - wctx.zvni = zvni; + wctx.zevpn = zevpn; wctx.vty = vty; wctx.addr_width = 15; wctx.flags = SHOW_REMOTE_NEIGH_FROM_VTEP; wctx.r_vtep_ip = vtep_ip; wctx.json = json; - hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); - hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx); + hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width, + &wctx); + hash_iterate(zevpn->neigh_table, zebra_evpn_print_neigh_hash, &wctx); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -6734,7 +2606,7 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty, vni_t vni, bool use_json) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; uint32_t num_neigh; struct neigh_walk_ctx wctx; json_object *json = NULL; @@ -6742,17 +2614,17 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty, if (!is_evpn_enabled()) return; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - num_neigh = hashcount(zvni->neigh_table); + num_neigh = hashcount(zevpn->neigh_table); if (!num_neigh) return; - num_neigh = num_dup_detected_neighs(zvni); + num_neigh = num_dup_detected_neighs(zevpn); if (!num_neigh) return; @@ -6764,23 +2636,25 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty, * the maximum width. */ memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); - wctx.zvni = zvni; + wctx.zevpn = zevpn; wctx.vty = vty; wctx.addr_width = 15; wctx.json = json; - hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx); + hash_iterate(zevpn->neigh_table, zebra_evpn_find_neigh_addr_width, + &wctx); if (!use_json) { vty_out(vty, "Number of ARPs (local and remote) known for this VNI: %u\n", num_neigh); - vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n", + vty_out(vty, "%*s %-6s %-8s %-17s %-30s\n", -wctx.addr_width, "IP", "Type", - "State", "MAC", "Remote VTEP"); + "State", "MAC", "Remote ES/VTEP"); } else json_object_int_add(json, "numArpNd", num_neigh); - hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash, &wctx); + hash_iterate(zevpn->neigh_table, zebra_evpn_print_dad_neigh_hash, + &wctx); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -6795,7 +2669,7 @@ void zebra_vxlan_print_neigh_vni_dad(struct vty *vty, void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, bool use_json) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; uint32_t num_macs; struct mac_walk_ctx wctx; json_object *json = NULL; @@ -6803,15 +2677,15 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, if (!is_evpn_enabled()) return; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { if (use_json) vty_out(vty, "{}\n"); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - num_macs = num_valid_macs(zvni); + num_macs = num_valid_macs(zevpn); if (!num_macs) return; @@ -6821,7 +2695,7 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, } memset(&wctx, 0, sizeof(struct mac_walk_ctx)); - wctx.zvni = zvni; + wctx.zevpn = zevpn; wctx.vty = vty; wctx.json = json_mac; @@ -6829,12 +2703,15 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, vty_out(vty, "Number of MACs (local and remote) known for this VNI: %u\n", num_macs); - vty_out(vty, "%-17s %-6s %-21s %-5s %s\n", "MAC", "Type", - "Intf/Remote VTEP", "VLAN", "Seq #'s"); + vty_out(vty, + "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n"); + vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC", + "Type", "Flags", "Intf/Remote ES/VTEP", + "VLAN", "Seq #'s"); } else json_object_int_add(json, "numMacs", num_macs); - hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); + hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx); if (use_json) { json_object_object_add(json, "macs", json_mac); @@ -6865,7 +2742,7 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf, wctx.vty = vty; wctx.json = json; wctx.print_dup = print_dup; - hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); + hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -6896,7 +2773,7 @@ void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty, wctx.vty = vty; wctx.json = json; wctx.print_dup = print_dup; - hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni_detail, + hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn_detail, &wctx); if (use_json) { @@ -6927,7 +2804,7 @@ void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; wctx.r_vtep_ip = vtep_ip; wctx.json = json; - hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx); + hash_iterate(zvrf->evpn_table, zevpn_print_mac_hash_all_evpn, &wctx); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( @@ -6943,22 +2820,22 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct ethaddr *macaddr, bool use_json) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; zebra_mac_t *mac; json_object *json = NULL; if (!is_evpn_enabled()) return; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { if (use_json) vty_out(vty, "{}\n"); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - mac = zvni_mac_lookup(zvni, macaddr); + mac = zebra_evpn_mac_lookup(zevpn, macaddr); if (!mac) { if (use_json) vty_out(vty, "{}\n"); @@ -6972,7 +2849,7 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, if (use_json) json = json_object_new_object(); - zvni_print_mac(mac, vty, json); + zebra_evpn_print_mac(mac, vty, json); if (use_json) { vty_out(vty, "%s\n", json_object_to_json_string_ext( json, JSON_C_TO_STRING_PRETTY)); @@ -6985,7 +2862,7 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, bool use_json) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; struct mac_walk_ctx wctx; uint32_t num_macs; json_object *json = NULL; @@ -6994,17 +2871,17 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty, if (!is_evpn_enabled()) return; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - num_macs = num_valid_macs(zvni); + num_macs = num_valid_macs(zevpn); if (!num_macs) return; - num_macs = num_dup_detected_macs(zvni); + num_macs = num_dup_detected_macs(zevpn); if (!num_macs) return; @@ -7014,7 +2891,7 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty, } memset(&wctx, 0, sizeof(struct mac_walk_ctx)); - wctx.zvni = zvni; + wctx.zevpn = zevpn; wctx.vty = vty; wctx.json = json_mac; @@ -7022,12 +2899,12 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty, vty_out(vty, "Number of MACs (local and remote) known for this VNI: %u\n", num_macs); - vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type", - "Intf/Remote VTEP", "VLAN"); + vty_out(vty, "%-17s %-6s %-5s %-30s %-5s\n", "MAC", "Type", + "Flags", "Intf/Remote ES/VTEP", "VLAN"); } else json_object_int_add(json, "numMacs", num_macs); - hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, &wctx); + hash_iterate(zevpn->mac_table, zebra_evpn_print_dad_mac_hash, &wctx); if (use_json) { json_object_object_add(json, "macs", json_mac); @@ -7041,7 +2918,7 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty, int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni, struct ethaddr *macaddr) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; zebra_mac_t *mac; struct listnode *node = NULL; zebra_neigh_t *nbr = NULL; @@ -7049,13 +2926,13 @@ int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni, if (!is_evpn_enabled()) return 0; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { zlog_warn("VNI %u does not exist\n", vni); return -1; } - mac = zvni_mac_lookup(zvni, macaddr); + mac = zebra_evpn_mac_lookup(zevpn, macaddr); if (!mac) { zlog_warn("Requested MAC does not exist in VNI %u\n", vni); return -1; @@ -7080,7 +2957,8 @@ int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni, if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) ZEBRA_NEIGH_SET_INACTIVE(nbr); else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) - zvni_neigh_install(zvni, nbr); + zebra_evpn_rem_neigh_install( + zevpn, nbr, false /*was_static*/); } UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); @@ -7103,20 +2981,20 @@ int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni, /* Local: Notify Peer VTEPs, Remote: Install the entry */ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { /* Inform to BGP */ - if (zvni_mac_send_add_to_client(zvni->vni, - &mac->macaddr, - mac->flags, - mac->loc_seq)) + if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr, + mac->flags, mac->loc_seq, + mac->es)) return 0; /* Process all neighbors associated with this MAC. */ - zvni_process_neigh_on_local_mac_change(zvni, mac, 0); + zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, + 0 /*es_change*/); } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - zvni_process_neigh_on_remote_mac_add(zvni, mac); + zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac); /* Install the entry. */ - zvni_mac_install(zvni, mac); + zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */); } return 0; @@ -7125,7 +3003,7 @@ int zebra_vxlan_clear_dup_detect_vni_mac(struct zebra_vrf *zvrf, vni_t vni, int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni, struct ipaddr *ip) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; zebra_neigh_t *nbr; zebra_mac_t *mac; char buf[INET6_ADDRSTRLEN]; @@ -7134,13 +3012,13 @@ int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni, if (!is_evpn_enabled()) return 0; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { zlog_debug("VNI %u does not exist\n", vni); return -1; } - nbr = zvni_neigh_lookup(zvni, ip); + nbr = zebra_evpn_neigh_lookup(zevpn, ip); if (!nbr) { zlog_warn("Requested host IP does not exist in VNI %u\n", vni); return -1; @@ -7154,7 +3032,7 @@ int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni, return -1; } - mac = zvni_mac_lookup(zvni, &nbr->emac); + mac = zebra_evpn_mac_lookup(zevpn, &nbr->emac); if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { zlog_warn( @@ -7175,21 +3053,21 @@ int zebra_vxlan_clear_dup_detect_vni_ip(struct zebra_vrf *zvrf, vni_t vni, THREAD_OFF(nbr->dad_ip_auto_recovery_timer); if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) { - zvni_neigh_send_add_to_client(zvni->vni, ip, - &nbr->emac, - nbr->flags, nbr->loc_seq); + zebra_evpn_neigh_send_add_to_client(zevpn->vni, ip, &nbr->emac, + nbr->mac, nbr->flags, + nbr->loc_seq); } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) { - zvni_neigh_install(zvni, nbr); + zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/); } return 0; } -static void zvni_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt) +static void zevpn_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt) { struct mac_walk_ctx *wctx = ctxt; zebra_mac_t *mac; - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; struct listnode *node = NULL; zebra_neigh_t *nbr = NULL; @@ -7197,7 +3075,7 @@ static void zvni_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt) if (!mac) return; - zvni = wctx->zvni; + zevpn = wctx->zevpn; if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) return; @@ -7224,87 +3102,50 @@ static void zvni_clear_dup_mac_hash(struct hash_bucket *bucket, void *ctxt) /* Local: Notify Peer VTEPs, Remote: Install the entry */ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { /* Inform to BGP */ - if (zvni_mac_send_add_to_client(zvni->vni, - &mac->macaddr, - mac->flags, mac->loc_seq)) + if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr, + mac->flags, mac->loc_seq, + mac->es)) return; /* Process all neighbors associated with this MAC. */ - zvni_process_neigh_on_local_mac_change(zvni, mac, 0); + zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, + 0 /*es_change*/); } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - zvni_process_neigh_on_remote_mac_add(zvni, mac); + zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac); /* Install the entry. */ - zvni_mac_install(zvni, mac); + zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */); } } -static void zvni_clear_dup_neigh_hash(struct hash_bucket *bucket, void *ctxt) -{ - struct neigh_walk_ctx *wctx = ctxt; - zebra_neigh_t *nbr; - zebra_vni_t *zvni; - char buf[INET6_ADDRSTRLEN]; - - nbr = (zebra_neigh_t *)bucket->data; - if (!nbr) - return; - - zvni = wctx->zvni; - - if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) - return; - - if (IS_ZEBRA_DEBUG_VXLAN) { - ipaddr2str(&nbr->ip, buf, sizeof(buf)); - zlog_debug("%s: clear neigh %s dup state, flags 0x%x seq %u", - __func__, buf, nbr->flags, nbr->loc_seq); - } - - UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); - nbr->dad_count = 0; - nbr->detect_start_time.tv_sec = 0; - nbr->detect_start_time.tv_usec = 0; - nbr->dad_dup_detect_time = 0; - THREAD_OFF(nbr->dad_ip_auto_recovery_timer); - - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) { - zvni_neigh_send_add_to_client(zvni->vni, &nbr->ip, - &nbr->emac, - nbr->flags, nbr->loc_seq); - } else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) { - zvni_neigh_install(zvni, nbr); - } -} - -static void zvni_clear_dup_detect_hash_vni_all(struct hash_bucket *bucket, +static void zevpn_clear_dup_detect_hash_vni_all(struct hash_bucket *bucket, void **args) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; struct zebra_vrf *zvrf; struct mac_walk_ctx m_wctx; struct neigh_walk_ctx n_wctx; - zvni = (zebra_vni_t *)bucket->data; - if (!zvni) + zevpn = (zebra_evpn_t *)bucket->data; + if (!zevpn) return; zvrf = (struct zebra_vrf *)args[0]; - if (hashcount(zvni->neigh_table)) { + if (hashcount(zevpn->neigh_table)) { memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); - n_wctx.zvni = zvni; + n_wctx.zevpn = zevpn; n_wctx.zvrf = zvrf; - hash_iterate(zvni->neigh_table, zvni_clear_dup_neigh_hash, - &n_wctx); + hash_iterate(zevpn->neigh_table, + zebra_evpn_clear_dup_neigh_hash, &n_wctx); } - if (num_valid_macs(zvni)) { + if (num_valid_macs(zevpn)) { memset(&m_wctx, 0, sizeof(struct mac_walk_ctx)); - m_wctx.zvni = zvni; + m_wctx.zevpn = zevpn; m_wctx.zvrf = zvrf; - hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx); + hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx); } } @@ -7318,41 +3159,41 @@ int zebra_vxlan_clear_dup_detect_vni_all(struct zebra_vrf *zvrf) args[0] = zvrf; - hash_iterate(zvrf->vni_table, + hash_iterate(zvrf->evpn_table, (void (*)(struct hash_bucket *, void *)) - zvni_clear_dup_detect_hash_vni_all, args); + zevpn_clear_dup_detect_hash_vni_all, args); return 0; } int zebra_vxlan_clear_dup_detect_vni(struct zebra_vrf *zvrf, vni_t vni) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; struct mac_walk_ctx m_wctx; struct neigh_walk_ctx n_wctx; if (!is_evpn_enabled()) return 0; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { zlog_warn("VNI %u does not exist\n", vni); - return -1; + return CMD_WARNING; } - if (hashcount(zvni->neigh_table)) { + if (hashcount(zevpn->neigh_table)) { memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); - n_wctx.zvni = zvni; + n_wctx.zevpn = zevpn; n_wctx.zvrf = zvrf; - hash_iterate(zvni->neigh_table, zvni_clear_dup_neigh_hash, - &n_wctx); + hash_iterate(zevpn->neigh_table, + zebra_evpn_clear_dup_neigh_hash, &n_wctx); } - if (num_valid_macs(zvni)) { + if (num_valid_macs(zevpn)) { memset(&m_wctx, 0, sizeof(struct mac_walk_ctx)); - m_wctx.zvni = zvni; + m_wctx.zevpn = zevpn; m_wctx.zvrf = zvrf; - hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx); + hash_iterate(zevpn->mac_table, zevpn_clear_dup_mac_hash, &m_wctx); } return 0; @@ -7365,7 +3206,7 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip, bool use_json) { - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; uint32_t num_macs; struct mac_walk_ctx wctx; json_object *json = NULL; @@ -7373,15 +3214,15 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, if (!is_evpn_enabled()) return; - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { if (use_json) vty_out(vty, "{}\n"); else vty_out(vty, "%% VNI %u does not exist\n", vni); return; } - num_macs = num_valid_macs(zvni); + num_macs = num_valid_macs(zevpn); if (!num_macs) return; @@ -7391,12 +3232,12 @@ void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, } memset(&wctx, 0, sizeof(struct mac_walk_ctx)); - wctx.zvni = zvni; + wctx.zevpn = zevpn; wctx.vty = vty; wctx.flags = SHOW_REMOTE_MAC_FROM_VTEP; wctx.r_vtep_ip = vtep_ip; wctx.json = json_mac; - hash_iterate(zvni->mac_table, zvni_print_mac_hash, &wctx); + hash_iterate(zevpn->mac_table, zebra_evpn_print_mac_hash, &wctx); if (use_json) { json_object_int_add(json, "numMacs", wctx.count); @@ -7423,7 +3264,7 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, json_object *json = NULL; void *args[2]; zebra_l3vni_t *zl3vni = NULL; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; if (!is_evpn_enabled()) return; @@ -7438,9 +3279,9 @@ void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, if (zl3vni) { zl3vni_print(zl3vni, (void *)args); } else { - zvni = zvni_lookup(vni); - if (zvni) - zvni_print(zvni, (void *)args); + zevpn = zebra_evpn_lookup(vni); + if (zevpn) + zebra_evpn_print(zevpn, (void *)args); else if (!json) vty_out(vty, "%% VNI %u does not exist\n", vni); } @@ -7478,7 +3319,7 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj) return; num_l3vnis = hashcount(zrouter.l3vni_table); - num_l2vnis = hashcount(zvrf->vni_table); + num_l2vnis = hashcount(zvrf->evpn_table); num_vnis = num_l2vnis + num_l3vnis; if (uj) { @@ -7550,9 +3391,10 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf, args[1] = json; /* Display all L2-VNIs */ - hash_iterate(zvrf->vni_table, - (void (*)(struct hash_bucket *, void *))zvni_print_hash, - args); + hash_iterate( + zvrf->evpn_table, + (void (*)(struct hash_bucket *, void *))zebra_evpn_print_hash, + args); /* Display all L3-VNIs */ hash_iterate(zrouter.l3vni_table, @@ -7616,7 +3458,7 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf, { json_object *json_array = NULL; struct zebra_ns *zns = NULL; - struct zvni_evpn_show zes; + struct zebra_evpn_show zes; if (!is_evpn_enabled()) return; @@ -7634,10 +3476,10 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf, zes.use_json = use_json; /* Display all L2-VNIs */ - hash_iterate( - zvrf->vni_table, - (void (*)(struct hash_bucket *, void *))zvni_print_hash_detail, - &zes); + hash_iterate(zvrf->evpn_table, + (void (*)(struct hash_bucket *, + void *))zebra_evpn_print_hash_detail, + &zes); /* Display all L3-VNIs */ hash_iterate(zrouter.l3vni_table, @@ -7664,12 +3506,8 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp, struct ipaddr *ip) { char buf[INET6_ADDRSTRLEN]; - char buf2[ETHER_ADDR_STRLEN]; - zebra_neigh_t *n = NULL; - zebra_vni_t *zvni = NULL; - zebra_mac_t *zmac = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; - struct zebra_vrf *zvrf; /* check if this is a remote neigh entry corresponding to remote * next-hop @@ -7681,80 +3519,29 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp, /* We are only interested in neighbors on an SVI that resides on top * of a VxLAN bridge. */ - zvni = zvni_from_svi(ifp, link_if); - if (!zvni) { + zevpn = zebra_evpn_from_svi(ifp, link_if); + if (!zevpn) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "%s: Del neighbor %s VNI is not present for interface %s", + "%s: Del neighbor %s EVPN is not present for interface %s", __func__, ipaddr2str(ip, buf, sizeof(buf)), ifp->name); return 0; } - if (!zvni->vxlan_if) { + if (!zevpn->vxlan_if) { zlog_debug( "VNI %u hash %p doesn't have intf upon local neighbor DEL", - zvni->vni, zvni); + zevpn->vni, zevpn); return -1; } if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u", ipaddr2str(ip, buf, sizeof(buf)), ifp->name, - ifp->ifindex, zvni->vni); - - /* If entry doesn't exist, nothing to do. */ - n = zvni_neigh_lookup(zvni, ip); - if (!n) - return 0; + ifp->ifindex, zevpn->vni); - zmac = zvni_mac_lookup(zvni, &n->emac); - if (!zmac) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "Trying to del a neigh %s without a mac %s on VNI %u", - ipaddr2str(ip, buf, sizeof(buf)), - prefix_mac2str(&n->emac, buf2, sizeof(buf2)), - zvni->vni); - - return 0; - } - - /* If it is a remote entry, the kernel has aged this out or someone has - * deleted it, it needs to be re-installed as Quagga is the owner. - */ - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { - zvni_neigh_install(zvni, n); - return 0; - } - - zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); - if (!zvrf) { - zlog_debug("%s: VNI %u vrf lookup failed.", __func__, - zvni->vni); - return -1; - } - - /* In case of feeze action, if local neigh is in duplicate state, - * Mark the Neigh as inactive before sending delete request to BGPd, - * If BGPd has remote entry, it will re-install - */ - if (zvrf->dad_freeze && - CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)) - ZEBRA_NEIGH_SET_INACTIVE(n); - - /* Remove neighbor from BGP. */ - zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0, n->state); - - /* Delete this neighbor entry. */ - zvni_neigh_del(zvni, n); - - /* see if the AUTO mac needs to be deleted */ - if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO) - && !listcount(zmac->neigh_list)) - zvni_mac_del(zvni, zmac); - - return 0; + return zebra_evpn_neigh_del_ip(zevpn, ip); } /* @@ -7769,11 +3556,12 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, struct ethaddr *macaddr, uint16_t state, bool is_ext, - bool is_router) + bool is_router, + bool local_inactive, bool dp_static) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; /* check if this is a remote neigh entry corresponding to remote @@ -7786,32 +3574,34 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, /* We are only interested in neighbors on an SVI that resides on top * of a VxLAN bridge. */ - zvni = zvni_from_svi(ifp, link_if); - if (!zvni) + zevpn = zebra_evpn_from_svi(ifp, link_if); + if (!zevpn) return 0; - if (IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH) zlog_debug( - "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u", + "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s%s%s-> L2-VNI %u", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, state, is_ext ? "ext-learned " : "", is_router ? "router " : "", - zvni->vni); + local_inactive ? "local_inactive " : "", + zevpn->vni); /* Is this about a local neighbor or a remote one? */ if (!is_ext) - return zvni_local_neigh_update(zvni, ifp, ip, macaddr, - is_router); + return zebra_evpn_local_neigh_update(zevpn, ifp, ip, macaddr, + is_router, local_inactive, + dp_static); - return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state); + return zebra_evpn_remote_neigh_update(zevpn, ifp, ip, macaddr, state); } static int32_t zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni, struct ethaddr *macaddr, uint16_t *ipa_len, struct ipaddr *ip, struct in_addr *vtep_ip, - uint8_t *flags, uint32_t *seq) + uint8_t *flags, uint32_t *seq, esi_t *esi) { uint16_t l = 0; @@ -7849,6 +3639,8 @@ zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni, STREAM_GETC(s, *flags); STREAM_GETL(s, *seq); l += 5; + STREAM_GET(esi, s, sizeof(esi_t)); + l += sizeof(esi_t); } return l; @@ -7880,7 +3672,7 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS) while (l < hdr->length) { int res_length = zebra_vxlan_remote_macip_helper( false, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip, NULL, - NULL); + NULL, NULL); if (res_length == -1) goto stream_failure; @@ -7921,6 +3713,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) uint32_t seq; char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; + esi_t esi; + char esi_buf[ESI_STR_LEN]; memset(&macaddr, 0, sizeof(struct ethaddr)); memset(&ip, 0, sizeof(struct ipaddr)); @@ -7936,25 +3730,32 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) while (l < hdr->length) { int res_length = zebra_vxlan_remote_macip_helper( true, s, &vni, &macaddr, &ipa_len, &ip, &vtep_ip, - &flags, &seq); + &flags, &seq, &esi); if (res_length == -1) goto stream_failure; l += res_length; - if (IS_ZEBRA_DEBUG_VXLAN) + if (IS_ZEBRA_DEBUG_VXLAN) { + if (memcmp(&esi, zero_esi, sizeof(esi_t))) + esi_to_str(&esi, esi_buf, sizeof(esi_buf)); + else + strlcpy(esi_buf, "-", ESI_STR_LEN); zlog_debug( - "Recv MACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s from %s", + "Recv %sMACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %s ESI %s from %s", + (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) ? + "sync-" : "", vni, prefix_mac2str(&macaddr, buf, sizeof(buf)), ipa_len ? " IP " : "", ipa_len ? ipaddr2str(&ip, buf1, sizeof(buf1)) : "", - flags, seq, inet_ntoa(vtep_ip), + flags, seq, inet_ntoa(vtep_ip), esi_buf, zebra_route_string(client->proto)); + } process_remote_macip_add(vni, &macaddr, ipa_len, &ip, - flags, seq, vtep_ip); + flags, seq, vtep_ip, &esi); } stream_failure: @@ -7971,7 +3772,7 @@ int zebra_vxlan_check_readd_vtep(struct interface *ifp, struct zebra_vrf *zvrf = NULL; struct zebra_l2info_vxlan *vxl; vni_t vni; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_vtep_t *zvtep = NULL; zif = ifp->info; @@ -7989,12 +3790,12 @@ int zebra_vxlan_check_readd_vtep(struct interface *ifp, return -1; /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) return 0; /* If the remote vtep entry doesn't exists nothing to do */ - zvtep = zvni_vtep_find(zvni, &vtep_ip); + zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip); if (!zvtep) return 0; @@ -8003,7 +3804,7 @@ int zebra_vxlan_check_readd_vtep(struct interface *ifp, "Del MAC for remote VTEP %s intf %s(%u) VNI %u - readd", inet_ntoa(vtep_ip), ifp->name, ifp->ifindex, vni); - zvni_vtep_install(zvni, zvtep); + zebra_evpn_vtep_install(zevpn, zvtep); return 0; } @@ -8019,7 +3820,7 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp, struct zebra_if *zif; struct zebra_l2info_vxlan *vxl; vni_t vni; - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; zebra_mac_t *mac; char buf[ETHER_ADDR_STRLEN]; @@ -8033,12 +3834,12 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp, return 0; /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) return 0; /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup(zvni, macaddr); + mac = zebra_evpn_mac_lookup(zevpn, macaddr); if (!mac) return 0; @@ -8053,16 +3854,17 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp, ifp->ifindex, vni, mac->flags); /* Remove MAC from BGP. */ - zvni_mac_send_del_to_client(zvni->vni, macaddr); + zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags, + false /* force */); /* * If there are no neigh associated with the mac delete the mac * else mark it as AUTO for forward reference */ if (!listcount(mac->neigh_list)) { - zvni_mac_del(zvni, mac); + zebra_evpn_mac_del(zevpn, mac); } else { - UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); + UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS); UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); } @@ -8082,7 +3884,7 @@ int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, struct zebra_if *zif = NULL; struct zebra_l2info_vxlan *vxl = NULL; vni_t vni; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; zebra_mac_t *mac = NULL; char buf[ETHER_ADDR_STRLEN]; @@ -8102,12 +3904,12 @@ int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, return zebra_vxlan_readd_remote_rmac(zl3vni, macaddr); /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) return 0; /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup(zvni, macaddr); + mac = zebra_evpn_mac_lookup(zevpn, macaddr); if (!mac) return 0; @@ -8120,7 +3922,7 @@ int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, vni); - zvni_mac_install(zvni, mac); + zebra_evpn_rem_mac_install(zevpn, mac, false /* was_static */); return 0; } @@ -8130,57 +3932,22 @@ int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, struct ethaddr *macaddr, vlanid_t vid) { - zebra_vni_t *zvni; - zebra_mac_t *mac; - char buf[ETHER_ADDR_STRLEN]; + zebra_evpn_t *zevpn; /* We are interested in MACs only on ports or (port, VLAN) that * map to a VNI. */ - zvni = zvni_map_vlan(ifp, br_if, vid); - if (!zvni) + zevpn = zebra_evpn_map_vlan(ifp, br_if, vid); + if (!zevpn) return 0; - if (!zvni->vxlan_if) { + if (!zevpn->vxlan_if) { zlog_debug( "VNI %u hash %p doesn't have intf upon local MAC DEL", - zvni->vni, zvni); + zevpn->vni, zevpn); return -1; } - /* If entry doesn't exist, nothing to do. */ - mac = zvni_mac_lookup(zvni, macaddr); - if (!mac) - return 0; - - /* Is it a local entry? */ - if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) - return 0; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("DEL MAC %s intf %s(%u) VID %u -> VNI %u seq %u flags 0x%x nbr count %u", - prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, - ifp->ifindex, vid, zvni->vni, mac->loc_seq, - mac->flags, listcount(mac->neigh_list)); - - /* Update all the neigh entries associated with this mac */ - zvni_process_neigh_on_local_mac_del(zvni, mac); - - /* Remove MAC from BGP. */ - zvni_mac_send_del_to_client(zvni->vni, macaddr); - - /* - * If there are no neigh associated with the mac delete the mac - * else mark it as AUTO for forward reference - */ - if (!listcount(mac->neigh_list)) { - zvni_mac_del(zvni, mac); - } else { - UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); - UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - } - - return 0; + return zebra_evpn_del_local_mac(zevpn, macaddr, ifp); } /* @@ -8189,201 +3956,52 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, int zebra_vxlan_local_mac_add_update(struct interface *ifp, struct interface *br_if, struct ethaddr *macaddr, vlanid_t vid, - bool sticky) + bool sticky, bool local_inactive, + bool dp_static) { - zebra_vni_t *zvni; - zebra_mac_t *mac; + zebra_evpn_t *zevpn; struct zebra_vrf *zvrf; char buf[ETHER_ADDR_STRLEN]; - bool mac_sticky = false; - bool inform_client = false; - bool upd_neigh = false; - bool is_dup_detect = false; - struct in_addr vtep_ip = {.s_addr = 0}; - ns_id_t local_ns_id = NS_DEFAULT; - zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); - if (zvrf && zvrf->zns) - local_ns_id = zvrf->zns->ns_id; + assert(ifp); /* We are interested in MACs only on ports or (port, VLAN) that - * map to a VNI. + * map to an EVPN. */ - zvni = zvni_map_vlan(ifp, br_if, vid); - if (!zvni) { + zevpn = zebra_evpn_map_vlan(ifp, br_if, vid); + if (!zevpn) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - " Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI", + " Add/Update %sMAC %s intf %s(%u) VID %u, could not find EVPN", sticky ? "sticky " : "", prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, vid); return 0; } - if (!zvni->vxlan_if) { + if (!zevpn->vxlan_if) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( " VNI %u hash %p doesn't have intf upon local MAC ADD", - zvni->vni, zvni); + zevpn->vni, zevpn); return -1; } - zvrf = zebra_vrf_get_evpn(); + zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id); if (!zvrf) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug(" No Evpn Global Vrf found"); + zlog_debug(" No Vrf found for vrf_id: %d", + zevpn->vxlan_if->vrf_id); return -1; } - /* Check if we need to create or update or it is a NO-OP. */ - mac = zvni_mac_lookup(zvni, macaddr); - if (!mac) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u", - sticky ? "sticky " : "", - prefix_mac2str(macaddr, buf, sizeof(buf)), - ifp->name, ifp->ifindex, vid, zvni->vni); - - mac = zvni_mac_add(zvni, macaddr); - if (!mac) { - flog_err( - EC_ZEBRA_MAC_ADD_FAILED, - "Failed to add MAC %s intf %s(%u) VID %u VNI %u", - prefix_mac2str(macaddr, buf, sizeof(buf)), - ifp->name, ifp->ifindex, vid, zvni->vni); - return -1; - } - SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); - mac->fwd_info.local.ifindex = ifp->ifindex; - mac->fwd_info.local.ns_id = local_ns_id; - mac->fwd_info.local.vid = vid; - if (sticky) - SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - inform_client = true; - - } else { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u curFlags 0x%x", - sticky ? "sticky " : "", - prefix_mac2str(macaddr, buf, sizeof(buf)), - ifp->name, ifp->ifindex, vid, zvni->vni, - mac->flags); - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) - mac_sticky = true; - - /* - * Update any changes and if changes are relevant to - * BGP, note it. - */ - if (mac_sticky == sticky - && mac->fwd_info.local.ifindex == ifp->ifindex - && mac->fwd_info.local.ns_id == local_ns_id - && mac->fwd_info.local.vid == vid) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - " Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, " - "entry exists and has not changed ", - sticky ? "sticky " : "", - prefix_mac2str(macaddr, buf, - sizeof(buf)), - ifp->name, ifp->ifindex, vid, - zvni->vni); - return 0; - } - if (mac_sticky != sticky) { - if (sticky) - SET_FLAG(mac->flags, - ZEBRA_MAC_STICKY); - else - UNSET_FLAG(mac->flags, - ZEBRA_MAC_STICKY); - inform_client = true; - } - - memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); - mac->fwd_info.local.ifindex = ifp->ifindex; - mac->fwd_info.local.ns_id = local_ns_id; - mac->fwd_info.local.vid = vid; - - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) || - CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) { - bool do_dad = false; - - /* - * MAC has either moved or was "internally" created due - * to a neighbor learn and is now actually learnt. If - * it was learnt as a remote sticky MAC, this is an - * operator error. - */ - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) { - flog_warn( - EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT, - "MAC %s already learnt as remote sticky MAC behind VTEP %s VNI %u", - prefix_mac2str(macaddr, buf, - sizeof(buf)), - inet_ntoa(mac->fwd_info.r_vtep_ip), - zvni->vni); - return 0; - } - - /* If an actual move, compute MAC's seq number */ - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - mac->loc_seq = MAX(mac->rem_seq + 1, - mac->loc_seq); - vtep_ip = mac->fwd_info.r_vtep_ip; - /* Trigger DAD for remote MAC */ - do_dad = true; - } - - UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); - UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); - SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); - memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); - mac->fwd_info.local.ifindex = ifp->ifindex; - mac->fwd_info.local.ns_id = local_ns_id; - mac->fwd_info.local.vid = vid; - if (sticky) - SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - else - UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); - /* - * We have to inform BGP of this MAC as well as process - * all neighbors. - */ - inform_client = true; - upd_neigh = true; - - zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac, vtep_ip, - do_dad, - &is_dup_detect, - true); - if (is_dup_detect) { - inform_client = false; - upd_neigh = false; - } - } - } - - /* Inform BGP if required. */ - if (inform_client) { - if (zvni_mac_send_add_to_client(zvni->vni, macaddr, - mac->flags, mac->loc_seq)) - return -1; - } - - /* Process all neighbors associated with this MAC, if required. */ - if (upd_neigh) - zvni_process_neigh_on_local_mac_change(zvni, mac, 0); - - return 0; + return zebra_evpn_add_update_local_mac(zvrf, zevpn, ifp, macaddr, vid, + sticky, local_inactive, + dp_static); } /* - * Handle message from client to delete a remote VTEP for a VNI. + * Handle message from client to delete a remote VTEP for an EVPN. */ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) { @@ -8391,7 +4009,7 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) unsigned short l = 0; vni_t vni; struct in_addr vtep_ip; - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; zebra_vtep_t *zvtep; struct interface *ifp; struct zebra_if *zif; @@ -8430,21 +4048,20 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) zebra_route_string(client->proto)); /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Failed to locate VNI hash upon remote VTEP DEL, " - "VNI %u", + "Failed to locate VNI hash upon remote VTEP DEL, VNI %u", vni); continue; } - ifp = zvni->vxlan_if; + ifp = zevpn->vxlan_if; if (!ifp) { zlog_debug( "VNI %u hash %p doesn't have intf upon remote VTEP DEL", - zvni->vni, zvni); + zevpn->vni, zevpn); continue; } zif = ifp->info; @@ -8459,12 +4076,12 @@ void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS) * and * then, the VTEP entry itself and remove it. */ - zvtep = zvni_vtep_find(zvni, &vtep_ip); + zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip); if (!zvtep) continue; - zvni_vtep_uninstall(zvni, &vtep_ip); - zvni_vtep_del(zvni, zvtep); + zebra_evpn_vtep_uninstall(zevpn, &vtep_ip); + zebra_evpn_vtep_del(zevpn, zvtep); } stream_failure: @@ -8472,7 +4089,7 @@ stream_failure: } /* - * Handle message from client to add a remote VTEP for a VNI. + * Handle message from client to add a remote VTEP for an EVPN. */ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) { @@ -8480,7 +4097,7 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) unsigned short l = 0; vni_t vni; struct in_addr vtep_ip; - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; struct interface *ifp; struct zebra_if *zif; int flood_control; @@ -8515,21 +4132,21 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) zebra_route_string(client->proto)); /* Locate VNI hash entry - expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { flog_err( EC_ZEBRA_VTEP_ADD_FAILED, - "Failed to locate VNI hash upon remote VTEP ADD, VNI %u", + "Failed to locate EVPN hash upon remote VTEP ADD, VNI %u", vni); continue; } - ifp = zvni->vxlan_if; + ifp = zevpn->vxlan_if; if (!ifp) { flog_err( EC_ZEBRA_VTEP_ADD_FAILED, "VNI %u hash %p doesn't have intf upon remote VTEP ADD", - zvni->vni, zvni); + zevpn->vni, zevpn); continue; } @@ -8539,7 +4156,7 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) if (!if_is_operative(ifp) || !zif->brslave_info.br_if) continue; - zvtep = zvni_vtep_find(zvni, &vtep_ip); + zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip); if (zvtep) { /* If the remote VTEP already exists check if * the flood mode has changed @@ -8551,18 +4168,20 @@ void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS) * is no longer; get rid of the HER fdb * entry installed before */ - zvni_vtep_uninstall(zvni, &vtep_ip); + zebra_evpn_vtep_uninstall(zevpn, + &vtep_ip); zvtep->flood_control = flood_control; - zvni_vtep_install(zvni, zvtep); + zebra_evpn_vtep_install(zevpn, zvtep); } } else { - zvtep = zvni_vtep_add(zvni, &vtep_ip, flood_control); + zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, + flood_control); if (zvtep) - zvni_vtep_install(zvni, zvtep); + zebra_evpn_vtep_install(zevpn, zvtep); else flog_err(EC_ZEBRA_VTEP_ADD_FAILED, - "Failed to add remote VTEP, VNI %u zvni %p", - vni, zvni); + "Failed to add remote VTEP, VNI %u zevpn %p", + vni, zevpn); } } @@ -8583,7 +4202,7 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p, { struct ipaddr ip; struct ethaddr macaddr; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; memset(&ip, 0, sizeof(struct ipaddr)); memset(&macaddr, 0, sizeof(struct ethaddr)); @@ -8627,14 +4246,15 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p, svi_if_link = if_lookup_by_index_per_ns( zebra_ns_lookup(NS_DEFAULT), svi_if_zif->link_ifindex); - zvni = zvni_from_svi(svi_if, svi_if_link); + zevpn = zebra_evpn_from_svi(svi_if, + svi_if_link); } } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) { /* * If it is a vlan unaware bridge then svi is the bridge * itself */ - zvni = zvni_from_svi(svi_if, svi_if); + zevpn = zebra_evpn_from_svi(svi_if, svi_if); } } else if (IS_ZEBRA_IF_VLAN(ifp)) { struct zebra_if *svi_if_zif = @@ -8648,18 +4268,18 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p, zebra_ns_lookup(NS_DEFAULT), svi_if_zif->link_ifindex); if (svi_if_link) - zvni = zvni_from_svi(ifp, svi_if_link); + zevpn = zebra_evpn_from_svi(ifp, svi_if_link); } } else if (IS_ZEBRA_IF_BRIDGE(ifp)) { - zvni = zvni_from_svi(ifp, ifp); + zevpn = zebra_evpn_from_svi(ifp, ifp); } - if (!zvni) + if (!zevpn) return 0; - if (!zvni->vxlan_if) { + if (!zevpn->vxlan_if) { zlog_debug("VNI %u hash %p doesn't have intf upon MACVLAN up", - zvni->vni, zvni); + zevpn->vni, zevpn); return -1; } @@ -8678,9 +4298,9 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p, if (add) - zvni_gw_macip_add(ifp, zvni, &macaddr, &ip); + zebra_evpn_gw_macip_add(ifp, zevpn, &macaddr, &ip); else - zvni_gw_macip_del(ifp, zvni, &ip); + zebra_evpn_gw_macip_del(ifp, zevpn, &ip); return 0; } @@ -8690,7 +4310,7 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p, * SVI can be associated to either L3-VNI or L2-VNI. * For L2-VNI: At this point, this is a NOP since * the kernel deletes the neighbor entries on this SVI (if any). - * We only need to update the vrf corresponding to zvni. + * We only need to update the vrf corresponding to zevpn. * For L3-VNI: L3-VNI is operationally down, update mac-ip routes and delete * from bgp */ @@ -8707,17 +4327,17 @@ int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) /* remove association with svi-if */ zl3vni->svi_if = NULL; } else { - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; - /* since we dont have svi corresponding to zvni, we associate it + /* since we dont have svi corresponding to zevpn, we associate it * to default vrf. Note: the corresponding neigh entries on the * SVI would have already been deleted */ - zvni = zvni_from_svi(ifp, link_if); - if (zvni) { - zvni->vrf_id = VRF_DEFAULT; + zevpn = zebra_evpn_from_svi(ifp, link_if); + if (zevpn) { + zevpn->vrf_id = VRF_DEFAULT; /* update the tenant vrf in BGP */ - zvni_send_add_to_client(zvni); + zebra_evpn_send_add_to_client(zevpn); } } return 0; @@ -8733,7 +4353,7 @@ int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) */ int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if) { - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; zl3vni = zl3vni_from_svi(ifp, link_if); @@ -8750,31 +4370,31 @@ int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if) /* process SVI up for l2-vni */ struct neigh_walk_ctx n_wctx; - zvni = zvni_from_svi(ifp, link_if); - if (!zvni) + zevpn = zebra_evpn_from_svi(ifp, link_if); + if (!zevpn) return 0; - if (!zvni->vxlan_if) { + if (!zevpn->vxlan_if) { zlog_debug( "VNI %u hash %p doesn't have intf upon SVI up", - zvni->vni, zvni); + zevpn->vni, zevpn); return -1; } if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( "SVI %s(%u) VNI %u VRF %s is UP, installing neighbors", - ifp->name, ifp->ifindex, zvni->vni, + ifp->name, ifp->ifindex, zevpn->vni, vrf_id_to_name(ifp->vrf_id)); /* update the vrf information for l2-vni and inform bgp */ - zvni->vrf_id = ifp->vrf_id; - zvni_send_add_to_client(zvni); + zevpn->vrf_id = ifp->vrf_id; + zebra_evpn_send_add_to_client(zevpn); /* Install any remote neighbors for this VNI. */ memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); - n_wctx.zvni = zvni; - hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, + n_wctx.zevpn = zevpn; + hash_iterate(zevpn->neigh_table, zebra_evpn_install_neigh_hash, &n_wctx); } @@ -8861,7 +4481,7 @@ int zebra_vxlan_if_down(struct interface *ifp) struct zebra_if *zif = NULL; struct zebra_l2info_vxlan *vxl = NULL; zebra_l3vni_t *zl3vni = NULL; - zebra_vni_t *zvni; + zebra_evpn_t *zevpn; /* Check if EVPN is enabled. */ if (!is_evpn_enabled()) @@ -8887,25 +4507,25 @@ int zebra_vxlan_if_down(struct interface *ifp) ifp->ifindex, vni); /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { zlog_debug( "Failed to locate VNI hash at DOWN, IF %s(%u) VNI %u", ifp->name, ifp->ifindex, vni); return -1; } - assert(zvni->vxlan_if == ifp); + assert(zevpn->vxlan_if == ifp); /* Delete this VNI from BGP. */ - zvni_send_del_to_client(zvni->vni); + zebra_evpn_send_del_to_client(zevpn); /* Free up all neighbors and MACs, if any. */ - zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC); + zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH); + zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC); /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all(zvni, 1); + zebra_evpn_vtep_del_all(zevpn, 1); } return 0; } @@ -8918,7 +4538,7 @@ int zebra_vxlan_if_up(struct interface *ifp) vni_t vni; struct zebra_if *zif = NULL; struct zebra_l2info_vxlan *vxl = NULL; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; /* Check if EVPN is enabled. */ @@ -8956,29 +4576,29 @@ int zebra_vxlan_if_up(struct interface *ifp) ifp->ifindex, vni); /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { zlog_debug( - "Failed to locate VNI hash at UP, IF %s(%u) VNI %u", + "Failed to locate EVPN hash at UP, IF %s(%u) VNI %u", ifp->name, ifp->ifindex, vni); return -1; } - assert(zvni->vxlan_if == ifp); + assert(zevpn->vxlan_if == ifp); vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); if (vlan_if) { - zvni->vrf_id = vlan_if->vrf_id; + zevpn->vrf_id = vlan_if->vrf_id; zl3vni = zl3vni_from_vrf(vlan_if->vrf_id); if (zl3vni) - listnode_add_sort(zl3vni->l2vnis, zvni); + listnode_add_sort(zl3vni->l2vnis, zevpn); } /* If part of a bridge, inform BGP about this VNI. */ /* Also, read and populate local MACs and neighbors. */ if (zif->brslave_info.br_if) { - zvni_send_add_to_client(zvni); - zvni_read_mac_neigh(zvni, ifp); + zebra_evpn_send_add_to_client(zevpn); + zebra_evpn_read_mac_neigh(zevpn, ifp); } } @@ -8994,7 +4614,7 @@ int zebra_vxlan_if_del(struct interface *ifp) vni_t vni; struct zebra_if *zif = NULL; struct zebra_l2info_vxlan *vxl = NULL; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; /* Check if EVPN is enabled. */ @@ -9027,8 +4647,8 @@ int zebra_vxlan_if_del(struct interface *ifp) ifp->ifindex); /* Locate hash entry; it is expected to exist. */ - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { zlog_debug( "Failed to locate VNI hash at del, IF %s(%u) VNI %u", ifp->name, ifp->ifindex, vni); @@ -9036,25 +4656,24 @@ int zebra_vxlan_if_del(struct interface *ifp) } /* remove from l3-vni list */ - zl3vni = zl3vni_from_vrf(zvni->vrf_id); + zl3vni = zl3vni_from_vrf(zevpn->vrf_id); if (zl3vni) - listnode_delete(zl3vni->l2vnis, zvni); - + listnode_delete(zl3vni->l2vnis, zevpn); /* Delete VNI from BGP. */ - zvni_send_del_to_client(zvni->vni); + zebra_evpn_send_del_to_client(zevpn); /* Free up all neighbors and MAC, if any. */ - zvni_neigh_del_all(zvni, 0, 0, DEL_ALL_NEIGH); - zvni_mac_del_all(zvni, 0, 0, DEL_ALL_MAC); + zebra_evpn_neigh_del_all(zevpn, 0, 0, DEL_ALL_NEIGH); + zebra_evpn_mac_del_all(zevpn, 0, 0, DEL_ALL_MAC); /* Free up all remote VTEPs, if any. */ - zvni_vtep_del_all(zvni, 0); + zebra_evpn_vtep_del_all(zevpn, 0); /* Delete the hash entry. */ - if (zvni_del(zvni)) { + if (zebra_evpn_vxlan_del(zevpn)) { flog_err(EC_ZEBRA_VNI_DEL_FAILED, - "Failed to del VNI hash %p, IF %s(%u) VNI %u", - zvni, ifp->name, ifp->ifindex, zvni->vni); + "Failed to del EVPN hash %p, IF %s(%u) VNI %u", + zevpn, ifp->name, ifp->ifindex, zevpn->vni); return -1; } } @@ -9069,7 +4688,7 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags) vni_t vni; struct zebra_if *zif = NULL; struct zebra_l2info_vxlan *vxl = NULL; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; /* Check if EVPN is enabled. */ @@ -9140,10 +4759,10 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags) } else { /* Update VNI hash. */ - zvni = zvni_lookup(vni); - if (!zvni) { + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { zlog_debug( - "Failed to find L2-VNI hash on update, IF %s(%u) VNI %u", + "Failed to find EVPN hash on update, IF %s(%u) VNI %u", ifp->name, ifp->ifindex, vni); return -1; } @@ -9160,10 +4779,10 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags) && (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) { /* Delete from client, remove all remote VTEPs */ /* Also, free up all MACs and neighbors. */ - zvni_send_del_to_client(zvni->vni); - zvni_neigh_del_all(zvni, 1, 0, DEL_ALL_NEIGH); - zvni_mac_del_all(zvni, 1, 0, DEL_ALL_MAC); - zvni_vtep_del_all(zvni, 1); + zebra_evpn_send_del_to_client(zevpn); + zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH); + zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC); + zebra_evpn_vtep_del_all(zevpn, 1); return 0; } @@ -9172,20 +4791,23 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags) /* Remove all existing local neigh and MACs for this VNI * (including from BGP) */ - zvni_neigh_del_all(zvni, 0, 1, DEL_LOCAL_MAC); - zvni_mac_del_all(zvni, 0, 1, DEL_LOCAL_MAC); + zebra_evpn_neigh_del_all(zevpn, 0, 1, DEL_LOCAL_MAC); + zebra_evpn_mac_del_all(zevpn, 0, 1, DEL_LOCAL_MAC); } - if (zvni->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr || - zvni->mcast_grp.s_addr != vxl->mcast_grp.s_addr) { - zebra_vxlan_sg_deref(zvni->local_vtep_ip, - zvni->mcast_grp); + if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr || + zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) { + zebra_vxlan_sg_deref(zevpn->local_vtep_ip, + zevpn->mcast_grp); zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp); - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->mcast_grp = vxl->mcast_grp; + zevpn->local_vtep_ip = vxl->vtep_ip; + zevpn->mcast_grp = vxl->mcast_grp; + /* on local vtep-ip check if ES orig-ip + * needs to be updated + */ + zebra_evpn_es_set_base_evpn(zevpn); } - zvni->vxlan_if = ifp; - + zevpn_vxlan_if_set(zevpn, ifp, true /* set */); /* Take further actions needed. * Note that if we are here, there is a change of interest. */ @@ -9198,7 +4820,7 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags) & (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE | ZEBRA_VXLIF_MCAST_GRP_CHANGE)) - zvni_send_add_to_client(zvni); + zebra_evpn_send_add_to_client(zevpn); /* If there is a valid new master or a VLAN mapping change, * read and populate local MACs and neighbors. @@ -9206,22 +4828,22 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags) * for this VNI (based on new VLAN). */ if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) - zvni_read_mac_neigh(zvni, ifp); + zebra_evpn_read_mac_neigh(zevpn, ifp); else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) { struct mac_walk_ctx m_wctx; struct neigh_walk_ctx n_wctx; - zvni_read_mac_neigh(zvni, ifp); + zebra_evpn_read_mac_neigh(zevpn, ifp); memset(&m_wctx, 0, sizeof(struct mac_walk_ctx)); - m_wctx.zvni = zvni; - hash_iterate(zvni->mac_table, zvni_install_mac_hash, - &m_wctx); + m_wctx.zevpn = zevpn; + hash_iterate(zevpn->mac_table, + zebra_evpn_install_mac_hash, &m_wctx); memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx)); - n_wctx.zvni = zvni; - hash_iterate(zvni->neigh_table, zvni_install_neigh_hash, - &n_wctx); + n_wctx.zevpn = zevpn; + hash_iterate(zevpn->neigh_table, + zebra_evpn_install_neigh_hash, &n_wctx); } } @@ -9236,7 +4858,7 @@ int zebra_vxlan_if_add(struct interface *ifp) vni_t vni; struct zebra_if *zif = NULL; struct zebra_l2info_vxlan *vxl = NULL; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; zebra_l3vni_t *zl3vni = NULL; /* Check if EVPN is enabled. */ @@ -9276,35 +4898,39 @@ int zebra_vxlan_if_add(struct interface *ifp) /* process if-add for l2-vni */ struct interface *vlan_if = NULL; - /* Create or update VNI hash. */ - zvni = zvni_lookup(vni); - if (!zvni) { - zvni = zvni_add(vni); - if (!zvni) { + /* Create or update EVPN hash. */ + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) { + zevpn = zebra_evpn_add(vni); + if (!zevpn) { flog_err( EC_ZEBRA_VNI_ADD_FAILED, - "Failed to add VNI hash, IF %s(%u) VNI %u", + "Failed to add EVPN hash, IF %s(%u) VNI %u", ifp->name, ifp->ifindex, vni); return -1; } } - if (zvni->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr || - zvni->mcast_grp.s_addr != vxl->mcast_grp.s_addr) { - zebra_vxlan_sg_deref(zvni->local_vtep_ip, - zvni->mcast_grp); + if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr || + zevpn->mcast_grp.s_addr != vxl->mcast_grp.s_addr) { + zebra_vxlan_sg_deref(zevpn->local_vtep_ip, + zevpn->mcast_grp); zebra_vxlan_sg_ref(vxl->vtep_ip, vxl->mcast_grp); - zvni->local_vtep_ip = vxl->vtep_ip; - zvni->mcast_grp = vxl->mcast_grp; + zevpn->local_vtep_ip = vxl->vtep_ip; + zevpn->mcast_grp = vxl->mcast_grp; + /* on local vtep-ip check if ES orig-ip + * needs to be updated + */ + zebra_evpn_es_set_base_evpn(zevpn); } - zvni->vxlan_if = ifp; + zevpn_vxlan_if_set(zevpn, ifp, true /* set */); vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if); if (vlan_if) { - zvni->vrf_id = vlan_if->vrf_id; + zevpn->vrf_id = vlan_if->vrf_id; zl3vni = zl3vni_from_vrf(vlan_if->vrf_id); if (zl3vni) - listnode_add_sort(zl3vni->l2vnis, zvni); + listnode_add_sort(zl3vni->l2vnis, zevpn); } if (IS_ZEBRA_DEBUG_VXLAN) { @@ -9331,10 +4957,10 @@ int zebra_vxlan_if_add(struct interface *ifp) return 0; /* Inform BGP */ - zvni_send_add_to_client(zvni); + zebra_evpn_send_add_to_client(zevpn); /* Read and populate local MACs and neighbors */ - zvni_read_mac_neigh(zvni, ifp); + zebra_evpn_read_mac_neigh(zevpn, ifp); } return 0; @@ -9412,7 +5038,7 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni, : "NIL"); /* formulate l2vni list */ - hash_iterate(zvrf_evpn->vni_table, zvni_add_to_l3vni_list, + hash_iterate(zvrf_evpn->evpn_table, zevpn_add_to_l3vni_list, zl3vni); if (is_l3vni_oper_up(zl3vni)) @@ -9480,8 +5106,15 @@ int zebra_vxlan_vrf_disable(struct zebra_vrf *zvrf) if (!zl3vni) return 0; - zl3vni->vrf_id = VRF_UNKNOWN; zebra_vxlan_process_l3vni_oper_down(zl3vni); + + /* delete and uninstall all rmacs */ + hash_iterate(zl3vni->rmac_table, zl3vni_del_rmac_hash_entry, zl3vni); + /* delete and uninstall all next-hops */ + hash_iterate(zl3vni->nh_table, zl3vni_del_nh_hash_entry, zl3vni); + + zl3vni->vrf_id = VRF_UNKNOWN; + return 0; } @@ -9535,7 +5168,7 @@ void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS) /* Install or uninstall flood entries corresponding to * remote VTEPs. */ - hash_iterate(zvrf->vni_table, zvni_handle_flooding_remote_vteps, + hash_iterate(zvrf->evpn_table, zebra_evpn_handle_flooding_remote_vteps, zvrf); stream_failure: @@ -9551,7 +5184,7 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS) struct stream *s; int advertise; vni_t vni = 0; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; struct interface *ifp = NULL; if (!EVPN_ENABLED(zvrf)) { @@ -9578,11 +5211,13 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS) if (advertise) { zvrf->advertise_svi_macip = advertise; - hash_iterate(zvrf->vni_table, - zvni_gw_macip_add_for_vni_hash, NULL); + hash_iterate(zvrf->evpn_table, + zebra_evpn_gw_macip_add_for_evpn_hash, + NULL); } else { - hash_iterate(zvrf->vni_table, - zvni_svi_macip_del_for_vni_hash, NULL); + hash_iterate(zvrf->evpn_table, + zebra_evpn_svi_macip_del_for_evpn_hash, + NULL); zvrf->advertise_svi_macip = advertise; } @@ -9591,27 +5226,27 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS) struct zebra_l2info_vxlan zl2_info; struct interface *vlan_if = NULL; - zvni = zvni_lookup(vni); - if (!zvni) + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) return; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( "EVPN SVI macip Adv %s on VNI %d , currently %s", advertise ? "enabled" : "disabled", vni, - advertise_svi_macip_enabled(zvni) + advertise_svi_macip_enabled(zevpn) ? "enabled" : "disabled"); - if (zvni->advertise_svi_macip == advertise) + if (zevpn->advertise_svi_macip == advertise) return; /* Store flag even though SVI is not present. * Once SVI comes up triggers self MAC-IP route add. */ - zvni->advertise_svi_macip = advertise; + zevpn->advertise_svi_macip = advertise; - ifp = zvni->vxlan_if; + ifp = zevpn->vxlan_if; if (!ifp) return; @@ -9629,10 +5264,10 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS) if (advertise) { /* Add primary SVI MAC-IP */ - zvni_add_macip_for_intf(vlan_if, zvni); + zebra_evpn_add_macip_for_intf(vlan_if, zevpn); } else { /* Del primary SVI MAC-IP */ - zvni_del_macip_for_intf(vlan_if, zvni); + zebra_evpn_del_macip_for_intf(vlan_if, zevpn); } } @@ -9649,7 +5284,7 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS) struct stream *s; int advertise; vni_t vni = 0; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; struct interface *ifp = NULL; struct zebra_if *zif = NULL; struct zebra_l2info_vxlan zl2_info; @@ -9665,22 +5300,22 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS) STREAM_GETC(s, advertise); STREAM_GET(&vni, s, 3); - zvni = zvni_lookup(vni); - if (!zvni) + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) return; - if (zvni->advertise_subnet == advertise) + if (zevpn->advertise_subnet == advertise) return; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s", advertise ? "enabled" : "disabled", vni, - zvni->advertise_subnet ? "enabled" : "disabled"); + zevpn->advertise_subnet ? "enabled" : "disabled"); - zvni->advertise_subnet = advertise; + zevpn->advertise_subnet = advertise; - ifp = zvni->vxlan_if; + ifp = zevpn->vxlan_if; if (!ifp) return; @@ -9697,10 +5332,10 @@ void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS) if (!vlan_if) return; - if (zvni->advertise_subnet) - zvni_advertise_subnet(zvni, vlan_if, 1); + if (zevpn->advertise_subnet) + zebra_evpn_advertise_subnet(zevpn, vlan_if, 1); else - zvni_advertise_subnet(zvni, vlan_if, 0); + zebra_evpn_advertise_subnet(zevpn, vlan_if, 0); stream_failure: return; @@ -9715,7 +5350,7 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) struct stream *s; int advertise; vni_t vni = 0; - zebra_vni_t *zvni = NULL; + zebra_evpn_t *zevpn = NULL; struct interface *ifp = NULL; if (!EVPN_ENABLED(zvrf)) { @@ -9741,12 +5376,14 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) zvrf->advertise_gw_macip = advertise; - if (advertise_gw_macip_enabled(zvni)) - hash_iterate(zvrf->vni_table, - zvni_gw_macip_add_for_vni_hash, NULL); + if (advertise_gw_macip_enabled(zevpn)) + hash_iterate(zvrf->evpn_table, + zebra_evpn_gw_macip_add_for_evpn_hash, + NULL); else - hash_iterate(zvrf->vni_table, - zvni_gw_macip_del_for_vni_hash, NULL); + hash_iterate(zvrf->evpn_table, + zebra_evpn_gw_macip_del_for_evpn_hash, + NULL); } else { struct zebra_if *zif = NULL; @@ -9754,23 +5391,23 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) struct interface *vlan_if = NULL; struct interface *vrr_if = NULL; - zvni = zvni_lookup(vni); - if (!zvni) + zevpn = zebra_evpn_lookup(vni); + if (!zevpn) return; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( "EVPN gateway macip Adv %s on VNI %d , currently %s", advertise ? "enabled" : "disabled", vni, - advertise_gw_macip_enabled(zvni) ? "enabled" + advertise_gw_macip_enabled(zevpn) ? "enabled" : "disabled"); - if (zvni->advertise_gw_macip == advertise) + if (zevpn->advertise_gw_macip == advertise) return; - zvni->advertise_gw_macip = advertise; + zevpn->advertise_gw_macip = advertise; - ifp = zvni->vxlan_if; + ifp = zevpn->vxlan_if; if (!ifp) return; @@ -9787,22 +5424,22 @@ void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS) if (!vlan_if) return; - if (advertise_gw_macip_enabled(zvni)) { + if (advertise_gw_macip_enabled(zevpn)) { /* Add primary SVI MAC-IP */ - zvni_add_macip_for_intf(vlan_if, zvni); + zebra_evpn_add_macip_for_intf(vlan_if, zevpn); /* Add VRR MAC-IP - if any*/ vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); if (vrr_if) - zvni_add_macip_for_intf(vrr_if, zvni); + zebra_evpn_add_macip_for_intf(vrr_if, zevpn); } else { /* Del primary MAC-IP */ - zvni_del_macip_for_intf(vlan_if, zvni); + zebra_evpn_del_macip_for_intf(vlan_if, zevpn); /* Del VRR MAC-IP - if any*/ vrr_if = zebra_get_vrr_intf_for_svi(vlan_if); if (vrr_if) - zvni_del_macip_for_intf(vrr_if, zvni); + zebra_evpn_del_macip_for_intf(vrr_if, zevpn); } } @@ -9810,25 +5447,6 @@ stream_failure: return; } -static int macfdb_read_ns(struct ns *ns, - void *_in_param __attribute__((unused)), - void **out_param __attribute__((unused))) -{ - struct zebra_ns *zns = ns->info; - - macfdb_read(zns); - return NS_WALK_CONTINUE; -} - -static int neigh_read_ns(struct ns *ns, - void *_in_param __attribute__((unused)), - void **out_param __attribute__((unused))) -{ - struct zebra_ns *zns = ns->info; - - neigh_read(zns); - return NS_WALK_CONTINUE; -} /* * Handle message from client to learn (or stop learning) about VNIs and MACs. @@ -9870,23 +5488,30 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) /* Note BUM handling */ zvrf->vxlan_flood_ctrl = flood_ctrl; - /* Build VNI hash table and inform BGP. */ - zvni_build_hash_table(); + /* Replay all ESs */ + zebra_evpn_es_send_all_to_client(true /* add */); + + /* Build EVPN hash table and inform BGP. */ + zevpn_build_hash_table(); /* Add all SVI (L3 GW) MACs to BGP*/ - hash_iterate(zvrf->vni_table, zvni_gw_macip_add_for_vni_hash, - NULL); + hash_iterate(zvrf->evpn_table, + zebra_evpn_gw_macip_add_for_evpn_hash, NULL); /* Read the MAC FDB */ - ns_walk_func(macfdb_read_ns, NULL, NULL); + macfdb_read(zvrf->zns); /* Read neighbors */ - ns_walk_func(neigh_read_ns, NULL, NULL); + neigh_read(zvrf->zns); } else { - /* Cleanup VTEPs for all VNIs - uninstall from + /* Cleanup VTEPs for all EVPNs - uninstall from * kernel and free entries. */ - hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); + hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, + zvrf); + + /* Delete all ESs in BGP */ + zebra_evpn_es_send_all_to_client(false /* add */); /* cleanup all l3vnis */ hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL); @@ -9900,35 +5525,41 @@ stream_failure: } /* - * Allocate VNI hash table for this VRF and do other initialization. + * Allocate EVPN hash table for this VRF and do other initialization. * NOTE: Currently supported only for default VRF. */ void zebra_vxlan_init_tables(struct zebra_vrf *zvrf) { if (!zvrf) return; - zvrf->vni_table = hash_create(vni_hash_keymake, vni_hash_cmp, - "Zebra VRF VNI Table"); + zvrf->evpn_table = + hash_create(zebra_evpn_hash_keymake, zebra_evpn_hash_cmp, + "Zebra VRF EVPN Table"); zvrf->vxlan_sg_table = hash_create(zebra_vxlan_sg_hash_key_make, zebra_vxlan_sg_hash_eq, "Zebra VxLAN SG Table"); } -/* Cleanup VNI info, but don't free the table. */ +/* Cleanup EVPN info, but don't free the table. */ void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf) { + struct zebra_vrf *evpn_zvrf = zebra_vrf_get_evpn(); + if (!zvrf) return; - hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); + hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf); hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_cleanup, NULL); + + if (zvrf == evpn_zvrf) + zebra_evpn_es_cleanup(); } -/* Close all VNI handling */ +/* Close all EVPN handling */ void zebra_vxlan_close_tables(struct zebra_vrf *zvrf) { if (!zvrf) return; - hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); - hash_free(zvrf->vni_table); + hash_iterate(zvrf->evpn_table, zebra_evpn_vxlan_cleanup_all, zvrf); + hash_free(zvrf->evpn_table); } /* init the l3vni table */ @@ -9937,12 +5568,14 @@ void zebra_vxlan_init(void) zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp, "Zebra VRF L3 VNI table"); zrouter.evpn_vrf = NULL; + zebra_evpn_mh_init(); } /* free l3vni table */ void zebra_vxlan_disable(void) { hash_free(zrouter.l3vni_table); + zebra_evpn_mh_terminate(); } /* get the l3vni svi ifindex */ @@ -9957,128 +5590,6 @@ ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id) return zl3vni->svi_if->ifindex; } -static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t) -{ - struct zebra_vrf *zvrf = NULL; - zebra_neigh_t *nbr = NULL; - zebra_vni_t *zvni = NULL; - char buf1[INET6_ADDRSTRLEN]; - char buf2[ETHER_ADDR_STRLEN]; - - nbr = THREAD_ARG(t); - - /* since this is asynchronous we need sanity checks*/ - zvrf = vrf_info_lookup(nbr->zvni->vrf_id); - if (!zvrf) - return 0; - - zvni = zvni_lookup(nbr->zvni->vni); - if (!zvni) - return 0; - - nbr = zvni_neigh_lookup(zvni, &nbr->ip); - if (!nbr) - return 0; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired", - __func__, - prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)), - ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), nbr->flags, - nbr->dad_count, zvni->vni); - - UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); - nbr->dad_count = 0; - nbr->detect_start_time.tv_sec = 0; - nbr->detect_start_time.tv_usec = 0; - nbr->dad_dup_detect_time = 0; - nbr->dad_ip_auto_recovery_timer = NULL; - ZEBRA_NEIGH_SET_ACTIVE(nbr); - - /* Send to BGP */ - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) { - zvni_neigh_send_add_to_client(zvni->vni, &nbr->ip, &nbr->emac, - nbr->flags, nbr->loc_seq); - } else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) { - zvni_neigh_install(zvni, nbr); - } - - return 0; -} - -static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t) -{ - struct zebra_vrf *zvrf = NULL; - zebra_mac_t *mac = NULL; - zebra_vni_t *zvni = NULL; - struct listnode *node = NULL; - zebra_neigh_t *nbr = NULL; - char buf[ETHER_ADDR_STRLEN]; - - mac = THREAD_ARG(t); - - /* since this is asynchronous we need sanity checks*/ - zvrf = vrf_info_lookup(mac->zvni->vrf_id); - if (!zvrf) - return 0; - - zvni = zvni_lookup(mac->zvni->vni); - if (!zvni) - return 0; - - mac = zvni_mac_lookup(zvni, &mac->macaddr); - if (!mac) - return 0; - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr mac %s flags 0x%x learn count %u host count %u auto recovery expired", - __func__, - prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - mac->flags, mac->dad_count, listcount(mac->neigh_list)); - - /* Remove all IPs as duplicate associcated with this MAC */ - for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) { - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) { - if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) - ZEBRA_NEIGH_SET_INACTIVE(nbr); - else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) - zvni_neigh_install(zvni, nbr); - } - - UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); - nbr->dad_count = 0; - nbr->detect_start_time.tv_sec = 0; - nbr->dad_dup_detect_time = 0; - } - - UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE); - mac->dad_count = 0; - mac->detect_start_time.tv_sec = 0; - mac->detect_start_time.tv_usec = 0; - mac->dad_dup_detect_time = 0; - mac->dad_mac_auto_recovery_timer = NULL; - - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { - /* Inform to BGP */ - if (zvni_mac_send_add_to_client(zvni->vni, &mac->macaddr, - mac->flags, mac->loc_seq)) - return -1; - - /* Process all neighbors associated with this MAC. */ - zvni_process_neigh_on_local_mac_change(zvni, mac, 0); - - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - zvni_process_neigh_on_remote_mac_add(zvni, mac); - - /* Install the entry. */ - zvni_mac_install(zvni, mac); - } - - return 0; -} - /************************** vxlan SG cache management ************************/ /* Inform PIM about the mcast group */ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf, @@ -10330,87 +5841,6 @@ void zebra_vxlan_sg_replay(ZAPI_HANDLER_ARGS) hash_iterate(zvrf->vxlan_sg_table, zebra_vxlan_sg_replay_send, NULL); } -/************************** EVPN BGP config management ************************/ -/* Notify Local MACs to the clienti, skips GW MAC */ -static void zvni_send_mac_hash_entry_to_client(struct hash_bucket *bucket, - void *arg) -{ - struct mac_walk_ctx *wctx = arg; - zebra_mac_t *zmac = bucket->data; - - if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_DEF_GW)) - return; - - if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) - zvni_mac_send_add_to_client(wctx->zvni->vni, &zmac->macaddr, - zmac->flags, zmac->loc_seq); -} - -/* Iterator to Notify Local MACs of a L2VNI */ -static void zvni_send_mac_to_client(zebra_vni_t *zvni) -{ - struct mac_walk_ctx wctx; - - if (!zvni->mac_table) - return; - - memset(&wctx, 0, sizeof(struct mac_walk_ctx)); - wctx.zvni = zvni; - - hash_iterate(zvni->mac_table, zvni_send_mac_hash_entry_to_client, - &wctx); -} - -/* Notify Neighbor entries to the Client, skips the GW entry */ -static void zvni_send_neigh_hash_entry_to_client(struct hash_bucket *bucket, - void *arg) -{ - struct mac_walk_ctx *wctx = arg; - zebra_neigh_t *zn = bucket->data; - zebra_mac_t *zmac = NULL; - - if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_DEF_GW)) - return; - - if (CHECK_FLAG(zn->flags, ZEBRA_NEIGH_LOCAL) && - IS_ZEBRA_NEIGH_ACTIVE(zn)) { - zmac = zvni_mac_lookup(wctx->zvni, &zn->emac); - if (!zmac) - return; - - zvni_neigh_send_add_to_client(wctx->zvni->vni, &zn->ip, - &zn->emac, zn->flags, - zn->loc_seq); - } -} - -/* Iterator of a specific L2VNI */ -static void zvni_send_neigh_to_client(zebra_vni_t *zvni) -{ - struct neigh_walk_ctx wctx; - - memset(&wctx, 0, sizeof(struct neigh_walk_ctx)); - wctx.zvni = zvni; - - hash_iterate(zvni->neigh_table, zvni_send_neigh_hash_entry_to_client, - &wctx); -} - -static void zvni_evpn_cfg_cleanup(struct hash_bucket *bucket, void *ctxt) -{ - zebra_vni_t *zvni = NULL; - - zvni = (zebra_vni_t *)bucket->data; - zvni->advertise_gw_macip = 0; - zvni->advertise_svi_macip = 0; - zvni->advertise_subnet = 0; - - zvni_neigh_del_all(zvni, 1, 0, - DEL_REMOTE_NEIGH | DEL_REMOTE_NEIGH_FROM_VTEP); - zvni_mac_del_all(zvni, 1, 0, - DEL_REMOTE_MAC | DEL_REMOTE_MAC_FROM_VTEP); - zvni_vtep_del_all(zvni, 1); -} /* Cleanup EVPN configuration of a specific VRF */ static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf) @@ -10422,7 +5852,7 @@ static void zebra_evpn_vrf_cfg_cleanup(struct zebra_vrf *zvrf) zvrf->advertise_svi_macip = 0; zvrf->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL; - hash_iterate(zvrf->vni_table, zvni_evpn_cfg_cleanup, NULL); + hash_iterate(zvrf->evpn_table, zebra_evpn_cfg_cleanup, NULL); if (zvrf->l3vni) zl3vni = zl3vni_lookup(zvrf->l3vni); |
