Skip to content

Commit

Permalink
zebra: handle bridge mac address update in evpn contexts
Browse files Browse the repository at this point in the history
when running bgp evpn rt5 setup, the Rmac sent in BGP updates
stands for the MAC address of the bridge interface. After
having loaded frr configuration, the Rmac address is not refreshed.
This issue can be easily reproduced by executing some commands:

ip netns exec cust1 ip link set dev br1000 address  2e:ab:45:aa:bb:cc

Actually, the BGP EVPN contexts are kept unchanged.
That commit proposes to fix this by intercepting the mac address
change, and refreshing the vxlan interfaces attached to te bridge
interface that changed its MAC address.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
  • Loading branch information
pguibert6WIND committed Sep 17, 2021
1 parent 2490726 commit c762010
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 18 deletions.
34 changes: 24 additions & 10 deletions zebra/if_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (IS_ZEBRA_IF_BOND(ifp))
zebra_l2if_update_bond(ifp, true);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp, bridge_ifindex, ns_id);
zebra_l2if_update_bridge_slave(ifp, bridge_ifindex, ns_id,
ZEBRA_BRIDGE_NO_ACTION);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
zebra_l2if_update_bond_slave(ifp, bond_ifindex, !!bypass);

Expand Down Expand Up @@ -1644,9 +1645,9 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifp, linkinfo[IFLA_INFO_DATA],
1, link_nsid);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex,
ns_id);
zebra_l2if_update_bridge_slave(
ifp, bridge_ifindex, ns_id,
ZEBRA_BRIDGE_NO_ACTION);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
zebra_l2if_update_bond_slave(ifp, bond_ifindex,
!!bypass);
Expand All @@ -1670,6 +1671,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if_handle_vrf_change(ifp, vrf_id);
} else {
bool was_bridge_slave, was_bond_slave;
uint8_t chgflags = ZEBRA_BRIDGE_NO_ACTION;

/* Interface update. */
if (IS_ZEBRA_DEBUG_KERNEL)
Expand Down Expand Up @@ -1711,6 +1713,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if_down(ifp);
rib_update(RIB_UPDATE_KERNEL);
} else if (if_is_operative(ifp)) {
bool mac_updated = false;

/* Must notify client daemons of new
* interface status. */
if (IS_ZEBRA_DEBUG_KERNEL)
Expand All @@ -1721,9 +1725,11 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)

/* Update EVPN VNI when SVI MAC change
*/
if (IS_ZEBRA_IF_VLAN(ifp) &&
memcmp(old_hw_addr, ifp->hw_addr,
INTERFACE_HWADDR_MAX)) {
if (memcmp(old_hw_addr, ifp->hw_addr,
INTERFACE_HWADDR_MAX))
mac_updated = true;
if (IS_ZEBRA_IF_VLAN(ifp)
&& mac_updated) {
struct interface *link_if;

link_if =
Expand All @@ -1733,6 +1739,13 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (link_if)
zebra_vxlan_svi_up(ifp,
link_if);
} else if (mac_updated
&& IS_ZEBRA_IF_BRIDGE(ifp)) {
zlog_debug(
"Intf %s(%u) bridge changed MAC address",
name, ifp->ifindex);
chgflags =
ZEBRA_BRIDGE_MASTER_MAC_CHANGE;
}
}
} else {
Expand All @@ -1758,12 +1771,13 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
netlink_interface_update_l2info(
ifp, linkinfo[IFLA_INFO_DATA],
0, link_nsid);
if (IS_ZEBRA_IF_BRIDGE(ifp))
zebra_l2if_update_bridge(ifp, chgflags);
if (IS_ZEBRA_IF_BOND(ifp))
zebra_l2if_update_bond(ifp, true);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex,
ns_id);
zebra_l2if_update_bridge_slave(
ifp, bridge_ifindex, ns_id, chgflags);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
zebra_l2if_update_bond_slave(ifp, bond_ifindex,
!!bypass);
Expand Down
36 changes: 29 additions & 7 deletions zebra/zebra_l2.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
/* static function declarations */

