mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 23:11:21 +00:00
zebra: importation of bgp evpn rt5 from vni with other netns
With vrf-lite mechanisms, it is possible to create layer 3 vnis by creating a bridge interface in default vr, by creating a vxlan interface that is attached to that bridge interface, then by moving the vxlan interface to the wished vrf. With vrf-netns mechanism, it is slightly different since bridged interfaces can not be separated in different network namespaces. To make it work, the setup consists in : - creating a vxlan interface on default vrf. - move the vxlan interface to the wished vrf ( with an other netns) - create a bridge interface in the wished vrf - attach the vxlan interface to that bridged interface from that point, if BGP is enabled to advertise vnis in default vrf, then vxlan interfaces are discovered appropriately in other vrfs, provided that the link interface still resides in the vrf where l2vpn is advertised. to import ipv4 entries from a separate vrf, into the l2vpn, the configuration of vni in the dedicated vrf + the advertisement of ipv4 entries in bgp vrf will import the entries in the bgp l2vpn. the modification consists in parsing the vxlan interfaces in all network namespaces, where the link resides in the same network namespace as the bgp core instance where bgp l2vpn is enabled. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
14ddb3d9c4
commit
28254125d0
@ -51,7 +51,7 @@ static struct ns *ns_lookup_name_internal(const char *name);
|
||||
|
||||
RB_GENERATE(ns_head, ns, entry, ns_compare)
|
||||
|
||||
static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
|
||||
struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
|
||||
|
||||
static struct ns *default_ns;
|
||||
static int ns_current_ns_fd;
|
||||
|
@ -34,7 +34,7 @@ static inline int ns_compare(const struct ns *ns, const struct ns *ns2);
|
||||
|
||||
RB_GENERATE(ns_head, ns, entry, ns_compare)
|
||||
|
||||
static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
|
||||
struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
|
||||
|
||||
static inline int ns_compare(const struct ns *a, const struct ns *b)
|
||||
{
|
||||
|
2
lib/ns.h
2
lib/ns.h
@ -71,6 +71,8 @@ struct ns {
|
||||
RB_HEAD(ns_head, ns);
|
||||
RB_PROTOTYPE(ns_head, ns, entry, ns_compare)
|
||||
|
||||
extern struct ns_head ns_tree;
|
||||
|
||||
/*
|
||||
* API for managing NETNS. eg from zebra daemon
|
||||
* one want to manage the list of NETNS, etc...
|
||||
|
@ -229,3 +229,25 @@ int zebra_ns_config_write(struct vty *vty, struct ns *ns)
|
||||
vty_out(vty, " netns %s\n", ns->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zebra_ns_list_walk(int (*exec_for_each_zns)(struct zebra_ns *zns,
|
||||
void *param_in,
|
||||
void **param_out),
|
||||
void *param_in,
|
||||
void **param_out)
|
||||
{
|
||||
struct ns *ns;
|
||||
struct zebra_ns *zns;
|
||||
int ret;
|
||||
|
||||
RB_FOREACH (ns, ns_head, &ns_tree) {
|
||||
zns = (struct zebra_ns *)ns->info;
|
||||
if (!zns && ns->ns_id == NS_DEFAULT)
|
||||
zns = zebra_ns_lookup(ns->ns_id);
|
||||
if (!zns)
|
||||
continue;
|
||||
ret = exec_for_each_zns(zns, param_in, param_out);
|
||||
if (ret == ZNS_WALK_STOP)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,14 @@ int zebra_ns_final_shutdown(struct ns *ns);
|
||||
|
||||
int zebra_ns_config_write(struct vty *vty, struct ns *ns);
|
||||
|
||||
#define ZNS_WALK_CONTINUE 0
|
||||
#define ZNS_WALK_STOP 1
|
||||
void zebra_ns_list_walk(int (*exec_for_each_zns)(struct zebra_ns *zns,
|
||||
void *param_in,
|
||||
void **param_out),
|
||||
void *param_in,
|
||||
void **param_out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -4115,18 +4115,20 @@ static int zvni_send_del_to_client(vni_t vni)
|
||||
return zserv_send_message(client, s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the VNI hash table by going over the VxLAN interfaces. This
|
||||
* is called when EVPN (advertise-all-vni) is enabled.
|
||||
*/
|
||||
static void zvni_build_hash_table(void)
|
||||
static int zvni_build_hash_table_zns(struct zebra_ns *zns,
|
||||
void *param_in __attribute__((unused)),
|
||||
void **param_out __attribute__((unused)))
|
||||
{
|
||||
struct zebra_ns *zns;
|
||||
struct route_node *rn;
|
||||
struct interface *ifp;
|
||||
struct zebra_vrf *zvrf;
|
||||
|
||||
zvrf = zebra_vrf_get_evpn();
|
||||
|
||||
if (!zvrf)
|
||||
return ZNS_WALK_STOP;
|
||||
|
||||
/* Walk VxLAN interfaces and create VNI hash. */
|
||||
zns = zebra_ns_lookup(NS_DEFAULT);
|
||||
for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
|
||||
vni_t vni;
|
||||
zebra_vni_t *zvni = NULL;
|
||||
@ -4143,7 +4145,15 @@ static void zvni_build_hash_table(void)
|
||||
|
||||
vxl = &zif->l2info.vxl;
|
||||
vni = vxl->vni;
|
||||
|
||||
/* link of VXLAN interface should be in zebra_evpn_vrf */
|
||||
if (zvrf->zns->ns_id != vxl->link_nsid) {
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"Intf %s(%u) VNI %u, link not in same "
|
||||
"namespace than BGP EVPN core instance ",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
continue;
|
||||
}
|
||||
/* L3-VNI and L2-VNI are handled seperately */
|
||||
zl3vni = zl3vni_lookup(vni);
|
||||
if (zl3vni) {
|
||||
@ -4212,7 +4222,7 @@ static void zvni_build_hash_table(void)
|
||||
zlog_debug(
|
||||
"Failed to add VNI hash, IF %s(%u) L2-VNI %u",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
return;
|
||||
return ZNS_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
if (zvni->local_vtep_ip.s_addr !=
|
||||
@ -4249,6 +4259,19 @@ static void zvni_build_hash_table(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ZNS_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the VNI hash table by going over the VxLAN interfaces. This
|
||||
* is called when EVPN (advertise-all-vni) is enabled.
|
||||
*/
|
||||
|
||||
static void zvni_build_hash_table(void)
|
||||
{
|
||||
zebra_ns_list_walk(zvni_build_hash_table_zns,
|
||||
(void *)NULL,
|
||||
(void **)NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5033,14 +5056,21 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
|
||||
static int zl3vni_map_to_vxlan_if_zns(struct zebra_ns *zns,
|
||||
void *_zl3vni,
|
||||
void **_pifp)
|
||||
{
|
||||
struct zebra_ns *zns = NULL;
|
||||
zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)_zl3vni;
|
||||
struct route_node *rn = NULL;
|
||||
struct interface *ifp = NULL;
|
||||
struct zebra_vrf *zvrf;
|
||||
|
||||
zvrf = zebra_vrf_get_evpn();
|
||||
|
||||
if (!zvrf)
|
||||
return ZNS_WALK_STOP;
|
||||
|
||||
/* loop through all vxlan-interface */
|
||||
zns = zebra_ns_lookup(NS_DEFAULT);
|
||||
for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
|
||||
|
||||
struct zebra_if *zif = NULL;
|
||||
@ -5055,13 +5085,39 @@ struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
|
||||
continue;
|
||||
|
||||
vxl = &zif->l2info.vxl;
|
||||
if (vxl->vni == zl3vni->vni) {
|
||||
zl3vni->local_vtep_ip = vxl->vtep_ip;
|
||||
return ifp;
|
||||
if (vxl->vni != zl3vni->vni)
|
||||
continue;
|
||||
|
||||
/* link of VXLAN interface should be in zebra_evpn_vrf */
|
||||
if (zvrf->zns->ns_id != vxl->link_nsid) {
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"Intf %s(%u) VNI %u, link not in same "
|
||||
"namespace than BGP EVPN core instance ",
|
||||
ifp->name, ifp->ifindex, vxl->vni);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
zl3vni->local_vtep_ip = vxl->vtep_ip;
|
||||
if (_pifp)
|
||||
*_pifp = (void *)ifp;
|
||||
return ZNS_WALK_STOP;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return ZNS_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
|
||||
{
|
||||
struct interface **p_ifp;
|
||||
struct interface *ifp = NULL;
|
||||
|
||||
p_ifp = &ifp;
|
||||
|
||||
zebra_ns_list_walk(zl3vni_map_to_vxlan_if_zns,
|
||||
(void *)zl3vni, (void **)p_ifp);
|
||||
return ifp;
|
||||
}
|
||||
|
||||
struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
|
||||
|
Loading…
Reference in New Issue
Block a user