mirror_frr/zebra/zebra_vxlan_private.h
Anuradha Karuppiah b169fd6fd5 zebra: support for MAC-IP sync routes
MAC-IP routes are used for syncing local entries across redundant
switches in an EVPN-MH setup. A path from a peer that has a local
ES as destination is tagged as a SYNC path. The SYNC path results in the
addition of local MAC and/or local neigh entry in zebra and in the
dataplane.

Implementation overview
=======================
1. Three new flags "local-inactive", "peer-active" and "peer-proxy"
are maintained per-local-MAC and per-local-Neigh entry.
2. The "peer-XXX" flags are set and cleared via SYNC path updates
from BGP. Proxy sync paths result in the setting of "peer-proxy" flag
(and non-proxies result in the "peer-active").
3. A neigh entry that has a "peer-XXX" flag set is programmed as
"static" in the dataplane.
4. A MAC entry that has a "peer-XXX" flag set or is referenced by
a sync-neigh entry (that has a "peer-XXX" flags set) is programmed
as "static" in the dataplane.
5. The sync-seq number is used to normalize the MM seq number across
all the redundant switches i.e. the max MM seq number across all
switches is used by each of the switches. This commit also includes
the changes needed for extended MM seq syncing.
6. A MAC/neigh entry has to be local-active or peer-active to sent to
BGP. An entry that is NOT local-active is sent with the proxy flag (so
BGP can "proxy" advertise it).
7. The "peer-active" flag is aged out by zebra by using a hold_timer
(this is instead of being abruptly dropped on SYNC path delete). This
age-out is needed to handle peer-switch restart (procedures are specified
in draft-rbickhart-evpn-ip-mac-proxy-adv). The holdtime needs to be
sufficiently long to allow an external neighmgr daemon or the dataplane
component to independently probe and establish local reachability of a
host. The MAC and neigh hold time values are configurable.
PS: In the future this probing may happen in FRR itself.

CLI changes to display sync info
================================
MAC
===
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
root@torm-11:mgmt:~# net show evpn mac vni 1000
Number of MACs (local and remote) known for this VNI: 6
Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy
MAC               Type   Flags Intf/Remote ES/VTEP            VLAN  Seq #'s
00:02:00:00:00:25 local        vlan1000                       1000  0/0
02:02:00:00:00:02 local  PI    hostbond1                      1000  0/0
02:02:00:00:00:06 remote       03:00:00:00:00:02:11:00:00:01        0/0
02:02:00:00:00:01 local  X     hostbond1                      1000  0/0
00:00:00:00:00:11 local  PI    hostbond1                      1000  0/0
02:02:00:00:00:05 remote       03:00:00:00:00:02:11:00:00:01        0/0
root@torm-11:mgmt:~#
root@torm-11:mgmt:~# net show evpn mac vni 1000 mac 00:00:00:00:00:11
MAC: 00:00:00:00:00:11
 ESI: 03:00:00:00:00:01:11:00:00:01
 Intf: hostbond1(58) VLAN: 1000
 Sync-info: neigh#: 0 local-inactive peer-active >>>>>>>>>>>>
 Local Seq: 0 Remote Seq: 0
 Neighbors:
    No Neighbors
root@torm-11:mgmt:~#
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
neigh
=====
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
root@torm-11:mgmt:~# net show evpn arp vni 1003
Number of ARPs (local and remote) known for this VNI: 4
Flags: I=local-inactive, P=peer-active, X=peer-proxy
Neighbor             Type   Flags State    MAC               Remote ES/VTEP                 Seq #'s
2001:fee1:0:3::6     local        active   00:02:00:00:00:25                                0/0
45.0.3.66            local  P     active   00:02:00:00:00:66                                0/0
45.0.3.6             local        active   00:02:00:00:00:25                                0/0
fe80::202:ff:fe00:25 local        active   00:02:00:00:00:25                                0/0
root@torm-11:mgmt:~#
root@torm-11:mgmt:~# net show evpn arp vni 1003 ip 45.0.3.66
IP: 45.0.3.66
 Type: local
 State: active
 MAC: 00:02:00:00:00:66
 Sync-info: peer-active >>>>>>>>>>>>>>>>
 Local Seq: 0 Remote Seq: 0
