rtadv_if_fini(zebra_if);
+ zebra_l2_bridge_if_cleanup(ifp);
zebra_evpn_if_cleanup(zebra_if);
zebra_evpn_mac_ifp_del(ifp);
#include "bitfield.h"
#include "zebra/zebra_l2.h"
+#include "zebra/zebra_l2_bridge_if.h"
#include "zebra/zebra_nhg_private.h"
#include "zebra/zebra_router.h"
#include "zebra/rtadv.h"
#include "zebra/rt_netlink.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_l2.h"
+#include "zebra/zebra_l2_bridge_if.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_vxlan.h"
if (json == NULL) {
vty_out(vty, "VNI: %u\n", zevpn->vni);
vty_out(vty, " Type: %s\n", "L2");
+ vty_out(vty, " Vlan: %u\n", zevpn->vid);
+ vty_out(vty, " Bridge: %s\n",
+ zevpn->bridge_if ? zevpn->bridge_if->name : "-");
vty_out(vty, " Tenant VRF: %s\n", vrf_id_to_name(zevpn->vrf_id));
} else {
json_object_int_add(json, "vni", zevpn->vni);
void *_in_param,
void **_p_zevpn)
{
+ int found = 0;
struct zebra_ns *zns = ns->info;
struct route_node *rn;
struct interface *br_if;
struct zebra_evpn *zevpn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
- struct zebra_vxlan_vni *vni;
struct zebra_from_svi_param *in_param =
(struct zebra_from_svi_param *)_in_param;
+ vlanid_t vid;
+ vni_t vni_id = 0;
+ uint8_t bridge_vlan_aware;
assert(p_zevpn && in_param);
br_if = in_param->br_if;
+ assert(br_if);
zif = in_param->zif;
assert(zif);
- assert(br_if);
+ vid = in_param->vid;
+ bridge_vlan_aware = in_param->bridge_vlan_aware;
- /* 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;
-
- if (zif->brslave_info.br_if != br_if)
- continue;
-
- vni = zebra_vxlan_if_access_vlan_find(
- zif, in_param->bridge_vlan_aware, in_param->vid);
+ if (bridge_vlan_aware) {
+ vni_id = zebra_l2_bridge_if_vni_find(zif, vid);
+ if (vni_id)
+ found = 1;
+ } else {
+ /* 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;
+
+ if (zif->brslave_info.br_if != br_if)
+ continue;
+
+ vni_id = zebra_vxlan_if_access_vlan_vni_find(zif, vid,
+ br_if);
+ if (vni_id) {
+ found = 1;
+ break;
+ }
- if (!in_param->bridge_vlan_aware || vni) {
- zevpn = zebra_evpn_lookup(vni->vni);
- *p_zevpn = zevpn;
- return NS_WALK_STOP;
}
}
- return NS_WALK_CONTINUE;
+ if (!found)
+ return NS_WALK_CONTINUE;
+
+ zevpn = zebra_evpn_lookup(vni_id);
+ *p_zevpn = zevpn;
+ return NS_WALK_STOP;
}
/*
struct zebra_evpn *zevpn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
- struct zebra_vxlan_vni *vni;
+ struct zebra_if *br_zif;
+ struct zebra_l2_bridge_vlan *bvlan;
struct zebra_from_svi_param *in_param =
(struct zebra_from_svi_param *)_in_param;
int found = 0;
+ vni_t vni_id = 0;
+ vlanid_t vid = 0;
+ uint8_t bridge_vlan_aware;
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;
-
- if (zif->brslave_info.br_if != br_if)
- continue;
-
- vni = zebra_vxlan_if_access_vlan_find(
- zif, in_param->bridge_vlan_aware, in_param->vid);
- if (!in_param->bridge_vlan_aware || vni) {
+ bridge_vlan_aware = in_param->bridge_vlan_aware;
+ vid = in_param->vid;
+ br_zif = br_if->info;
+ assert(br_zif);
+
+ if (bridge_vlan_aware) {
+ bvlan = zebra_l2_bridge_if_vlan_find(br_zif, vid);
+ if (bvlan && bvlan->access_bd && bvlan->access_bd->vni) {
found = 1;
+ vni_id = bvlan->access_bd->vni;
+ }
+ } else {
+ /* 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;
+
+ if (zif->brslave_info.br_if != br_if)
+ continue;
+
+ vni_id = zebra_vxlan_if_access_vlan_vni_find(zif, vid,
+ br_if);
+ if (vni_id)
+ found = 1;
break;
}
}
if (!found)
return NS_WALK_CONTINUE;
- zevpn = zebra_evpn_lookup(vni->vni);
+ zevpn = zebra_evpn_lookup(vni_id);
if (p_zevpn)
*p_zevpn = zevpn;
return NS_WALK_STOP;
uint32_t flags;
#define ZEVPN_READY_FOR_BGP (1 << 0) /* ready to be sent to BGP */
+ /* Corresponding Bridge information */
+ vlanid_t vid;
+ struct interface *bridge_if;
+
/* Flag for advertising gw macip */
uint8_t advertise_gw_macip;
zebra_evpn_vxl_evpn_set(zif, zevpn, set);
}
+
+/* EVPN<=>Bridge interface association */
+static inline void zevpn_bridge_if_set(struct zebra_evpn *zevpn,
+ struct interface *ifp, bool set)
+{
+ if (set) {
+ if (zevpn->bridge_if == ifp)
+ return;
+ zevpn->bridge_if = ifp;
+ } else {
+ if (!zevpn->bridge_if)
+ return;
+ zevpn->bridge_if = NULL;
+ }
+}
+
+/* EVPN<=>Bridge interface association */
+static inline void zl3vni_bridge_if_set(struct zebra_l3vni *zl3vni,
+ struct interface *ifp, bool set)
+{
+ if (set) {
+ if (zl3vni->bridge_if == ifp)
+ return;
+ zl3vni->bridge_if = ifp;
+ } else {
+ if (!zl3vni->bridge_if)
+ return;
+ zl3vni->bridge_if = NULL;
+ }
+}
#include "zebra/rt_netlink.h"
#include "zebra/interface.h"
#include "zebra/zebra_l2.h"
+#include "zebra/zebra_l2_bridge_if.h"
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_vxlan_if.h"
#include "zebra/zebra_evpn_mh.h"
int add)
{
struct zebra_if *zif;
+ struct zebra_l2_bridge_if *br;
zif = ifp->info;
assert(zif);
- /* Copy over the L2 information. */
- memcpy(&zif->l2info.br, bridge_info, sizeof(*bridge_info));
+ br = BRIDGE_FROM_ZEBRA_IF(zif);
+ br->vlan_aware = bridge_info->bridge.vlan_aware;
+ zebra_l2_bridge_if_add(ifp);
/* Link all slaves to this bridge */
map_slaves_to_bridge(ifp, 1, false, ZEBRA_BRIDGE_NO_ACTION);
*/
void zebra_l2_bridge_del(struct interface *ifp)
{
+ zebra_l2_bridge_if_del(ifp);
+
/* Unlink all slaves to this bridge */
map_slaves_to_bridge(ifp, 0, false, ZEBRA_BRIDGE_NO_ACTION);
}
#include "zebra/rt_netlink.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_l2.h"
+#include "zebra/zebra_l2_bridge_if.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_vxlan.h"
vty_out(vty, "VNI: %u\n", zl3vni->vni);
vty_out(vty, " Type: %s\n", "L3");
vty_out(vty, " Tenant VRF: %s\n", zl3vni_vrf_name(zl3vni));
+ vty_out(vty, " Vlan: %u\n", zl3vni->vid);
+ vty_out(vty, " Bridge: %s\n",
+ zl3vni->bridge_if ? zl3vni->bridge_if->name : "-");
vty_out(vty, " Local Vtep Ip: %pI4\n",
&zl3vni->local_vtep_ip);
vty_out(vty, " Vxlan-Intf: %s\n",
int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn)
{
+ zevpn->vid = 0;
zevpn_vxlan_if_set(zevpn, zevpn->vxlan_if, false /* set */);
+ zevpn_bridge_if_set(zevpn, zevpn->bridge_if, false /* set */);
/* Remove references to the BUM mcast grp */
zebra_vxlan_sg_deref(zevpn->local_vtep_ip, zevpn->mcast_grp);
struct zebra_l3vni *zl3vni;
struct interface *ifp;
struct zebra_l2info_vxlan *vxl;
+ struct interface *br_if;
ifp = zif->ifp;
vxl = &zif->l2info.vxl;
zebra_evpn_es_set_base_evpn(zevpn);
}
zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
- vlan_if = zvni_map_to_svi(vnip->access_vlan,
- zif->brslave_info.br_if);
+ br_if = zif->brslave_info.br_if;
+ zevpn_bridge_if_set(zevpn, br_if, true /* set */);
+ vlan_if = zvni_map_to_svi(vnip->access_vlan, br_if);
if (vlan_if) {
+ zevpn->vid = vnip->access_vlan;
zevpn->svi_if = vlan_if;
zevpn->vrf_id = vlan_if->vrf->vrf_id;
zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
static int zl3vni_from_svi_ns(struct ns *ns, void *_in_param, void **_p_zl3vni)
{
+ int found = 0;
+ vni_t vni_id = 0;
struct zebra_ns *zns = ns->info;
struct zebra_l3vni **p_zl3vni = (struct zebra_l3vni **)_p_zl3vni;
struct zebra_from_svi_param *in_param =
struct route_node *rn = NULL;
struct interface *tmp_if = NULL;
struct zebra_if *zif = NULL;
- struct zebra_vxlan_vni *vni = NULL;
+ struct zebra_if *br_zif = NULL;
assert(in_param && p_zl3vni);
- /* loop through all vxlan-interface */
- 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;
+ br_zif = in_param->br_if->info;
+ assert(br_zif);
- if (zif->brslave_info.br_if != in_param->br_if)
- continue;
+ if (in_param->bridge_vlan_aware) {
+ vni_id = zebra_l2_bridge_if_vni_find(br_zif, in_param->vid);
+ if (vni_id)
+ found = 1;
+ } else {
+ /* loop through all vxlan-interface */
+ 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;
- vni = zebra_vxlan_if_access_vlan_find(zif, in_param->bridge_vlan_aware,
- in_param->vid);
- if (!in_param->bridge_vlan_aware || vni) {
- *p_zl3vni = zl3vni_lookup(vni->vni);
- return NS_WALK_STOP;
+ if (zif->brslave_info.br_if != in_param->br_if)
+ continue;
+
+ vni_id = zebra_vxlan_if_access_vlan_vni_find(zif, in_param->vid,
+ in_param->br_if);
+ if (vni_id) {
+ found = 1;
+ break;
+ }
}
}
- return NS_WALK_CONTINUE;
+ if (!found)
+ return NS_WALK_CONTINUE;
+
+ *p_zl3vni = zl3vni_lookup(vni_id);
+ return NS_WALK_STOP;
}
/*
return ret;
}
-static int zebra_vxlan_if_vni_access_vlan_find(struct zebra_if *zif,
- struct zebra_vxlan_vni *vni,
- void *ctxt)
-{
- int ret = HASHWALK_CONTINUE;
- struct zebra_vxlan_if_vlan_ctx *ctx;
-
- ctx = (struct zebra_vxlan_if_vlan_ctx *)ctxt;
-
- if (vni->access_vlan == ctx->vid) {
- ctx->vni = vni;
- ret = HASHWALK_ABORT;
- }
- return ret;
-}
-
static void zebra_vxlan_if_vni_iterate_callback(struct hash_bucket *bucket,
void *ctxt)
{
struct zebra_if *zif;
struct zebra_evpn *zevpn;
struct zebra_l3vni *zl3vni;
+ struct interface *br_if;
/* Check if EVPN is enabled. */
if (!is_evpn_enabled())
/* remove the association with vxlan_if */
memset(&zl3vni->local_vtep_ip, 0, sizeof(struct in_addr));
zl3vni->vxlan_if = NULL;
+ zl3vni->vid = 0;
+ br_if = zif->brslave_info.br_if;
+ zl3vni_bridge_if_set(zl3vni, br_if, false /* unset */);
} else {
/* process if-del for l2-vni*/
struct zebra_evpn *zevpn;
struct zebra_l3vni *zl3vni;
struct interface *vlan_if;
+ struct interface *br_if;
/* Check if EVPN is enabled. */
if (!is_evpn_enabled())
/* Update local tunnel IP. */
zl3vni->local_vtep_ip = vxl->vtep_ip;
+ zl3vni->vid = (zl3vni->vid != vnip->access_vlan)
+ ? vnip->access_vlan
+ : zl3vni->vid;
+ br_if = zif->brslave_info.br_if;
+ zl3vni_bridge_if_set(zl3vni, br_if, true /* set */);
+
/* if we have a valid new master, process l3-vni oper up */
if (chgflags & ZEBRA_VXLIF_MASTER_CHANGE) {
if (if_is_operative(ifp) && is_l3vni_oper_up(zl3vni))
zebra_evpn_es_set_base_evpn(zevpn);
}
zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
- vlan_if = zvni_map_to_svi(vnip->access_vlan,
- zif->brslave_info.br_if);
+ zevpn->vid = (zevpn->vid != vnip->access_vlan)
+ ? vnip->access_vlan
+ : zevpn->vid;
+ br_if = zif->brslave_info.br_if;
+ zevpn_bridge_if_set(zevpn, br_if, true /* set */);
+
+ vlan_if = zvni_map_to_svi(vnip->access_vlan, br_if);
if (vlan_if)
zevpn->svi_if = vlan_if;
struct zebra_l2info_vxlan *vxl;
struct zebra_evpn *zevpn;
struct zebra_l3vni *zl3vni;
+ struct interface *br_if;
/* Check if EVPN is enabled. */
if (!is_evpn_enabled())
zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
+ zl3vni->vid = vnip->access_vlan;
+ br_if = zif->brslave_info.br_if;
+ zl3vni_bridge_if_set(zl3vni, br_if, true /* set */);
+
if (is_l3vni_oper_up(zl3vni))
zebra_vxlan_process_l3vni_oper_up(zl3vni);
} else {
zebra_evpn_es_set_base_evpn(zevpn);
}
zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
- vlan_if = zvni_map_to_svi(vnip->access_vlan,
- zif->brslave_info.br_if);
+ br_if = zif->brslave_info.br_if;
+ zevpn_bridge_if_set(zevpn, br_if, true /* set */);
+ vlan_if = zvni_map_to_svi(vnip->access_vlan, br_if);
if (vlan_if) {
+ zevpn->vid = vnip->access_vlan;
zevpn->svi_if = vlan_if;
zevpn->vrf_id = vlan_if->vrf->vrf_id;
zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
hash_walk(vni_info->vni_table, zebra_vxlan_if_vni_walk_callback, &ctx);
}
-struct zebra_vxlan_vni *zebra_vxlan_if_access_vlan_find(struct zebra_if *zif,
- uint8_t vlan_aware,
- vlanid_t vid)
+vni_t zebra_vxlan_if_access_vlan_vni_find(struct zebra_if *zif, vlanid_t vid,
+ struct interface *br_if)
{
struct zebra_vxlan_vni *vni = NULL;
- struct zebra_vxlan_if_vlan_ctx ctx;
- if (IS_ZEBRA_VXLAN_IF_VNI(zif)) {
- vni = zebra_vxlan_if_vni_find(zif, 0);
- if (vlan_aware && vni->access_vlan != vid)
- vni = NULL;
- return vni;
- }
-
- ctx.vid = vid;
- ctx.vni = NULL;
- zebra_vxlan_if_vni_walk(zif, zebra_vxlan_if_vni_access_vlan_find,
- (void *)&ctx);
- vni = ctx.vni;
+ /* Expected to be called only for vlan-unware bridges */
+ assert(!IS_ZEBRA_IF_BRIDGE_VLAN_AWARE((struct zebra_if *)br_if->info));
+ vni = zebra_vxlan_if_vni_find(zif, 0);
+ assert(vni);
- return vni;
+ return vni->vni;
}
int zebra_vxlan_if_vni_table_add_update(struct interface *ifp,
struct zebra_vxlan_vni vni_tmp;
struct zebra_vxlan_vni_info *vni_info;
- /* Check if EVPN is enabled. */
- if (!is_evpn_enabled())
- return 0;
-
zif = ifp->info;
assert(zif);
struct zebra_if *zif;
struct zebra_vxlan_vni_info *vni_info;
- /* Check if EVPN is enabled. */
- if (!is_evpn_enabled())
- return 0;
-
zif = ifp->info;
assert(zif);
/* This should be called in SVD context only */
assert(IS_ZEBRA_VXLAN_IF_SVD(zif));
- /* First inser into the table */
+ /* First insert into the table */
vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
hash_get(vni_info->vni_table, (void *)vni, zebra_vxlan_vni_alloc);
/*
- * Zebra VxLAN (EVPN) Data structures and definitions
+ * Zebra VxLAN (EVPN) interface data structures and definitions
* These are public definitions referenced by other files.
* Copyright (C) 2021 Cumulus Networks, Inc.
* Sharath Ramamurthy
struct zebra_vxlan_vni *,
void *),
void *arg);
-extern struct zebra_vxlan_vni *
-zebra_vxlan_if_access_vlan_find(struct zebra_if *zif, uint8_t vlan_aware,
- vlanid_t vid);
+extern vni_t zebra_vxlan_if_access_vlan_vni_find(struct zebra_if *zif,
+ vlanid_t vid,
+ struct interface *br_if);
extern int zebra_vxlan_if_vni_mcast_group_update(struct interface *ifp,
vni_t vni_id,
struct in_addr *mcast_group);
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;