diff --git a/modules/infra/api/gr_infra.h b/modules/infra/api/gr_infra.h index 83e5d909b..913ee6135 100644 --- a/modules/infra/api/gr_infra.h +++ b/modules/infra/api/gr_infra.h @@ -70,6 +70,7 @@ struct __gr_iface_base { uint16_t vrf_id; // L3 addressing and routing domain uint16_t domain_id; // L2 xconnect peer interface id }; + uint32_t speed; //!< Link speed in Megabit/sec. }; struct gr_iface { @@ -93,7 +94,6 @@ struct __gr_iface_info_port_base { uint16_t rxq_size; uint16_t txq_size; uint16_t bond_iface_id; - uint32_t link_speed; //!< Physical link speed in Megabit/sec. struct rte_ether_addr mac; }; diff --git a/modules/infra/cli/bond.c b/modules/infra/cli/bond.c index d610ff9ff..2233e1fcc 100644 --- a/modules/infra/cli/bond.c +++ b/modules/infra/cli/bond.c @@ -36,10 +36,10 @@ static void bond_show(struct gr_api_client *c, const struct gr_iface *iface) { const struct gr_iface_info_port *port; port = (const struct gr_iface_info_port *)member->info; printf(" mac: " ETH_F "\n", &port->mac); - if (port->link_speed == UINT32_MAX) + if (member->speed == UINT32_MAX) printf(" speed: unknown\n"); else - printf(" speed: %u Mb/s\n", port->link_speed); + printf(" speed: %u Mb/s\n", member->speed); } free(member); diff --git a/modules/infra/cli/iface.c b/modules/infra/cli/iface.c index 51e80b383..5dc2d0ff6 100644 --- a/modules/infra/cli/iface.c +++ b/modules/infra/cli/iface.c @@ -464,6 +464,10 @@ static cmd_status_t iface_show(struct gr_api_client *c, const struct ec_pnode *p printf("flags: %s\n", buf); printf("vrf: %u\n", iface->vrf_id); printf("mtu: %u\n", iface->mtu); + if (iface->speed == UINT32_MAX) + printf("speed: unknown\n"); + else + printf("speed: %u Mb/s\n", iface->speed); type = type_from_id(iface->type); assert(type != NULL); diff --git a/modules/infra/cli/port.c b/modules/infra/cli/port.c index ce499768b..5d14116a9 100644 --- a/modules/infra/cli/port.c +++ b/modules/infra/cli/port.c @@ -28,10 +28,6 @@ static void port_show(struct gr_api_client *c, const struct gr_iface *iface) { printf("bond: %u\n", port->bond_iface_id); free(bond); } - if (port->link_speed == UINT32_MAX) - printf("speed: unknown\n"); - else - printf("speed: %u Mb/s\n", port->link_speed); printf("n_rxq: %u\n", port->n_rxq); printf("n_txq: %u\n", port->n_txq); printf("rxq_size: %u\n", port->rxq_size); diff --git a/modules/infra/control/bond.c b/modules/infra/control/bond.c index a3e245ea4..2c6931baf 100644 --- a/modules/infra/control/bond.c +++ b/modules/infra/control/bond.c @@ -234,6 +234,7 @@ void bond_update_active_members(struct iface *iface) { struct iface_info_bond *bond = iface_info_bond(iface); const struct iface *member; uint8_t *active_ids = NULL; + uint32_t speed = 0; switch (bond->mode) { case GR_BOND_MODE_ACTIVE_BACKUP: @@ -248,6 +249,7 @@ void bond_update_active_members(struct iface *iface) { for (uint8_t i = 0; i < bond->n_members; i++) { member = bond->members[i].iface; if (i == active_member) { + speed = member->speed; gr_vec_add(active_ids, i); LOG(INFO, "bond %s active member is now %s", @@ -261,7 +263,6 @@ void bond_update_active_members(struct iface *iface) { case GR_BOND_MODE_LACP: for (uint8_t i = 0; i < bond->n_members; i++) { struct bond_member *member = &bond->members[i]; - const struct iface_info_port *port = iface_info_port(member->iface); // The port_number must *never* be zero, // otherwise some switches reject the LACP packets. @@ -272,7 +273,7 @@ void bond_update_active_members(struct iface *iface) { member->local.system_mac = bond->mac; // Key based on port speed (in Mb/s): simplified encoding for aggregation // Ports with same speed can aggregate together - member->local.key = rte_cpu_to_be_16(port->link_speed); + member->local.key = rte_cpu_to_be_16(member->iface->speed); if (member->last_rx == 0) { member->local.state = LACP_STATE_ACTIVE | LACP_STATE_AGGREGATABLE | LACP_STATE_FAST | LACP_STATE_DEFAULTED @@ -294,11 +295,18 @@ void bond_update_active_members(struct iface *iface) { iface->name, member->iface->name); gr_vec_add(active_ids, i); + if (member->iface->speed != RTE_ETH_SPEED_NUM_UNKNOWN) + speed += member->iface->speed; } } break; } + if (speed != 0) + iface->speed = speed; + else + iface->speed = RTE_ETH_SPEED_NUM_UNKNOWN; + if (gr_vec_len(active_ids) > 0) { for (unsigned i = 0; i < ARRAY_DIM(bond->redirection_table); i++) { bond->redirection_table[i] = active_ids[i % gr_vec_len(active_ids)]; diff --git a/modules/infra/control/iface.c b/modules/infra/control/iface.c index 6690de741..088d5aa41 100644 --- a/modules/infra/control/iface.c +++ b/modules/infra/control/iface.c @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -107,6 +108,7 @@ struct iface *iface_create(const struct gr_iface *conf, const void *api_info) { goto fail; iface->base = conf->base; + iface->speed = RTE_ETH_SPEED_NUM_UNKNOWN; iface->id = ifid; // this is only accessed by the API, no need to copy the name to DPDK memory (hugepages) iface->name = strndup(conf->name, GR_IFACE_NAME_SIZE); @@ -513,6 +515,7 @@ static void iface_event(uint32_t event, const void *obj) { str = "STATUS_UP"; gr_vec_foreach (struct iface *s, iface->subinterfaces) { s->state |= GR_IFACE_S_RUNNING; + s->speed = iface->speed; gr_event_push(event, s); } break; @@ -520,6 +523,7 @@ static void iface_event(uint32_t event, const void *obj) { str = "STATUS_DOWN"; gr_vec_foreach (struct iface *s, iface->subinterfaces) { s->state &= ~GR_IFACE_S_RUNNING; + s->speed = RTE_ETH_SPEED_NUM_UNKNOWN; gr_event_push(event, s); } break; diff --git a/modules/infra/control/loopback.c b/modules/infra/control/loopback.c index af054b057..9358592bc 100644 --- a/modules/infra/control/loopback.c +++ b/modules/infra/control/loopback.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -260,6 +261,7 @@ static int iface_loopback_init(struct iface *iface, const void * /* api_info */) iface->flags = GR_IFACE_F_UP; iface->state = GR_IFACE_S_RUNNING; + iface->speed = RTE_ETH_SPEED_NUM_10G; lo->ev = event_new( ev_base, lo->fd, diff --git a/modules/infra/control/port.c b/modules/infra/control/port.c index f3974b443..38b9f2d62 100644 --- a/modules/infra/control/port.c +++ b/modules/infra/control/port.c @@ -643,7 +643,6 @@ static struct event *link_event; static void link_event_cb(evutil_socket_t, short /*what*/, void * /*priv*/) { unsigned max_sleep_us, rx_buffer_us; struct rte_eth_rxq_info qinfo; - struct iface_info_port *port; struct rte_eth_link link; struct queue_map *qmap; struct worker *worker; @@ -664,13 +663,11 @@ static void link_event_cb(evutil_socket_t, short /*what*/, void * /*priv*/) { if (iface == NULL) continue; - port = iface_info_port(iface); - if (rte_eth_link_get_nowait(qmap->port_id, &link) < 0) { LOG(WARNING, "rte_eth_link_get_nowait: %s", strerror(rte_errno)); continue; } - port->link_speed = link.link_speed; + iface->speed = link.link_speed; if (link.link_status == RTE_ETH_LINK_UP) { if (!(iface->state & GR_IFACE_S_RUNNING)) { diff --git a/modules/infra/control/vlan.c b/modules/infra/control/vlan.c index eb5c8ded7..71246b377 100644 --- a/modules/infra/control/vlan.c +++ b/modules/infra/control/vlan.c @@ -84,6 +84,7 @@ static int iface_vlan_reconfig( iface_add_subinterface(next_parent, iface); iface->state = next_parent->state; iface->mtu = next_parent->mtu; + iface->speed = next_parent->speed; if ((ret = rte_hash_add_key_data(vlan_hash, &next_key, iface)) < 0) return errno_log(-ret, "rte_hash_add_key_data"); diff --git a/modules/ipip/control.c b/modules/ipip/control.c index fa3523a05..a2d88b465 100644 --- a/modules/ipip/control.c +++ b/modules/ipip/control.c @@ -95,6 +95,7 @@ static int iface_ipip_init(struct iface *iface, const void *api_info) { struct gr_iface conf; int ret; + iface->speed = RTE_ETH_SPEED_NUM_10G; if (iface->mtu == 0) iface->mtu = 1480; diff --git a/smoke/_init.sh b/smoke/_init.sh index cedb6449d..cc7cfb5ea 100644 --- a/smoke/_init.sh +++ b/smoke/_init.sh @@ -224,8 +224,8 @@ if [ "$test_frr" = true ] && [ "$run_frr" = true ]; then cat >$builddir/frr_install/etc/frr/daemons <$builddir/frr_install/etc/frr/frr.conf <${frr_namespace_folder}/daemons <$frr_namespace_folder/frr.conf <