mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 15:33:56 +00:00
zebra: evpn pip extract vrr mac
Extract mac-vlan interface mac when a l3vni add is sent to bgp Per L3VNI maintain vrr interface. An api to extract vrr mac address from a vlan id, associated master svi device. When a l3vni operational up event is sent to bgpd, extract vrr rmac along with svi rmac. Ticket:CM-26190 Reviewed By: Testing Done: Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
This commit is contained in:
parent
5394a27663
commit
06d9cde5c7
@ -118,6 +118,8 @@ static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n);
|
|||||||
static zebra_vni_t *zvni_from_svi(struct interface *ifp,
|
static zebra_vni_t *zvni_from_svi(struct interface *ifp,
|
||||||
struct interface *br_if);
|
struct interface *br_if);
|
||||||
static struct interface *zvni_map_to_svi(vlanid_t vid, 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);
|
||||||
|
|
||||||
/* l3-vni next-hop neigh related APIs */
|
/* l3-vni next-hop neigh related APIs */
|
||||||
static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni,
|
static zebra_neigh_t *zl3vni_nh_lookup(zebra_l3vni_t *zl3vni,
|
||||||
@ -3684,7 +3686,7 @@ static zebra_vni_t *zvni_from_svi(struct interface *ifp,
|
|||||||
* of two cases:
|
* of two cases:
|
||||||
* (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
|
* (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface
|
||||||
* linked to the bridge
|
* linked to the bridge
|
||||||
* (b) In the case of a VLAN-unaware bridge, the SVI is the bridge inteface
|
* (b) In the case of a VLAN-unaware bridge, the SVI is the bridge interface
|
||||||
* itself
|
* itself
|
||||||
*/
|
*/
|
||||||
static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
|
static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
|
||||||
@ -3735,6 +3737,52 @@ static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
|
|||||||
return found ? tmp_if : NULL;
|
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)
|
||||||
|
{
|
||||||
|
struct zebra_ns *zns;
|
||||||
|
struct route_node *rn;
|
||||||
|
struct interface *tmp_if = NULL;
|
||||||
|
struct zebra_if *zif;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* Identify corresponding VLAN interface. */
|
||||||
|
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)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (zif->link == svi_if) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found ? tmp_if : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install remote MAC into the forwarding plane.
|
* Install remote MAC into the forwarding plane.
|
||||||
*/
|
*/
|
||||||
@ -4151,6 +4199,16 @@ static void zvni_build_hash_table(void)
|
|||||||
*/
|
*/
|
||||||
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
||||||
|
|
||||||
|
/* Associate l3vni to mac-vlan and extract VRR MAC */
|
||||||
|
zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
|
zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
|
||||||
|
vni, zl3vni->svi_if ? zl3vni->svi_if->name
|
||||||
|
: "NIL",
|
||||||
|
zl3vni->mac_vlan_if ?
|
||||||
|
zl3vni->mac_vlan_if->name : "NIL");
|
||||||
|
|
||||||
if (is_l3vni_oper_up(zl3vni))
|
if (is_l3vni_oper_up(zl3vni))
|
||||||
zebra_vxlan_process_l3vni_oper_up(zl3vni);
|
zebra_vxlan_process_l3vni_oper_up(zl3vni);
|
||||||
|
|
||||||
@ -5056,6 +5114,24 @@ struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
|
|||||||
return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
|
return zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct interface *zl3vni_map_to_mac_vlan_if(zebra_l3vni_t *zl3vni)
|
||||||
|
{
|
||||||
|
struct zebra_if *zif = NULL; /* zebra_if for vxlan_if */
|
||||||
|
|
||||||
|
if (!zl3vni)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!zl3vni->vxlan_if)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
zif = zl3vni->vxlan_if->info;
|
||||||
|
if (!zif)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return zvni_map_to_macvlan(zif->brslave_info.br_if, zl3vni->svi_if);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id)
|
zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id)
|
||||||
{
|
{
|
||||||
struct zebra_vrf *zvrf = NULL;
|
struct zebra_vrf *zvrf = NULL;
|
||||||
@ -5139,6 +5215,19 @@ static zebra_l3vni_t *zl3vni_from_svi(struct interface *ifp,
|
|||||||
return zl3vni;
|
return zl3vni;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void zl3vni_get_vrr_rmac(zebra_l3vni_t *zl3vni,
|
||||||
|
struct ethaddr *rmac)
|
||||||
|
{
|
||||||
|
if (!zl3vni)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!is_l3vni_oper_up(zl3vni))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (zl3vni->mac_vlan_if && if_is_operative(zl3vni->mac_vlan_if))
|
||||||
|
memcpy(rmac->octet, zl3vni->mac_vlan_if->hw_addr, ETH_ALEN);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inform BGP about l3-vni.
|
* Inform BGP about l3-vni.
|
||||||
*/
|
*/
|
||||||
@ -5146,35 +5235,54 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
|
|||||||
{
|
{
|
||||||
struct stream *s = NULL;
|
struct stream *s = NULL;
|
||||||
struct zserv *client = NULL;
|
struct zserv *client = NULL;
|
||||||
struct ethaddr rmac;
|
struct ethaddr svi_rmac, vrr_rmac = {.octet = {0} };
|
||||||
|
struct zebra_vrf *zvrf;
|
||||||
char buf[ETHER_ADDR_STRLEN];
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
|
char buf1[ETHER_ADDR_STRLEN];
|
||||||
|
bool is_anycast_mac = true;
|
||||||
|
|
||||||
client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
|
client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
|
||||||
/* BGP may not be running. */
|
/* BGP may not be running. */
|
||||||
if (!client)
|
if (!client)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* get the rmac */
|
zvrf = zebra_vrf_lookup_by_id(zl3vni->vrf_id);
|
||||||
memset(&rmac, 0, sizeof(struct ethaddr));
|
assert(zvrf);
|
||||||
zl3vni_get_rmac(zl3vni, &rmac);
|
|
||||||
|
/* get the svi and vrr rmac values */
|
||||||
|
memset(&svi_rmac, 0, sizeof(struct ethaddr));
|
||||||
|
zl3vni_get_svi_rmac(zl3vni, &svi_rmac);
|
||||||
|
zl3vni_get_vrr_rmac(zl3vni, &vrr_rmac);
|
||||||
|
|
||||||
|
/* In absence of vrr mac use svi mac as anycast MAC value */
|
||||||
|
if (is_zero_mac(&vrr_rmac)) {
|
||||||
|
memcpy(&vrr_rmac, &svi_rmac, ETH_ALEN);
|
||||||
|
is_anycast_mac = false;
|
||||||
|
}
|
||||||
|
|
||||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||||
|
|
||||||
|
/* The message is used for both vni add and/or update like
|
||||||
|
* vrr mac is added for l3vni SVI.
|
||||||
|
*/
|
||||||
zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
|
zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
|
||||||
stream_putl(s, zl3vni->vni);
|
stream_putl(s, zl3vni->vni);
|
||||||
stream_put(s, &rmac, sizeof(struct ethaddr));
|
stream_put(s, &svi_rmac, sizeof(struct ethaddr));
|
||||||
stream_put_in_addr(s, &zl3vni->local_vtep_ip);
|
stream_put_in_addr(s, &zl3vni->local_vtep_ip);
|
||||||
stream_put(s, &zl3vni->filter, sizeof(int));
|
stream_put(s, &zl3vni->filter, sizeof(int));
|
||||||
stream_putl(s, zl3vni->svi_if->ifindex);
|
stream_putl(s, zl3vni->svi_if->ifindex);
|
||||||
|
stream_put(s, &vrr_rmac, sizeof(struct ethaddr));
|
||||||
|
stream_putl(s, is_anycast_mac);
|
||||||
|
|
||||||
/* Write packet size. */
|
/* Write packet size. */
|
||||||
stream_putw_at(s, 0, stream_get_endp(s));
|
stream_putw_at(s, 0, stream_get_endp(s));
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"Send L3_VNI_ADD %u VRF %s RMAC %s local-ip %s filter %s to %s",
|
"Send L3_VNI_ADD %u VRF %s RMAC %s VRR %s local-ip %s filter %s to %s",
|
||||||
zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
|
zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
|
||||||
prefix_mac2str(&rmac, buf, sizeof(buf)),
|
prefix_mac2str(&svi_rmac, buf, sizeof(buf)),
|
||||||
|
prefix_mac2str(&vrr_rmac, buf1, sizeof(buf1)),
|
||||||
inet_ntoa(zl3vni->local_vtep_ip),
|
inet_ntoa(zl3vni->local_vtep_ip),
|
||||||
CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
|
CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
|
||||||
? "prefix-routes-only"
|
? "prefix-routes-only"
|
||||||
@ -8531,15 +8639,18 @@ int zebra_vxlan_if_up(struct interface *ifp)
|
|||||||
|
|
||||||
zl3vni = zl3vni_lookup(vni);
|
zl3vni = zl3vni_lookup(vni);
|
||||||
if (zl3vni) {
|
if (zl3vni) {
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
|
||||||
zlog_debug("Intf %s(%u) L3-VNI %u is UP", ifp->name,
|
|
||||||
ifp->ifindex, vni);
|
|
||||||
|
|
||||||
/* we need to associate with SVI, if any, we can associate with
|
/* we need to associate with SVI, if any, we can associate with
|
||||||
* svi-if only after association with vxlan-intf is complete
|
* svi-if only after association with vxlan-intf is complete
|
||||||
*/
|
*/
|
||||||
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
||||||
|
zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
|
zlog_debug("Intf %s(%u) L3-VNI %u is UP svi_if %s mac_vlan_if %s"
|
||||||
|
, ifp->name, ifp->ifindex, vni,
|
||||||
|
zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
|
||||||
|
zl3vni->mac_vlan_if ?
|
||||||
|
zl3vni->mac_vlan_if->name : "NIL");
|
||||||
|
|
||||||
if (is_l3vni_oper_up(zl3vni))
|
if (is_l3vni_oper_up(zl3vni))
|
||||||
zebra_vxlan_process_l3vni_oper_up(zl3vni);
|
zebra_vxlan_process_l3vni_oper_up(zl3vni);
|
||||||
@ -8702,6 +8813,8 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
|
|||||||
zebra_vxlan_process_l3vni_oper_down(zl3vni);
|
zebra_vxlan_process_l3vni_oper_down(zl3vni);
|
||||||
zl3vni->svi_if = NULL;
|
zl3vni->svi_if = NULL;
|
||||||
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
||||||
|
zl3vni->mac_vlan_if =
|
||||||
|
zl3vni_map_to_mac_vlan_if(zl3vni);
|
||||||
zl3vni->local_vtep_ip = vxl->vtep_ip;
|
zl3vni->local_vtep_ip = vxl->vtep_ip;
|
||||||
if (is_l3vni_oper_up(zl3vni))
|
if (is_l3vni_oper_up(zl3vni))
|
||||||
zebra_vxlan_process_l3vni_oper_up(
|
zebra_vxlan_process_l3vni_oper_up(
|
||||||
@ -8861,6 +8974,8 @@ int zebra_vxlan_if_add(struct interface *ifp)
|
|||||||
* after association with vxlan_if is complete */
|
* after association with vxlan_if is complete */
|
||||||
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
||||||
|
|
||||||
|
zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
|
||||||
|
|
||||||
if (is_l3vni_oper_up(zl3vni))
|
if (is_l3vni_oper_up(zl3vni))
|
||||||
zebra_vxlan_process_l3vni_oper_up(zl3vni);
|
zebra_vxlan_process_l3vni_oper_up(zl3vni);
|
||||||
} else {
|
} else {
|
||||||
@ -8993,6 +9108,16 @@ int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
|
|||||||
*/
|
*/
|
||||||
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
||||||
|
|
||||||
|
zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||||
|
zlog_debug("%s: l3vni %u svi_if %s mac_vlan_if %s",
|
||||||
|
__PRETTY_FUNCTION__, vni,
|
||||||
|
zl3vni->svi_if ?
|
||||||
|
zl3vni->svi_if->name : "NIL",
|
||||||
|
zl3vni->mac_vlan_if ?
|
||||||
|
zl3vni->mac_vlan_if->name : "NIL");
|
||||||
|
|
||||||
/* formulate l2vni list */
|
/* formulate l2vni list */
|
||||||
hash_iterate(zvrf_evpn->vni_table, zvni_add_to_l3vni_list,
|
hash_iterate(zvrf_evpn->vni_table, zvni_add_to_l3vni_list,
|
||||||
zl3vni);
|
zl3vni);
|
||||||
|
@ -125,6 +125,8 @@ struct zebra_l3vni_t_ {
|
|||||||
/* SVI interface corresponding to the l3vni */
|
/* SVI interface corresponding to the l3vni */
|
||||||
struct interface *svi_if;
|
struct interface *svi_if;
|
||||||
|
|
||||||
|
struct interface *mac_vlan_if;
|
||||||
|
|
||||||
/* list of L2 VNIs associated with the L3 VNI */
|
/* list of L2 VNIs associated with the L3 VNI */
|
||||||
struct list *l2vnis;
|
struct list *l2vnis;
|
||||||
|
|
||||||
@ -215,7 +217,8 @@ static inline vrf_id_t zl3vni_vrf_id(zebra_l3vni_t *zl3vni)
|
|||||||
return zl3vni->vrf_id;
|
return zl3vni->vrf_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void zl3vni_get_rmac(zebra_l3vni_t *zl3vni, struct ethaddr *rmac)
|
static inline void zl3vni_get_svi_rmac(zebra_l3vni_t *zl3vni,
|
||||||
|
struct ethaddr *rmac)
|
||||||
{
|
{
|
||||||
if (!zl3vni)
|
if (!zl3vni)
|
||||||
return;
|
return;
|
||||||
@ -433,6 +436,7 @@ struct nh_walk_ctx {
|
|||||||
extern zebra_l3vni_t *zl3vni_from_vrf(vrf_id_t vrf_id);
|
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_vxlan_if(zebra_l3vni_t *zl3vni);
|
||||||
extern struct interface *zl3vni_map_to_svi_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);
|
||||||
|
|
||||||
DECLARE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
|
DECLARE_HOOK(zebra_rmac_update, (zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
|
||||||
bool delete, const char *reason), (rmac, zl3vni, delete, reason))
|
bool delete, const char *reason), (rmac, zl3vni, delete, reason))
|
||||||
|
Loading…
Reference in New Issue
Block a user