unittest/vslib/TestSwitchBCM56850.cpp (359 lines of code) (raw):
#include "SwitchBCM56850.h"
#include "meta/sai_serialize.h"
#include <gtest/gtest.h>
#include <memory>
using namespace saivs;
TEST(SwitchBCM56850, ctr)
{
auto sc = std::make_shared<SwitchConfig>(0, "");
auto signal = std::make_shared<Signal>();
auto eventQueue = std::make_shared<EventQueue>(signal);
sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
sc->m_useTapDevice = false;
sc->m_laneMap = LaneMap::getDefaultLaneMap(0);
sc->m_eventQueue = eventQueue;
auto scc = std::make_shared<SwitchConfigContainer>();
scc->insert(sc);
SwitchBCM56850 sw(
0x2100000000,
std::make_shared<RealObjectIdManager>(0, scc),
sc);
SwitchBCM56850 sw2(
0x2100000000,
std::make_shared<RealObjectIdManager>(0, scc),
sc,
nullptr);
sai_attribute_t attr;
attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
attr.value.booldata = true;
EXPECT_EQ(sw.initialize_default_objects(1, &attr), SAI_STATUS_SUCCESS);
}
TEST(SwitchBCM56850, refresh_bridge_port_list)
{
auto sc = std::make_shared<SwitchConfig>(0, "");
auto signal = std::make_shared<Signal>();
auto eventQueue = std::make_shared<EventQueue>(signal);
sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
sc->m_useTapDevice = false;
sc->m_laneMap = LaneMap::getDefaultLaneMap(0);
sc->m_eventQueue = eventQueue;
auto scc = std::make_shared<SwitchConfigContainer>();
scc->insert(sc);
SwitchBCM56850 sw(
0x2100000000,
std::make_shared<RealObjectIdManager>(0, scc),
sc);
sai_attribute_t attr;
attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
attr.value.booldata = true;
EXPECT_EQ(sw.initialize_default_objects(1, &attr), SAI_STATUS_SUCCESS);
attr.id = SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID;
attr.value.oid = SAI_NULL_OBJECT_ID;
EXPECT_EQ(sw.get(SAI_OBJECT_TYPE_SWITCH, "oid:0x2100000000", 1, &attr), SAI_STATUS_SUCCESS);
EXPECT_NE(attr.value.oid, SAI_NULL_OBJECT_ID);
auto boid = attr.value.oid;
auto sboid = sai_serialize_object_id(boid);
sai_object_id_t list[128];
attr.id = SAI_BRIDGE_ATTR_PORT_LIST;
attr.value.objlist.count = 128;
attr.value.objlist.list = list;
EXPECT_EQ(sw.get(SAI_OBJECT_TYPE_BRIDGE, sboid, 1, &attr), SAI_STATUS_SUCCESS);
//std::cout << sw.dump_switch_database_for_warm_restart();
}
static std::map<sai_object_id_t, WarmBootState> g_warmBootState;
// TODO move to utils
static bool getWarmBootState(
_In_ const char* warmBootFile,
_In_ std::shared_ptr<RealObjectIdManager> roidm)
{
SWSS_LOG_ENTER();
std::ifstream ifs;
ifs.open(warmBootFile);
if (!ifs.is_open())
{
SWSS_LOG_ERROR("failed to open: %s", warmBootFile);
return false;
}
std::string line;
while (std::getline(ifs, line))
{
SWSS_LOG_DEBUG("line: %s", line.c_str());
// line format: OBJECT_TYPE OBJECT_ID ATTR_ID ATTR_VALUE
std::istringstream iss(line);
std::string strObjectType;
std::string strObjectId;
std::string strAttrId;
std::string strAttrValue;
iss >> strObjectType >> strObjectId;
if (strObjectType == SAI_VS_FDB_INFO)
{
/*
* If we read line from fdb info set and use tap device is enabled
* just parse line and repopulate fdb info set.
*/
FdbInfo fi = FdbInfo::deserialize(strObjectId);
auto switchId = roidm->switchIdQuery(fi.m_portId);
if (switchId == SAI_NULL_OBJECT_ID)
{
SWSS_LOG_ERROR("switchIdQuery returned NULL on fi.m_port = %s",
sai_serialize_object_id(fi.m_portId).c_str());
g_warmBootState.clear();
return false;
}
g_warmBootState[switchId].m_switchId = switchId;
g_warmBootState[switchId].m_fdbInfoSet.insert(fi);
continue;
}
iss >> strAttrId >> strAttrValue;
sai_object_meta_key_t metaKey;
sai_deserialize_object_meta_key(strObjectType + ":" + strObjectId, metaKey);
/*
* Since all objects we are creating, then during warm boot we need to
* get the biggest object index, so after warm boot we can start
* generating new objects with index value not colliding with objects
* loaded from warm boot scenario. We only need to consider OID
* objects.
*/
roidm->updateWarmBootObjectIndex(metaKey.objectkey.key.object_id);
// query each object for switch id
auto switchId = roidm->switchIdQuery(metaKey.objectkey.key.object_id);
if (switchId == SAI_NULL_OBJECT_ID)
{
SWSS_LOG_ERROR("switchIdQuery returned NULL on oid = %s",
sai_serialize_object_id(metaKey.objectkey.key.object_id).c_str());
g_warmBootState.clear();
return false;
}
g_warmBootState[switchId].m_switchId = switchId;
auto &objectHash = g_warmBootState[switchId].m_objectHash[metaKey.objecttype]; // will create if not exist
if (objectHash.find(strObjectId) == objectHash.end())
{
objectHash[strObjectId] = {};
}
if (strAttrId == "NULL")
{
// skip empty attributes
continue;
}
objectHash[strObjectId][strAttrId] =
std::make_shared<SaiAttrWrap>(strAttrId, strAttrValue);
}
// NOTE notification pointers should be restored by attr_list when creating switch
ifs.close();
return true;
}
TEST(SwitchBCM56850, warm_update_queues)
{
auto sc = std::make_shared<SwitchConfig>(0, "");
auto signal = std::make_shared<Signal>();
auto eventQueue = std::make_shared<EventQueue>(signal);
sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
sc->m_useTapDevice = false;
sc->m_laneMap = LaneMap::getDefaultLaneMap(0);
sc->m_eventQueue = eventQueue;
auto scc = std::make_shared<SwitchConfigContainer>();
scc->insert(sc);
auto roidm = std::make_shared<RealObjectIdManager>(0, scc);
EXPECT_TRUE(getWarmBootState("files/mlnx2700.warm.bin", roidm));
auto warmBootState = std::make_shared<WarmBootState>(g_warmBootState.at(0x2100000000)); // copy ctr
SwitchBCM56850 sw(
0x2100000000,
roidm,
sc,
warmBootState);
sai_attribute_t attr;
attr.id = SAI_SWITCH_ATTR_INIT_SWITCH;
attr.value.booldata = true;
EXPECT_EQ(sw.warm_boot_initialize_objects(), SAI_STATUS_SUCCESS);
attr.id = SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID;
attr.value.oid = SAI_NULL_OBJECT_ID;
EXPECT_EQ(sw.get(SAI_OBJECT_TYPE_SWITCH, "oid:0x2100000000", 1, &attr), SAI_STATUS_SUCCESS);
EXPECT_NE(attr.value.oid, SAI_NULL_OBJECT_ID);
auto boid = attr.value.oid;
auto sboid = sai_serialize_object_id(boid);
sai_object_id_t list[128];
attr.id = SAI_BRIDGE_ATTR_PORT_LIST;
attr.value.objlist.count = 128;
attr.value.objlist.list = list;
EXPECT_EQ(sw.get(SAI_OBJECT_TYPE_BRIDGE, sboid, 1, &attr), SAI_STATUS_SUCCESS);
}
TEST(SwitchBCM56850, test_tunnel_term_capability)
{
auto sc = std::make_shared<SwitchConfig>(0, "");
auto signal = std::make_shared<Signal>();
auto eventQueue = std::make_shared<EventQueue>(signal);
sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
sc->m_useTapDevice = false;
sc->m_laneMap = LaneMap::getDefaultLaneMap(0);
sc->m_eventQueue = eventQueue;
auto scc = std::make_shared<SwitchConfigContainer>();
scc->insert(sc);
SwitchBCM56850 sw(
0x2100000000,
std::make_shared<RealObjectIdManager>(0, scc),
sc);
sai_s32_list_t enum_val_cap;
int32_t list[2];
enum_val_cap.count = 2;
enum_val_cap.list = list;
EXPECT_EQ(sw.queryAttrEnumValuesCapability(0x2100000000,
SAI_OBJECT_TYPE_TUNNEL,
SAI_TUNNEL_ATTR_PEER_MODE,
&enum_val_cap),
SAI_STATUS_SUCCESS);
EXPECT_EQ(enum_val_cap.count, 2);
int modes_found = 0;
for (uint32_t i = 0; i < enum_val_cap.count; i++)
{
if (enum_val_cap.list[i] == SAI_TUNNEL_PEER_MODE_P2MP || enum_val_cap.list[i] == SAI_TUNNEL_PEER_MODE_P2P)
{
modes_found++;
}
}
EXPECT_EQ(modes_found, 2);
}
TEST(SwitchBCM56850, test_vlan_flood_capability)
{
auto sc = std::make_shared<SwitchConfig>(0, "");
auto signal = std::make_shared<Signal>();
auto eventQueue = std::make_shared<EventQueue>(signal);
sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
sc->m_useTapDevice = false;
sc->m_laneMap = LaneMap::getDefaultLaneMap(0);
sc->m_eventQueue = eventQueue;
auto scc = std::make_shared<SwitchConfigContainer>();
scc->insert(sc);
SwitchBCM56850 sw(
0x2100000000,
std::make_shared<RealObjectIdManager>(0, scc),
sc);
sai_s32_list_t enum_val_cap;
int32_t list[4];
enum_val_cap.count = 4;
enum_val_cap.list = list;
EXPECT_EQ(sw.queryAttrEnumValuesCapability(0x2100000000,
SAI_OBJECT_TYPE_VLAN,
SAI_VLAN_ATTR_UNKNOWN_UNICAST_FLOOD_CONTROL_TYPE,
&enum_val_cap),
SAI_STATUS_SUCCESS);
EXPECT_EQ(enum_val_cap.count, 3);
int flood_types_found = 0;
for (uint32_t i = 0; i < enum_val_cap.count; i++)
{
if (enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_ALL ||
enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_NONE ||
enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_L2MC_GROUP)
{
flood_types_found++;
}
}
EXPECT_EQ(flood_types_found, 3);
memset(list, 0, sizeof(list));
flood_types_found = 0;
enum_val_cap.count = 4;
enum_val_cap.list = list;
EXPECT_EQ(sw.queryAttrEnumValuesCapability(0x2100000000,
SAI_OBJECT_TYPE_VLAN,
SAI_VLAN_ATTR_UNKNOWN_MULTICAST_FLOOD_CONTROL_TYPE,
&enum_val_cap),
SAI_STATUS_SUCCESS);
EXPECT_EQ(enum_val_cap.count, 3);
for (uint32_t i = 0; i < enum_val_cap.count; i++)
{
if (enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_ALL ||
enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_NONE ||
enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_L2MC_GROUP)
{
flood_types_found++;
}
}
EXPECT_EQ(flood_types_found, 3);
memset(list, 0, sizeof(list));
flood_types_found = 0;
enum_val_cap.count = 4;
enum_val_cap.list = list;
EXPECT_EQ(sw.queryAttrEnumValuesCapability(0x2100000000,
SAI_OBJECT_TYPE_VLAN,
SAI_VLAN_ATTR_BROADCAST_FLOOD_CONTROL_TYPE,
&enum_val_cap),
SAI_STATUS_SUCCESS);
EXPECT_EQ(enum_val_cap.count, 3);
for (uint32_t i = 0; i < enum_val_cap.count; i++)
{
if (enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_ALL ||
enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_NONE ||
enum_val_cap.list[i] == SAI_VLAN_FLOOD_CONTROL_TYPE_L2MC_GROUP)
{
flood_types_found++;
}
}
EXPECT_EQ(flood_types_found, 3);
}
TEST(SwitchBCM56850, test_nexthop_group_type_enum_values_capability)
{
auto sc = std::make_shared<SwitchConfig>(0, "");
auto signal = std::make_shared<Signal>();
auto eventQueue = std::make_shared<EventQueue>(signal);
sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
sc->m_useTapDevice = false;
sc->m_laneMap = LaneMap::getDefaultLaneMap(0);
sc->m_eventQueue = eventQueue;
auto scc = std::make_shared<SwitchConfigContainer>();
scc->insert(sc);
SwitchBCM56850 sw(
0x2100000000,
std::make_shared<RealObjectIdManager>(0, scc),
sc);
sai_s32_list_t enum_val_cap;
int32_t list[5];
memset(list, 0, sizeof(list));
enum_val_cap.count = 4;
enum_val_cap.list = list;
EXPECT_EQ(sw.queryAttrEnumValuesCapability(0x2100000000,
SAI_OBJECT_TYPE_NEXT_HOP_GROUP,
SAI_NEXT_HOP_GROUP_ATTR_TYPE,
&enum_val_cap),
SAI_STATUS_BUFFER_OVERFLOW);
enum_val_cap.count = 5;
EXPECT_EQ(sw.queryAttrEnumValuesCapability(0x2100000000,
SAI_OBJECT_TYPE_NEXT_HOP_GROUP,
SAI_NEXT_HOP_GROUP_ATTR_TYPE,
&enum_val_cap),
SAI_STATUS_SUCCESS);
EXPECT_EQ(enum_val_cap.count, 5);
int nexthop_group_types_found = 0;
for (uint32_t i = 0; i < enum_val_cap.count; i++)
{
if (enum_val_cap.list[i] == SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP ||
enum_val_cap.list[i] == SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_ORDERED_ECMP ||
enum_val_cap.list[i] == SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP ||
enum_val_cap.list[i] == SAI_NEXT_HOP_GROUP_TYPE_PROTECTION ||
enum_val_cap.list[i] == SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED)
{
nexthop_group_types_found++;
}
}
EXPECT_EQ(nexthop_group_types_found, 5);
}
TEST(SwitchBCM56850, test_port_autoneg_fec_override_support)
{
auto sc = std::make_shared<SwitchConfig>(0, "");
auto signal = std::make_shared<Signal>();
auto eventQueue = std::make_shared<EventQueue>(signal);
sc->m_saiSwitchType = SAI_SWITCH_TYPE_NPU;
sc->m_switchType = SAI_VS_SWITCH_TYPE_BCM56850;
sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
sc->m_useTapDevice = false;
sc->m_laneMap = LaneMap::getDefaultLaneMap(0);
sc->m_eventQueue = eventQueue;
auto scc = std::make_shared<SwitchConfigContainer>();
scc->insert(sc);
SwitchBCM56850 sw(
0x2100000000,
std::make_shared<RealObjectIdManager>(0, scc),
sc);
sai_attr_capability_t attr_capability;
EXPECT_EQ(sw.queryAttributeCapability(0x2100000000,
SAI_OBJECT_TYPE_PORT,
SAI_PORT_ATTR_AUTO_NEG_FEC_MODE_OVERRIDE,
&attr_capability),
SAI_STATUS_SUCCESS);
EXPECT_EQ(attr_capability.create_implemented, false);
EXPECT_EQ(attr_capability.set_implemented, false);
EXPECT_EQ(attr_capability.get_implemented, false);
}