From 88a7aaeacfb93caf90c9cb7a57ab1951afbf624f Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 3 Oct 2019 17:11:37 +0200 Subject: [PATCH] zebra: bridge layer2 information records ns_id where bridge is when working with vrf netns backend, two bridges interfaces may have the same bridge interface index, but not the same namespace. because in vrf netns backend mode, a bridge slave always belong to the same network namespace, then a check with the namespace id and the ns id of the bridge interface permits to resolve correctly the interface pointer. The problem could occur if a same index of two bridge interfaces can be found on two different namespaces. Signed-off-by: Philippe Guibert --- zebra/if_netlink.c | 8 +++++--- zebra/zebra_l2.c | 18 +++++++++++++++--- zebra/zebra_l2.h | 4 +++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index c3eab60148..90a08bbd6c 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -850,7 +850,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) 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); @@ -1442,7 +1442,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) 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) { @@ -1543,7 +1544,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) 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); } diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index d8674beb41..417056ecb0 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -54,7 +54,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; @@ -73,7 +79,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) @@ -250,10 +257,12 @@ 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; @@ -264,9 +273,12 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp, return; old_bridge_ifindex = zif->brslave_info.bridge_ifindex; - if (old_bridge_ifindex == 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) { diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h index 79d2e4feca..f3b15c7770 100644 --- a/zebra/zebra_l2.h +++ b/zebra/zebra_l2.h @@ -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 */ @@ -102,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); -- 2.39.5