Merge pull request #5077 from pguibert6WIND/vxlan_link

BGP EVPN vrf netns backend
This commit is contained in:
Donatas Abraitis 2020-05-19 09:12:38 +03:00 committed by GitHub
commit a6943f9dab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 581 additions and 172 deletions

View File

@ -16234,6 +16234,10 @@ void bgp_vty_init(void)
&no_neighbor_route_reflector_client_cmd);
install_element(BGP_EVPN_NODE, &neighbor_route_reflector_client_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_route_reflector_client_cmd);
install_element(BGP_EVPN_NODE, &neighbor_nexthop_self_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_nexthop_self_cmd);
install_element(BGP_EVPN_NODE, &neighbor_nexthop_self_force_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_nexthop_self_force_cmd);
/* "neighbor route-server" commands.*/
install_element(BGP_NODE, &neighbor_route_server_client_hidden_cmd);

View File

@ -1143,7 +1143,8 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
api_nh->ifindex = 0;
}
}
api_nh->gate.ipv6 = *nexthop;
if (nexthop)
api_nh->gate.ipv6 = *nexthop;
return true;
}

View File

@ -1227,10 +1227,6 @@ struct peer *peer_new(struct bgp *bgp)
peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
}
/* set nexthop-unchanged for l2vpn evpn by default */
SET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
PEER_FLAG_NEXTHOP_UNCHANGED);
SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
/* Initialize per peer bgp GR FSM */

View File

@ -2391,6 +2391,27 @@ the same behavior of using same next-hop and RMAC values.
Enables or disables advertise-pip feature, specifiy system-IP and/or system-MAC
parameters.
Support with VRF network namespace backend
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It is possible to separate overlay networks contained in VXLAN interfaces from
underlay networks by using VRFs. VRF-lite and VRF-netns backends can be used for
that. In the latter case, this is necessary to set both bridge and vxlan interface
on the same network namespace, as below example illustrates:
.. code-block:: shell
# linux shell
ip netns add vrf1
ip link add name vxlan101 type vxlan id 101 dstport 4789 dev eth0 local 10.1.1.1
ip link set dev vxlan101 netns vrf1
ip netns exec vrf1 ip link set dev lo up
ip netns exec vrf1 brctl addbr bridge101
ip netns exec vrf1 brctl addif bridge101 vxlan101
This makes possible to separate not only layer 3 networks like VRF-lite networks.
Also, VRF netns based make possible to separate layer 2 networks on separate VRF
instances.
.. _bgp-cisco-compatibility:
Cisco Compatibility

View File

@ -16,6 +16,7 @@ enum {
NETNSA_NSID,
NETNSA_PID,
NETNSA_FD,
NETNSA_TARGET_NSID,
__NETNSA_MAX,
};

View File

@ -379,12 +379,20 @@ struct ns *ns_lookup(ns_id_t ns_id)
return ns_lookup_internal(ns_id);
}
void ns_walk_func(int (*func)(struct ns *))
void ns_walk_func(int (*func)(struct ns *,
void *param_in,
void **param_out),
void *param_in,
void **param_out)
{
struct ns *ns = NULL;
int ret;
RB_FOREACH (ns, ns_head, &ns_tree)
func(ns);
RB_FOREACH (ns, ns_head, &ns_tree) {
ret = func(ns, param_in, param_out);
if (ret == NS_WALK_STOP)
return;
}
}
const char *ns_get_name(struct ns *ns)
@ -584,9 +592,33 @@ int ns_socket(int domain, int type, int protocol, ns_id_t ns_id)
return ret;
}
/* if relative link_nsid matches default netns,
* then return default absolute netns value
* otherwise, return NS_UNKNOWN
*/
ns_id_t ns_id_get_absolute(ns_id_t ns_id_reference, ns_id_t link_nsid)
{
struct ns *ns;
ns = ns_lookup(ns_id_reference);
if (!ns)
return NS_UNKNOWN;
if (ns->relative_default_ns != link_nsid)
return NS_UNKNOWN;
ns = ns_get_default();
assert(ns);
return ns->ns_id;
}
ns_id_t ns_get_default_id(void)
{
if (default_ns)
return default_ns->ns_id;
return NS_DEFAULT_INTERNAL;
}
struct ns *ns_get_default(void)
{
return default_ns;
}

View File

@ -53,6 +53,11 @@ struct ns {
/* Identifier, mapped on the NSID value */
ns_id_t internal_ns_id;
/* Identifier, value of NSID of default netns,
* relative value in that local netns
*/
ns_id_t relative_default_ns;
/* Name */
char *name;
@ -120,7 +125,14 @@ int ns_socket(int domain, int type, int protocol, ns_id_t ns_id);
extern char *ns_netns_pathname(struct vty *vty, const char *name);
/* Parse and execute a function on all the NETNS */
extern void ns_walk_func(int (*func)(struct ns *));
#define NS_WALK_CONTINUE 0
#define NS_WALK_STOP 1
extern void ns_walk_func(int (*func)(struct ns *,
void *,
void **),
void *param_in,
void **param_out);
/* API to get the NETNS name, from the ns pointer */
extern const char *ns_get_name(struct ns *ns);
@ -174,7 +186,9 @@ extern struct ns *ns_lookup_name(const char *name);
*/
extern int ns_enable(struct ns *ns, void (*func)(ns_id_t, void *));
extern struct ns *ns_get_created(struct ns *ns, char *name, ns_id_t ns_id);
extern ns_id_t ns_id_get_absolute(ns_id_t ns_id_reference, ns_id_t link_nsid);
extern void ns_disable(struct ns *ns);
extern struct ns *ns_get_default(void);
#ifdef __cplusplus
}