root@torm-11:mgmt:~#
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
2020-08-05 06:46:13 -07:00

587 lines
16 KiB
C

/*
* Zebra VxLAN (EVPN) Data structures and definitions
* These are "internal" to this function.
* Copyright (C) 2016, 2017 Cumulus Networks, Inc.
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _ZEBRA_VXLAN_PRIVATE_H
#define _ZEBRA_VXLAN_PRIVATE_H
#include <zebra.h>
#include "if.h"
#include "linklist.h"
#include "zebra_vxlan.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ERR_STR_SZ 256
/* definitions */
typedef struct zebra_vni_t_ zebra_vni_t;
typedef struct zebra_vtep_t_ zebra_vtep_t;
typedef struct zebra_mac_t_ zebra_mac_t;
typedef struct zebra_neigh_t_ zebra_neigh_t;
typedef struct zebra_l3vni_t_ zebra_l3vni_t;
/*
* VTEP info
*
* Right now, this just has each remote VTEP's IP address.
*/
struct zebra_vtep_t_ {
/* Remote IP. */
/* NOTE: Can only be IPv4 right now. */
struct in_addr vtep_ip;
/* Flood mode (one of enum vxlan_flood_control) based on the PMSI
* tunnel type advertised by the remote VTEP
*/
int flood_control;
/* Links. */
struct zebra_vtep_t_ *next;
struct zebra_vtep_t_ *prev;
};
RB_HEAD(zebra_es_evi_rb_head, zebra_evpn_es_evi);
RB_PROTOTYPE(zebra_es_evi_rb_head, zebra_evpn_es_evi, rb_node,
zebra_es_evi_rb_cmp);
/*
* VNI hash table
*
* Contains information pertaining to a VNI:
* - the list of remote VTEPs (with this VNI)
*/
struct zebra_vni_t_ {
/* VNI - key */
vni_t vni;
/* ES flags */
uint32_t flags;
#define ZVNI_READY_FOR_BGP (1 << 0) /* ready to be sent to BGP */
/* Flag for advertising gw macip */
uint8_t advertise_gw_macip;
/* Flag for advertising svi macip */
uint8_t advertise_svi_macip;
/* Flag for advertising gw macip */
uint8_t advertise_subnet;
/* Corresponding VxLAN interface. */
struct interface *vxlan_if;
/* List of remote VTEPs */
zebra_vtep_t *vteps;
/* Local IP */
struct in_addr local_vtep_ip;
/* PIM-SM MDT group for BUM flooding */
struct in_addr mcast_grp;
/* tenant VRF, if any */
vrf_id_t vrf_id;
/* List of local or remote MAC */
struct hash *mac_table;
/* List of local or remote neighbors (MAC+IP) */
struct hash *neigh_table;
/* RB tree of ES-EVIs */
struct zebra_es_evi_rb_head es_evi_rb_tree;
/* List of local ESs */
struct list *local_es_evi_list;
};
/* L3 VNI hash table */
struct zebra_l3vni_t_ {
/* VNI key */
vni_t vni;
/* vrf_id */
vrf_id_t vrf_id;
uint32_t filter;
#define PREFIX_ROUTES_ONLY (1 << 0) /* l3-vni used for prefix routes only */
/* Local IP */
struct in_addr local_vtep_ip;
/* kernel interface for l3vni */
struct interface *vxlan_if;
/* SVI interface corresponding to the l3vni */
struct interface *svi_if;
struct interface *mac_vlan_if;
/* list of L2 VNIs associated with the L3 VNI */
struct list *l2vnis;
/* list of remote router-macs */
struct hash *rmac_table;
/* list of remote vtep-ip neigh */
struct hash *nh_table;
};
/* get the vx-intf name for l3vni */
static inline const char *zl3vni_vxlan_if_name(zebra_l3vni_t *zl3vni)
{
return zl3vni->vxlan_if ? zl3vni->vxlan_if->name : "None";
}
/* get the svi intf name for l3vni */
static inline const char *zl3vni_svi_if_name(zebra_l3vni_t *zl3vni)
{
return zl3vni->svi_if ? zl3vni->svi_if->name : "None";
}
/* get the vrf name for l3vni */
static inline const char *zl3vni_vrf_name(zebra_l3vni_t *zl3vni)
{
return vrf_id_to_name(zl3vni->vrf_id);
}
/* get the rmac string */
static inline const char *zl3vni_rmac2str(zebra_l3vni_t *zl3vni, char *buf,
int size)
{
char *ptr;
if (!buf)
ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
else {
assert(size >= ETHER_ADDR_STRLEN);
ptr = buf;
}
if (zl3vni->mac_vlan_if)
snprintf(ptr, (ETHER_ADDR_STRLEN),
"%02x:%02x:%02x:%02x:%02x:%02x",
(uint8_t)zl3vni->mac_vlan_if->hw_addr[0],
(uint8_t)zl3vni->mac_vlan_if->hw_addr[1],
(uint8_t)zl3vni->mac_vlan_if->hw_addr[2],
(uint8_t)zl3vni->mac_vlan_if->hw_addr[3],
(uint8_t)zl3vni->mac_vlan_if->hw_addr[4],
(uint8_t)zl3vni->mac_vlan_if->hw_addr[5]);
else if (zl3vni->svi_if)
snprintf(ptr, (ETHER_ADDR_STRLEN),
"%02x:%02x:%02x:%02x:%02x:%02x",
(uint8_t)zl3vni->svi_if->hw_addr[0],
(uint8_t)zl3vni->svi_if->hw_addr[1],
(uint8_t)zl3vni->svi_if->hw_addr[2],
(uint8_t)zl3vni->svi_if->hw_addr[3],
(uint8_t)zl3vni->svi_if->hw_addr[4],
(uint8_t)zl3vni->svi_if->hw_addr[5]);
else
snprintf(ptr, ETHER_ADDR_STRLEN, "None");
return ptr;
}
/* get the sys mac string */
static inline const char *zl3vni_sysmac2str(zebra_l3vni_t *zl3vni, char *buf,
int size)
{
char *ptr;
if (!buf)
ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
else {
assert(size >= ETHER_ADDR_STRLEN);
ptr = buf;
}
if (zl3vni->svi_if)
snprintf(ptr, (ETHER_ADDR_STRLEN),
"%02x:%02x:%02x:%02x:%02x:%02x",
(uint8_t)zl3vni->svi_if->hw_addr[0],
(uint8_t)zl3vni->svi_if->hw_addr[1],
(uint8_t)zl3vni->svi_if->hw_addr[2],
(uint8_t)zl3vni->svi_if->hw_addr[3],
(uint8_t)zl3vni->svi_if->hw_addr[4],
(uint8_t)zl3vni->svi_if->hw_addr[5]);
else
snprintf(ptr, ETHER_ADDR_STRLEN, "None");
return ptr;
}
/*
* l3-vni is oper up when:
* 0. if EVPN is enabled (advertise-all-vni cfged)
* 1. it is associated to a vxlan-intf
* 2. Associated vxlan-intf is oper up
* 3. it is associated to an SVI
* 4. associated SVI is oper up
*/
static inline int is_l3vni_oper_up(zebra_l3vni_t *zl3vni)
{
return (is_evpn_enabled() && zl3vni && (zl3vni->vrf_id != VRF_UNKNOWN)
&& zl3vni->vxlan_if && if_is_operative(zl3vni->vxlan_if)
&& zl3vni->svi_if && if_is_operative(zl3vni->svi_if));
}
static inline const char *zl3vni_state2str(zebra_l3vni_t *zl3vni)
{
if (!zl3vni)
return NULL;
if (is_l3vni_oper_up(zl3vni))
return "Up";
else
return "Down";
return NULL;
}
static inline vrf_id_t zl3vni_vrf_id(zebra_l3vni_t *zl3vni)
{
return zl3vni->vrf_id;
}
static inline void zl3vni_get_svi_rmac(zebra_l3vni_t *zl3vni,
struct ethaddr *rmac)
{
if (!zl3vni)
return;
if (!is_l3vni_oper_up(zl3vni))
return;
if (zl3vni->svi_if && if_is_operative(zl3vni->svi_if))
memcpy(rmac->octet, zl3vni->svi_if->hw_addr, ETH_ALEN);
}
struct host_rb_entry {
RB_ENTRY(host_rb_entry) hl_entry;
struct prefix p;
};
RB_HEAD(host_rb_tree_entry, host_rb_entry);
RB_PROTOTYPE(host_rb_tree_entry, host_rb_entry, hl_entry,
host_rb_entry_compare);
/*
* MAC hash table.
*
* This table contains the MAC addresses pertaining to this VNI.
* This includes local MACs learnt on an attached VLAN that maps
* to this VNI as well as remote MACs learnt and installed by BGP.
* Local MACs will be known either on a VLAN sub-interface or
* on (port, VLAN); however, it is sufficient for zebra to maintain
* against the VNI i.e., it does not need to retain the local "port"
* information. The correct VNI will be obtained as zebra maintains
* the mapping (of VLAN to VNI).
*/
struct zebra_mac_t_ {
/* MAC address. */
struct ethaddr macaddr;
uint32_t flags;
#define ZEBRA_MAC_LOCAL 0x01
#define ZEBRA_MAC_REMOTE 0x02
#define ZEBRA_MAC_AUTO 0x04 /* Auto created for neighbor. */
#define ZEBRA_MAC_STICKY 0x08 /* Static MAC */
#define ZEBRA_MAC_REMOTE_RMAC 0x10 /* remote router mac */
#define ZEBRA_MAC_DEF_GW 0x20
/* remote VTEP advertised MAC as default GW */
#define ZEBRA_MAC_REMOTE_DEF_GW 0x40
#define ZEBRA_MAC_DUPLICATE 0x80
#define ZEBRA_MAC_FPM_SENT 0x100 /* whether or not this entry was sent. */
/* MAC is locally active on an ethernet segment peer */
#define ZEBRA_MAC_ES_PEER_ACTIVE 0x200
/* MAC has been proxy-advertised by peers. This means we need to
* keep the entry for forwarding but cannot advertise it
*/
#define ZEBRA_MAC_ES_PEER_PROXY 0x400
/* We have not been able to independently establish that the host is
* local connected but one or more ES peers claims it is.
* We will maintain the entry for forwarding purposes and continue
* to advertise it as locally attached but with a "proxy" flag
*/
#define ZEBRA_MAC_LOCAL_INACTIVE 0x800
#define ZEBRA_MAC_ALL_LOCAL_FLAGS (ZEBRA_MAC_LOCAL |\
ZEBRA_MAC_LOCAL_INACTIVE)
#define ZEBRA_MAC_ALL_PEER_FLAGS (ZEBRA_MAC_ES_PEER_PROXY |\
ZEBRA_MAC_ES_PEER_ACTIVE)
/* back pointer to zvni */
zebra_vni_t *zvni;
/* Local or remote info. */
union {
struct {
ifindex_t ifindex;
vlanid_t vid;
} local;
struct in_addr r_vtep_ip;
} fwd_info;
/* Local or remote ES */
struct zebra_evpn_es *es;
/* memory used to link the mac to the es */
struct listnode es_listnode;
/* Mobility sequence numbers associated with this entry. */
uint32_t rem_seq;
uint32_t loc_seq;
/* List of neigh associated with this mac */
struct list *neigh_list;
/* list of hosts pointing to this remote RMAC */
struct host_rb_tree_entry host_rb;
/* Duplicate mac detection */
uint32_t dad_count;
struct thread *dad_mac_auto_recovery_timer;
struct timeval detect_start_time;
time_t dad_dup_detect_time;
/* used for ageing out the PEER_ACTIVE flag */
struct thread *hold_timer;
/* number of neigh entries (using this mac) that have
* ZEBRA_MAC_ES_PEER_ACTIVE or ZEBRA_NEIGH_ES_PEER_PROXY
*/
uint32_t sync_neigh_cnt;
};
/*
* Context for MAC hash walk - used by callbacks.
*/
struct mac_walk_ctx {
zebra_vni_t *zvni; /* VNI hash */
struct zebra_vrf *zvrf; /* VRF - for client notification. */
int uninstall; /* uninstall from kernel? */
int upd_client; /* uninstall from client? */
uint32_t flags;
#define DEL_LOCAL_MAC 0x1
#define DEL_REMOTE_MAC 0x2
#define DEL_ALL_MAC (DEL_LOCAL_MAC | DEL_REMOTE_MAC)
#define DEL_REMOTE_MAC_FROM_VTEP 0x4
#define SHOW_REMOTE_MAC_FROM_VTEP 0x8
struct in_addr r_vtep_ip; /* To walk MACs from specific VTEP */
struct vty *vty; /* Used by VTY handlers */
uint32_t count; /* Used by VTY handlers */
struct json_object *json; /* Used for JSON Output */
bool print_dup; /* Used to print dup addr list */
};
struct rmac_walk_ctx {
struct vty *vty;
struct json_object *json;
};
/* temporary datastruct to pass info between the mac-update and
* neigh-update while handling mac-ip routes
*/
struct sync_mac_ip_ctx {
bool ignore_macip;
bool mac_created;
bool mac_inactive;
bool mac_dp_update_deferred;
zebra_mac_t *mac;
};
#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.
*
* This table contains the neighbors (IP to MAC bindings) pertaining to
* this VNI. This includes local neighbors learnt on the attached VLAN
* device that maps to this VNI as well as remote neighbors learnt and
* installed by BGP.
* Local neighbors will be known against the VLAN device (SVI); however,
* it is sufficient for zebra to maintain against the VNI. The correct
* VNI will be obtained as zebra maintains the mapping (of VLAN to VNI).
*/
struct zebra_neigh_t_ {
/* IP address. */
struct ipaddr ip;
/* MAC address. */
struct ethaddr emac;
/* Back pointer to MAC. Only applicable to hosts in a L2-VNI. */
zebra_mac_t *mac;
/* Underlying interface. */
ifindex_t ifindex;
zebra_vni_t *zvni;
uint32_t flags;
#define ZEBRA_NEIGH_LOCAL 0x01
#define ZEBRA_NEIGH_REMOTE 0x02
#define ZEBRA_NEIGH_REMOTE_NH 0x04 /* neigh entry for remote vtep */
#define ZEBRA_NEIGH_DEF_GW 0x08
#define ZEBRA_NEIGH_ROUTER_FLAG 0x10
#define ZEBRA_NEIGH_DUPLICATE 0x20
#define ZEBRA_NEIGH_SVI_IP 0x40
/* rxed from an ES peer */
#define ZEBRA_NEIGH_ES_PEER_ACTIVE 0x80
/* rxed from an ES peer as a proxy advertisement */
#define ZEBRA_NEIGH_ES_PEER_PROXY 0x100
/* We have not been able to independently establish that the host
* is local connected
*/
#define ZEBRA_NEIGH_LOCAL_INACTIVE 0x200
#define ZEBRA_NEIGH_ALL_LOCAL_FLAGS (ZEBRA_NEIGH_LOCAL |\
ZEBRA_NEIGH_LOCAL_INACTIVE)
#define ZEBRA_NEIGH_ALL_PEER_FLAGS (ZEBRA_NEIGH_ES_PEER_PROXY |\
ZEBRA_NEIGH_ES_PEER_ACTIVE)
enum zebra_neigh_state state;
/* Remote VTEP IP - applicable only for remote neighbors. */
struct in_addr r_vtep_ip;
/*
* Mobility sequence numbers associated with this entry. The rem_seq
* represents the sequence number from the client (BGP) for the most
* recent add or update of this entry while the loc_seq represents
* the sequence number informed (or to be informed) by zebra to BGP
* for this entry.
*/
uint32_t rem_seq;
uint32_t loc_seq;
/* list of hosts pointing to this remote NH entry */
struct host_rb_tree_entry host_rb;
/* Duplicate ip detection */
uint32_t dad_count;
struct thread *dad_ip_auto_recovery_timer;
struct timeval detect_start_time;
time_t dad_dup_detect_time;
/* used for ageing out the PEER_ACTIVE flag */
struct thread *hold_timer;
};
/*
* Context for neighbor hash walk - used by callbacks.
*/
struct neigh_walk_ctx {
zebra_vni_t *zvni; /* VNI hash */
struct zebra_vrf *zvrf; /* VRF - for client notification. */
int uninstall; /* uninstall from kernel? */
int upd_client; /* uninstall from client? */
uint32_t flags;
#define DEL_LOCAL_NEIGH 0x1
#define DEL_REMOTE_NEIGH 0x2
#define DEL_ALL_NEIGH (DEL_LOCAL_NEIGH | DEL_REMOTE_NEIGH)
#define DEL_REMOTE_NEIGH_FROM_VTEP 0x4
#define SHOW_REMOTE_NEIGH_FROM_VTEP 0x8
struct in_addr r_vtep_ip; /* To walk neighbors from specific VTEP */
struct vty *vty; /* Used by VTY handlers */
uint32_t count; /* Used by VTY handlers */
uint8_t addr_width; /* Used by VTY handlers */
struct json_object *json; /* Used for JSON Output */
};
/* context for neigh hash walk - update l3vni and rmac */
struct neigh_l3info_walk_ctx {
zebra_vni_t *zvni;
zebra_l3vni_t *zl3vni;
int add;
};
struct nh_walk_ctx {
struct vty *vty;
struct json_object *json;
};
extern zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id);
extern struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni);
extern struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni);
extern struct interface *zl3vni_map_to_mac_vlan_if(zebra_l3vni_t *zl3vni);
extern zebra_l3vni_t *zl3vni_lookup(vni_t vni);
DECLARE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
bool delete, const char *reason), (rmac, zl3vni, delete, reason))
#ifdef __cplusplus
}
#endif
/*
* Multicast hash table.
*
* This table contains -
* 1. The (S, G) entries used for encapsulating and forwarding BUM traffic.
* S is the local VTEP-IP and G is a BUM mcast group address.
* 2. The (X, G) entries used for terminating a BUM flow.
* Multiple L2-VNIs can share the same MDT hence the need to maintain
* an aggregated table that pimd can consume without much
* re-interpretation.
*/
typedef struct zebra_vxlan_sg_ {
struct zebra_vrf *zvrf;
struct prefix_sg sg;
char sg_str[PREFIX_SG_STR_LEN];
/* For SG - num of L2 VNIs using this entry for sending BUM traffic */
/* For XG - num of SG using this as parent */
uint32_t ref_cnt;
} zebra_vxlan_sg_t;
extern zebra_vni_t *zvni_lookup(vni_t vni);
extern void zebra_vxlan_sync_mac_dp_install(zebra_mac_t *mac, bool set_inactive,
bool force_clear_static, const char *caller);
#endif /* _ZEBRA_VXLAN_PRIVATE_H */