summaryrefslogtreecommitdiff
path: root/zebra/zebra_l2.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_l2.c')
-rw-r--r--zebra/zebra_l2.c102
1 files changed, 89 insertions, 13 deletions
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index 19d8bfd733..c1ad91c8ca 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -41,6 +41,7 @@
#include "zebra/zebra_memory.h"
#include "zebra/zebra_vrf.h"
#include "zebra/rt_netlink.h"
+#include "zebra/interface.h"
#include "zebra/zebra_l2.h"
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_evpn_mh.h"
@@ -109,24 +110,99 @@ void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave)
br_slave->br_if = NULL;
}
-void zebra_l2_map_slave_to_bond(struct zebra_l2info_bondslave *bond_slave,
- vrf_id_t vrf_id)
+void zebra_l2_map_slave_to_bond(struct zebra_if *zif, vrf_id_t vrf_id)
{
struct interface *bond_if;
+ struct zebra_if *bond_zif;
+ struct zebra_l2info_bondslave *bond_slave = &zif->bondslave_info;
- /* TODO: Handle change of master */
bond_if = if_lookup_by_index_all_vrf(bond_slave->bond_ifindex);
- if (bond_if)
- bond_slave->bond_if = bond_if;
- else
- bond_slave->bond_if = if_create_ifindex(bond_slave->bond_ifindex,
- vrf_id);
+ if (bond_if == bond_slave->bond_if)
+ return;
+
+ /* unlink the slave from the old master */
+ zebra_l2_unmap_slave_from_bond(zif);
+
+ /* If the bond is present and ready link the bond-member
+ * to it
+ */
+ if (bond_if && (bond_zif = bond_if->info)) {
+ if (bond_zif->bond_info.mbr_zifs) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("bond mbr %s linked to %s",
+ zif->ifp->name, bond_if->name);
+ bond_slave->bond_if = bond_if;
+ /* link the slave to the new bond master */
+ listnode_add(bond_zif->bond_info.mbr_zifs, zif);
+ /* inherit protodown flags from the es-bond */
+ if (zebra_evpn_is_es_bond(bond_if))
+ zebra_evpn_mh_update_protodown_bond_mbr(
+ zif, false /*clear*/, __func__);
+ }
+ } else {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("bond mbr %s link to bond skipped",
+ zif->ifp->name);
+ }
+}
+
+void zebra_l2_unmap_slave_from_bond(struct zebra_if *zif)
+{
+ struct zebra_l2info_bondslave *bond_slave = &zif->bondslave_info;
+ struct zebra_if *bond_zif;
+
+ if (!bond_slave->bond_if) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("bond mbr %s unlink from bond skipped",
+ zif->ifp->name);
+ return;
+ }
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("bond mbr %s un-linked from %s", zif->ifp->name,
+ bond_slave->bond_if->name);
+
+ /* unlink the slave from the bond master */
+ bond_zif = bond_slave->bond_if->info;
+ /* clear protodown flags */
+ if (zebra_evpn_is_es_bond(bond_zif->ifp))
+ zebra_evpn_mh_update_protodown_bond_mbr(zif, true /*clear*/,
+ __func__);
+ listnode_delete(bond_zif->bond_info.mbr_zifs, zif);
+ bond_slave->bond_if = NULL;
}
-void zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave)
+void zebra_l2if_update_bond(struct interface *ifp, bool add)
{
- if (bond_slave != NULL)
- bond_slave->bond_if = NULL;
+ struct zebra_if *zif;
+ struct zebra_l2info_bond *bond;
+
+ zif = ifp->info;
+ assert(zif);
+ bond = &zif->bond_info;
+
+ if (add) {
+ if (!bond->mbr_zifs) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("bond %s mbr list create",
+ ifp->name);
+ bond->mbr_zifs = list_new();
+ }
+ } else {
+ struct listnode *node;
+ struct listnode *nnode;
+ struct zebra_if *bond_mbr;
+
+ if (!bond->mbr_zifs)
+ return;
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("bond %s mbr list delete", ifp->name);
+ for (ALL_LIST_ELEMENTS(bond->mbr_zifs, node, nnode, bond_mbr))
+ zebra_l2_unmap_slave_from_bond(bond_mbr);
+
+ list_delete(&bond->mbr_zifs);
+ }
}
/*
@@ -318,9 +394,9 @@ void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex)
/* Set up or remove link with master */
if (bond_ifindex != IFINDEX_INTERNAL)
- zebra_l2_map_slave_to_bond(&zif->bondslave_info, ifp->vrf_id);
+ zebra_l2_map_slave_to_bond(zif, ifp->vrf_id);
else if (old_bond_ifindex != IFINDEX_INTERNAL)
- zebra_l2_unmap_slave_from_bond(&zif->bondslave_info);
+ zebra_l2_unmap_slave_from_bond(zif);
}
void zebra_vlan_bitmap_compute(struct interface *ifp,