@@ -561,3 +561,206 @@ TEST(SwitchBCM56850, test_port_autoneg_fec_override_support)
561561 EXPECT_EQ (attr_capability.set_implemented , false );
562562 EXPECT_EQ (attr_capability.get_implemented , false );
563563}
564+
565+ TEST (SwitchBCM56850, test_refresh_port_oper_speed_configured_speed)
566+ {
567+ /*
568+ * Test that refresh_port_oper_speed returns the administratively
569+ * configured port speed when m_useConfiguredSpeedAsOperSpeed is true,
570+ * i.e., it propagates SAI_PORT_ATTR_SPEED to SAI_PORT_ATTR_OPER_SPEED
571+ * without consulting sysfs.
572+ */
573+
574+ auto sc = std::make_shared<SwitchConfig>(0 , " " );
575+ auto signal = std::make_shared<Signal>();
576+ auto eventQueue = std::make_shared<EventQueue>(signal);
577+
578+ sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
579+ sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
580+ sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
581+ sc->m_useTapDevice = false ;
582+ sc->m_laneMap = LaneMap::getDefaultLaneMap (0 );
583+ sc->m_eventQueue = eventQueue;
584+ sc->m_useConfiguredSpeedAsOperSpeed = true ;
585+
586+ auto scc = std::make_shared<SwitchConfigContainer>();
587+
588+ scc->insert (sc);
589+
590+ SwitchBCM56850 sw (
591+ 0x2100000000 ,
592+ std::make_shared<RealObjectIdManager>(0 , scc),
593+ sc);
594+
595+ sai_attribute_t attr;
596+
597+ attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
598+ attr.value .booldata = true ;
599+
600+ ASSERT_EQ (sw.initialize_default_objects (1 , &attr), SAI_STATUS_SUCCESS);
601+
602+ // Get the port list
603+ sai_object_id_t port_list[64 ];
604+
605+ attr.id = SAI_SWITCH_ATTR_PORT_LIST;
606+ attr.value .objlist .count = 64 ;
607+ attr.value .objlist .list = port_list;
608+
609+ ASSERT_EQ (sw.get (SAI_OBJECT_TYPE_SWITCH, " oid:0x2100000000" , 1 , &attr), SAI_STATUS_SUCCESS);
610+ ASSERT_GT (attr.value .objlist .count , (uint32_t )0 );
611+
612+ auto port_id = port_list[0 ];
613+ auto sport = sai_serialize_object_id (port_id);
614+
615+ // Set port oper status to UP so refresh_port_oper_speed uses configured speed path
616+ attr.id = SAI_PORT_ATTR_OPER_STATUS;
617+ attr.value .s32 = SAI_PORT_OPER_STATUS_UP;
618+ ASSERT_EQ (sw.set (SAI_OBJECT_TYPE_PORT, sport, &attr), SAI_STATUS_SUCCESS);
619+
620+ // Set configured speed to 40000
621+ attr.id = SAI_PORT_ATTR_SPEED;
622+ attr.value .u32 = 40000 ;
623+ ASSERT_EQ (sw.set (SAI_OBJECT_TYPE_PORT, sport, &attr), SAI_STATUS_SUCCESS);
624+
625+ // Call refresh_port_oper_speed — with m_useConfiguredSpeedAsOperSpeed=true,
626+ // it should use configured speed (40000) instead of querying sysfs
627+ ASSERT_EQ (sw.refresh_port_oper_speed (port_id), SAI_STATUS_SUCCESS);
628+
629+ // Verify oper speed matches configured speed
630+ attr.id = SAI_PORT_ATTR_OPER_SPEED;
631+ ASSERT_EQ (sw.get (SAI_OBJECT_TYPE_PORT, sport, 1 , &attr), SAI_STATUS_SUCCESS);
632+ EXPECT_EQ (attr.value .u32 , (uint32_t )40000 );
633+ }
634+
635+ TEST (SwitchBCM56850, test_refresh_port_oper_speed_down_port)
636+ {
637+ /*
638+ * Test that refresh_port_oper_speed returns 0 for ports that are
639+ * operationally down, regardless of configured speed.
640+ */
641+
642+ auto sc = std::make_shared<SwitchConfig>(0 , " " );
643+ auto signal = std::make_shared<Signal>();
644+ auto eventQueue = std::make_shared<EventQueue>(signal);
645+
646+ sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
647+ sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
648+ sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
649+ sc->m_useTapDevice = false ;
650+ sc->m_laneMap = LaneMap::getDefaultLaneMap (0 );
651+ sc->m_eventQueue = eventQueue;
652+
653+ auto scc = std::make_shared<SwitchConfigContainer>();
654+
655+ scc->insert (sc);
656+
657+ SwitchBCM56850 sw (
658+ 0x2100000000 ,
659+ std::make_shared<RealObjectIdManager>(0 , scc),
660+ sc);
661+
662+ sai_attribute_t attr;
663+
664+ attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
665+ attr.value .booldata = true ;
666+
667+ ASSERT_EQ (sw.initialize_default_objects (1 , &attr), SAI_STATUS_SUCCESS);
668+
669+ // Get a port
670+ sai_object_id_t port_list[64 ];
671+
672+ attr.id = SAI_SWITCH_ATTR_PORT_LIST;
673+ attr.value .objlist .count = 64 ;
674+ attr.value .objlist .list = port_list;
675+
676+ ASSERT_EQ (sw.get (SAI_OBJECT_TYPE_SWITCH, " oid:0x2100000000" , 1 , &attr), SAI_STATUS_SUCCESS);
677+ ASSERT_GT (attr.value .objlist .count , (uint32_t )0 );
678+
679+ auto port_id = port_list[0 ];
680+ auto sport = sai_serialize_object_id (port_id);
681+
682+ // Port is down by default — refresh should set oper speed to 0
683+ attr.id = SAI_PORT_ATTR_OPER_STATUS;
684+ attr.value .s32 = SAI_PORT_OPER_STATUS_DOWN;
685+ ASSERT_EQ (sw.set (SAI_OBJECT_TYPE_PORT, sport, &attr), SAI_STATUS_SUCCESS);
686+
687+ // Set configured speed to 40000 (should be ignored for down ports)
688+ attr.id = SAI_PORT_ATTR_SPEED;
689+ attr.value .u32 = 40000 ;
690+ ASSERT_EQ (sw.set (SAI_OBJECT_TYPE_PORT, sport, &attr), SAI_STATUS_SUCCESS);
691+
692+ ASSERT_EQ (sw.refresh_port_oper_speed (port_id), SAI_STATUS_SUCCESS);
693+
694+ attr.id = SAI_PORT_ATTR_OPER_SPEED;
695+ ASSERT_EQ (sw.get (SAI_OBJECT_TYPE_PORT, sport, 1 , &attr), SAI_STATUS_SUCCESS);
696+ EXPECT_EQ (attr.value .u32 , (uint32_t )0 );
697+ }
698+
699+ TEST (SwitchBCM56850, test_refresh_port_oper_speed_fallback_no_tap)
700+ {
701+ /*
702+ * Test that when m_useConfiguredSpeedAsOperSpeed is false and no TAP
703+ * device exists (vs_get_oper_speed fails), refresh_port_oper_speed
704+ * reports 0 instead of a bogus value.
705+ */
706+
707+ auto sc = std::make_shared<SwitchConfig>(0 , " " );
708+ auto signal = std::make_shared<Signal>();
709+ auto eventQueue = std::make_shared<EventQueue>(signal);
710+
711+ sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
712+ sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
713+ sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
714+ sc->m_useTapDevice = false ;
715+ sc->m_laneMap = LaneMap::getDefaultLaneMap (0 );
716+ sc->m_eventQueue = eventQueue;
717+ sc->m_useConfiguredSpeedAsOperSpeed = false ;
718+
719+ auto scc = std::make_shared<SwitchConfigContainer>();
720+
721+ scc->insert (sc);
722+
723+ SwitchBCM56850 sw (
724+ 0x2100000000 ,
725+ std::make_shared<RealObjectIdManager>(0 , scc),
726+ sc);
727+
728+ sai_attribute_t attr;
729+
730+ attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
731+ attr.value .booldata = true ;
732+
733+ ASSERT_EQ (sw.initialize_default_objects (1 , &attr), SAI_STATUS_SUCCESS);
734+
735+ // Get a port
736+ sai_object_id_t port_list[64 ];
737+
738+ attr.id = SAI_SWITCH_ATTR_PORT_LIST;
739+ attr.value .objlist .count = 64 ;
740+ attr.value .objlist .list = port_list;
741+
742+ ASSERT_EQ (sw.get (SAI_OBJECT_TYPE_SWITCH, " oid:0x2100000000" , 1 , &attr), SAI_STATUS_SUCCESS);
743+ ASSERT_GT (attr.value .objlist .count , (uint32_t )0 );
744+
745+ auto port_id = port_list[0 ];
746+ auto sport = sai_serialize_object_id (port_id);
747+
748+ // Set port to UP
749+ attr.id = SAI_PORT_ATTR_OPER_STATUS;
750+ attr.value .s32 = SAI_PORT_OPER_STATUS_UP;
751+ ASSERT_EQ (sw.set (SAI_OBJECT_TYPE_PORT, sport, &attr), SAI_STATUS_SUCCESS);
752+
753+ // Set configured speed
754+ attr.id = SAI_PORT_ATTR_SPEED;
755+ attr.value .u32 = 100000 ;
756+ ASSERT_EQ (sw.set (SAI_OBJECT_TYPE_PORT, sport, &attr), SAI_STATUS_SUCCESS);
757+
758+ // Without TAP devices, vs_get_oper_speed will fail (no host interface)
759+ // refresh_port_oper_speed should report 0 when sysfs is unavailable
760+ ASSERT_EQ (sw.refresh_port_oper_speed (port_id), SAI_STATUS_SUCCESS);
761+
762+ // Verify oper speed is 0 (no valid sysfs speed, no fallback to configured)
763+ attr.id = SAI_PORT_ATTR_OPER_SPEED;
764+ ASSERT_EQ (sw.get (SAI_OBJECT_TYPE_PORT, sport, 1 , &attr), SAI_STATUS_SUCCESS);
765+ EXPECT_EQ (attr.value .u32 , (uint32_t )0 );
766+ }
0 commit comments