Skip to content

Commit 076bc35

Browse files
NO-NOS: [qsfp_service] Support AOC modules in the qsfp hw test media checks
Signed-off-by: Zackary Ayoun <zackary@nexthop.ai>
1 parent 8896ff9 commit 076bc35

5 files changed

Lines changed: 69 additions & 10 deletions

File tree

cmake/QsfpServiceTestHwTest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ target_link_libraries(hw_transceiver_utils
2626
Folly::folly
2727
fboss_error
2828
platform_mapping
29+
port_test_utils
2930
switch_config_cpp2
3031
transceiver_cpp2
3132
transceiver_manager

fboss/qsfp_service/test/hw_test/BUCK

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ cpp_library(
2323
"fbsource//third-party/fmt:fmt",
2424
"fbsource//third-party/googletest:gtest",
2525
"//fboss/agent:fboss-error",
26+
"//fboss/agent/test/utils:port_test_utils",
2627
"//fboss/lib/config:fboss_config_utils",
2728
"//fboss/qsfp_service:transceiver-manager",
2829
"//fboss/qsfp_service/module/properties:transceiver-properties-manager",

fboss/qsfp_service/test/hw_test/HwI2cSelectTest.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
#include "fboss/qsfp_service/test/hw_test/HwPortUtils.h"
66
#include "fboss/qsfp_service/test/hw_test/HwQsfpEnsemble.h"
7+
#include "fboss/qsfp_service/test/hw_test/HwTransceiverUtils.h"
78

8-
#include <folly/gen/Base.h>
99
#include <folly/logging/xlog.h>
1010

1111
namespace facebook::fboss {
@@ -68,21 +68,23 @@ TEST_F(HwTest, i2cUniqueSerialNumbers) {
6868
if (snIds.find(sn) == snIds.end()) {
6969
snIds[sn] = tcvrId;
7070
} else {
71-
// Found duplicated serial numbers, module must be DAC and connected to
72-
// another DAC on the other end
71+
// Found duplicated serial numbers, module must be a single cable
72+
// assembly (DAC/AEC/AOC) connected back to itself on the other end
7373
auto neighborId = snIds[sn];
7474
CHECK(cabledNames.find(tcvrId) != cabledNames.end());
7575
CHECK(cabledNames.find(neighborId) != cabledNames.end());
7676
EXPECT_EQ(cabledNames[tcvrId].first, cabledNames[neighborId].second);
7777
EXPECT_EQ(cabledNames[tcvrId].second, cabledNames[neighborId].first);
7878

79-
auto transmitterTech =
80-
*(transceiverInfo[tcvrId].tcvrState()->cable()->transmitterTech());
81-
EXPECT_EQ(TransmitterTechnology::COPPER, transmitterTech);
82-
83-
transmitterTech = *(
84-
transceiverInfo[neighborId].tcvrState()->cable()->transmitterTech());
85-
EXPECT_EQ(TransmitterTechnology::COPPER, transmitterTech);
79+
for (auto id : {tcvrId, neighborId}) {
80+
const auto& tcvrState = *transceiverInfo[id].tcvrState();
81+
auto transmitterTech = *(tcvrState.cable()->transmitterTech());
82+
EXPECT_TRUE(
83+
transmitterTech == TransmitterTechnology::COPPER ||
84+
utility::HwTransceiverUtils::isAoc(tcvrState))
85+
<< "Transceiver " << id
86+
<< " shares a serial number but is neither copper nor AOC";
87+
}
8688
}
8789
}
8890
}

fboss/qsfp_service/test/hw_test/HwTransceiverUtils.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
#include "fboss/qsfp_service/test/hw_test/HwTransceiverUtils.h"
1111

12+
#include <algorithm>
1213
#include <set>
1314

1415
#include <fmt/format.h>
@@ -18,8 +19,10 @@
1819
#include "fboss/agent/FbossError.h"
1920
#include "fboss/agent/gen-cpp2/switch_config_types.h"
2021
#include "fboss/agent/platforms/common/PlatformMapping.h"
22+
#include "fboss/agent/test/utils/PortTestUtils.h"
2123
#include "fboss/lib/config/PlatformConfigUtils.h"
2224
#include "fboss/qsfp_service/TransceiverManager.h"
25+
#include "fboss/qsfp_service/module/cmis/CmisHelper.h"
2326
#include "fboss/qsfp_service/module/properties/TransceiverPropertiesManager.h"
2427

2528
namespace facebook::fboss::utility {
@@ -354,6 +357,14 @@ void HwTransceiverUtils::verifyMediaInterfaceCompliance(
354357
mediaInterfaces.push_back(allMediaInterfaces[mediaLane]);
355358
}
356359

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+
357368
switch (profile) {
358369
case cfg::PortProfileID::PROFILE_10G_1_NRZ_NOFEC_OPTICAL:
359370
verify10gProfile(tcvrState, mgmtInterface, mediaInterfaces);
@@ -651,6 +662,41 @@ void HwTransceiverUtils::verifyCopper800gProfile(
651662
}
652663
}
653664

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+
654700
void HwTransceiverUtils::verifyDataPathEnabled(
655701
const TcvrState& tcvrState,
656702
const std::string& portName) {

fboss/qsfp_service/test/hw_test/HwTransceiverUtils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,16 @@ class HwTransceiverUtils {
5050
time_t timeReference,
5151
bool expectedReset);
5252

53+
// Active optical cable: reports ACTIVE_CABLES media type encoding like an
54+
// AEC, but an optical transmitter. Its media interface union carries
55+
// activeCuCode, not smfCode.
56+
static bool isAoc(const TcvrState& tcvrState);
57+
5358
private:
59+
static void verifyActiveOpticalCableProfile(
60+
TransceiverManagementInterface mgmtInterface,
61+
const std::vector<MediaInterfaceId>& mediaInterfaces,
62+
cfg::PortProfileID profile);
5463
static void verifyOpticsSettings(
5564
const TcvrState& tcvrState,
5665
const std::string& portName,

0 commit comments

Comments
 (0)