View File

@ -652,7 +652,8 @@ int vrf_handler_create(struct vty *vty, const char *vrfname,
}
int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
ns_id_t ns_id, ns_id_t internal_ns_id)
ns_id_t ns_id, ns_id_t internal_ns_id,
ns_id_t rel_def_ns_id)
{
struct ns *ns = NULL;
@ -700,6 +701,7 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
}
ns = ns_get_created(ns, pathname, ns_id);
ns->internal_ns_id = internal_ns_id;
ns->relative_default_ns = rel_def_ns_id;
ns->vrf_ctxt = (void *)vrf;
vrf->ns_ctxt = (void *)ns;
/* update VRF netns NAME */
@ -797,7 +799,9 @@ DEFUN_NOSH (vrf_netns,
frr_with_privs(vrf_daemon_privs) {
ret = vrf_netns_handler_create(vty, vrf, pathname,
NS_UNKNOWN, NS_UNKNOWN);
NS_UNKNOWN,
NS_UNKNOWN,
NS_UNKNOWN);
}
return ret;
}

View File

@ -315,7 +315,7 @@ extern int vrf_handler_create(struct vty *vty, const char *name,
*/
extern int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf,
char *pathname, ns_id_t ext_ns_id,
ns_id_t ns_id);
ns_id_t ns_id, ns_id_t rel_def_ns_id);
/* used internally to enable or disable VRF.
* Notify a change in the VRF ID of the VRF

View File

@ -482,6 +482,7 @@ static int netlink_extract_vxlan_info(struct rtattr *link_data,
struct rtattr *attr[IFLA_VXLAN_MAX + 1];
vni_t vni_in_msg;
struct in_addr vtep_ip_in_msg;
ifindex_t ifindex_link;
memset(vxl_info, 0, sizeof(*vxl_info));
memset(attr, 0, sizeof(attr));
@ -510,6 +511,15 @@ static int netlink_extract_vxlan_info(struct rtattr *link_data,
*(struct in_addr *)RTA_DATA(attr[IFLA_VXLAN_GROUP]);
}
if (!attr[IFLA_VXLAN_LINK]) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("IFLA_VXLAN_LINK missing "
"from VXLAN IF message");
} else {
ifindex_link =
*(ifindex_t *)RTA_DATA(attr[IFLA_VXLAN_LINK]);
vxl_info->ifindex_link = ifindex_link;
}
return 0;
}
@ -519,7 +529,8 @@ static int netlink_extract_vxlan_info(struct rtattr *link_data,
* its members. Likewise, for VxLAN interface.
*/
static void netlink_interface_update_l2info(struct interface *ifp,
struct rtattr *link_data, int add)
struct rtattr *link_data, int add,
ns_id_t link_nsid)
{
if (!link_data)
return;
@ -538,7 +549,12 @@ static void netlink_interface_update_l2info(struct interface *ifp,
struct zebra_l2info_vxlan vxlan_info;
netlink_extract_vxlan_info(link_data, &vxlan_info);
vxlan_info.link_nsid = link_nsid;
zebra_l2_vxlanif_add_update(ifp, &vxlan_info, add);
if (link_nsid != NS_UNKNOWN &&
vxlan_info.ifindex_link)
zebra_if_update_link(ifp, vxlan_info.ifindex_link,
link_nsid);
}
}
@ -622,6 +638,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifindex_t link_ifindex = IFINDEX_INTERNAL;
ifindex_t bond_ifindex = IFINDEX_INTERNAL;
struct zebra_if *zif;
ns_id_t link_nsid = ns_id;
zns = zebra_ns_lookup(ns_id);
ifi = NLMSG_DATA(h);
@ -705,6 +722,11 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (tb[IFLA_LINK])
link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);
if (tb[IFLA_LINK_NETNSID]) {
link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]);
link_nsid = ns_id_get_absolute(ns_id, link_nsid);
}
/* Add interface.
* We add by index first because in some cases such as the master
* interface, we have the index before we have the name. Fixing
@ -749,9 +771,10 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
/* Extract and save L2 interface information, take additional actions.
*/
netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1);
netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA],
1, link_nsid);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp, bridge_ifindex);
zebra_l2if_update_bridge_slave(ifp, bridge_ifindex, ns_id);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
zebra_l2if_update_bond_slave(ifp, bond_ifindex);
@ -1168,6 +1191,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifindex_t link_ifindex = IFINDEX_INTERNAL;
uint8_t old_hw_addr[INTERFACE_HWADDR_MAX];
struct zebra_if *zif;
ns_id_t link_nsid = ns_id;
zns = zebra_ns_lookup(ns_id);
ifi = NLMSG_DATA(h);
@ -1235,6 +1259,10 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (tb[IFLA_LINK])
link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);
if (tb[IFLA_LINK_NETNSID]) {
link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]);
link_nsid = ns_id_get_absolute(ns_id, link_nsid);
}
if (tb[IFLA_IFALIAS]) {
desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]);
}
@ -1319,10 +1347,12 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
/* Extract and save L2 interface information, take
* additional actions. */
netlink_interface_update_l2info(
ifp, linkinfo[IFLA_INFO_DATA], 1);
ifp, linkinfo[IFLA_INFO_DATA],
1, link_nsid);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
bridge_ifindex,
ns_id);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
zebra_l2if_update_bond_slave(ifp, bond_ifindex);
} else if (ifp->vrf_id != vrf_id) {
@ -1421,10 +1451,12 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
/* Extract and save L2 interface information, take
* additional actions. */
netlink_interface_update_l2info(
ifp, linkinfo[IFLA_INFO_DATA], 0);
ifp, linkinfo[IFLA_INFO_DATA],
0, link_nsid);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
bridge_ifindex,
ns_id);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
zebra_l2if_update_bond_slave(ifp, bond_ifindex);
}

