diff --git a/vslib/vpp/SwitchVpp.cpp b/vslib/vpp/SwitchVpp.cpp index 469cdf2f62..fc6792dae1 100644 --- a/vslib/vpp/SwitchVpp.cpp +++ b/vslib/vpp/SwitchVpp.cpp @@ -2838,6 +2838,8 @@ sai_status_t SwitchVpp::refresh_port_oper_speed( { /* VPP reports link_speed in Kbps, SAI uses Mbps */ attr.value.u32 = vpp_speed_kbps / 1000; + SWSS_LOG_NOTICE("port oper speed from VPP: %s %u Kbps -> %u Mbps", + hwif_name.c_str(), vpp_speed_kbps, attr.value.u32); } else { @@ -2845,6 +2847,8 @@ sai_status_t SwitchVpp::refresh_port_oper_speed( attr.id = SAI_PORT_ATTR_SPEED; CHECK_STATUS(get(SAI_OBJECT_TYPE_PORT, port_id, 1, &attr)); + SWSS_LOG_NOTICE("port oper speed fallback to configured: %s %u Mbps", + hwif_name.c_str(), attr.value.u32); } } diff --git a/vslib/vpp/SwitchVpp.h b/vslib/vpp/SwitchVpp.h index b7a75f9e4a..e2f7e6cc04 100644 --- a/vslib/vpp/SwitchVpp.h +++ b/vslib/vpp/SwitchVpp.h @@ -709,6 +709,12 @@ namespace saivs _In_ uint32_t vlan_id, _In_ uint32_t mtu); + // set ethernet interface link speed + sai_status_t vpp_set_port_speed ( + _In_ sai_object_id_t object_id, + _In_ uint32_t vlan_id, + _In_ uint32_t speed); + sai_status_t UpdatePort( _In_ sai_object_id_t object_id, _In_ uint32_t attr_count, diff --git a/vslib/vpp/SwitchVppRif.cpp b/vslib/vpp/SwitchVppRif.cpp index b7e6048c02..d674e964c4 100644 --- a/vslib/vpp/SwitchVppRif.cpp +++ b/vslib/vpp/SwitchVppRif.cpp @@ -399,6 +399,12 @@ void SwitchVpp::vppProcessEvents () SWSS_LOG_NOTICE("Checking for any VS events status %d", ret); while ((evp = vpp_ev_dequeue())) { if (evp->type == VPP_INTF_LINK_STATUS) { + if (evp->data.intf_status.link_up) { + /* Refresh cached link speed from VPP on link-up. + * The initial sw_interface_dump may have cached speed=0 + * if the link was down at startup. */ + vpp_refresh_interface_speed(evp->data.intf_status.hwif_name); + } asyncIntfStateUpdate(evp->data.intf_status.hwif_name, evp->data.intf_status.link_up); SWSS_LOG_NOTICE("Received port link event for %s state %s", @@ -572,6 +578,31 @@ sai_status_t SwitchVpp::vpp_set_interface_mtu ( return SAI_STATUS_SUCCESS; } +sai_status_t SwitchVpp::vpp_set_port_speed ( + _In_ sai_object_id_t object_id, + _In_ uint32_t vlan_id, + _In_ uint32_t speed) +{ + SWSS_LOG_ENTER(); + + if (is_ip_nbr_active() == false) { + return SAI_STATUS_SUCCESS; + } + + std::string ifname; + + if (vpp_get_hwif_name(object_id, vlan_id, ifname) == true) { + const char *hwif_name = ifname.c_str(); + + // SAI port speed is in Mbps, VPP link speed is in Kbps + uint32_t link_speed = speed * 1000; + + sw_interface_set_link_speed(hwif_name, link_speed); + SWSS_LOG_NOTICE("Updating port %s speed to %u Mbps", hwif_name, speed); + } + return SAI_STATUS_SUCCESS; +} + sai_status_t SwitchVpp::UpdatePort( _In_ sai_object_id_t object_id, _In_ uint32_t attr_count, @@ -662,6 +693,13 @@ sai_status_t SwitchVpp::UpdatePort( vpp_set_port_mtu(object_id, 0, attr_type->value.u32); } + attr_type = sai_metadata_get_attr_by_id(SAI_PORT_ATTR_SPEED, attr_count, attr_list); + + if (attr_type != NULL) + { + vpp_set_port_speed(object_id, 0, attr_type->value.u32); + } + return SAI_STATUS_SUCCESS; } diff --git a/vslib/vpp/vppxlate/SaiVppXlate.c b/vslib/vpp/vppxlate/SaiVppXlate.c index 1308cdabf1..3266ece002 100644 --- a/vslib/vpp/vppxlate/SaiVppXlate.c +++ b/vslib/vpp/vppxlate/SaiVppXlate.c @@ -1005,6 +1005,12 @@ vl_api_sw_interface_set_mtu_reply_t_handler (vl_api_sw_interface_set_mtu_reply_t set_reply_status(retval); } static void +vl_api_sw_interface_set_link_speed_reply_t_handler (vl_api_sw_interface_set_link_speed_reply_t *msg) +{ + int retval = (int)ntohl((uint32_t)msg->retval); + set_reply_status(retval); +} +static void vl_api_sw_interface_set_mac_address_reply_t_handler (vl_api_sw_interface_set_mac_address_reply_t *msg) { int retval = (int)ntohl((uint32_t)msg->retval); @@ -1632,6 +1638,7 @@ static void vpp_base_vpe_init(void) _(INTERFACE_MSG_ID(SW_INTERFACE_SET_FLAGS_REPLY), sw_interface_set_flags_reply) \ _(INTERFACE_MSG_ID(SW_INTERFACE_SET_PROMISC_REPLY), sw_interface_set_promisc_reply) \ _(INTERFACE_MSG_ID(SW_INTERFACE_SET_MTU_REPLY), sw_interface_set_mtu_reply) \ + _(INTERFACE_MSG_ID(SW_INTERFACE_SET_LINK_SPEED_REPLY), sw_interface_set_link_speed_reply) \ _(INTERFACE_MSG_ID(SW_INTERFACE_SET_MAC_ADDRESS_REPLY), sw_interface_set_mac_address_reply) \ _(INTERFACE_MSG_ID(SW_INTERFACE_SET_UNNUMBERED_REPLY), sw_interface_set_unnumbered_reply) \ _(INTERFACE_MSG_ID(HW_INTERFACE_SET_MTU_REPLY), hw_interface_set_mtu_reply) \ @@ -3465,6 +3472,48 @@ int interface_get_state (const char *hwif_name, bool *link_is_up) return ret; } +int vpp_refresh_interface_speed (const char *hwif_name) +{ + vat_main_t *vam = &vat_main; + vl_api_sw_interface_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + VPP_LOCK(); + + __plugin_msg_base = interface_msg_id_base; + + M (SW_INTERFACE_DUMP, mp); + + u32 idx = get_swif_idx(vam, hwif_name); + if (idx == (u32) -1) { + SAIVPP_ERROR("%s: unable to get sw_index for %s", __func__, hwif_name); + VPP_UNLOCK(); + return -EINVAL; + } + mp->sw_if_index = htonl(idx); + /* context=0 so the details handler takes the normal path and + * updates link_speed_by_sw_index. */ + + S (mp); + + __plugin_msg_base = memclnt_msg_id_base; + PING (NULL, mp_ping); + S (mp_ping); + + WR (ret); + + if (ret) { + SAIVPP_ERROR("%s: dump failed(%d) for %s (idx %u)", __func__, ret, hwif_name, idx); + } else { + SAIVPP_INFO("%s: refreshed speed for %s (idx %u)", __func__, hwif_name, idx); + } + + VPP_UNLOCK(); + + return ret; +} + int vpp_get_interface_speed (const char *hwif_name, uint32_t *speed) { vat_main_t *vam = &vat_main; @@ -3557,6 +3606,46 @@ int sw_interface_set_mtu (const char *hwif_name, uint32_t mtu) return ret; } +int sw_interface_set_link_speed (const char *hwif_name, uint32_t link_speed) +{ + vat_main_t *vam = &vat_main; + vl_api_sw_interface_set_link_speed_t *mp; + int ret; + + VPP_LOCK(); + + __plugin_msg_base = interface_msg_id_base; + + M (SW_INTERFACE_SET_LINK_SPEED, mp); + if (hwif_name) { + u32 idx; + + idx = get_swif_idx(vam, hwif_name); + if (idx != (u32) -1) { + mp->sw_if_index = htonl(idx); + } else { + SAIVPP_ERROR("Unable to get sw_index for %s\n", hwif_name); + VPP_UNLOCK(); + return -EINVAL; + } + } else { + VPP_UNLOCK(); + return -EINVAL; + } + mp->link_speed = htonl(link_speed); + + S (mp); + + WR (ret); + + if (ret) { SAIVPP_ERROR("%s failed(%d) %s link_speed %u", __func__, ret, hwif_name, link_speed); } + else { SAIVPP_INFO("%s %s link_speed %u", __func__, hwif_name, link_speed); } + + VPP_UNLOCK(); + + return ret; +} + int sw_interface_set_mac (const char *hwif_name, uint8_t *mac_address) { vat_main_t *vam = &vat_main; diff --git a/vslib/vpp/vppxlate/SaiVppXlate.h b/vslib/vpp/vppxlate/SaiVppXlate.h index 7f6ac1e898..c52e9a178d 100644 --- a/vslib/vpp/vppxlate/SaiVppXlate.h +++ b/vslib/vpp/vppxlate/SaiVppXlate.h @@ -300,6 +300,7 @@ typedef enum { extern int interface_set_promiscuous (const char *hwif_name, bool enable); extern int hw_interface_set_mtu(const char *hwif_name, uint32_t mtu); extern int sw_interface_set_mtu(const char *hwif_name, uint32_t mtu); + extern int sw_interface_set_link_speed(const char *hwif_name, uint32_t link_speed); extern int sw_interface_set_mac(const char *hwif_name, uint8_t *mac_address); extern int sw_interface_ip6_enable_disable(const char *hwif_name, bool enable); extern int ip_vrf_add(uint32_t vrf_id, const char *vrf_name, bool is_ipv6); @@ -325,6 +326,7 @@ typedef enum { extern int vpp_tunterm_acl_interface_add_del (uint32_t tunterm_index, bool is_bind, const char *hwif_name); extern int interface_get_state(const char *hwif_name, bool *link_is_up); + extern int vpp_refresh_interface_speed(const char *hwif_name); extern int vpp_get_interface_speed(const char *hwif_name, uint32_t *speed); extern int vpp_sync_for_events(); extern int vpp_bridge_domain_add_del(uint32_t bridge_id, bool is_add);