diff --git a/vslib/vpp/SwitchVpp.cpp b/vslib/vpp/SwitchVpp.cpp index 8b1110a4..4f60ba6c 100644 --- a/vslib/vpp/SwitchVpp.cpp +++ b/vslib/vpp/SwitchVpp.cpp @@ -2202,3 +2202,46 @@ sai_status_t SwitchVpp::refresh_read_only( // For all other cases, delegate to the base class implementation return SwitchStateBase::refresh_read_only(meta, object_id); } + +sai_status_t SwitchVpp::refresh_port_oper_speed( + _In_ sai_object_id_t port_id) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + + attr.id = SAI_PORT_ATTR_OPER_STATUS; + + CHECK_STATUS(get(SAI_OBJECT_TYPE_PORT, port_id, 1, &attr)); + + if (attr.value.s32 == SAI_PORT_OPER_STATUS_DOWN) + { + attr.value.u32 = 0; + } + else + { + std::string hwif_name; + uint32_t vpp_speed_kbps = 0; + + if (vpp_get_hwif_name(port_id, 0, hwif_name) && + vpp_get_interface_speed(hwif_name.c_str(), &vpp_speed_kbps) == 0 && + vpp_speed_kbps > 0) + { + /* VPP reports link_speed in Kbps, SAI uses Mbps */ + attr.value.u32 = vpp_speed_kbps / 1000; + } + else + { + /* Fall back to configured SAI_PORT_ATTR_SPEED */ + attr.id = SAI_PORT_ATTR_SPEED; + + CHECK_STATUS(get(SAI_OBJECT_TYPE_PORT, port_id, 1, &attr)); + } + } + + attr.id = SAI_PORT_ATTR_OPER_SPEED; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); + + return SAI_STATUS_SUCCESS; +} diff --git a/vslib/vpp/SwitchVpp.h b/vslib/vpp/SwitchVpp.h index 9f41724d..6963732e 100644 --- a/vslib/vpp/SwitchVpp.h +++ b/vslib/vpp/SwitchVpp.h @@ -79,6 +79,9 @@ namespace saivs _In_ const sai_attr_metadata_t *meta, _In_ sai_object_id_t object_id) override; + virtual sai_status_t refresh_port_oper_speed( + _In_ sai_object_id_t port_id) override; + private: // from vpp VirtualSwitchSaiInterface void setPortStats( diff --git a/vslib/vpp/vppxlate/SaiVppXlate.c b/vslib/vpp/vppxlate/SaiVppXlate.c index 474ede5a..845d62dc 100644 --- a/vslib/vpp/vppxlate/SaiVppXlate.c +++ b/vslib/vpp/vppxlate/SaiVppXlate.c @@ -473,6 +473,7 @@ static uintptr_t get_index_ptr (uint32_t idx) vat_main_t vat_main; uword *interface_name_by_sw_index = NULL; +uword *link_speed_by_sw_index = NULL; f64 vat_time_now (vat_main_t * vam) @@ -690,6 +691,9 @@ vl_api_sw_interface_details_t_handler (vl_api_sw_interface_details_t *mp) ntohl (mp->sw_if_index)); hash_set (interface_name_by_sw_index, ntohl (mp->sw_if_index), s); + /* Save link speed (in Kbps) per interface */ + hash_set (link_speed_by_sw_index, ntohl (mp->sw_if_index), ntohl (mp->link_speed)); + /* In sub interface case, fill the sub interface table entry */ if (mp->sw_if_index != mp->sup_sw_if_index) { @@ -1536,6 +1540,7 @@ api_sw_interface_dump (vat_main_t *vam) /* Interface name is from the index_table which is already freed */ hash_free (interface_name_by_sw_index); + hash_free (link_speed_by_sw_index); vec_foreach (sub, vam->sw_if_subif_table) { @@ -1781,6 +1786,7 @@ int init_vpp_client() vam->socket_name = format (0, "%s%c", API_SOCKET_FILE, 0); vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword)); interface_name_by_sw_index = hash_create (0, sizeof (uword)); + link_speed_by_sw_index = hash_create (0, sizeof (uword)); if (vsc_socket_connect(vam, client_name) == 0) { int rc; @@ -2733,6 +2739,32 @@ int interface_get_state (const char *hwif_name, bool *link_is_up) return ret; } +int vpp_get_interface_speed (const char *hwif_name, uint32_t *speed) +{ + vat_main_t *vam = &vat_main; + uword *p; + + VPP_LOCK(); + + u32 idx = get_swif_idx(vam, hwif_name); + if (idx == (u32) -1) { + VPP_UNLOCK(); + return -EINVAL; + } + + p = hash_get(link_speed_by_sw_index, idx); + if (!p) { + VPP_UNLOCK(); + return -ENOENT; + } + + *speed = (uint32_t) p[0]; + + VPP_UNLOCK(); + + return 0; +} + int vpp_sync_for_events () { vat_main_t *vam = &vat_main; diff --git a/vslib/vpp/vppxlate/SaiVppXlate.h b/vslib/vpp/vppxlate/SaiVppXlate.h index 16838066..0dab30f4 100644 --- a/vslib/vpp/vppxlate/SaiVppXlate.h +++ b/vslib/vpp/vppxlate/SaiVppXlate.h @@ -297,6 +297,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_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); extern int set_sw_interface_l2_bridge(const char *hwif_name, uint32_t bridge_id, bool l2_enable, uint32_t port_type);