summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--zebra/if_netlink.c31
-rw-r--r--zebra/interface.c18
-rw-r--r--zebra/interface.h10
-rw-r--r--zebra/zebra_l2.c38
-rw-r--r--zebra/zebra_l2.h11
5 files changed, 105 insertions, 3 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 8e459160c..f4bd19356 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -243,7 +243,8 @@ static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt)
}
}
-static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
+static void netlink_determine_zebra_iftype(const char *kind,
+ zebra_iftype_t *zif_type)
{
*zif_type = ZEBRA_IF_OTHER;
@@ -262,6 +263,10 @@ static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
*zif_type = ZEBRA_IF_MACVLAN;
else if (strcmp(kind, "veth") == 0)
*zif_type = ZEBRA_IF_VETH;
+ else if (strcmp(kind, "bond") == 0)
+ *zif_type = ZEBRA_IF_BOND;
+ else if (strcmp(kind, "bond_slave") == 0)
+ *zif_type = ZEBRA_IF_BOND_SLAVE;
}
#define parse_rtattr_nested(tb, max, rta) \
@@ -585,6 +590,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
+ ifindex_t bond_ifindex = IFINDEX_INTERNAL;
struct zebra_if *zif;
zns = zebra_ns_lookup(ns_id);
@@ -635,7 +641,10 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (linkinfo[IFLA_INFO_SLAVE_KIND])
slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
- netlink_determine_zebra_iftype(kind, &zif_type);
+ if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0)
+ netlink_determine_zebra_iftype("bond_slave", &zif_type);
+ else
+ netlink_determine_zebra_iftype(kind, &zif_type);
}
/* If VRF, create the VRF structure itself. */
@@ -653,6 +662,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex =
*(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+ } else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) {
+ zif_slave_type = ZEBRA_IF_SLAVE_BOND;
+ bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
@@ -700,6 +712,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp, bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
return 0;
}
@@ -1081,6 +1095,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zebra_iftype_t zif_type = ZEBRA_IF_OTHER;
zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
+ ifindex_t bond_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
@@ -1180,6 +1195,11 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex =
*(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+ } else if (slave_kind
+ && (strcmp(slave_kind, "bond") == 0)) {
+ zif_slave_type = ZEBRA_IF_SLAVE_BOND;
+ bond_ifindex =
+ *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
@@ -1239,6 +1259,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
} else if (ifp->vrf_id != vrf_id) {
/* VRF change for an interface. */
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1250,7 +1272,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if_handle_vrf_change(ifp, vrf_id);
} else {
- int was_bridge_slave;
+ bool was_bridge_slave, was_bond_slave;
/* Interface update. */
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1273,6 +1295,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
/* Update interface type - NOTE: Only slave_type can
* change. */
was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp);
+ was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp);
zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
netlink_interface_update_hw_addr(tb, ifp);
@@ -1312,6 +1335,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
}
} else {
/* Delete interface notification from kernel */
diff --git a/zebra/interface.c b/zebra/interface.c
index afb08f701..76e0a09c1 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1150,6 +1150,15 @@ static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
return "VETH";
break;
+ case ZEBRA_IF_BOND:
+ return "bond";
+
+ case ZEBRA_IF_BOND_SLAVE:
+ return "bond_slave";
+
+ case ZEBRA_IF_MACVLAN:
+ return "macvlan";
+
default:
return "Unknown";
break;
@@ -1279,6 +1288,15 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
br_slave->bridge_ifindex);
}
+ if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
+ struct zebra_l2info_bondslave *bond_slave;
+
+ bond_slave = &zebra_if->bondslave_info;
+ if (bond_slave->bond_ifindex != IFINDEX_INTERNAL)
+ vty_out(vty, " Master (bond) ifindex %u\n",
+ bond_slave->bond_ifindex);
+ }
+
if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
vty_out(vty, " Link ifindex %u", zebra_if->link_ifindex);
if (zebra_if->link)
diff --git a/zebra/interface.h b/zebra/interface.h
index e4c05e8dc..01dd69777 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -1,3 +1,4 @@
+
/* Interface function header.
* Copyright (C) 1999 Kunihiro Ishiguro
*
@@ -192,6 +193,8 @@ typedef enum {
ZEBRA_IF_VLAN, /* VLAN sub-interface */
ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/
ZEBRA_IF_VETH, /* VETH interface*/
+ ZEBRA_IF_BOND, /* Bond */
+ ZEBRA_IF_BOND_SLAVE, /* Bond */
} zebra_iftype_t;
/* Zebra "slave" interface type */
@@ -199,6 +202,7 @@ typedef enum {
ZEBRA_IF_SLAVE_NONE, /* Not a slave */
ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */
ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */
+ ZEBRA_IF_SLAVE_BOND, /* Bond member */
ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */
} zebra_slave_iftype_t;
@@ -268,6 +272,8 @@ struct zebra_if {
*/
struct zebra_l2info_brslave brslave_info;
+ struct zebra_l2info_bondslave bondslave_info;
+
/* Link fields - for sub-interfaces. */
ifindex_t link_ifindex;
struct interface *link;
@@ -324,6 +330,10 @@ static inline void zebra_if_set_ziftype(struct interface *ifp,
#define IS_ZEBRA_IF_VRF_SLAVE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF)
+#define IS_ZEBRA_IF_BOND_SLAVE(ifp) \
+ (((struct zebra_if *)(ifp->info))->zif_slave_type \
+ == ZEBRA_IF_SLAVE_BOND)
+
extern void zebra_if_init(void);
extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, uint32_t);
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index 529fc48ed..f4b2fe479 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -99,6 +99,23 @@ 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)
+{
+ struct interface *bond_if;
+
+ /* TODO: Handle change of master */
+ bond_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+ bond_slave->bond_ifindex);
+ if (bond_if)
+ bond_slave->bond_if = bond_if;
+}
+
+void zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave)
+{
+ if (bond_slave != NULL)
+ bond_slave->bond_if = NULL;
+}
+
/*
* Handle Bridge interface add or update. Update relevant info,
* map slaves (if any) to the bridge.
@@ -238,3 +255,24 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
zebra_l2_unmap_slave_from_bridge(&zif->brslave_info);
}
}
+
+void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex)
+{
+ struct zebra_if *zif;
+ ifindex_t old_bond_ifindex;
+
+ zif = ifp->info;
+ assert(zif);
+
+ old_bond_ifindex = zif->bondslave_info.bond_ifindex;
+ if (old_bond_ifindex == bond_ifindex)
+ return;
+
+ zif->bondslave_info.bond_ifindex = bond_ifindex;
+
+ /* Set up or remove link with master */
+ if (bond_ifindex != IFINDEX_INTERNAL)
+ zebra_l2_map_slave_to_bond(&zif->bondslave_info);
+ else if (old_bond_ifindex != IFINDEX_INTERNAL)
+ zebra_l2_unmap_slave_from_bond(&zif->bondslave_info);
+}
diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h
index db6cb0e53..68c9d4a7a 100644
--- a/zebra/zebra_l2.h
+++ b/zebra/zebra_l2.h
@@ -52,6 +52,11 @@ struct zebra_l2info_vxlan {
vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */
};
+struct zebra_l2info_bondslave {
+ ifindex_t bond_ifindex; /* Bridge Master */
+ struct interface *bond_if; /* Pointer to master */
+};
+
union zebra_l2if_info {
struct zebra_l2info_bridge br;
struct zebra_l2info_vlan vl;
@@ -70,6 +75,10 @@ union zebra_l2if_info {
extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave);
extern void
zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave);
+extern void
+zebra_l2_map_slave_to_bond(struct zebra_l2info_bondslave *bond_slave);
+extern void
+zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave);
extern void zebra_l2_bridge_add_update(struct interface *ifp,
struct zebra_l2info_bridge *bridge_info,
int add);
@@ -85,4 +94,6 @@ extern void zebra_l2_vxlanif_del(struct interface *ifp);
extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
ifindex_t bridge_ifindex);
+extern void zebra_l2if_update_bond_slave(struct interface *ifp,
+ ifindex_t bond_ifindex);
#endif /* _ZEBRA_L2_H */