View File

@ -1236,6 +1236,23 @@ static void nbr_connected_dump_vty(struct vty *vty,
vty_out(vty, "\n");
}
static const char *zebra_zifslavetype_2str(zebra_slave_iftype_t zif_slave_type)
{
switch (zif_slave_type) {
case ZEBRA_IF_SLAVE_BRIDGE:
return "Bridge";
case ZEBRA_IF_SLAVE_VRF:
return "Vrf";
case ZEBRA_IF_SLAVE_BOND:
return "Bond";
case ZEBRA_IF_SLAVE_OTHER:
return "Other";
case ZEBRA_IF_SLAVE_NONE:
return "None";
}
return "None";
}
static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
{
switch (zif_type) {
@ -1463,6 +1480,9 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
vty_out(vty, " Interface Type %s\n",
zebra_ziftype_2str(zebra_if->zif_type));
vty_out(vty, " Interface Slave Type %s\n",
zebra_zifslavetype_2str(zebra_if->zif_slave_type));
if (IS_ZEBRA_IF_BRIDGE(ifp)) {
struct zebra_l2info_bridge *bridge_info;
@ -1488,6 +1508,17 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
if (vxlan_info->mcast_grp.s_addr != INADDR_ANY)
vty_out(vty, " Mcast Group %s",
inet_ntoa(vxlan_info->mcast_grp));
if (vxlan_info->ifindex_link &&
(vxlan_info->link_nsid != NS_UNKNOWN)) {
struct interface *ifp;
ifp = if_lookup_by_index_per_ns(
zebra_ns_lookup(vxlan_info->link_nsid),
vxlan_info->ifindex_link);
vty_out(vty, " Link Interface %s",
ifp == NULL ? "Unknown" :
ifp->name);
}
vty_out(vty, "\n");
}

View File

@ -177,7 +177,7 @@ static void sigint(void)
vrf_terminate();
rtadv_terminate();
ns_walk_func(zebra_ns_early_shutdown);
ns_walk_func(zebra_ns_early_shutdown, NULL, NULL);
zebra_ns_notify_close();
access_list_reset();
@ -208,7 +208,7 @@ int zebra_finalize(struct thread *dummy)
zlog_info("Zebra final shutdown");
/* Final shutdown of ns resources */
ns_walk_func(zebra_ns_final_shutdown);
ns_walk_func(zebra_ns_final_shutdown, NULL, NULL);
/* Stop dplane thread and finish any cleanup */
zebra_dplane_shutdown();

View File

@ -53,7 +53,13 @@ static void map_slaves_to_bridge(struct interface *br_if, int link)
{
struct vrf *vrf;
struct interface *ifp;
struct zebra_vrf *zvrf;
struct zebra_ns *zns;
zvrf = zebra_vrf_lookup_by_id(br_if->vrf_id);
assert(zvrf);
zns = zvrf->zns;
assert(zns);
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
FOR_ALL_INTERFACES (vrf, ifp) {
struct zebra_if *zif;
@ -72,7 +78,8 @@ static void map_slaves_to_bridge(struct interface *br_if, int link)
br_slave = &zif->brslave_info;
if (link) {
if (br_slave->bridge_ifindex == br_if->ifindex)
if (br_slave->bridge_ifindex == br_if->ifindex &&
br_slave->ns_id == zns->ns_id)
br_slave->br_if = br_if;
} else {
if (br_slave->br_if == br_if)
@ -83,12 +90,14 @@ static void map_slaves_to_bridge(struct interface *br_if, int link)
}
/* Public functions */
void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave)
void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave,
struct zebra_ns *zns)
{
struct interface *br_if;
/* TODO: Handle change of master */
br_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
assert(zns);
br_if = if_lookup_by_index_per_ns(zebra_ns_lookup(zns->ns_id),
br_slave->bridge_ifindex);
if (br_if)
br_slave->br_if = br_if;
@ -237,23 +246,32 @@ void zebra_l2_vxlanif_del(struct interface *ifp)
* from a bridge before it can be mapped to another bridge.
*/
void zebra_l2if_update_bridge_slave(struct interface *ifp,
ifindex_t bridge_ifindex)
ifindex_t bridge_ifindex,
ns_id_t ns_id)
{
struct zebra_if *zif;
ifindex_t old_bridge_ifindex;
ns_id_t old_ns_id;
struct zebra_vrf *zvrf;
zif = ifp->info;
assert(zif);
old_bridge_ifindex = zif->brslave_info.bridge_ifindex;
if (old_bridge_ifindex == bridge_ifindex)
zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
if (!zvrf)
return;
zif->brslave_info.bridge_ifindex = bridge_ifindex;
old_bridge_ifindex = zif->brslave_info.bridge_ifindex;
old_ns_id = zif->brslave_info.ns_id;
if (old_bridge_ifindex == bridge_ifindex &&
old_ns_id == zif->brslave_info.ns_id)
return;
zif->brslave_info.ns_id = ns_id;
zif->brslave_info.bridge_ifindex = bridge_ifindex;
/* Set up or remove link with master */
if (bridge_ifindex != IFINDEX_INTERNAL) {
zebra_l2_map_slave_to_bridge(&zif->brslave_info);
zebra_l2_map_slave_to_bridge(&zif->brslave_info, zvrf->zns);
/* In the case of VxLAN, invoke the handler for EVPN. */
if (zif->zif_type == ZEBRA_IF_VXLAN)
zebra_vxlan_if_update(ifp, ZEBRA_VXLIF_MASTER_CHANGE);

View File

@ -37,6 +37,7 @@ extern "C" {
struct zebra_l2info_brslave {
ifindex_t bridge_ifindex; /* Bridge Master */
struct interface *br_if; /* Pointer to master */
ns_id_t ns_id; /* network namespace where bridge is */
};
/* zebra L2 interface information - bridge interface */
@ -55,6 +56,10 @@ struct zebra_l2info_vxlan {
struct in_addr vtep_ip; /* Local tunnel IP */
vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */
struct in_addr mcast_grp;
ifindex_t ifindex_link; /* Interface index of interface
* linked with VXLAN
*/
ns_id_t link_nsid;
};
struct zebra_l2info_bondslave {
@ -77,7 +82,8 @@ union zebra_l2if_info {
#define IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif) ((zif)->l2info.br.vlan_aware == 1)
extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave);
extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave,
struct zebra_ns *zns);
extern void
zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave);
extern void
@ -97,7 +103,8 @@ extern void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp,
vlanid_t access_vlan);
extern void zebra_l2_vxlanif_del(struct interface *ifp);
extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
ifindex_t bridge_ifindex);
ifindex_t bridge_ifindex,
ns_id_t ns_id);
extern void zebra_l2if_update_bond_slave(struct interface *ifp,
ifindex_t bond_ifindex);

View File

@ -159,27 +159,34 @@ static ns_id_t extract_nsid(struct nlmsghdr *nlh, char *buf)
return ns_id;
}
ns_id_t zebra_ns_id_get(const char *netnspath)
/* fd_param = -1 is ignored.
* netnspath set to null is ignored.
* one of the 2 params is mandatory. netnspath is looked in priority
*/
ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param)
{
int ns_id = -1;
struct sockaddr_nl snl;
int fd, sock, ret;
int fd = -1, sock, ret;
unsigned int seq;
ns_id_t return_nsid = NS_UNKNOWN;
/* netns path check */
if (!netnspath)
if (!netnspath && fd_param == -1)
return NS_UNKNOWN;
fd = open(netnspath, O_RDONLY);
if (fd == -1)
return NS_UNKNOWN;
if (netnspath) {
fd = open(netnspath, O_RDONLY);
if (fd == -1)
return NS_UNKNOWN;
} else if (fd_param != -1)
fd = fd_param;
/* netlink socket */
sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (sock < 0) {
flog_err_sys(EC_LIB_SOCKET, "netlink( %u) socket() error: %s",
sock, safe_strerror(errno));
close(fd);
if (fd_param == -1)
close(fd);
return NS_UNKNOWN;
}
memset(&snl, 0, sizeof(snl));
@ -192,7 +199,8 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
"netlink( %u) socket() bind error: %s", sock,
safe_strerror(errno));
close(sock);
close(fd);
if (fd_param == -1)
close(fd);
return NS_UNKNOWN;
}
@ -214,7 +222,8 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
ret = send_receive(sock, nlh, seq, buf);
if (ret < 0) {
close(sock);
close(fd);
if (fd_param == -1)
close(fd);
return NS_UNKNOWN;
}
nlh = (struct nlmsghdr *)buf;
@ -258,7 +267,8 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
"netlink( %u) recvfrom() error 2 when reading: %s",
fd, safe_strerror(errno));
close(sock);
close(fd);
if (fd_param == -1)
close(fd);
if (errno == ENOTSUP) {
zlog_debug("NEWNSID locally generated");
return zebra_ns_id_get_fallback(netnspath);
@ -278,7 +288,8 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
ret = send_receive(sock, nlh, seq, buf);
if (ret < 0) {
close(sock);
close(fd);
if (fd_param == -1)
close(fd);
return NS_UNKNOWN;
}
nlh = (struct nlmsghdr *)buf;
@ -309,16 +320,18 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
} while (len != 0 && ret == 0);
}
close(fd);
if (fd_param == -1)
close(fd);
close(sock);
return return_nsid;
}
#else
ns_id_t zebra_ns_id_get(const char *netnspath)
ns_id_t zebra_ns_id_get(const char *netnspath, int fd __attribute__ ((unused)))
{
return zebra_ns_id_get_fallback(netnspath);
}
#endif /* ! defined(HAVE_NETLINK) */
#ifdef HAVE_NETNS
@ -354,7 +367,7 @@ ns_id_t zebra_ns_id_get_default(void)
return NS_DEFAULT_INTERNAL;
}
close(fd);
return zebra_ns_id_get((char *)NS_DEFAULT_NAME);
return zebra_ns_id_get((char *)NS_DEFAULT_NAME, -1);
#else /* HAVE_NETNS */
return NS_DEFAULT_INTERNAL;
#endif /* !HAVE_NETNS */