/* Private functions */
static void map_slaves_to_bridge(struct interface *br_if, int link)
static void map_slaves_to_bridge(struct interface *br_if, int link,
bool update_slave, uint8_t chgflags)
{
struct vrf *vrf;
struct interface *ifp;
Expand Down Expand Up @@ -79,9 +80,17 @@ 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 &&
br_slave->ns_id == zns->ns_id)
if (br_slave->bridge_ifindex == br_if->ifindex
&& br_slave->ns_id == zns->ns_id) {
br_slave->br_if = br_if;
if (update_slave) {
zebra_l2if_update_bridge_slave(
ifp,
br_slave->bridge_ifindex,
br_slave->ns_id,
chgflags);
}
}
} else {
if (br_slave->br_if == br_if)
br_slave->br_if = NULL;
Expand Down Expand Up @@ -261,7 +270,7 @@ void zebra_l2_bridge_add_update(struct interface *ifp,
memcpy(&zif->l2info.br, bridge_info, sizeof(*bridge_info));

/* Link all slaves to this bridge */
map_slaves_to_bridge(ifp, 1);
map_slaves_to_bridge(ifp, 1, false, ZEBRA_BRIDGE_NO_ACTION);
}

/*
Expand All @@ -270,7 +279,14 @@ void zebra_l2_bridge_add_update(struct interface *ifp,
void zebra_l2_bridge_del(struct interface *ifp)
{
/* Unlink all slaves to this bridge */
map_slaves_to_bridge(ifp, 0);
map_slaves_to_bridge(ifp, 0, false, ZEBRA_BRIDGE_NO_ACTION);
}

void zebra_l2if_update_bridge(struct interface *ifp, uint8_t chgflags)
{
if (!chgflags)
return;
map_slaves_to_bridge(ifp, 1, true, chgflags);
}

/*
Expand Down Expand Up @@ -398,8 +414,8 @@ 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,
ns_id_t ns_id)
ifindex_t bridge_ifindex, ns_id_t ns_id,
uint8_t chgflags)
{
struct zebra_if *zif;
ifindex_t old_bridge_ifindex;
Expand All @@ -413,6 +429,12 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
if (!zvrf)
return;

if (zif->zif_type == ZEBRA_IF_VXLAN
&& chgflags != ZEBRA_BRIDGE_NO_ACTION) {
if (ZEBRA_BRIDGE_MASTER_MAC_CHANGE)
zebra_vxlan_if_update(ifp,
ZEBRA_VXLIF_MASTER_MAC_CHANGE);
}
old_bridge_ifindex = zif->brslave_info.bridge_ifindex;
old_ns_id = zif->brslave_info.ns_id;
if (old_bridge_ifindex == bridge_ifindex &&
Expand Down
6 changes: 5 additions & 1 deletion zebra/zebra_l2.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
extern "C" {
#endif

#define ZEBRA_BRIDGE_NO_ACTION (0)
#define ZEBRA_BRIDGE_MASTER_MAC_CHANGE (1 << 1)

/* zebra L2 interface information - bridge slave (linkage to bridge) */
struct zebra_l2info_brslave {
ifindex_t bridge_ifindex; /* Bridge Master */
Expand Down Expand Up @@ -121,7 +124,7 @@ extern void zebra_l2_greif_del(struct interface *ifp);
extern void zebra_l2_vxlanif_del(struct interface *ifp);
extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
ifindex_t bridge_ifindex,
ns_id_t ns_id);
ns_id_t ns_id, uint8_t chgflags);

extern void zebra_l2if_update_bond_slave(struct interface *ifp,
ifindex_t bond_ifindex, bool bypass);
Expand All @@ -130,6 +133,7 @@ extern void zebra_vlan_bitmap_compute(struct interface *ifp,
extern void zebra_vlan_mbr_re_eval(struct interface *ifp,
bitfield_t vlan_bitmap);
extern void zebra_l2if_update_bond(struct interface *ifp, bool add);
extern void zebra_l2if_update_bridge(struct interface *ifp, uint8_t chgflags);

#ifdef __cplusplus
}
Expand Down
7 changes: 7 additions & 0 deletions zebra/zebra_vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -5043,6 +5043,13 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
return 0;
}

if ((chgflags & ZEBRA_VXLIF_MASTER_MAC_CHANGE)
&& if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) {
zebra_vxlan_process_l3vni_oper_down(zl3vni);
zebra_vxlan_process_l3vni_oper_up(zl3vni);
return 0;
}

/* access-vlan change - process oper down, associate with new
* svi_if and then process oper up again
*/
Expand Down
1 change: 1 addition & 0 deletions zebra/zebra_vxlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ is_vxlan_flooding_head_end(void)
#define ZEBRA_VXLIF_MASTER_CHANGE (1 << 1)
#define ZEBRA_VXLIF_VLAN_CHANGE (1 << 2)
#define ZEBRA_VXLIF_MCAST_GRP_CHANGE (1 << 3)
#define ZEBRA_VXLIF_MASTER_MAC_CHANGE (1 << 4)


#define VNI_STR_LEN 32
Expand Down

0 comments on commit c762010

Please sign in to comment.