|
9 | 9 | */ |
10 | 10 | #include "fboss/qsfp_service/test/hw_test/HwTransceiverUtils.h" |
11 | 11 |
|
| 12 | +#include <algorithm> |
12 | 13 | #include <set> |
13 | 14 |
|
14 | 15 | #include <fmt/format.h> |
|
18 | 19 | #include "fboss/agent/FbossError.h" |
19 | 20 | #include "fboss/agent/gen-cpp2/switch_config_types.h" |
20 | 21 | #include "fboss/agent/platforms/common/PlatformMapping.h" |
| 22 | +#include "fboss/agent/test/utils/PortTestUtils.h" |
21 | 23 | #include "fboss/lib/config/PlatformConfigUtils.h" |
22 | 24 | #include "fboss/qsfp_service/TransceiverManager.h" |
| 25 | +#include "fboss/qsfp_service/module/cmis/CmisHelper.h" |
23 | 26 | #include "fboss/qsfp_service/module/properties/TransceiverPropertiesManager.h" |
24 | 27 |
|
25 | 28 | namespace facebook::fboss::utility { |
@@ -354,6 +357,14 @@ void HwTransceiverUtils::verifyMediaInterfaceCompliance( |
354 | 357 | mediaInterfaces.push_back(allMediaInterfaces[mediaLane]); |
355 | 358 | } |
356 | 359 |
|
| 360 | + if (isAoc(tcvrState)) { |
| 361 | + // An AOC programs like an active cable regardless of the profile's |
| 362 | + // copper/optical suffix, so the per-profile verifiers below (which |
| 363 | + // read smfCode or expect a copper transmitter) don't apply. |
| 364 | + verifyActiveOpticalCableProfile(mgmtInterface, mediaInterfaces, profile); |
| 365 | + return; |
| 366 | + } |
| 367 | + |
357 | 368 | switch (profile) { |
358 | 369 | case cfg::PortProfileID::PROFILE_10G_1_NRZ_NOFEC_OPTICAL: |
359 | 370 | verify10gProfile(tcvrState, mgmtInterface, mediaInterfaces); |
@@ -651,6 +662,41 @@ void HwTransceiverUtils::verifyCopper800gProfile( |
651 | 662 | } |
652 | 663 | } |
653 | 664 |
|
| 665 | +bool HwTransceiverUtils::isAoc(const TcvrState& tcvrState) { |
| 666 | + return TransceiverManager::activeCable(tcvrState) && |
| 667 | + *tcvrState.cable()->transmitterTech() == TransmitterTechnology::OPTICAL; |
| 668 | +} |
| 669 | + |
| 670 | +void HwTransceiverUtils::verifyActiveOpticalCableProfile( |
| 671 | + const TransceiverManagementInterface mgmtInterface, |
| 672 | + const std::vector<MediaInterfaceId>& mediaInterfaces, |
| 673 | + cfg::PortProfileID profile) { |
| 674 | + EXPECT_EQ(mgmtInterface, TransceiverManagementInterface::CMIS); |
| 675 | + |
| 676 | + const auto& speedApplications = CmisHelper::getActiveSpeedApplication(); |
| 677 | + auto expectedCodesIt = speedApplications.find(utility::getSpeed(profile)); |
| 678 | + if (expectedCodesIt == speedApplications.end()) { |
| 679 | + throw FbossError( |
| 680 | + "No active cable application for profile ", |
| 681 | + apache::thrift::util::enumNameSafe(profile)); |
| 682 | + } |
| 683 | + const auto& expectedCodes = expectedCodesIt->second; |
| 684 | + const auto& activeMediaMap = CmisHelper::getActiveMediaInterfaceMapping(); |
| 685 | + |
| 686 | + for (const auto& mediaId : mediaInterfaces) { |
| 687 | + auto activeCuCode = *mediaId.media()->activeCuCode(); |
| 688 | + EXPECT_TRUE( |
| 689 | + std::find(expectedCodes.begin(), expectedCodes.end(), activeCuCode) != |
| 690 | + expectedCodes.end()) |
| 691 | + << "Unexpected activeCuCode " |
| 692 | + << apache::thrift::util::enumNameSafe(activeCuCode) << " for profile " |
| 693 | + << apache::thrift::util::enumNameSafe(profile); |
| 694 | + auto mediaCodeIt = activeMediaMap.find(activeCuCode); |
| 695 | + ASSERT_TRUE(mediaCodeIt != activeMediaMap.end()); |
| 696 | + EXPECT_EQ(*mediaId.code(), mediaCodeIt->second); |
| 697 | + } |
| 698 | +} |
| 699 | + |
654 | 700 | void HwTransceiverUtils::verifyDataPathEnabled( |
655 | 701 | const TcvrState& tcvrState, |
656 | 702 | const std::string& portName) { |
|
0 commit comments