@@ -757,54 +757,80 @@ bool PortsOrch::setHostIntfsStripTag(Port &port, sai_hostif_vlan_tag_t strip)
757757 return true ;
758758}
759759
760- bool PortsOrch::validatePortSpeed ( sai_object_id_t port_id, sai_uint32_t speed)
760+ bool PortsOrch::isSpeedSupported ( const std::string& alias, sai_object_id_t port_id, sai_uint32_t speed)
761761{
762+ // This method will return false iff we get a list of supported speeds and the requested speed
763+ // is not supported
764+ // Otherwise the method will return true (even if we received errors)
765+
762766 sai_attribute_t attr;
763767 sai_status_t status;
764768
765769 // "Lazy" query of supported speeds for given port
766770 // Once received the list will be stored in m_portSupportedSpeeds
767771 if (!m_portSupportedSpeeds.count (port_id))
768772 {
769- attr.id = SAI_PORT_ATTR_SUPPORTED_SPEED;
770- attr.value .u32list .count = 0 ;
771- attr.value .u32list .list = NULL ;
773+ const auto size_guess = 25 ; // Guess the size which could be enough
772774
773- status = sai_port_api->get_port_attribute (port_id, 1 , &attr);
774- if (status == SAI_STATUS_BUFFER_OVERFLOW)
775- {
776- std::vector<sai_uint32_t > speeds (attr.value .u32list .count );
775+ std::vector<sai_uint32_t > speeds (size_guess);
776+
777+ for (int attempt = 0 ; attempt < 2 ; ++attempt) // two attempts to get our value
778+ { // first with the guess,
779+ // other with the returned value
780+ attr.id = SAI_PORT_ATTR_SUPPORTED_SPEED;
781+ attr.value .u32list .count = static_cast <uint32_t >(speeds.size ());
777782 attr.value .u32list .list = speeds.data ();
783+
778784 status = sai_port_api->get_port_attribute (port_id, 1 , &attr);
779- if (status == SAI_STATUS_SUCCESS )
785+ if (status != SAI_STATUS_BUFFER_OVERFLOW )
780786 {
781- m_portSupportedSpeeds[port_id] = speeds;
782- }
783- else
784- {
785- SWSS_LOG_ERROR (" Failed to get supported speed list for port %lx" , port_id);
786- return false ;
787+ break ;
787788 }
789+
790+ speeds.resize (attr.value .u32list .count ); // if our guess was wrong
791+ // retry with the correct value
788792 }
789- // TODO: change to macro SAI_STATUS_IS_ATTR_NOT_SUPPORTED once it is fixed in SAI
790- // https://github.com/opencomputeproject/SAI/pull/710
791- else if ((((status) & (~0xFFFF )) == SAI_STATUS_ATTR_NOT_SUPPORTED_0) ||
792- (((status) & (~0xFFFF )) == SAI_STATUS_ATTR_NOT_IMPLEMENTED_0) ||
793- (status == SAI_STATUS_NOT_IMPLEMENTED))
793+
794+ if (status == SAI_STATUS_SUCCESS)
794795 {
795- // unable to validate speed if attribute is not supported on platform
796- // assuming input value is correct
797- SWSS_LOG_WARN (" Unable to validate speed for port %lx. Not supported by platform" , port_id);
798- return true ;
796+ speeds.resize (attr.value .u32list .count );
797+ m_portSupportedSpeeds[port_id] = speeds;
799798 }
800799 else
801800 {
802- SWSS_LOG_ERROR (" Failed to get number of supported speeds for port %lx" , port_id);
803- return false ;
801+ if (status == SAI_STATUS_BUFFER_OVERFLOW)
802+ {
803+ // something went wrong in SAI implementation
804+ SWSS_LOG_ERROR (" Failed to get supported speed list for port %s id=%lx. Not enough container size" ,
805+ alias.c_str (), port_id);
806+ }
807+ else if (SAI_STATUS_IS_ATTR_NOT_SUPPORTED (status) ||
808+ SAI_STATUS_IS_ATTR_NOT_IMPLEMENTED (status) ||
809+ status == SAI_STATUS_NOT_IMPLEMENTED)
810+ {
811+ // unable to validate speed if attribute is not supported on platform
812+ // assuming input value is correct
813+ SWSS_LOG_WARN (" Unable to validate speed for port %s id=%lx. Not supported by platform" ,
814+ alias.c_str (), port_id);
815+ }
816+ else
817+ {
818+ SWSS_LOG_ERROR (" Failed to get a list of supported speeds for port %s id=%lx. Error=%d" ,
819+ alias.c_str (), port_id, status);
820+ }
821+ m_portSupportedSpeeds[port_id] = {}; // use an empty list,
822+ // we don't want to get the port speed for this port again
823+ return true ; // we can't check if the speed is valid, so return true to change the speed
804824 }
825+
805826 }
806827
807- PortSupportedSpeeds &supp_speeds = m_portSupportedSpeeds[port_id];
828+ const PortSupportedSpeeds &supp_speeds = m_portSupportedSpeeds[port_id];
829+ if (supp_speeds.size () == 0 )
830+ {
831+ // we don't have the list for this port, so return true to change speed anyway
832+ return true ;
833+ }
808834
809835 return std::find (supp_speeds.begin (), supp_speeds.end (), speed) != supp_speeds.end ();
810836}
@@ -1236,9 +1262,8 @@ void PortsOrch::doPortTask(Consumer &consumer)
12361262 {
12371263 sai_uint32_t current_speed;
12381264
1239- if (!validatePortSpeed ( p.m_port_id , speed))
1265+ if (!isSpeedSupported (alias, p.m_port_id , speed))
12401266 {
1241- SWSS_LOG_ERROR (" Failed to set speed %u for port %s. The value is not supported" , speed, alias.c_str ());
12421267 it++;
12431268 continue ;
12441269 }
0 commit comments