View File

@ -24,7 +24,7 @@
extern "C" {
#endif
extern ns_id_t zebra_ns_id_get(const char *netnspath);
extern ns_id_t zebra_ns_id_get(const char *netnspath, int fd);
extern ns_id_t zebra_ns_id_get_default(void);
#ifdef __cplusplus

View File

@ -72,13 +72,14 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
char *netnspath = ns_netns_pathname(NULL, name);
struct vrf *vrf;
int ret;
ns_id_t ns_id, ns_id_external;
ns_id_t ns_id, ns_id_external, ns_id_relative = NS_UNKNOWN;
struct ns *default_ns;
if (netnspath == NULL)
return;
frr_with_privs(&zserv_privs) {
ns_id = zebra_ns_id_get(netnspath);
ns_id = zebra_ns_id_get(netnspath, -1);
}
if (ns_id == NS_UNKNOWN)
return;
@ -97,9 +98,21 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
ns_map_nsid_with_external(ns_id, false);
return;
}
default_ns = ns_get_default();
/* force kernel ns_id creation in that new vrf */
frr_with_privs(&zserv_privs) {
ns_switch_to_netns(netnspath);
ns_id_relative = zebra_ns_id_get(NULL, default_ns->fd);
ns_switchback_to_initial();
}
frr_with_privs(&zserv_privs) {
ret = vrf_netns_handler_create(NULL, vrf, netnspath,
ns_id_external, ns_id);
ns_id_external,
ns_id,
ns_id_relative);
}
if (ret != CMD_SUCCESS) {
flog_warn(EC_ZEBRA_NS_VRF_CREATION_FAILED,

View File

@ -153,20 +153,25 @@ static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete)
/* During zebra shutdown, do partial cleanup while the async dataplane
* is still running.
*/
int zebra_ns_early_shutdown(struct ns *ns)
int zebra_ns_early_shutdown(struct ns *ns,
void *param_in __attribute__((unused)),
void **param_out __attribute__((unused)))
{
struct zebra_ns *zns = ns->info;
if (zns == NULL)
return 0;
return zebra_ns_disable_internal(zns, false);
zebra_ns_disable_internal(zns, false);
return NS_WALK_CONTINUE;
}
/* During zebra shutdown, do final cleanup
* after all dataplane work is complete.
*/
int zebra_ns_final_shutdown(struct ns *ns)
int zebra_ns_final_shutdown(struct ns *ns,
void *param_in __attribute__((unused)),
void **param_out __attribute__((unused)))
{
struct zebra_ns *zns = ns->info;
@ -175,7 +180,7 @@ int zebra_ns_final_shutdown(struct ns *ns)
kernel_terminate(zns, true);
return 0;
return NS_WALK_CONTINUE;
}
int zebra_ns_init(const char *optional_default_name)
@ -183,12 +188,16 @@ int zebra_ns_init(const char *optional_default_name)
struct ns *default_ns;
ns_id_t ns_id;
ns_id_t ns_id_external;
struct ns *ns;
frr_with_privs(&zserv_privs) {
ns_id = zebra_ns_id_get_default();
}
ns_id_external = ns_map_nsid_with_external(ns_id, true);
ns_init_management(ns_id_external, ns_id);
ns = ns_get_default();
if (ns)
ns->relative_default_ns = ns_id;
default_ns = ns_lookup(ns_get_default_id());
if (!default_ns) {

View File

@ -67,9 +67,12 @@ struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id);
int zebra_ns_init(const char *optional_default_name);
int zebra_ns_enable(ns_id_t ns_id, void **info);
int zebra_ns_disabled(struct ns *ns);
int zebra_ns_early_shutdown(struct ns *ns);
int zebra_ns_final_shutdown(struct ns *ns);
int zebra_ns_early_shutdown(struct ns *ns,
void *param_in __attribute__((unused)),
void **param_out __attribute__((unused)));
int zebra_ns_final_shutdown(struct ns *ns,
void *param_in __attribute__((unused)),
void **param_out __attribute__((unused)));
int zebra_ns_config_write(struct vty *vty, struct ns *ns);
#ifdef __cplusplus

View File

@ -1194,7 +1194,7 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
ifindex_t ifindex;
ifindex = mac->fwd_info.local.ifindex;
zns = zebra_ns_lookup(NS_DEFAULT);
zns = zebra_ns_lookup(mac->fwd_info.local.ns_id);
ifp = if_lookup_by_index_per_ns(zns, ifindex);
if (!ifp)
return;
@ -1276,7 +1276,7 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
ifindex_t ifindex;
ifindex = mac->fwd_info.local.ifindex;
zns = zebra_ns_lookup(NS_DEFAULT);
zns = zebra_ns_lookup(mac->fwd_info.local.ns_id);
ifp = if_lookup_by_index_per_ns(zns, ifindex);
if (!ifp)
return;
@ -1368,7 +1368,7 @@ static void zvni_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
return;
zns = zebra_ns_lookup(NS_DEFAULT);
zns = zebra_ns_lookup(mac->fwd_info.local.ns_id);
ifindex = mac->fwd_info.local.ifindex;
ifp = if_lookup_by_index_per_ns(zns, ifindex);
if (!ifp) // unexpected
@ -2731,7 +2731,12 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
zebra_mac_t *mac = NULL;
struct zebra_if *zif = NULL;
struct zebra_l2info_vxlan *vxl = NULL;
struct zebra_vrf *zvrf;
ns_id_t local_ns_id = NS_DEFAULT;
zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
if (zvrf && zvrf->zns)
local_ns_id = zvrf->zns->ns_id;
zif = zvni->vxlan_if->info;
if (!zif)
return -1;
@ -2756,6 +2761,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
mac->fwd_info.local.vid = vxl->access_vlan;
n = zvni_neigh_lookup(zvni, ip);
@ -3522,32 +3528,39 @@ static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr)
0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL);
}
/*
* Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
* notifications, to see if they are of interest.
*/
static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
struct interface *br_if, vlanid_t vid)
struct zvni_from_svi_param {
struct interface *br_if;
struct interface *svi_if;
struct zebra_if *zif;
uint8_t bridge_vlan_aware;
vlanid_t vid;
};
static int zvni_map_vlan_ns(struct ns *ns,
void *_in_param,
void **_p_zvni)
{
struct zebra_ns *zns;
struct zebra_ns *zns = ns->info;
struct route_node *rn;
struct interface *br_if;
zebra_vni_t **p_zvni = (zebra_vni_t **)_p_zvni;
zebra_vni_t *zvni;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
struct zebra_l2info_bridge *br;
struct zebra_l2info_vxlan *vxl = NULL;
uint8_t bridge_vlan_aware;
zebra_vni_t *zvni;
struct zvni_from_svi_param *in_param =
(struct zvni_from_svi_param *)_in_param;
int found = 0;
/* Determine if bridge is VLAN-aware or not */
zif = br_if->info;
if (!in_param)
return NS_WALK_STOP;
br_if = in_param->br_if;
zif = in_param->zif;
assert(zif);
br = &zif->l2info.br;
bridge_vlan_aware = br->vlan_aware;
assert(br_if);
/* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
/* TODO: Optimize with a hash. */
zns = zebra_ns_lookup(NS_DEFAULT);
for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
tmp_if = (struct interface *)rn->info;
if (!tmp_if)
@ -3562,17 +3575,101 @@ static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
if (zif->brslave_info.br_if != br_if)
continue;
if (!bridge_vlan_aware || vxl->access_vlan == vid) {
if (!in_param->bridge_vlan_aware
|| vxl->access_vlan == in_param->vid) {
found = 1;
break;
}
}
if (!found)
return NS_WALK_CONTINUE;
zvni = zvni_lookup(vxl->vni);
if (p_zvni)
*p_zvni = zvni;
return NS_WALK_STOP;
}
/*
* Map port or (port, VLAN) to a VNI. This is invoked upon getting MAC
* notifications, to see if they are of interest.
*/
static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
struct interface *br_if, vlanid_t vid)
{
struct zebra_if *zif;
struct zebra_l2info_bridge *br;
zebra_vni_t **p_zvni;
zebra_vni_t *zvni = NULL;
struct zvni_from_svi_param in_param;
/* Determine if bridge is VLAN-aware or not */
zif = br_if->info;
assert(zif);
br = &zif->l2info.br;
in_param.bridge_vlan_aware = br->vlan_aware;
in_param.vid = vid;
in_param.br_if = br_if;
in_param.zif = zif;
p_zvni = &zvni;
ns_walk_func(zvni_map_vlan_ns,
(void *)&in_param,
(void **)p_zvni);
return zvni;
}
static int zvni_from_svi_ns(struct ns *ns,
void *_in_param,
void **_p_zvni)
{
struct zebra_ns *zns = ns->info;
struct route_node *rn;
struct interface *br_if;
zebra_vni_t **p_zvni = (zebra_vni_t **)_p_zvni;
zebra_vni_t *zvni;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
struct zebra_l2info_vxlan *vxl = NULL;
struct zvni_from_svi_param *in_param =
(struct zvni_from_svi_param *)_in_param;
int found = 0;
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;
vxl = &zif->l2info.vxl;
if (zif->brslave_info.br_if != br_if)
continue;
if (!in_param->bridge_vlan_aware
|| vxl->access_vlan == !in_param->vid) {
found = 1;
break;
}
}
if (!found)
return NULL;
return NS_WALK_CONTINUE;
zvni = zvni_lookup(vxl->vni);
return zvni;
if (p_zvni)
*p_zvni = zvni;
return NS_WALK_STOP;
}
/*
@ -3582,16 +3679,11 @@ static zebra_vni_t *zvni_map_vlan(struct interface *ifp,
static zebra_vni_t *zvni_from_svi(struct interface *ifp,
struct interface *br_if)
{
struct zebra_ns *zns;
struct route_node *rn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
struct zebra_l2info_bridge *br;
struct zebra_l2info_vxlan *vxl = NULL;
uint8_t bridge_vlan_aware;
vlanid_t vid = 0;
zebra_vni_t *zvni;
int found = 0;
zebra_vni_t *zvni = NULL;
zebra_vni_t **p_zvni;
struct zebra_if *zif;
struct zvni_from_svi_param in_param;
if (!br_if)
return NULL;
@ -3604,8 +3696,10 @@ static zebra_vni_t *zvni_from_svi(struct interface *ifp,
zif = br_if->info;
assert(zif);
br = &zif->l2info.br;
bridge_vlan_aware = br->vlan_aware;
if (bridge_vlan_aware) {
in_param.bridge_vlan_aware = br->vlan_aware;
in_param.vid = 0;
if (in_param.bridge_vlan_aware) {
struct zebra_l2info_vlan *vl;
if (!IS_ZEBRA_IF_VLAN(ifp))
@ -3614,37 +3708,54 @@ static zebra_vni_t *zvni_from_svi(struct interface *ifp,
zif = ifp->info;
assert(zif);
vl = &zif->l2info.vl;
vid = vl->vid;
in_param.vid = vl->vid;
}
in_param.br_if = br_if;
in_param.zif = zif;
p_zvni = &zvni;
/* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
ns_walk_func(zvni_from_svi_ns,
(void *)&in_param,
(void **)p_zvni);
return zvni;
}
static int zvni_map_to_svi_ns(struct ns *ns,
void *_in_param,
void **_p_ifp)
{
struct zebra_ns *zns = ns->info;
struct route_node *rn;
struct zvni_from_svi_param *in_param =
(struct zvni_from_svi_param *)_in_param;
struct zebra_l2info_vlan *vl;
struct interface *tmp_if = NULL;
struct interface **p_ifp = (struct interface **)_p_ifp;
struct zebra_if *zif;
if (!in_param)
return NS_WALK_STOP;
/* TODO: Optimize with a hash. */
zns = zebra_ns_lookup(NS_DEFAULT);
for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
tmp_if = (struct interface *)rn->info;
if (!tmp_if)
/* 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_VXLAN)
if (!zif || zif->zif_type != ZEBRA_IF_VLAN
|| zif->link != in_param->br_if)
continue;
if (!if_is_operative(tmp_if))
continue;
vxl = &zif->l2info.vxl;
vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
if (zif->brslave_info.br_if != br_if)
continue;
if (!bridge_vlan_aware || vxl->access_vlan == vid) {
found = 1;
break;
if (vl->vid == in_param->vid) {
if (p_ifp)
*p_ifp = tmp_if;
return NS_WALK_STOP;
}
}
if (!found)
return NULL;
zvni = zvni_lookup(vxl->vni);
return zvni;
return NS_WALK_CONTINUE;
}
/* Map to SVI on bridge corresponding to specified VLAN. This can be one
@ -3656,15 +3767,11 @@ static zebra_vni_t *zvni_from_svi(struct interface *ifp,
*/
static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
{
struct zebra_ns *zns;
struct route_node *rn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
struct zebra_l2info_bridge *br;
struct zebra_l2info_vlan *vl;
uint8_t bridge_vlan_aware;
int found = 0;
struct zvni_from_svi_param in_param;
struct interface **p_ifp;
/* Defensive check, caller expected to invoke only with valid bridge. */
if (!br_if)
return NULL;
@ -3673,33 +3780,56 @@ static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
zif = br_if->info;
assert(zif);
br = &zif->l2info.br;
bridge_vlan_aware = br->vlan_aware;
in_param.bridge_vlan_aware = br->vlan_aware;
/* Check oper status of the SVI. */
if (!bridge_vlan_aware)
if (!in_param.bridge_vlan_aware)
return if_is_operative(br_if) ? br_if : NULL;
in_param.vid = vid;
in_param.br_if = br_if;
in_param.zif = NULL;
p_ifp = &tmp_if;
/* Identify corresponding VLAN interface. */
ns_walk_func(zvni_map_to_svi_ns,
(void *)&in_param,
(void **)p_ifp);
return tmp_if;
}
static int zvni_map_to_macvlan_ns(struct ns *ns,
void *_in_param,
void **_p_ifp)
{
struct zebra_ns *zns = ns->info;
struct zvni_from_svi_param *in_param =
(struct zvni_from_svi_param *)_in_param;
struct interface **p_ifp = (struct interface **)_p_ifp;
struct route_node *rn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
if (!in_param)
return NS_WALK_STOP;
/* Identify corresponding VLAN interface. */
/* TODO: Optimize with a hash. */
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_VLAN
|| zif->link != br_if)
continue;
vl = &zif->l2info.vl;
if (vl->vid == vid) {
found = 1;
break;
if (!zif || zif->zif_type != ZEBRA_IF_MACVLAN)
continue;
if (zif->link == in_param->svi_if) {
if (p_ifp)
*p_ifp = tmp_if;
return NS_WALK_STOP;
}
}
return found ? tmp_if : NULL;
return NS_WALK_CONTINUE;
}
/* Map to MAC-VLAN interface corresponding to specified SVI interface.
@ -3707,11 +3837,10 @@ 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)
{
struct zebra_ns *zns;
struct route_node *rn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
int found = 0;
struct interface **p_ifp;
struct zvni_from_svi_param in_param;
/* Defensive check, caller expected to invoke only with valid bridge. */
if (!br_if)
@ -3726,28 +3855,19 @@ static struct interface *zvni_map_to_macvlan(struct interface *br_if,
zif = br_if->info;
assert(zif);
in_param.vid = 0;
in_param.br_if = br_if;
in_param.zif = NULL;
in_param.svi_if = svi_if;
p_ifp = &tmp_if;
/* 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;
ns_walk_func(zvni_map_to_macvlan_ns,
(void *)&in_param,
(void **)p_ifp);
return tmp_if;
}
/*
* Install remote MAC into the forwarding plane.
*/
@ -3900,6 +4020,7 @@ static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac)
static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp)
{
struct zebra_ns *zns;
struct zebra_vrf *zvrf;
struct zebra_if *zif;
struct interface *vlan_if;
struct zebra_l2info_vxlan *vxl;
@ -3907,7 +4028,10 @@ static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp)
zif = ifp->info;
vxl = &zif->l2info.vxl;
zns = zebra_ns_lookup(NS_DEFAULT);
zvrf = zebra_vrf_lookup_by_id(zvni->vrf_id);
if (!zvrf || !zvrf->zns)
return;
zns = zvrf->zns;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
@ -4115,18 +4239,21 @@ 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_ns(struct ns *ns,
void *param_in __attribute__((unused)),
void **param_out __attribute__((unused)))
{
struct zebra_ns *zns;
struct zebra_ns *zns = ns->info;
struct route_node *rn;
struct interface *ifp;
struct zebra_vrf *zvrf;
zvrf = zebra_vrf_get_evpn();
if (!zvrf)
return NS_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 +4270,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 +4347,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 NS_WALK_CONTINUE;
}
if (zvni->local_vtep_ip.s_addr !=
@ -4249,6 +4384,19 @@ static void zvni_build_hash_table(void)
}
}
}
return NS_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)
{
ns_walk_func(zvni_build_hash_table_ns,
(void *)NULL,
(void **)NULL);
}
/*
@ -5033,14 +5181,22 @@ 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_ns(struct ns *ns,
void *_zl3vni,
void **_pifp)
{
struct zebra_ns *zns = NULL;
struct zebra_ns *zns = ns->info;
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 NS_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 +5211,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 NS_WALK_STOP;
}
return NULL;
return NS_WALK_CONTINUE;
}
struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni)
{
struct interface **p_ifp;
struct interface *ifp = NULL;
p_ifp = &ifp;
ns_walk_func(zl3vni_map_to_vxlan_if_ns,
(void *)zl3vni, (void **)p_ifp);
return ifp;
}
struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)
@ -5537,7 +5719,7 @@ static void process_remote_macip_add(vni_t vni,
return;
}
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
zvrf = zebra_vrf_get_evpn();
if (!zvrf)
return;
@ -8018,6 +8200,11 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
bool upd_neigh = false;
bool is_dup_detect = false;
struct in_addr vtep_ip = {.s_addr = 0};
ns_id_t local_ns_id = NS_DEFAULT;
zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
if (zvrf && zvrf->zns)
local_ns_id = zvrf->zns->ns_id;
/* We are interested in MACs only on ports or (port, VLAN) that
* map to a VNI.
@ -8041,11 +8228,10 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
return -1;
}
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
zvrf = zebra_vrf_get_evpn();
if (!zvrf) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(" No Vrf found for vrf_id: %d",
zvni->vxlan_if->vrf_id);
zlog_debug(" No Evpn Global Vrf found");
return -1;
}
@ -8070,6 +8256,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
}
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
mac->fwd_info.local.vid = vid;
if (sticky)
SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
@ -8094,6 +8281,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
*/
if (mac_sticky == sticky
&& mac->fwd_info.local.ifindex == ifp->ifindex
&& mac->fwd_info.local.ns_id == local_ns_id
&& mac->fwd_info.local.vid == vid) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
@ -8118,6 +8306,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
mac->fwd_info.local.vid = vid;
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ||
@ -8155,6 +8344,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
mac->fwd_info.local.vid = vid;
if (sticky)
SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
@ -9620,6 +9810,25 @@ stream_failure:
return;
}
static int macfdb_read_ns(struct ns *ns,
void *_in_param __attribute__((unused)),
void **out_param __attribute__((unused)))
{
struct zebra_ns *zns = ns->info;
macfdb_read(zns);
return NS_WALK_CONTINUE;
}
static int neigh_read_ns(struct ns *ns,
void *_in_param __attribute__((unused)),
void **out_param __attribute__((unused)))
{
struct zebra_ns *zns = ns->info;
neigh_read(zns);
return NS_WALK_CONTINUE;
}
/*
* Handle message from client to learn (or stop learning) about VNIs and MACs.
@ -9669,10 +9878,10 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
NULL);
/* Read the MAC FDB */
macfdb_read(zvrf->zns);
ns_walk_func(macfdb_read_ns, NULL, NULL);
/* Read neighbors */
neigh_read(zvrf->zns);
ns_walk_func(neigh_read_ns, NULL, NULL);
} else {
/* Cleanup VTEPs for all VNIs - uninstall from
* kernel and free entries.

View File

@ -310,6 +310,7 @@ struct zebra_mac_t_ {
union {
struct {
ifindex_t ifindex;
ns_id_t ns_id;
vlanid_t vid;
} local;