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);
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);
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)
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)
/* 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 =
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 {
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);
/* 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;
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;
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);
}
/*
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);
}
/*
* 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;
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 &&
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 */
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);
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
}
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
*/
#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