mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 03:29:06 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			265 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0-or-later
 | 
						|
/*
 | 
						|
 * Zebra VxLAN (EVPN) Data structures and definitions
 | 
						|
 * These are "internal" to this function.
 | 
						|
 * Copyright (C) 2016, 2017 Cumulus Networks, Inc.
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef _ZEBRA_VXLAN_PRIVATE_H
 | 
						|
#define _ZEBRA_VXLAN_PRIVATE_H
 | 
						|
 | 
						|
#include <zebra.h>
 | 
						|
 | 
						|
#include "if.h"
 | 
						|
#include "linklist.h"
 | 
						|
#include "zebra_vxlan.h"
 | 
						|
#include "zebra_vxlan_if.h"
 | 
						|
#include "zebra_evpn.h"
 | 
						|
#include "zebra_evpn_mac.h"
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
extern "C" {
 | 
						|
#endif
 | 
						|
 | 
						|
#define ERR_STR_SZ 256
 | 
						|
 | 
						|
/* L3 VNI hash table */
 | 
						|
struct zebra_l3vni {
 | 
						|
 | 
						|
	/* 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 */
 | 
						|
 | 
						|
	/* Corresponding Bridge information */
 | 
						|
	vlanid_t vid;
 | 
						|
	struct interface *bridge_if;
 | 
						|
 | 
						|
	/* 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;
 | 
						|
};
 | 
						|
 | 
						|
#define IS_ZL3VNI_SVD_BACKED(zl3vni)                                           \
 | 
						|
	(zl3vni->vxlan_if && zl3vni->vxlan_if->info &&                         \
 | 
						|
	 IS_ZEBRA_VXLAN_IF_SVD((struct zebra_if *)zl3vni->vxlan_if->info))
 | 
						|
 | 
						|
/* get the vx-intf name for l3vni */
 | 
						|
static inline const char *zl3vni_vxlan_if_name(struct zebra_l3vni *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(struct zebra_l3vni *zl3vni)
 | 
						|
{
 | 
						|
	return zl3vni->svi_if ? zl3vni->svi_if->name : "None";
 | 
						|
}
 | 
						|
 | 
						|
/* get the vrf name for l3vni */
 | 
						|
static inline const char *zl3vni_vrf_name(struct zebra_l3vni *zl3vni)
 | 
						|
{
 | 
						|
	return vrf_id_to_name(zl3vni->vrf_id);
 | 
						|
}
 | 
						|
 | 
						|
/* get the rmac string */
 | 
						|
static inline const char *zl3vni_rmac2str(struct zebra_l3vni *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(struct zebra_l3vni *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(struct zebra_l3vni *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(struct zebra_l3vni *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(struct zebra_l3vni *zl3vni)
 | 
						|
{
 | 
						|
	return zl3vni->vrf_id;
 | 
						|
}
 | 
						|
 | 
						|
static inline void zl3vni_get_svi_rmac(struct zebra_l3vni *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);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* context for neigh hash walk - update l3vni and rmac */
 | 
						|
struct neigh_l3info_walk_ctx {
 | 
						|
 | 
						|
	struct zebra_evpn *zevpn;
 | 
						|
	struct zebra_l3vni *zl3vni;
 | 
						|
	int add;
 | 
						|
};
 | 
						|
 | 
						|
struct nh_walk_ctx {
 | 
						|
 | 
						|
	struct vty *vty;
 | 
						|
	struct json_object *json;
 | 
						|
};
 | 
						|
 | 
						|
extern struct zebra_l3vni *zl3vni_from_vrf(vrf_id_t vrf_id);
 | 
						|
extern struct interface *zl3vni_map_to_vxlan_if(struct zebra_l3vni *zl3vni);
 | 
						|
extern struct interface *zl3vni_map_to_svi_if(struct zebra_l3vni *zl3vni);
 | 
						|
extern struct interface *zl3vni_map_to_mac_vlan_if(struct zebra_l3vni *zl3vni);
 | 
						|
extern struct zebra_l3vni *zl3vni_lookup(vni_t vni);
 | 
						|
extern vni_t vni_id_from_svi(struct interface *ifp, struct interface *br_if);
 | 
						|
 | 
						|
DECLARE_HOOK(zebra_rmac_update,
 | 
						|
	     (struct zebra_mac * rmac, struct zebra_l3vni *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.
 | 
						|
 */
 | 
						|
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;
 | 
						|
};
 | 
						|
 | 
						|
extern struct zebra_evpn *zevpn_lookup(vni_t vni);
 | 
						|
extern void zebra_vxlan_sync_mac_dp_install(struct zebra_mac *mac,
 | 
						|
					    bool set_inactive,
 | 
						|
					    bool force_clear_static,
 | 
						|
					    const char *caller);
 | 
						|
extern bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf);
 | 
						|
extern void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip,
 | 
						|
			       struct in_addr mcast_grp);
 | 
						|
extern void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
 | 
						|
				 struct in_addr mcast_grp);
 | 
						|
extern void zebra_vxlan_process_l3vni_oper_up(struct zebra_l3vni *zl3vni);
 | 
						|
extern void zebra_vxlan_process_l3vni_oper_down(struct zebra_l3vni *zl3vni);
 | 
						|
extern int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn);
 | 
						|
 | 
						|
#endif /* _ZEBRA_VXLAN_PRIVATE_H */
 |