diff --git a/modules/infra/api/gr_infra.h b/modules/infra/api/gr_infra.h index 045b5c787..5255711e2 100644 --- a/modules/infra/api/gr_infra.h +++ b/modules/infra/api/gr_infra.h @@ -212,6 +212,7 @@ typedef enum { GR_EVENT_IFACE_POST_RECONFIG = EVENT_TYPE(GR_INFRA_MODULE, 0x0005), GR_EVENT_IFACE_STATUS_UP = EVENT_TYPE(GR_INFRA_MODULE, 0x0006), GR_EVENT_IFACE_STATUS_DOWN = EVENT_TYPE(GR_INFRA_MODULE, 0x0007), + GR_EVENT_IFACE_MAC_CHANGE = EVENT_TYPE(GR_INFRA_MODULE, 0x0008), } gr_event_iface_t; // interface management /////////////////////////////////////////////////////// diff --git a/modules/infra/api/iface.c b/modules/infra/api/iface.c index 834069f6e..92dbb8957 100644 --- a/modules/infra/api/iface.c +++ b/modules/infra/api/iface.c @@ -163,7 +163,7 @@ static int iface_event_serialize(const void *obj, void **buf) { static struct gr_event_serializer iface_serializer = { .callback = iface_event_serialize, - .ev_count = 7, + .ev_count = 8, .ev_types = { GR_EVENT_IFACE_ADD, GR_EVENT_IFACE_POST_ADD, @@ -172,6 +172,7 @@ static struct gr_event_serializer iface_serializer = { GR_EVENT_IFACE_POST_RECONFIG, GR_EVENT_IFACE_STATUS_UP, GR_EVENT_IFACE_STATUS_DOWN, + GR_EVENT_IFACE_MAC_CHANGE, }, }; diff --git a/modules/infra/cli/iface.c b/modules/infra/cli/iface.c index c1cf79667..cbdd37415 100644 --- a/modules/infra/cli/iface.c +++ b/modules/infra/cli/iface.c @@ -561,6 +561,9 @@ static void iface_event_print(uint32_t event, const void *obj) { case GR_EVENT_IFACE_POST_RECONFIG: action = "reconf"; break; + case GR_EVENT_IFACE_MAC_CHANGE: + action = "mac change"; + break; default: action = "?"; break; @@ -572,7 +575,7 @@ static void iface_event_print(uint32_t event, const void *obj) { static struct cli_event_printer printer = { .print = iface_event_print, - .ev_count = 7, + .ev_count = 8, .ev_types = { GR_EVENT_IFACE_ADD, GR_EVENT_IFACE_POST_ADD, @@ -581,6 +584,7 @@ static struct cli_event_printer printer = { GR_EVENT_IFACE_STATUS_UP, GR_EVENT_IFACE_STATUS_DOWN, GR_EVENT_IFACE_POST_RECONFIG, + GR_EVENT_IFACE_MAC_CHANGE, }, }; diff --git a/modules/infra/control/bond.c b/modules/infra/control/bond.c index 5852e1966..ae1ec9a05 100644 --- a/modules/infra/control/bond.c +++ b/modules/infra/control/bond.c @@ -362,9 +362,8 @@ static int bond_reconfig( } else { mac = api->mac; } - if (bond_mac_set(iface, &mac) < 0) + if (iface_set_eth_addr(iface, &mac) < 0) return errno_set(errno); - bond->mac = mac; } if (set_attrs & (GR_BOND_SET_MEMBERS | GR_BOND_SET_PRIMARY)) diff --git a/modules/infra/control/iface.c b/modules/infra/control/iface.c index af08ba1ff..f80032ca7 100644 --- a/modules/infra/control/iface.c +++ b/modules/infra/control/iface.c @@ -295,6 +295,7 @@ void iface_del_subinterface(struct iface *parent, struct iface *sub) { int iface_set_eth_addr(struct iface *iface, const struct rte_ether_addr *mac) { const struct iface_type *type; + int ret; if (iface == NULL) return errno_set(EINVAL); @@ -304,7 +305,11 @@ int iface_set_eth_addr(struct iface *iface, const struct rte_ether_addr *mac) { if (type->set_eth_addr == NULL) return errno_set(EOPNOTSUPP); - return type->set_eth_addr(iface, mac); + ret = type->set_eth_addr(iface, mac); + if (ret == 0) + gr_event_push(GR_EVENT_IFACE_MAC_CHANGE, iface); + + return ret; } int iface_add_eth_addr(struct iface *iface, const struct rte_ether_addr *mac) { @@ -512,6 +517,11 @@ static void iface_event(uint32_t event, const void *obj) { gr_event_push(event, s); } break; + case GR_EVENT_IFACE_MAC_CHANGE: + str = "MAC_CHANGE"; + gr_vec_foreach (struct iface *s, iface->subinterfaces) + gr_event_push(event, s); + break; default: str = "?"; break; @@ -521,7 +531,7 @@ static void iface_event(uint32_t event, const void *obj) { static struct gr_event_subscription iface_event_handler = { .callback = iface_event, - .ev_count = 7, + .ev_count = 8, .ev_types = { GR_EVENT_IFACE_ADD, GR_EVENT_IFACE_POST_ADD, @@ -530,6 +540,7 @@ static struct gr_event_subscription iface_event_handler = { GR_EVENT_IFACE_POST_RECONFIG, GR_EVENT_IFACE_STATUS_UP, GR_EVENT_IFACE_STATUS_DOWN, + GR_EVENT_IFACE_MAC_CHANGE, }, }; diff --git a/modules/infra/control/port.c b/modules/infra/control/port.c index 5823c5505..b29ca6fef 100644 --- a/modules/infra/control/port.c +++ b/modules/infra/control/port.c @@ -330,7 +330,7 @@ static int iface_port_reconfig( return ret; } - if (set_attrs & GR_PORT_SET_MAC && (ret = port_mac_set(iface, &api->mac)) < 0) + if (set_attrs & GR_PORT_SET_MAC && (ret = iface_set_eth_addr(iface, &api->mac)) < 0) return ret; if (!p->started && (ret = rte_eth_dev_start(p->port_id)) < 0) diff --git a/modules/infra/control/port_test.c b/modules/infra/control/port_test.c index 01a1afe2a..a24f9761c 100644 --- a/modules/infra/control/port_test.c +++ b/modules/infra/control/port_test.c @@ -28,6 +28,9 @@ struct rte_rcu_qsbr *gr_datapath_rcu(void) { static struct rte_rcu_qsbr rcu; return &rcu; } +int iface_set_eth_addr(struct iface *, const struct rte_ether_addr *) { + return 0; +} mock_func(struct iface *, iface_from_id(uint16_t)); mock_func(struct iface *, iface_next(gr_iface_type_t, const struct iface *)); mock_func(int, port_unplug(struct iface_info_port *)); diff --git a/modules/infra/control/vlan.c b/modules/infra/control/vlan.c index 0b9c9fe39..304cde93e 100644 --- a/modules/infra/control/vlan.c +++ b/modules/infra/control/vlan.c @@ -47,9 +47,14 @@ static int iface_vlan_reconfig( if ((cur_parent = iface_from_id(cur->parent_id)) == NULL) return -errno; if (set_attrs & GR_VLAN_SET_MAC) { - // reconfig, *not initial config* - // remove previous mac filter (ignore errors) - iface_del_eth_addr(cur_parent, &cur->mac); + struct rte_ether_addr parent_mac; + if (iface_get_eth_addr(cur_parent, &parent_mac) == 0 + && rte_is_same_ether_addr(&parent_mac, &cur->mac)) { + // inherited/primary MAC: nothing to delete + } else { + // remove previous mac filter (ignore errors) + iface_del_eth_addr(cur_parent, &cur->mac); + } } } else { cur_parent = NULL; @@ -90,15 +95,8 @@ static int iface_vlan_reconfig( } if (set_attrs & GR_VLAN_SET_MAC) { - struct iface *parent = iface_from_id(cur->parent_id); - if (rte_is_zero_ether_addr(&next->mac)) { - if ((ret = iface_get_eth_addr(parent, &cur->mac)) < 0) - return ret; - } else { - if ((ret = iface_add_eth_addr(parent, &next->mac)) < 0) - return ret; - cur->mac = next->mac; - } + if ((ret = iface_set_eth_addr(iface, &next->mac)) < 0) + return ret; } return 0; @@ -157,6 +155,23 @@ static int iface_vlan_get_eth_addr(const struct iface *iface, struct rte_ether_a return 0; } +static int iface_vlan_set_eth_addr(struct iface *iface, const struct rte_ether_addr *mac) { + struct iface_info_vlan *vlan = iface_info_vlan(iface); + struct iface *parent = iface_from_id(vlan->parent_id); + int ret; + + if (rte_is_zero_ether_addr(mac)) { + if ((ret = iface_get_eth_addr(parent, &vlan->mac)) < 0) + return ret; + } else { + if ((ret = iface_add_eth_addr(parent, mac)) < 0) + return ret; + vlan->mac = *mac; + } + + return 0; +} + static int iface_vlan_add_eth_addr(struct iface *iface, const struct rte_ether_addr *mac) { const struct iface_info_vlan *vlan = iface_info_vlan(iface); struct iface *parent = iface_from_id(vlan->parent_id); @@ -194,6 +209,7 @@ static struct iface_type iface_type_vlan = { .fini = iface_vlan_fini, .set_up_down = iface_vlan_up_down, .get_eth_addr = iface_vlan_get_eth_addr, + .set_eth_addr = iface_vlan_set_eth_addr, .add_eth_addr = iface_vlan_add_eth_addr, .del_eth_addr = iface_vlan_del_eth_addr, .to_api = vlan_to_api, diff --git a/modules/infra/control/worker_test.c b/modules/infra/control/worker_test.c index b28f07e68..18e6a8509 100644 --- a/modules/infra/control/worker_test.c +++ b/modules/infra/control/worker_test.c @@ -57,6 +57,10 @@ struct iface *iface_next(gr_iface_type_t /*type_id*/, const struct iface *prev) return NULL; } +int iface_set_eth_addr(struct iface *, const struct rte_ether_addr *) { + return 0; +} + mock_func(int, worker_graph_reload(struct worker *, gr_vec struct iface_info_port **)); mock_func(int, worker_graph_reload_all(gr_vec struct iface_info_port **)); mock_func(void, worker_graph_free(struct worker *)); diff --git a/modules/ip/control/address.c b/modules/ip/control/address.c index 3298e6cc3..cc49e5c66 100644 --- a/modules/ip/control/address.c +++ b/modules/ip/control/address.c @@ -270,8 +270,8 @@ static struct gr_event_subscription iface_pre_rm_subscription = { }; static struct gr_event_subscription iface_up_subscription = { .callback = iface_up_cb, - .ev_count = 1, - .ev_types = {GR_EVENT_IFACE_STATUS_UP}, + .ev_count = 2, + .ev_types = {GR_EVENT_IFACE_STATUS_UP, GR_EVENT_IFACE_MAC_CHANGE}, }; static struct gr_event_serializer iface_addr_serializer = { .size = sizeof(struct gr_ip4_ifaddr), diff --git a/modules/ip6/control/address.c b/modules/ip6/control/address.c index 217113aed..e1df94860 100644 --- a/modules/ip6/control/address.c +++ b/modules/ip6/control/address.c @@ -419,6 +419,7 @@ static void ip6_iface_event_handler(uint32_t event, const void *obj) { gr_vec_free(addrs->nh); break; case GR_EVENT_IFACE_STATUS_UP: + case GR_EVENT_IFACE_MAC_CHANGE: addrs = &iface_addrs[iface->id]; gr_vec_foreach (nh, addrs->nh) { if (nh6_advertise(nh, NULL) < 0) @@ -471,11 +472,12 @@ static struct gr_module addr6_module = { static struct gr_event_subscription iface_event_subscription = { .callback = ip6_iface_event_handler, - .ev_count = 3, + .ev_count = 4, .ev_types = { GR_EVENT_IFACE_POST_ADD, GR_EVENT_IFACE_PRE_REMOVE, GR_EVENT_IFACE_STATUS_UP, + GR_EVENT_IFACE_MAC_CHANGE, }, };