in vslib/Sai.cpp [60:282]
sai_status_t Sai::apiInitialize(
_In_ uint64_t flags,
_In_ const sai_service_method_table_t *service_method_table)
{
MUTEX();
SWSS_LOG_ENTER();
if (m_apiInitialized)
{
SWSS_LOG_ERROR("%s: api already initialized", __PRETTY_FUNCTION__);
return SAI_STATUS_FAILURE;
}
if (flags != 0)
{
SWSS_LOG_ERROR("invalid flags passed to SAI API initialize");
return SAI_STATUS_INVALID_PARAMETER;
}
if ((service_method_table == NULL) ||
(service_method_table->profile_get_next_value == NULL) ||
(service_method_table->profile_get_value == NULL))
{
SWSS_LOG_ERROR("invalid service_method_table handle passed to SAI API initialize");
return SAI_STATUS_INVALID_PARAMETER;
}
memcpy(&m_service_method_table, service_method_table, sizeof(m_service_method_table));
auto switch_type = service_method_table->profile_get_value(0, SAI_KEY_VS_SWITCH_TYPE);
if (switch_type == NULL)
{
SWSS_LOG_ERROR("failed to obtain service method table value: %s", SAI_KEY_VS_SWITCH_TYPE);
return SAI_STATUS_FAILURE;
}
auto sai_switch_type = service_method_table->profile_get_value(0, SAI_KEY_VS_SAI_SWITCH_TYPE);
sai_switch_type_t saiSwitchType;
if (sai_switch_type == NULL)
{
SWSS_LOG_NOTICE("failed to obtain service method table value: %s", SAI_KEY_VS_SAI_SWITCH_TYPE);
saiSwitchType = SAI_SWITCH_TYPE_NPU;
}
else if (!SwitchConfig::parseSaiSwitchType(sai_switch_type, saiSwitchType))
{
return SAI_STATUS_FAILURE;
}
auto *laneMapFile = service_method_table->profile_get_value(0, SAI_KEY_VS_INTERFACE_LANE_MAP_FILE);
m_laneMapContainer = LaneMapFileParser::parseLaneMapFile(laneMapFile);
auto *fabricLaneMapFile = service_method_table->profile_get_value(0, SAI_KEY_VS_INTERFACE_FABRIC_LANE_MAP_FILE);
if (fabricLaneMapFile)
{
m_fabricLaneMapContainer = LaneMapFileParser::parseLaneMapFile(fabricLaneMapFile);
}
auto *corePortIndexMapFile = service_method_table->profile_get_value(0, SAI_KEY_VS_CORE_PORT_INDEX_MAP_FILE);
m_corePortIndexMapContainer = CorePortIndexMapFileParser::parseCorePortIndexMapFile(corePortIndexMapFile);
auto *resourceLimiterFile = service_method_table->profile_get_value(0, SAI_KEY_VS_RESOURCE_LIMITER_FILE);
m_resourceLimiterContainer = ResourceLimiterParser::parseFromFile(resourceLimiterFile);
auto boot_type = service_method_table->profile_get_value(0, SAI_KEY_BOOT_TYPE);
m_warm_boot_read_file = service_method_table->profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE);
m_warm_boot_write_file = service_method_table->profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE);
sai_vs_boot_type_t bootType;
if (!SwitchConfig::parseBootType(boot_type, bootType))
{
return SAI_STATUS_FAILURE;
}
sai_vs_switch_type_t switchType;
if (!SwitchConfig::parseSwitchType(switch_type, switchType))
{
return SAI_STATUS_FAILURE;
}
const char *use_tap_dev = service_method_table->profile_get_value(0, SAI_KEY_VS_HOSTIF_USE_TAP_DEVICE);
auto useTapDevice = SwitchConfig::parseBool(use_tap_dev);
SWSS_LOG_NOTICE("hostif use TAP device: %s", (useTapDevice ? "true" : "false"));
const char *use_configured_speed_as_oper_speed = service_method_table->profile_get_value(0, SAI_KEY_VS_USE_CONFIGURED_SPEED_AS_OPER_SPEED);
auto useConfiguredSpeedAsOperSpeed = SwitchConfig::parseBool(use_configured_speed_as_oper_speed);
SWSS_LOG_NOTICE("use configured speed as oper speed: %s", (useConfiguredSpeedAsOperSpeed ? "true" : "false"));
auto cstrGlobalContext = service_method_table->profile_get_value(0, SAI_KEY_VS_GLOBAL_CONTEXT);
m_globalContext = 0;
if (cstrGlobalContext != nullptr)
{
if (sscanf(cstrGlobalContext, "%u", &m_globalContext) != 1)
{
SWSS_LOG_WARN("failed to parse '%s' as uint32 using default globalContext", cstrGlobalContext);
m_globalContext = 0;
}
}
SWSS_LOG_NOTICE("using globalContext = %u", m_globalContext);
auto cstrContextConfig = service_method_table->profile_get_value(0, SAI_KEY_VS_CONTEXT_CONFIG);
auto ccc = ContextConfigContainer::loadFromFile(cstrContextConfig);
for (auto& cc: ccc->getAllContextConfigs())
{
auto context = std::make_shared<Context>(cc);
m_contextMap[cc->m_guid] = context;
}
auto context = getContext(m_globalContext);
if (context == nullptr)
{
SWSS_LOG_ERROR("no context defined for global context %u", m_globalContext);
return SAI_STATUS_FAILURE;
}
auto contextConfig = context->getContextConfig();
auto scc = contextConfig->m_scc;
if (scc->getSwitchConfigs().size() == 0)
{
SWSS_LOG_WARN("no switch configs defined, using default switch config");
auto sc = std::make_shared<SwitchConfig>(0, "");
scc->insert(sc);
}
// TODO currently switch configuration will share signal and event queue
// but it should be moved to Context class
m_signal = std::make_shared<Signal>();
m_eventQueue = std::make_shared<EventQueue>(m_signal);
for (auto& sc: scc->getSwitchConfigs())
{
// NOTE: switch index and hardware info is already populated
sc->m_saiSwitchType = saiSwitchType;
sc->m_switchType = switchType;
sc->m_bootType = bootType;
sc->m_useTapDevice = useTapDevice;
sc->m_useConfiguredSpeedAsOperSpeed = useConfiguredSpeedAsOperSpeed;
sc->m_laneMap = m_laneMapContainer->getLaneMap(sc->m_switchIndex);
if (sc->m_laneMap == nullptr)
{
SWSS_LOG_WARN("lane map for switch index %u is empty, loading default map (may have ifname conflict)", sc->m_switchIndex);
sc->m_laneMap = LaneMap::getDefaultLaneMap(sc->m_switchIndex);
}
if (m_fabricLaneMapContainer)
{
sc->m_fabricLaneMap = m_fabricLaneMapContainer->getLaneMap(sc->m_switchIndex);
}
sc->m_eventQueue = m_eventQueue;
sc->m_resourceLimiter = m_resourceLimiterContainer->getResourceLimiter(sc->m_switchIndex);
sc->m_corePortIndexMap = m_corePortIndexMapContainer->getCorePortIndexMap(sc->m_switchIndex);
}
// most important
// TODO move to Context class
m_vsSai = std::make_shared<VirtualSwitchSaiInterface>(contextConfig);
m_meta = std::make_shared<saimeta::Meta>(m_vsSai);
m_vsSai->setMeta(m_meta);
if (bootType == SAI_VS_BOOT_TYPE_WARM)
{
if (!m_vsSai->readWarmBootFile(m_warm_boot_read_file))
{
SWSS_LOG_WARN("failed to read warm boot read file, switching to COLD BOOT");
for (auto& sc: scc->getSwitchConfigs())
{
sc->m_bootType = SAI_VS_BOOT_TYPE_COLD;
}
}
}
startEventQueueThread();
startUnittestThread();
if (saiSwitchType == SAI_SWITCH_TYPE_NPU)
{
startFdbAgingThread();
}
m_apiInitialized = true;
return SAI_STATUS_SUCCESS;
}