]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: importation of bgp evpn rt5 from vni with other netns
authorPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 26 Sep 2019 16:49:59 +0000 (18:49 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 18 May 2020 12:11:03 +0000 (14:11 +0200)
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>
lib/netns_linux.c
lib/netns_other.c
lib/ns.h
zebra/zebra_ns.c
zebra/zebra_ns.h
zebra/zebra_vxlan.c

index 98f359401e377c4fc33e4e45dc652cd4ad3dd014..09a42b850bf301ec99f99ea84efe770726fe9d5b 100644 (file)
@@ -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;
index 740d2b621ed7d3e0bb2357efb6304fb23a28d8f7..b0aae4f8df082dd18652478964a226738e1fa9ff 100644 (file)
@@ -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)
 {
index 20e0a38e3b3e0d84586188171e7a8c1640199d79..1963b8a35968750efc194319b1614d132fc66ca7 100644 (file)
--- a/lib/ns.h
+++ b/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...
index 4e51437337896810655ab4cd375cb659be890927..4e23ca2f03f0130232d4ad2b5e9b381e51c6c426 100644 (file)
@@ -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;
+       }
+}
index dc79a83db0d878216b57ac9cde2231871acaccdb..fa2fd47c25bd793fb60aa3121c6a04b2e96de0a8 100644 (file)
@@ -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
index d85f48e570cef5418e7ce4f4f3f473ef9349fb8c..863eef17a3c1124f29d6ce3c741ec19ddd5be437 100644 (file)
@@ -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)