From b6938a74e5f73a2f29df12efb46e7121e79d3b86 Mon Sep 17 00:00:00 2001 From: Mitesh Kanjariya Date: Wed, 5 Jul 2017 15:03:14 -0700 Subject: [PATCH] zebra: Provide neigh-mac tie-in in zebra Currently, FRR does not do any linking between local MACs and neighbors. We found this necessary when dealing with centralized GW. A neigh is considered local only when the mac is learnt locally as well. Ticket: CM-16544 Review: CCR-6388 Unit-test: Manual/Evpn-Smoke Signed-off-by: Mitesh Kanjariya --- zebra/zebra_vxlan.c | 331 +++++++++++++++++++++++++++++++++--- zebra/zebra_vxlan_private.h | 19 ++- 2 files changed, 323 insertions(+), 27 deletions(-) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index cb555ff1ee..393ac997b3 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -74,7 +74,8 @@ static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni, static unsigned int neigh_hash_keymake(void *p); static int neigh_cmp(const void *p1, const void *p2); static void *zvni_neigh_alloc(void *p); -static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip); +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 int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg); static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall, @@ -200,10 +201,13 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json) json_object_string_add(json, "mac", buf1); } if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { - if (json == NULL) + if (json == NULL) { vty_out(vty, " Remote VTEP: %s", inet_ntoa(n->r_vtep_ip)); - else + vty_out(vty, " State: %s", IS_ZEBRA_NEIGH_ACTIVE(n) + ? "Active" + : "Inactive"); + } else json_object_string_add(json, "remoteVtep", inet_ntoa(n->r_vtep_ip)); } @@ -353,7 +357,10 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet, static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) { struct vty *vty; + zebra_neigh_t *n = NULL; + struct listnode *node = NULL; char buf1[20]; + char buf2[INET6_ADDRSTRLEN]; vty = (struct vty *)ctxt; vty_out(vty, "MAC: %s", @@ -371,11 +378,30 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) 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 { + } 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 "); + } + vty_out(vty, " ARP ref: %u\n", mac->neigh_refcnt); + + /* 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)), + CHECK_FLAG(n->flags, ZEBRA_MAC_LOCAL) + ? (IS_ZEBRA_NEIGH_ACTIVE(n) + ? "Active" + : "Inactive") + : ""); + } } - vty_out(vty, " ARP ref: %u", mac->neigh_refcnt); + vty_out(vty, "\n"); } @@ -432,7 +458,7 @@ static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt) else json_object_object_add(json_mac_hdr, buf1, json_mac); wctx->count++; - } else { + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) { if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip)) { @@ -789,16 +815,26 @@ static void *zvni_neigh_alloc(void *p) /* * Add neighbor entry. */ -static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip) +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; + + /* Associate the neigh to mac */ + zmac = zvni_mac_lookup(zvni, mac); + if (zmac) + listnode_add_sort(zmac->neigh_list, n); + return n; } @@ -808,6 +844,11 @@ static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip) 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); /* Free the VNI hash entry and allocated memory. */ tmp_n = hash_release(zvni->neigh_table, n); @@ -907,6 +948,146 @@ static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip) return n; } +/* Process all neigh associated to a mac upon local mac add event */ +static void zvni_process_neigh_on_local_mac_add(struct zebra_vrf *zvrf, + zebra_vni_t *zvni, + zebra_mac_t *zmac) +{ + zebra_neigh_t *n = NULL; + struct listnode *node = NULL; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + /* MAC is learnt locally, program all inactive neigh + * pointing to this mac */ + if (IS_ZEBRA_NEIGH_INACTIVE(n)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u: neigh %s (MAC %s) on VNI %u is now ACTIVE", + zvrf_id(zvrf), + ipaddr2str(&n->ip, buf2, + sizeof(buf2)), + prefix_mac2str(&n->emac, buf, + sizeof(buf)), + zvni->vni); + + ZEBRA_NEIGH_SET_ACTIVE(n); + zvni_neigh_send_add_to_client( + zvrf, zvni->vni, &n->ip, &n->emac, 0); + } else { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u: neigh %s (MAC %s) on VNI %u should NOT be ACTIVE", + zvrf_id(zvrf), + ipaddr2str(&n->ip, buf2, + sizeof(buf2)), + prefix_mac2str(&n->emac, buf, + sizeof(buf)), + zvni->vni); + } + } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { + /* TODO: assume the neigh has moved too ?? */ + } + } +} + +/* Process all neigh associated to a mac upon local mac del event */ +static void zvni_process_neigh_on_local_mac_del(struct zebra_vrf *zvrf, + zebra_vni_t *zvni, + zebra_mac_t *zmac) +{ + zebra_neigh_t *n = NULL; + struct listnode *node = NULL; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + if (IS_ZEBRA_NEIGH_ACTIVE(n)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u: neigh %s (MAC %s) on VNI %u is now INACTIVE", + zvrf_id(zvrf), + ipaddr2str(&n->ip, buf2, + sizeof(buf2)), + prefix_mac2str(&n->emac, buf, + sizeof(buf)), + zvni->vni); + + ZEBRA_NEIGH_SET_INACTIVE(n); + zvni_neigh_send_del_to_client( + zvrf, zvni->vni, &n->ip, &n->emac, 0); + } + } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_err( + "%u: local MAC %s getting deleted on VNI %u has remote neigh %s", + zvrf_id(zvrf), + prefix_mac2str(&n->emac, buf, + sizeof(buf)), + zvni->vni, + ipaddr2str(&n->ip, buf2, sizeof(buf2))); + } + } +} + +/* process all neigh associated to a mac entry upon remote mac add */ +static void zvni_process_neigh_on_remote_mac_add(struct zebra_vrf *zvrf, + zebra_vni_t *zvni, + zebra_mac_t *zmac) +{ + zebra_neigh_t *n = NULL; + struct listnode *node = NULL; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + if (IS_ZEBRA_NEIGH_ACTIVE(n)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u: neigh %s (MAC %s) on VNI %u INACTIVE", + zvrf_id(zvrf), + ipaddr2str(&n->ip, buf2, + sizeof(buf2)), + prefix_mac2str(&n->emac, buf, + sizeof(buf)), + zvni->vni); + + ZEBRA_NEIGH_SET_INACTIVE(n); + zvni_neigh_send_del_to_client( + zvrf, zvni->vni, &n->ip, &n->emac, 0); + } + } + } +} + +/* process all neigh associated to mac entry upon remote mac del */ +static void zvni_process_neigh_on_remote_mac_del(struct zebra_vrf *zvrf, + zebra_vni_t *zvni, + zebra_mac_t *zmac) +{ + zebra_neigh_t *n = NULL; + struct listnode *node = NULL; + char buf[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + + for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) { + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_err( + "%u: remote MAC %s getting deleted on VNI %u has local neigh %s", + zvrf_id(zvrf), + prefix_mac2str(&n->emac, buf, + sizeof(buf)), + zvni->vni, + ipaddr2str(&n->ip, buf2, sizeof(buf2))); + } + } +} + /* * Inform BGP about local neighbor addition. */ @@ -1153,7 +1334,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni, n = zvni_neigh_lookup(zvni, ip); if (!n) { - n = zvni_neigh_add(zvni, ip); + n = zvni_neigh_add(zvni, ip, macaddr); if (!n) { zlog_err( "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", @@ -1366,6 +1547,9 @@ static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr) mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc); assert(mac); + mac->neigh_list = list_new(); + mac->neigh_list->cmp = (int (*)(void *, void *))neigh_cmp; + return mac; } @@ -1376,6 +1560,8 @@ static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac) { zebra_mac_t *tmp_mac; + list_delete(mac->neigh_list); + /* Free the VNI hash entry and allocated memory. */ tmp_mac = hash_release(zvni->mac_table, mac); if (tmp_mac) @@ -2599,6 +2785,8 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp, zebra_neigh_t *n; struct zebra_vrf *zvrf; char buf[INET6_ADDRSTRLEN]; + char buf2[ETHER_ADDR_STRLEN]; + zebra_mac_t *zmac; /* We are only interested in neighbors on an SVI that resides on top * of a VxLAN bridge. @@ -2623,6 +2811,18 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp, if (!n) return 0; + zmac = zvni_mac_lookup(zvni, &n->emac); + if (!zmac) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_err( + "%u: trying to del a neigh %s without a mac %s on VNI %u", + ifp->vrf_id, 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. */ @@ -2636,11 +2836,18 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp, assert(zvrf); /* Remove neighbor from BGP. */ - zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac, 0); + if (IS_ZEBRA_NEIGH_ACTIVE(n)) + zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac, + 0); /* 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; } @@ -2657,6 +2864,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp, zebra_vni_t *zvni; zebra_neigh_t *n; struct zebra_vrf *zvrf; + zebra_mac_t *zmac; char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; int send_upd = 1, send_del = 0; @@ -2681,6 +2889,30 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp, ifp->ifindex, state, ext_learned ? "ext-learned " : "", zvni->vni); + /* create a dummy MAC if the MAC is not already present */ + zmac = zvni_mac_lookup(zvni, macaddr); + if (!zmac) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u: AUTO MAC %s created for neigh %s on VNI %u", + ifp->vrf_id, + prefix_mac2str(macaddr, buf, sizeof(buf)), + ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni); + + zmac = zvni_mac_add(zvni, macaddr); + if (!zmac) { + zlog_warn("%u:Failed to add MAC %s VNI %u", + zvrf_id(zvrf), + prefix_mac2str(macaddr, buf, sizeof(buf)), + zvni->vni); + return -1; + } + + memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info)); + memset(&zmac->flags, 0, sizeof(u_int32_t)); + SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO); + } + /* If same entry already exists, it might be a change or it might be a * move from remote to local. */ @@ -2716,7 +2948,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp, n->r_vtep_ip.s_addr = 0; } } else { - n = zvni_neigh_add(zvni, ip); + n = zvni_neigh_add(zvni, ip, macaddr); if (!n) { zlog_err( "%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u", @@ -2734,13 +2966,34 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp, /* Set "local" forwarding info. */ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); - memcpy(&n->emac, macaddr, ETH_ALEN); n->ifindex = ifp->ifindex; + /* Before we program this in BGP, we need to check if MAC is locally + * learnt as well */ + if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u: Skipping neigh %s add to client as MAC %s is not local on VNI %u", + ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), + zvni->vni); + + return 0; + } + /* Inform BGP if required. */ - if (send_upd) + if (send_upd) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%u: neigh %s (MAC %s) is now ACTIVE on VNI %u", + ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), + zvni->vni); + + ZEBRA_NEIGH_SET_ACTIVE(n); return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, macaddr, 0); + } return 0; } @@ -2868,6 +3121,9 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, } } else { if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { + zvni_process_neigh_on_remote_mac_del(zvrf, zvni, + mac); + if (!mac->neigh_refcnt) { zvni_mac_uninstall(zvni, mac, 0); zvni_mac_del(zvni, mac); @@ -3024,6 +3280,8 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, else UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); + zvni_process_neigh_on_remote_mac_add(zvrf, zvni, mac); + /* Install the entry. */ zvni_mac_install(zvni, mac); } @@ -3047,7 +3305,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, if (update_neigh) { if (!n) { - n = zvni_neigh_add(zvni, &ip); + n = zvni_neigh_add(zvni, &ip, &macaddr); if (!n) { zlog_warn( "%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", @@ -3070,12 +3328,12 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, if (old_mac) zvni_deref_ip2mac(zvni, old_mac, 1); mac->neigh_refcnt++; + memcpy(&n->emac, &macaddr, ETH_ALEN); } /* Set "remote" forwarding info. */ UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); /* TODO: Handle MAC change. */ - memcpy(&n->emac, &macaddr, ETH_ALEN); n->r_vtep_ip = vtep_ip; SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); @@ -3143,8 +3401,16 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp, zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr, (sticky ? ZEBRA_MAC_TYPE_STICKY : 0)); - /* Delete this MAC entry. */ - zvni_mac_del(zvni, mac); + /* + * 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); + SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + } return 0; } @@ -3251,8 +3517,19 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr, (sticky ? ZEBRA_MAC_TYPE_STICKY : 0)); - /* Delete this MAC entry. */ - zvni_mac_del(zvni, mac); + /* Update all the neigh entries associated with this mac */ + zvni_process_neigh_on_local_mac_del(zvrf, zvni, mac); + + /* + * 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); + SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); + } return 0; } @@ -3307,6 +3584,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, ? 1 : 0; + /* * return if nothing has changed. * inform bgp if sticky flag has changed @@ -3327,11 +3605,12 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, ifp->name, ifp->ifindex, vid, zvni->vni); return 0; - } else if (mac_sticky != sticky) + } else if (mac_sticky != sticky) { add = 1; - else + } else { add = 0; /* This is an update of local interface. */ + } } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { /* * If we have already learned the MAC as a remote sticky @@ -3367,8 +3646,9 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, /* Set "local" forwarding info. */ UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); - memset(&mac->fwd_info, 0, sizeof(mac->fwd_info)); + 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.vid = vid; @@ -3378,10 +3658,11 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); /* Inform BGP if required. */ - if (add) - return zvni_mac_send_add_to_client( - zvrf, zvni->vni, macaddr, - (sticky ? ZEBRA_MAC_TYPE_STICKY : 0)); + if (add) { + zvni_process_neigh_on_local_mac_add(zvrf, zvni, mac); + return zvni_mac_send_add_to_client(zvrf, zvni->vni, macaddr, + sticky); + } return 0; } diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index 2bf00291e7..8539311eab 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -115,6 +115,9 @@ struct zebra_mac_t_ { } fwd_info; u_int32_t neigh_refcnt; + + /* List of neigh associated with this mac */ + struct list *neigh_list; }; /* @@ -140,6 +143,16 @@ struct mac_walk_ctx { struct json_object *json; /* Used for JSON Output */ }; +enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 }; + +#define IS_ZEBRA_NEIGH_ACTIVE(n) n->state == ZEBRA_NEIGH_ACTIVE + +#define IS_ZEBRA_NEIGH_INACTIVE(n) n->state == ZEBRA_NEIGH_INACTIVE + +#define ZEBRA_NEIGH_SET_ACTIVE(n) n->state = ZEBRA_NEIGH_ACTIVE + +#define ZEBRA_NEIGH_SET_INACTIVE(n) n->state = ZEBRA_NEIGH_INACTIVE + /* * Neighbor hash table. * @@ -162,8 +175,10 @@ struct zebra_neigh_t_ { ifindex_t ifindex; u_int32_t flags; -#define ZEBRA_NEIGH_LOCAL 0x01 -#define ZEBRA_NEIGH_REMOTE 0x02 +#define ZEBRA_NEIGH_LOCAL 0x01 +#define ZEBRA_NEIGH_REMOTE 0x02 + + enum zebra_neigh_state state; /* Remote VTEP IP - applicable only for remote neighbors. */ struct in_addr r_vtep_ip; -- 2.39.5