diff --git a/orchagent/orch.h b/orchagent/orch.h index 5e8939c53f..a76be09972 100644 --- a/orchagent/orch.h +++ b/orchagent/orch.h @@ -243,6 +243,8 @@ class Orch virtual void doTask(swss::NotificationConsumer &consumer) { } virtual void doTask(swss::SelectableTimer &timer) { } + virtual void onWarmBootEnd() { } + void dumpPendingTasks(std::vector &ts); /** diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 0604174f0b..62a6ae1e8c 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -928,6 +928,8 @@ void OrchDaemon::start() */ bool OrchDaemon::warmRestoreAndSyncUp() { + SWSS_LOG_ENTER(); + WarmStart::setWarmStartState("orchagent", WarmStart::INITIALIZED); for (Orch *o : m_orchList) @@ -990,8 +992,10 @@ bool OrchDaemon::warmRestoreAndSyncUp() syncd_apply_view(); - /* Start dynamic state sync up */ - gPortsOrch->refreshPortStatus(); + for (Orch *o : m_orchList) + { + o->onWarmBootEnd(); + } /* * Note. Arp sync up is handled in neighsyncd. diff --git a/orchagent/p4orch/tests/fake_portorch.cpp b/orchagent/p4orch/tests/fake_portorch.cpp index d3f4c5b29b..23acc528d8 100644 --- a/orchagent/p4orch/tests/fake_portorch.cpp +++ b/orchagent/p4orch/tests/fake_portorch.cpp @@ -425,24 +425,11 @@ void PortsOrch::removeDefaultBridgePorts() { } -bool PortsOrch::initializePort(Port &port) -{ - return true; -} - -void PortsOrch::initializePriorityGroups(Port &port) -{ -} - void PortsOrch::initializePortBufferMaximumParameters(Port &port) { } -void PortsOrch::initializeQueues(Port &port) -{ -} - -bool PortsOrch::addHostIntfs(Port &port, string alias, sai_object_id_t &host_intfs_id) +bool PortsOrch::addHostIntfs(Port &port, string alias, sai_object_id_t &host_intfs_id, bool up) { return true; } @@ -507,7 +494,7 @@ sai_status_t PortsOrch::removePort(sai_object_id_t port_id) return SAI_STATUS_SUCCESS; } -bool PortsOrch::initPort(const PortConfig &port) +bool PortsOrch::initExistingPort(const PortConfig &port) { return true; } @@ -707,3 +694,7 @@ std::unordered_set PortsOrch::generateCounterStats(const vector void PortsOrch::doTask(swss::SelectableTimer &timer) { } + +void PortsOrch::onWarmBootEnd() +{ +} diff --git a/orchagent/port.h b/orchagent/port.h index 1c7c34999f..1d4384d408 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -18,12 +18,15 @@ extern "C" { #include #define DEFAULT_PORT_VLAN_ID 1 + +#define MAX_MACSEC_SECTAG_SIZE 32 + /* * Default MTU is derived from SAI_PORT_ATTR_MTU (1514) * Orchagent adds extra 22 bytes for Ethernet header and FCS, * hence setting to 1492 (1514 - 22) */ -#define DEFAULT_MTU 1492 +#define DEFAULT_MTU 1492 - MAX_MACSEC_SECTAG_SIZE /* * Default TPID is 8100 @@ -265,6 +268,8 @@ class Port uint32_t m_suppress_threshold = 0; uint32_t m_reuse_threshold = 0; uint32_t m_flap_penalty = 0; + + Role m_role; }; } diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 02fdf8927a..93d50ede83 100644 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -35,6 +35,7 @@ #include "subscriberstatetable.h" #include "saitam.h" +#include "warm_restart.h" extern sai_switch_api_t *sai_switch_api; extern sai_bridge_api_t *sai_bridge_api; @@ -90,6 +91,50 @@ struct PortAttrValue typedef PortAttrValue PortAttrValue_t; typedef std::map> PortSerdesAttrMap_t; +struct PortBulker +{ + std::vector oids; + std::vector attrCount; + std::vector attrList; + std::vector statuses; + + uint32_t count; + + PortBulker(uint32_t size) : + oids(size), + attrCount(size, 1), + attrList(size), + statuses(size, SAI_STATUS_NOT_EXECUTED), + count(0) + { + } + + void add(sai_object_id_t oid, sai_attribute_t& attr) + { + oids[count] = oid; + attrList[count] = attr; + count++; + } + + void executeGet(sai_bulk_op_error_mode_t errorMode = SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR) + { + if (count == 0) + { + return; + } + + std::vector attrs(count); + + for (size_t idx = 0; idx < count; idx++) + { + attrs[idx] = &attrList[idx]; + } + + sai_port_api->get_ports_attribute(count, oids.data(), attrCount.data(), + attrs.data(), errorMode, statuses.data()); + } +}; + // constants ---------------------------------------------------------------------------------------------------------- static map learn_mode_map = @@ -959,7 +1004,7 @@ void PortsOrch::setPortConfigState(port_config_state_t value) this->m_portConfigState = value; } -bool PortsOrch::addPortBulk(const std::vector &portList) +bool PortsOrch::addPortBulk(const std::vector &portList, std::vector& addedPorts) { // The method is used to create ports in a bulk mode. // The action takes place when: @@ -973,6 +1018,8 @@ bool PortsOrch::addPortBulk(const std::vector &portList) return true; } + addedPorts.reserve(portList.size()); + std::vector attrValueList; std::vector> attrDataList; std::vector attrCountList; @@ -987,6 +1034,12 @@ bool PortsOrch::addPortBulk(const std::vector &portList) sai_attribute_t attr; std::vector attrList; + addedPorts.emplace_back(cit.key, Port::PHY); + auto& p = addedPorts.back(); + + p.m_role = cit.role.value; + p.m_index = cit.index.value; + if (cit.lanes.is_set) { PortAttrValue_t attrValue; @@ -1006,6 +1059,7 @@ bool PortsOrch::addPortBulk(const std::vector &portList) attr.id = SAI_PORT_ATTR_SPEED; attr.value.u32 = cit.speed.value; attrList.push_back(attr); + p.m_speed = cit.speed.value; } if (cit.autoneg.is_set) @@ -1013,6 +1067,7 @@ bool PortsOrch::addPortBulk(const std::vector &portList) attr.id = SAI_PORT_ATTR_AUTO_NEG_MODE; attr.value.booldata = cit.autoneg.value; attrList.push_back(attr); + p.m_autoneg = cit.autoneg.value; } if (cit.fec.is_set) @@ -1140,6 +1195,7 @@ bool PortsOrch::addPortBulk(const std::vector &portList) } m_portListLaneMap[portList.at(i).lanes.value] = oidList.at(i); + addedPorts.at(i).m_port_id = oidList.at(i); m_portCount++; } @@ -1804,25 +1860,6 @@ bool PortsOrch::getPortAdminStatus(sai_object_id_t id, bool &up) return true; } -bool PortsOrch::getPortHostTxReady(const Port& port, bool &hostTxReadyVal) -{ - SWSS_LOG_ENTER(); - - sai_attribute_t attr; - attr.id = SAI_PORT_ATTR_HOST_TX_READY_STATUS; - - sai_status_t status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); - if (status != SAI_STATUS_SUCCESS) - { - hostTxReadyVal = false; - return false; - } - - hostTxReadyVal = attr.value.s32; - - return true; -} - bool PortsOrch::getPortMtu(const Port& port, sai_uint32_t &mtu) { SWSS_LOG_ENTER(); @@ -1883,7 +1920,6 @@ bool PortsOrch::setPortMtu(const Port& port, sai_uint32_t mtu) return true; } - bool PortsOrch::setPortTpid(Port &port, sai_uint16_t tpid) { SWSS_LOG_ENTER(); @@ -2720,7 +2756,6 @@ void PortsOrch::initPortSupportedSpeeds(const std::string& alias, sai_object_id_ m_portStateTable.set(alias, v); } - void PortsOrch::initPortCapAutoNeg(Port &port) { sai_status_t status; @@ -3492,7 +3527,7 @@ string PortsOrch::getPriorityGroupDropPacketsFlexCounterTableKey(string key) return string(PG_DROP_STAT_COUNTER_FLEX_COUNTER_GROUP) + ":" + key; } -bool PortsOrch::initPort(const PortConfig &port) +bool PortsOrch::initExistingPort(const PortConfig& port) { SWSS_LOG_ENTER(); @@ -3501,96 +3536,156 @@ bool PortsOrch::initPort(const PortConfig &port) const auto &index = port.index.value; const auto &lane_set = port.lanes.value; + /* Determine if the port has already been initialized before */ + auto it = m_portList.find(alias); + if (it != m_portList.end()) + { + SWSS_LOG_DEBUG("Port has already been initialized before alias:%s", alias.c_str()); + return true; + } + /* Determine if the lane combination exists in switch */ - if (m_portListLaneMap.find(lane_set) != m_portListLaneMap.end()) + if (m_portListLaneMap.find(lane_set) == m_portListLaneMap.end()) { - sai_object_id_t id = m_portListLaneMap[lane_set]; + SWSS_LOG_ERROR("Failed to locate port lane combination alias:%s", alias.c_str()); + return false; + } - /* Determine if the port has already been initialized before */ - if (m_portList.find(alias) != m_portList.end() && m_portList[alias].m_port_id == id) - { - SWSS_LOG_DEBUG("Port has already been initialized before alias:%s", alias.c_str()); - } - else - { - Port p(alias, Port::PHY); + sai_object_id_t id = m_portListLaneMap[lane_set]; - p.m_index = index; - p.m_port_id = id; + Port p(alias, Port::PHY); + p.m_role = role; + p.m_index = index; + p.m_port_id = id; - /* Initialize the port and create corresponding host interface */ - if (initializePort(p)) - { - /* Create associated Gearbox lane mapping */ - initGearboxPort(p); + /* initialize port admin status */ + if (!getPortAdminStatus(p.m_port_id, p.m_admin_state_up)) + { + SWSS_LOG_ERROR("Failed to get initial port admin status %s", p.m_alias.c_str()); + return false; + } - /* Add port to port list */ - m_portList[alias] = p; - saiOidToAlias[id] = alias; - m_port_ref_count[alias] = 0; - m_portOidToIndex[id] = index; + // Read port speed of an already existing port + if (!isAutoNegEnabled(p.m_port_id) && !getPortSpeed(p.m_port_id, p.m_speed)) + { + SWSS_LOG_ERROR("Failed to get initial port admin speed %d", p.m_speed); + return false; + } - /* Add port name map to counter table */ - FieldValueTuple tuple(p.m_alias, sai_serialize_object_id(p.m_port_id)); - vector fields; - fields.push_back(tuple); - m_counterTable->set("", fields); + /* initialize port mtu */ + if (!getPortMtu(p, p.m_mtu)) + { + SWSS_LOG_ERROR("Failed to get initial port mtu %d", p.m_mtu); + } - // Install a flex counter for this port to track stats - auto flex_counters_orch = gDirectory.get(); - /* Delay installing the counters if they are yet enabled - If they are enabled, install the counters immediately */ - if (flex_counters_orch->getPortCountersState()) - { - auto port_counter_stats = generateCounterStats(port_stat_ids, sai_serialize_port_stat); - port_stat_manager.setCounterIdList(p.m_port_id, - CounterType::PORT, port_counter_stats); - auto gbport_counter_stats = generateCounterStats(gbport_stat_ids, sai_serialize_port_stat); - if (p.m_system_side_id) - gb_port_stat_manager.setCounterIdList(p.m_system_side_id, - CounterType::PORT, gbport_counter_stats, p.m_switch_id); - if (p.m_line_side_id) - gb_port_stat_manager.setCounterIdList(p.m_line_side_id, - CounterType::PORT, gbport_counter_stats, p.m_switch_id); - } - if (flex_counters_orch->getPortBufferDropCountersState()) - { - auto port_buffer_drop_stats = generateCounterStats(port_buffer_drop_stat_ids, sai_serialize_port_stat); - port_buffer_drop_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_buffer_drop_stats); - } + return initPortsBulk({p}); +} + +bool PortsOrch::initPortsBulk(std::vector ports) +{ + SWSS_LOG_ENTER(); - PortUpdate update = { p, true }; - notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); + bool warmStart = WarmStart::isWarmStart(); - m_portList[alias].m_init = true; + bool status = true; - if (role == Port::Role::Rec || role == Port::Role::Inb) - { - m_recircPortRole[alias] = role; - } + SWSS_LOG_TIMER(__FUNCTION__); - // We have to test the size of m_queue_ids here since it isn't initialized on some platforms (like DPU) - if (p.m_host_tx_queue_configured && p.m_queue_ids.size() > p.m_host_tx_queue) - { - createPortBufferQueueCounters(p, to_string(p.m_host_tx_queue), false); - } + if (!initializePorts(ports)) + { + status = false; + } - SWSS_LOG_NOTICE("Initialized port %s", alias.c_str()); - } - else - { - SWSS_LOG_ERROR("Failed to initialize port %s", alias.c_str()); - return false; - } + for (auto& p: ports) + { + const auto& alias = p.m_alias; + + registerPort(p); + + if (!warmStart) + { + postPortInit(m_portList[alias]); } + + SWSS_LOG_NOTICE("Initialized port %s", alias.c_str()); } - else + + return status; +} + +void PortsOrch::registerPort(Port &p) +{ + SWSS_LOG_ENTER(); + + const auto &alias = p.m_alias; + const auto &role = p.m_role; + const auto &index = p.m_index; + const auto id = p.m_port_id; + + /* Create associated Gearbox lane mapping */ + initGearboxPort(p); + + /* Add port to port list */ + m_portList[alias] = p; + saiOidToAlias[id] = alias; + m_port_ref_count[alias] = 0; + m_portOidToIndex[id] = index; + + /* Add port name map to counter table */ + FieldValueTuple tuple(p.m_alias, sai_serialize_object_id(p.m_port_id)); + vector fields; + fields.push_back(tuple); + m_counterTable->set("", fields); + + // Install a flex counter for this port to track stats + auto flex_counters_orch = gDirectory.get(); + /* Delay installing the counters if they are yet enabled + If they are enabled, install the counters immediately */ + if (flex_counters_orch->getPortCountersState()) + { + auto port_counter_stats = generateCounterStats(port_stat_ids, sai_serialize_port_stat); + port_stat_manager.setCounterIdList(p.m_port_id, + CounterType::PORT, port_counter_stats); + auto gbport_counter_stats = generateCounterStats(gbport_stat_ids, sai_serialize_port_stat); + if (p.m_system_side_id) + gb_port_stat_manager.setCounterIdList(p.m_system_side_id, + CounterType::PORT, gbport_counter_stats, p.m_switch_id); + if (p.m_line_side_id) + gb_port_stat_manager.setCounterIdList(p.m_line_side_id, + CounterType::PORT, gbport_counter_stats, p.m_switch_id); + } + if (flex_counters_orch->getPortBufferDropCountersState()) { - SWSS_LOG_ERROR("Failed to locate port lane combination alias:%s", alias.c_str()); - return false; + auto port_buffer_drop_stats = generateCounterStats(port_buffer_drop_stat_ids, sai_serialize_port_stat); + port_buffer_drop_stat_manager.setCounterIdList(p.m_port_id, CounterType::PORT, port_buffer_drop_stats); } - return true; + PortUpdate update = { p, true }; + notify(SUBJECT_TYPE_PORT_CHANGE, static_cast(&update)); + + m_portList[alias].m_init = true; + + if (role == Port::Role::Rec || role == Port::Role::Inb) + { + m_recircPortRole[alias] = role; + } +} + +void PortsOrch::postPortInit(Port& p) +{ + SWSS_LOG_ENTER(); + + initializeSchedulerGroups(p); + initializePortBufferMaximumParameters(p); + + initPortSupportedSpeeds(p.m_alias, p.m_port_id); + initPortSupportedFecModes(p.m_alias, p.m_port_id); + + // We have to test the size of m_queue_ids here since it isn't initialized on some platforms (like DPU) + if (p.m_host_tx_queue_configured && p.m_queue_ids.size() > p.m_host_tx_queue) + { + createPortBufferQueueCounters(p, to_string(p.m_host_tx_queue), false); + } } void PortsOrch::deInitPort(string alias, sai_object_id_t port_id) @@ -3929,7 +4024,7 @@ void PortsOrch::doPortTask(Consumer &consumer) // TODO: // Fix the issue below // After PortConfigDone, while waiting for "PortInitDone" and the first gBufferOrch->isPortReady(alias), - // the complete m_lanesAliasSpeedMap may be populated again, so initPort() will be called more than once + // the complete m_lanesAliasSpeedMap may be populated again, so initExistingPort() will be called more than once // for the same port. /* Once all ports received, go through the each port and perform appropriate actions: @@ -3974,38 +4069,26 @@ void PortsOrch::doPortTask(Consumer &consumer) continue; } - if (!initPort(it->second)) + if (!initExistingPort(it->second)) { - // Failure has been recorded in initPort + // Failure has been recorded in initExistingPort it++; continue; } - initPortSupportedSpeeds(it->second.key, m_portListLaneMap[it->first]); - initPortSupportedFecModes(it->second.key, m_portListLaneMap[it->first]); - it++; } // Bulk port add if (!portsToAddList.empty()) { - if (!addPortBulk(portsToAddList)) + std::vector addedPorts; + if (!addPortBulk(portsToAddList, addedPorts)) { SWSS_LOG_THROW("PortsOrch initialization failure"); } - for (const auto &cit : portsToAddList) - { - if (!initPort(cit)) - { - // Failure has been recorded in initPort - continue; - } - - initPortSupportedSpeeds(cit.key, m_portListLaneMap[cit.lanes.value]); - initPortSupportedFecModes(cit.key, m_portListLaneMap[cit.lanes.value]); - } + initPortsBulk(addedPorts); } setPortConfigState(PORT_CONFIG_DONE); @@ -5615,6 +5698,25 @@ void PortsOrch::doTask() } } +void PortsOrch::onWarmBootEnd() +{ + SWSS_LOG_ENTER(); + + /* Start dynamic state sync up */ + refreshPortStatus(); + + // Do post boot port initialization + for (auto& it: m_portList) + { + Port& port = it.second; + + if (port.m_type == Port::PHY) + { + postPortInit(it.second); + } + } +} + void PortsOrch::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -5706,48 +5808,147 @@ void PortsOrch::initializeVoqs(Port &port) SWSS_LOG_INFO("Get voqs for port %s", port.m_alias.c_str()); } -void PortsOrch::initializeQueues(Port &port) +bool PortsOrch::initializePorts(std::vector& ports) { SWSS_LOG_ENTER(); - sai_attribute_t attr; - attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES; - sai_status_t status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); - if (status != SAI_STATUS_SUCCESS) + bool status = true; + + if (gMySwitchType != "dpu") { - SWSS_LOG_ERROR("Failed to get number of queues for port %s rv:%d", port.m_alias.c_str(), status); - task_process_status handle_status = handleSaiGetStatus(SAI_API_PORT, status); - if (handle_status != task_process_status::task_success) + initializePriorityGroupsBulk(ports); + initializeQueuesBulk(ports); + } + + /* initialize port host_tx_ready value (only for supporting systems) */ + if (m_cmisModuleAsicSyncSupported) + { + initializePortHostTxReadyBulk(ports); + } + + // Create host interfaces + for (auto iter = ports.begin(); iter != ports.end();) + { + Port& port = *iter; + + /* Check warm start states */ + vector tuples; + bool exist = m_portTable->get(port.m_alias, tuples); + string operStatus, flapCount = "0"; + if (exist) { - throw runtime_error("PortsOrch initialization failure."); + for (auto i : tuples) + { + if (fvField(i) == "oper_status") + { + operStatus = fvValue(i); + } + + if (fvField(i) == "flap_count") + { + flapCount = fvValue(i); + } + } + } + + SWSS_LOG_INFO("Port %s with oper %s flap_count=%s", port.m_alias.c_str(), operStatus.c_str(), flapCount.c_str()); + + /** + * Create database port oper status as DOWN if attr missing + * This status will be updated upon receiving port_oper_status_notification. + */ + if (operStatus == "up") + { + port.m_oper_status = SAI_PORT_OPER_STATUS_UP; + } + else if (operStatus.empty()) + { + port.m_oper_status = SAI_PORT_OPER_STATUS_DOWN; + /* Fill oper_status in db with default value "down" */ + m_portTable->hset(port.m_alias, "oper_status", "down"); + } + else + { + port.m_oper_status = SAI_PORT_OPER_STATUS_DOWN; + } + + // initalize port flap count + if (!flapCount.empty()) + { + try + { + port.m_flap_count = stoull(flapCount); + m_portTable->hset(port.m_alias, "flap_count", flapCount); + } + catch (const std::exception &e) + { + SWSS_LOG_ERROR("Failed to get port (%s) flap_count: %s", port.m_alias.c_str(), e.what()); + } } + + /* + * always initialize Port SAI_HOSTIF_ATTR_OPER_STATUS based on oper_status value in appDB. + */ + bool isUp = port.m_oper_status == SAI_PORT_OPER_STATUS_UP; + + /* Create host interface */ + if (!addHostIntfs(port, port.m_alias, port.m_hif_id, isUp)) + { + SWSS_LOG_ERROR("Failed to create host interface for port %s", port.m_alias.c_str()); + iter = ports.erase(iter); + status = false; + continue; + } + + iter++; } - SWSS_LOG_INFO("Get %d queues for port %s", attr.value.u32, port.m_alias.c_str()); - port.m_queue_ids.resize(attr.value.u32); - port.m_queue_lock.resize(attr.value.u32); + return status; +} - if (attr.value.u32 == 0) +void PortsOrch::initializePortHostTxReadyBulk(std::vector& ports) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_TIMER(__FUNCTION__); + + const auto portCount = static_cast(ports.size()); + + PortBulker bulker(portCount); + + for (auto& port: ports) { - return; + sai_attribute_t attr; + attr.id = SAI_PORT_ATTR_HOST_TX_READY_STATUS; + bulker.add(port.m_port_id, attr); } - attr.id = SAI_PORT_ATTR_QOS_QUEUE_LIST; - attr.value.objlist.count = (uint32_t)port.m_queue_ids.size(); - attr.value.objlist.list = port.m_queue_ids.data(); + bulker.executeGet(); - status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); - if (status != SAI_STATUS_SUCCESS) + size_t idx = 0; + for (auto& port: ports) { - SWSS_LOG_ERROR("Failed to get queue list for port %s rv:%d", port.m_alias.c_str(), status); - task_process_status handle_status = handleSaiGetStatus(SAI_API_PORT, status); - if (handle_status != task_process_status::task_success) + const auto status = bulker.statuses[idx]; + const auto& attr = bulker.attrList[idx]; + + idx++; + + bool hostTxReady = false; + + if (status == SAI_STATUS_SUCCESS) { - throw runtime_error("PortsOrch initialization failure."); + hostTxReady = attr.value.booldata; } - } + else + { + SWSS_LOG_ERROR("Failed to get host_tx_ready value from SAI to Port %" PRIx64 , port.m_port_id); + } + + string hostTxReadyStr = hostTxReady ? "true" : "false"; - SWSS_LOG_INFO("Get queues for port %s", port.m_alias.c_str()); + SWSS_LOG_DEBUG("Received host_tx_ready current status: port_id: 0x%" PRIx64 " status: %s", port.m_port_id, hostTxReadyStr.c_str()); + setHostTxReady(port, hostTxReadyStr); + } } void PortsOrch::initializeSchedulerGroups(Port &port) @@ -5794,198 +5995,194 @@ void PortsOrch::initializeSchedulerGroups(Port &port) SWSS_LOG_INFO("Got scheduler groups for port %s", port.m_alias.c_str()); } -void PortsOrch::initializePriorityGroups(Port &port) +void PortsOrch::initializePriorityGroupsBulk(std::vector& ports) { SWSS_LOG_ENTER(); - sai_attribute_t attr; - attr.id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS; - sai_status_t status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); - if (status != SAI_STATUS_SUCCESS) + SWSS_LOG_TIMER(__FUNCTION__); + + const auto portCount = static_cast(ports.size()); + + // Query number of ingress priority groups { - SWSS_LOG_ERROR("Failed to get number of priority groups for port %s rv:%d", port.m_alias.c_str(), status); - task_process_status handle_status = handleSaiGetStatus(SAI_API_PORT, status); - if (handle_status != task_process_status::task_success) + PortBulker bulker(portCount); + + for (const auto& port: ports) { - throw runtime_error("PortsOrch initialization failure."); + sai_attribute_t attr; + attr.id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS; + bulker.add(port.m_port_id, attr); } - } - SWSS_LOG_INFO("Get %d priority groups for port %s", attr.value.u32, port.m_alias.c_str()); - port.m_priority_group_ids.resize(attr.value.u32); + bulker.executeGet(); - if (attr.value.u32 == 0) - { - return; - } + size_t idx = 0; + for (auto& port: ports) + { + const auto status = bulker.statuses[idx]; + const auto& attr = bulker.attrList[idx]; - attr.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST; - attr.value.objlist.count = (uint32_t)port.m_priority_group_ids.size(); - attr.value.objlist.list = port.m_priority_group_ids.data(); + idx++; - status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); - if (status != SAI_STATUS_SUCCESS) + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to get number of priority groups for port %s rv:%d", port.m_alias.c_str(), status); + handleSaiGetStatus(SAI_API_PORT, status); + throw runtime_error("PortsOrch initialization failure."); + } + + SWSS_LOG_INFO("Get %d priority groups for port %s", attr.value.u32, port.m_alias.c_str()); + port.m_priority_group_ids.resize(attr.value.u32); + } + } + + // Query ingress priority groups lists { - SWSS_LOG_ERROR("Fail to get priority group list for port %s rv:%d", port.m_alias.c_str(), status); - task_process_status handle_status = handleSaiGetStatus(SAI_API_PORT, status); - if (handle_status != task_process_status::task_success) + PortBulker bulker(portCount); + + for (auto& port: ports) { - throw runtime_error("PortsOrch initialization failure."); + sai_attribute_t attr; + + if (port.m_priority_group_ids.size() == 0) + { + continue; + } + + attr.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST; + attr.value.objlist.list = port.m_priority_group_ids.data(); + attr.value.objlist.count = static_cast(port.m_priority_group_ids.size()); + bulker.add(port.m_port_id, attr); } - } - SWSS_LOG_INFO("Get priority groups for port %s", port.m_alias.c_str()); -} -void PortsOrch::initializePortBufferMaximumParameters(Port &port) -{ - sai_attribute_t attr; - vector fvVector; + bulker.executeGet(); - attr.id = SAI_PORT_ATTR_QOS_MAXIMUM_HEADROOM_SIZE; + size_t idx = 0; + for (auto& port: ports) + { + const auto status = bulker.statuses[idx]; - sai_status_t status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); - if (status != SAI_STATUS_SUCCESS) - { - SWSS_LOG_NOTICE("Unable to get the maximum headroom for port %s rv:%d, ignored", port.m_alias.c_str(), status); - } - else - { - port.m_maximum_headroom = attr.value.u32; - fvVector.emplace_back("max_headroom_size", to_string(port.m_maximum_headroom)); - } + idx++; - fvVector.emplace_back("max_priority_groups", to_string(port.m_priority_group_ids.size())); - fvVector.emplace_back("max_queues", to_string(port.m_queue_ids.size())); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Fail to get priority group list for port %s rv:%d", port.m_alias.c_str(), status); + handleSaiGetStatus(SAI_API_PORT, status); + throw runtime_error("PortsOrch initialization failure."); + } - m_stateBufferMaximumValueTable->set(port.m_alias, fvVector); + SWSS_LOG_INFO("Get priority groups for port %s", port.m_alias.c_str()); + } + } } -bool PortsOrch::initializePort(Port &port) +void PortsOrch::initializeQueuesBulk(std::vector& ports) { SWSS_LOG_ENTER(); - SWSS_LOG_NOTICE("Initializing port alias:%s pid:%" PRIx64, port.m_alias.c_str(), port.m_port_id); + SWSS_LOG_TIMER(__FUNCTION__); - if (gMySwitchType != "dpu") - { - initializePriorityGroups(port); - initializeQueues(port); - initializeSchedulerGroups(port); - initializePortBufferMaximumParameters(port); - } + const auto portCount = static_cast(ports.size()); - /* Create host interface */ - if (!addHostIntfs(port, port.m_alias, port.m_hif_id)) + // Query number of queues { - SWSS_LOG_ERROR("Failed to create host interface for port %s", port.m_alias.c_str()); - return false; - } + PortBulker bulker(portCount); - /* Check warm start states */ - vector tuples; - bool exist = m_portTable->get(port.m_alias, tuples); - string operStatus, flapCount = "0"; - if (exist) - { - for (auto i : tuples) + for (auto& port: ports) { - if (fvField(i) == "oper_status") - { - operStatus = fvValue(i); - } + sai_attribute_t attr; + attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES; + bulker.add(port.m_port_id, attr); + } + + bulker.executeGet(); - if (fvField(i) == "flap_count") + size_t idx = 0; + for (auto& port: ports) + { + const auto status = bulker.statuses[idx]; + const auto& attr = bulker.attrList[idx]; + + idx++; + + if (status != SAI_STATUS_SUCCESS) { - flapCount = fvValue(i); + SWSS_LOG_ERROR("Failed to get number of queues for port %s rv:%d", port.m_alias.c_str(), status); + handleSaiGetStatus(SAI_API_PORT, status); + throw runtime_error("PortsOrch initialization failure."); } + + SWSS_LOG_INFO("Get %d queues for port %s", attr.value.u32, port.m_alias.c_str()); + port.m_queue_ids.resize(attr.value.u32); + port.m_queue_lock.resize(attr.value.u32); } } - SWSS_LOG_INFO("Port %s with oper %s flap_count=%s", port.m_alias.c_str(), operStatus.c_str(), flapCount.c_str()); - /** - * Create database port oper status as DOWN if attr missing - * This status will be updated upon receiving port_oper_status_notification. - */ - if (operStatus == "up") - { - port.m_oper_status = SAI_PORT_OPER_STATUS_UP; - } - else if (operStatus.empty()) - { - port.m_oper_status = SAI_PORT_OPER_STATUS_DOWN; - /* Fill oper_status in db with default value "down" */ - m_portTable->hset(port.m_alias, "oper_status", "down"); - } - else + // Query queue lists { - port.m_oper_status = SAI_PORT_OPER_STATUS_DOWN; - } + PortBulker bulker(portCount); - // initalize port flap count - if (!flapCount.empty()) - { - try + for (auto& port: ports) { - port.m_flap_count = stoull(flapCount); - m_portTable->hset(port.m_alias, "flap_count", flapCount); + sai_attribute_t attr; + + if (port.m_queue_ids.size() == 0) + { + continue; + } + + attr.id = SAI_PORT_ATTR_QOS_QUEUE_LIST; + attr.value.objlist.list = port.m_queue_ids.data(); + attr.value.objlist.count = static_cast(port.m_queue_ids.size()); + bulker.add(port.m_port_id, attr); } - catch (const std::exception &e) + + bulker.executeGet(); + + size_t idx = 0; + for (auto& port: ports) { - SWSS_LOG_ERROR("Failed to get port (%s) flap_count: %s", port.m_alias.c_str(), e.what()); - } - } + const auto status = bulker.statuses[idx]; - /* initialize port admin status */ - if (!getPortAdminStatus(port.m_port_id, port.m_admin_state_up)) - { - SWSS_LOG_ERROR("Failed to get initial port admin status %s", port.m_alias.c_str()); - return false; - } + idx++; - /* initialize port admin speed */ - if (!isAutoNegEnabled(port.m_port_id) && !getPortSpeed(port.m_port_id, port.m_speed)) - { - SWSS_LOG_ERROR("Failed to get initial port admin speed %d", port.m_speed); - return false; - } + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Fail to get queue list for port %s rv:%d", port.m_alias.c_str(), status); + handleSaiGetStatus(SAI_API_PORT, status); + throw runtime_error("PortsOrch initialization failure."); + } - /* initialize port mtu */ - if (!getPortMtu(port, port.m_mtu)) - { - SWSS_LOG_ERROR("Failed to get initial port mtu %d", port.m_mtu); + SWSS_LOG_INFO("Get queues for port %s", port.m_alias.c_str()); + } } +} - /* initialize port host_tx_ready value (only for supporting systems) */ - if (m_cmisModuleAsicSyncSupported) - { - bool hostTxReadyVal; - if (!getPortHostTxReady(port, hostTxReadyVal)) - { - SWSS_LOG_ERROR("Failed to get host_tx_ready value from SAI to Port %" PRIx64 , port.m_port_id); - } - /* set value to state DB */ +void PortsOrch::initializePortBufferMaximumParameters(Port &port) +{ + sai_attribute_t attr; + vector fvVector; - string hostTxReadyStr = hostTxReadyVal ? "true" : "false"; + attr.id = SAI_PORT_ATTR_QOS_MAXIMUM_HEADROOM_SIZE; - SWSS_LOG_DEBUG("Received host_tx_ready current status: port_id: 0x%" PRIx64 " status: %s", port.m_port_id, hostTxReadyStr.c_str()); - setHostTxReady(port, hostTxReadyStr); + sai_status_t status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_NOTICE("Unable to get the maximum headroom for port %s rv:%d, ignored", port.m_alias.c_str(), status); } - - /* - * always initialize Port SAI_HOSTIF_ATTR_OPER_STATUS based on oper_status value in appDB. - */ - bool isUp = port.m_oper_status == SAI_PORT_OPER_STATUS_UP; - if (!setHostIntfsOperStatus(port, isUp)) + else { - SWSS_LOG_WARN("Failed to set operation status %s to host interface %s", - operStatus.c_str(), port.m_alias.c_str()); - return false; + port.m_maximum_headroom = attr.value.u32; + fvVector.emplace_back("max_headroom_size", to_string(port.m_maximum_headroom)); } - return true; + fvVector.emplace_back("max_priority_groups", to_string(port.m_priority_group_ids.size())); + fvVector.emplace_back("max_queues", to_string(port.m_queue_ids.size())); + + m_stateBufferMaximumValueTable->set(port.m_alias, fvVector); } -bool PortsOrch::addHostIntfs(Port &port, string alias, sai_object_id_t &host_intfs_id) +bool PortsOrch::addHostIntfs(Port &port, string alias, sai_object_id_t &host_intfs_id, bool up) { SWSS_LOG_ENTER(); @@ -6019,6 +6216,13 @@ bool PortsOrch::addHostIntfs(Port &port, string alias, sai_object_id_t &host_int port.m_host_tx_queue_configured = true; } + if (up) + { + attr.id = SAI_HOSTIF_ATTR_OPER_STATUS; + attr.value.booldata = up; + attrs.push_back(attr); + } + sai_status_t status = sai_hostif_api->create_hostif(&host_intfs_id, gSwitchId, (uint32_t)attrs.size(), attrs.data()); if (status != SAI_STATUS_SUCCESS) { @@ -6030,6 +6234,15 @@ bool PortsOrch::addHostIntfs(Port &port, string alias, sai_object_id_t &host_int } } + if (up) + { + SWSS_LOG_NOTICE("Set operation status %s to host interface %s", + up ? "UP" : "DOWN", port.m_alias.c_str()); + + event_params_t params = {{"ifname",port.m_alias},{"status", up ? "up" : "down"}}; + event_publish(g_events_handle, "if-state", ¶ms); + } + SWSS_LOG_NOTICE("Create host interface for port %s", alias.c_str()); return true; diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index a7edf3b4e5..6ea314f466 100644 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -23,7 +23,6 @@ #define FCS_LEN 4 #define VLAN_TAG_LEN 4 -#define MAX_MACSEC_SECTAG_SIZE 32 #define PORT_STAT_COUNTER_FLEX_COUNTER_GROUP "PORT_STAT_COUNTER" #define PORT_RATE_COUNTER_FLEX_COUNTER_GROUP "PORT_RATE_COUNTER" #define PORT_BUFFER_DROP_STAT_FLEX_COUNTER_GROUP "PORT_BUFFER_DROP_STAT" @@ -358,6 +357,7 @@ class PortsOrch : public Orch, public Subject bool m_cmisModuleAsicSyncSupported = false; void doTask() override; + void onWarmBootEnd() override; void doTask(Consumer &consumer); void doPortTask(Consumer &consumer); void doSendToIngressPortTask(Consumer &consumer); @@ -375,14 +375,17 @@ class PortsOrch : public Orch, public Subject void removeDefaultVlanMembers(); void removeDefaultBridgePorts(); - bool initializePort(Port &port); - void initializePriorityGroups(Port &port); + bool initializePorts(std::vector& ports); + + void initializePriorityGroupsBulk(std::vector& ports); + void initializeQueuesBulk(std::vector& ports); + void initializePortHostTxReadyBulk(std::vector& ports); + void initializePortBufferMaximumParameters(Port &port); - void initializeQueues(Port &port); void initializeSchedulerGroups(Port &port); void initializeVoqs(Port &port); - bool addHostIntfs(Port &port, string alias, sai_object_id_t &host_intfs_id); + bool addHostIntfs(Port &port, string alias, sai_object_id_t &host_intfs_id, bool up = false); bool setHostIntfsStripTag(Port &port, sai_hostif_vlan_tag_t strip); bool setBridgePortLearnMode(Port &port, sai_bridge_port_fdb_learning_mode_t learn_mode); @@ -399,7 +402,14 @@ class PortsOrch : public Orch, public Subject bool setDistributionOnLagMember(Port &lagMember, bool enableDistribution); sai_status_t removePort(sai_object_id_t port_id); - bool initPort(const PortConfig &port); + bool initExistingPort(const PortConfig &port); + + bool initPortsBulk(std::vector ports); + + void registerPort(Port &p); + + void postPortInit(Port &p); + void deInitPort(string alias, sai_object_id_t port_id); void initPortCapAutoNeg(Port &port); @@ -544,7 +554,7 @@ class PortsOrch : public Orch, public Subject auto getPortConfigState() const -> port_config_state_t; void setPortConfigState(port_config_state_t value); - bool addPortBulk(const std::vector &portList); + bool addPortBulk(const std::vector &portList, std::vector& addedPorts); bool removePortBulk(const std::vector &portList); /* Prototypes for Path Tracing */