From 8f615d04d04fdf2e46cf57f6982814eb22f28a55 Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Tue, 28 Jan 2025 05:27:41 -0800 Subject: [PATCH 01/11] Update YANG tree nodes to add vport leaf Signed-off-by: Sabeel Ansari --- stratum/hal/lib/yang/BUILD | 1 + stratum/hal/lib/yang/CMakeLists.txt | 3 +- stratum/hal/lib/yang/yang_parse_tree.cc | 7 ++ stratum/hal/lib/yang/yang_parse_tree.h | 4 + stratum/hal/lib/yang/yang_parse_tree_paths.h | 7 +- .../lib/yang/yang_parse_tree_virtual_port.cc | 82 +++++++++++++++++++ 6 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc diff --git a/stratum/hal/lib/yang/BUILD b/stratum/hal/lib/yang/BUILD index c59ed866a..a6ab89b43 100644 --- a/stratum/hal/lib/yang/BUILD +++ b/stratum/hal/lib/yang/BUILD @@ -78,6 +78,7 @@ stratum_cc_library( "yang_parse_tree_paths.cc", "yang_parse_tree_singleton.cc", "yang_parse_tree_system.cc", + "yang_parse_tree_virtual_port.cc", ], hdrs = [ "yang_parse_tree.h", diff --git a/stratum/hal/lib/yang/CMakeLists.txt b/stratum/hal/lib/yang/CMakeLists.txt index b812ad5ad..ed1f1ba21 100644 --- a/stratum/hal/lib/yang/CMakeLists.txt +++ b/stratum/hal/lib/yang/CMakeLists.txt @@ -1,6 +1,6 @@ # Build file for //stratum/hal/lib/yang # -# Copyright 2022-2024 Intel Corporation +# Copyright 2022-2025 Intel Corporation # SPDX-License-Identifier: Apache 2.0 # @@ -25,6 +25,7 @@ add_library(stratum_yang_parse_tree_o OBJECT yang_parse_tree_paths.h yang_parse_tree_singleton.cc yang_parse_tree_system.cc + yang_parse_tree_virtual_port.cc ) if(NOT DPDK_TARGET) diff --git a/stratum/hal/lib/yang/yang_parse_tree.cc b/stratum/hal/lib/yang/yang_parse_tree.cc index 2d2213de6..58d4dfc49 100644 --- a/stratum/hal/lib/yang/yang_parse_tree.cc +++ b/stratum/hal/lib/yang/yang_parse_tree.cc @@ -1,5 +1,6 @@ // Copyright 2018 Google LLC // Copyright 2018-present Open Networking Foundation +// Copyright 2022-2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "stratum/hal/lib/yang/yang_parse_tree.h" @@ -179,6 +180,8 @@ void YangParseTree::ProcessPushedConfig( AddSubtreeSystem(); // Add all IPsec-related gNMI paths. AddSubtreeIPsec(); + // Add all VirtualPort-related gNMI paths. + AddSubtreeVirtualPort(); // Add all node-related gNMI paths. for (const auto& node : change.new_config_.nodes()) { AddSubtreeNode(node); @@ -330,6 +333,10 @@ void YangParseTree::AddSubtreeIPsec() { YangParseTreePaths::AddSubtreeIPsec(this); } +void YangParseTree::AddSubtreeVirtualPort() { + YangParseTreePaths::AddSubtreeVirtualPort(this); +} + void YangParseTree::AddSubtreeAllInterfaces() { // No need to lock the mutex - it is locked by the method calling this one. diff --git a/stratum/hal/lib/yang/yang_parse_tree.h b/stratum/hal/lib/yang/yang_parse_tree.h index 25d3d78a7..11f170a4f 100644 --- a/stratum/hal/lib/yang/yang_parse_tree.h +++ b/stratum/hal/lib/yang/yang_parse_tree.h @@ -1,5 +1,6 @@ // Copyright 2018 Google LLC // Copyright 2018-present Open Networking Foundation +// Copyright 2022-2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef STRATUM_HAL_LIB_YANG_YANG_PARSE_TREE_H_ @@ -462,6 +463,9 @@ class YangParseTree { // Add supported leaf handles for IPsec. void AddSubtreeIPsec() EXCLUSIVE_LOCKS_REQUIRED(root_access_lock_); + // Add supported leaf handles for VirtualPort. + void AddSubtreeVirtualPort() EXCLUSIVE_LOCKS_REQUIRED(root_access_lock_); + // Configure the root element. void AddRoot() EXCLUSIVE_LOCKS_REQUIRED(root_access_lock_); diff --git a/stratum/hal/lib/yang/yang_parse_tree_paths.h b/stratum/hal/lib/yang/yang_parse_tree_paths.h index 643c9cd58..a95d2b04f 100644 --- a/stratum/hal/lib/yang/yang_parse_tree_paths.h +++ b/stratum/hal/lib/yang/yang_parse_tree_paths.h @@ -1,5 +1,6 @@ // Copyright 2018 Google LLC // Copyright 2018-present Open Networking Foundation +// Copyright 2022-2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef STRATUM_HAL_LIB_YANG_YANG_PARSE_TREE_PATHS_H_ @@ -52,10 +53,14 @@ class YangParseTreePaths { static void AddSubtreeSystem(YangParseTree* tree) EXCLUSIVE_LOCKS_REQUIRED(tree->root_access_lock_); - // Adds all supported paths for the specified system. + // Adds all supported paths for the specified IPsec. static void AddSubtreeIPsec(YangParseTree* tree) EXCLUSIVE_LOCKS_REQUIRED(tree->root_access_lock_); + // Adds all supported paths for the specified VirtualPort. + static void AddSubtreeVirtualPort(YangParseTree* tree) + EXCLUSIVE_LOCKS_REQUIRED(tree->root_access_lock_); + // Adds all supported wildcard interface-related paths. static void AddSubtreeAllInterfaces(YangParseTree* tree) EXCLUSIVE_LOCKS_REQUIRED(tree->root_access_lock_); diff --git a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc new file mode 100644 index 000000000..809bf2106 --- /dev/null +++ b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc @@ -0,0 +1,82 @@ +// Copyright 2025 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +// Implements the YangParseTreePaths::AddSubtreeVirtualPort() method and its +// supporting functions. + +#include "gnmi/gnmi.pb.h" +#include "stratum/glue/logging.h" +#include "stratum/glue/status/status_macros.h" +#include "stratum/hal/lib/common/gnmi_events.h" +#include "stratum/hal/lib/common/gnmi_publisher.h" +#include "stratum/hal/lib/common/utils.h" +#include "stratum/hal/lib/yang/yang_parse_tree.h" +#include "stratum/hal/lib/yang/yang_parse_tree_helpers.h" +#include "stratum/hal/lib/yang/yang_parse_tree_paths.h" + +namespace stratum { +namespace hal { + +using namespace stratum::hal::yang::helpers; + +namespace { + +//////////////////////////////////////////////////////////////////////////////// +// /virtual-ports/virtual-port/state/vsi +void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { + + auto poll_functor = [tree](const GnmiEvent& event, const ::gnmi::Path& path, + GnmiSubscribeStream* stream) { + // Create a data retrieval request. + DataRequest req; + auto* request = req.add_requests()->mutable_vport_vsi(); + // In-place definition of method retrieving data from generic response + // and saving into 'resp' local variable. + uint32 resp{}; + DataResponseWriter writer([&resp](const DataResponse& in) { + if (!in.has_vport_vsi()) return false; + resp = in.vport_vsi().vsi(); + return true; + }); + // Query the switch. The returned status is ignored as there is no way to + // notify the controller that something went wrong. The error is logged when + // it is created. + tree->GetSwitchInterface() + ->RetrieveValue(/*node_id*/ 0, req, &writer, /* details= */ nullptr) + .IgnoreError(); + return SendResponse(GetResponse(path, resp), stream); + }; + auto on_change_functor = UnsupportedFunc(); + node->SetOnPollHandler(poll_functor) + ->SetOnTimerHandler(poll_functor) + ->SetOnChangeHandler(on_change_functor); +} + +//////////////////////////////////////////////////////////////////////////////// +// /virtual-ports/virtual-port/state/oper-status +void SetUpVirtualPortFetchOperStatus(TreeNode* node, YangParseTree* tree) { + + // -- return unsupported func + auto poll_functor = UnsupportedFunc(); + node->SetOnTimerHandler(poll_functor) + ->SetOnPollHandler(poll_functor) + ->SetOnChangeHandler(poll_functor); + +} + +} // namespace + +////////////////////////////// +// AddSubtreeVirtualPort // +////////////////////////////// + +void YangParseTreePaths::AddSubtreeVirtualPort(YangParseTree* tree) { + TreeNode* node = + tree->AddNode(GetPath("virtual-ports")("virtual-port")("state")("vsi")()); + SetUpVirtualPortFetchVSI(node, tree); + node = tree->AddNode(GetPath("virtual-ports")("virtual-port")("state")("oper-status")()); + SetUpVirtualPortFetchOperStatus(node, tree); +} + +} // namespace hal +} // namespace stratum From 759919c393e2fab5ba8f7fcb1fdb92666c394fb6 Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Tue, 28 Jan 2025 07:30:13 -0800 Subject: [PATCH 02/11] Add common.proto entries for message exchange via SwitchInterface Signed-off-by: Sabeel Ansari --- stratum/hal/lib/common/common.proto | 13 +++++++++++++ stratum/hal/lib/tdi/es2k/es2k_switch.cc | 11 +++++++++++ .../hal/lib/yang/yang_parse_tree_virtual_port.cc | 1 - 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/stratum/hal/lib/common/common.proto b/stratum/hal/lib/common/common.proto index e7e7d6f82..87e6a713c 100644 --- a/stratum/hal/lib/common/common.proto +++ b/stratum/hal/lib/common/common.proto @@ -1564,6 +1564,15 @@ message IPsecOffloadInfo { int32 spi = 1; } +// VirtualPortInfo is used in DataRequest and DataResponse to retrieve the +// values from target. +message VirtualPortInfo { + uint32 global_resource_id = 1; + uint32 vsi = 2; + OperStatus oper_status = 3; +} + + // DataRequest is a message used internally to request data about a component // or a set of components through SwitchInterface. It is specifically used in // ConfigMonitoringService, as part of gNMI Get/Subscribe RPC implementation. @@ -1618,6 +1627,8 @@ message DataRequest { Port sdn_port_id = 22; Port target_dp_id = 23; IPsecOffloadInfo ipsec_offload_info = 24; + VirtualPortInfo vport_vsi = 25; + VirtualPortInfo vport_oper_status = 26; } } repeated Request requests = 1; @@ -1664,6 +1675,8 @@ message DataResponse { TargetDatapathId target_dp_id = 34; PacketDirValue packet_dir = 35; IPsecOffloadInfo ipsec_offload_info = 36; + VirtualPortInfo vport_vsi = 37; + VirtualPortInfo vport_oper_status = 38; } } diff --git a/stratum/hal/lib/tdi/es2k/es2k_switch.cc b/stratum/hal/lib/tdi/es2k/es2k_switch.cc index 51caff0e1..cfccd6863 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_switch.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_switch.cc @@ -244,6 +244,17 @@ ::util::Status Es2kSwitch::RetrieveValue(uint64 node_id, } break; } + // VirtualPort data request + case DataRequest::Request::kVportVsi: + case DataRequest::Request::kVportOperStatus: { +// auto vport_data = chassis_manager_->GetPortData(req); +// if (!vport_data.ok()) { +// status.Update(vport_data.status()); +// } else { +// resp = vport_data.ConsumeValueOrDie(); +// } + break; + } default: status = MAKE_ERROR(ERR_UNIMPLEMENTED) diff --git a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc index 809bf2106..a8ec4f3aa 100644 --- a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc +++ b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc @@ -24,7 +24,6 @@ namespace { //////////////////////////////////////////////////////////////////////////////// // /virtual-ports/virtual-port/state/vsi void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { - auto poll_functor = [tree](const GnmiEvent& event, const ::gnmi::Path& path, GnmiSubscribeStream* stream) { // Create a data retrieval request. From a742fd567fc2fff5a4822b4fadb9e4f5e9a50c80 Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Tue, 28 Jan 2025 12:13:10 -0800 Subject: [PATCH 03/11] Add es2k & tdi vport managers Signed-off-by: Sabeel Ansari --- stratum/hal/bin/tdi/es2k/es2k_main.cc | 9 +- stratum/hal/lib/tdi/CMakeLists.txt | 4 +- stratum/hal/lib/tdi/es2k/CMakeLists.txt | 4 +- .../hal/lib/tdi/es2k/es2k_chassis_manager.cc | 18 +- .../hal/lib/tdi/es2k/es2k_chassis_manager.h | 15 +- .../lib/tdi/es2k/es2k_virtual_port_manager.cc | 198 ++++++++++++++++++ .../lib/tdi/es2k/es2k_virtual_port_manager.h | 81 +++++++ .../hal/lib/tdi/tdi_virtual_port_manager.cc | 37 ++++ .../hal/lib/tdi/tdi_virtual_port_manager.h | 97 +++++++++ 9 files changed, 451 insertions(+), 12 deletions(-) create mode 100644 stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc create mode 100644 stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h create mode 100644 stratum/hal/lib/tdi/tdi_virtual_port_manager.cc create mode 100644 stratum/hal/lib/tdi/tdi_virtual_port_manager.h diff --git a/stratum/hal/bin/tdi/es2k/es2k_main.cc b/stratum/hal/bin/tdi/es2k/es2k_main.cc index 0f77a0443..78ebe4aad 100644 --- a/stratum/hal/bin/tdi/es2k/es2k_main.cc +++ b/stratum/hal/bin/tdi/es2k/es2k_main.cc @@ -1,6 +1,6 @@ // Copyright 2018-2019 Barefoot Networks, Inc. // Copyright 2020-present Open Networking Foundation -// Copyright 2022-2024 Intel Corporation +// Copyright 2022-2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include @@ -31,6 +31,7 @@ #include "stratum/hal/lib/tdi/tdi_packetio_manager.h" #include "stratum/hal/lib/tdi/tdi_pre_manager.h" #include "stratum/hal/lib/tdi/tdi_table_manager.h" +#include "stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h" #include "stratum/lib/macros.h" #include "stratum/lib/security/auth_policy_checker.h" #include "stratum/lib/security/credentials_manager.h" @@ -142,7 +143,11 @@ ::util::Status Main(absl::Notification* ready_sync, auto port_manager = Es2kPortManager::CreateSingleton(); - auto chassis_manager = Es2kChassisManager::CreateInstance(mode, port_manager); + auto virtual_port_manager = Es2kVirtualPortManager::CreateSingleton(); + + auto chassis_manager = Es2kChassisManager::CreateInstance(mode, + port_manager, + virtual_port_manager); auto ipsec_manager = TdiIpsecManager::CreateInstance( sde_wrapper, fixed_function_manager.get()); diff --git a/stratum/hal/lib/tdi/CMakeLists.txt b/stratum/hal/lib/tdi/CMakeLists.txt index 6e6ee8e9d..092068fea 100644 --- a/stratum/hal/lib/tdi/CMakeLists.txt +++ b/stratum/hal/lib/tdi/CMakeLists.txt @@ -1,6 +1,6 @@ # Build file for //stratum/hal/lib/tdi # -# Copyright 2022-2024 Intel Corporation +# Copyright 2022-2025 Intel Corporation # SPDX-License-Identifier: Apache 2.0 # @@ -48,6 +48,8 @@ add_library(stratum_tdi_common_o OBJECT tdi_sde_wrapper.h tdi_table_manager.cc tdi_table_manager.h + tdi_virtual_port_manager.cc + tdi_virtual_port_manager.h utils.cc utils.h ) diff --git a/stratum/hal/lib/tdi/es2k/CMakeLists.txt b/stratum/hal/lib/tdi/es2k/CMakeLists.txt index 7e2b7b381..3252cfe00 100644 --- a/stratum/hal/lib/tdi/es2k/CMakeLists.txt +++ b/stratum/hal/lib/tdi/es2k/CMakeLists.txt @@ -1,6 +1,6 @@ # Build file for //stratum/hal/lib/tdi/es2k # -# Copyright 2022-2023 Intel Corporation +# Copyright 2022-2023,2025 Intel Corporation # SPDX-License-Identifier: Apache 2.0 # @@ -24,4 +24,6 @@ target_sources(stratum_tdi_target_o PRIVATE es2k_sde_wrapper.cc es2k_switch.cc es2k_switch.h + es2k_virtual_port_manager.cc + es2k_virtual_port_manager.h ) diff --git a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc index d1dd05778..42888d6c0 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc @@ -20,6 +20,7 @@ #include "stratum/hal/lib/common/utils.h" #include "stratum/hal/lib/common/writer_interface.h" #include "stratum/hal/lib/tdi/es2k/es2k_port_manager.h" +#include "stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h" #include "stratum/hal/lib/tdi/tdi_global_vars.h" #include "stratum/lib/channel/channel.h" #include "stratum/lib/constants.h" @@ -38,7 +39,8 @@ constexpr int Es2kChassisManager::kMaxPortStatusEventDepth; constexpr int Es2kChassisManager::kMaxXcvrEventDepth; Es2kChassisManager::Es2kChassisManager(OperationMode mode, - Es2kPortManager* es2k_port_manager) + Es2kPortManager* es2k_port_manager, + Es2kVirtualPortManager* es2k_virtual_port_manager) : mode_(mode), initialized_(false), port_status_event_channel_(nullptr), @@ -52,7 +54,8 @@ Es2kChassisManager::Es2kChassisManager(OperationMode mode, node_id_to_port_id_to_sdk_port_id_(), node_id_to_sdk_port_id_to_port_id_(), xcvr_port_key_to_xcvr_state_(), - es2k_port_manager_(ABSL_DIE_IF_NULL(es2k_port_manager)) {} + es2k_port_manager_(ABSL_DIE_IF_NULL(es2k_port_manager)), + es2k_virtual_port_manager_(ABSL_DIE_IF_NULL(es2k_virtual_port_manager)) {} Es2kChassisManager::Es2kChassisManager() : mode_(OPERATION_MODE_STANDALONE), @@ -68,7 +71,8 @@ Es2kChassisManager::Es2kChassisManager() node_id_to_port_id_to_sdk_port_id_(), node_id_to_sdk_port_id_to_port_id_(), xcvr_port_key_to_xcvr_state_(), - es2k_port_manager_(nullptr) {} + es2k_port_manager_(nullptr), + es2k_virtual_port_manager_(nullptr) {} Es2kChassisManager::~Es2kChassisManager() = default; @@ -863,8 +867,12 @@ ::util::Status Es2kChassisManager::ReplayChassisConfig(uint64 node_id) { } std::unique_ptr Es2kChassisManager::CreateInstance( - OperationMode mode, Es2kPortManager* es2k_port_manager) { - return absl::WrapUnique(new Es2kChassisManager(mode, es2k_port_manager)); + OperationMode mode, + Es2kPortManager* es2k_port_manager, + Es2kVirtualPortManager* es2k_virtual_port_manager) { + return absl::WrapUnique(new Es2kChassisManager(mode, + es2k_port_manager, + es2k_virtual_port_manager)); } void Es2kChassisManager::SendPortOperStateGnmiEvent( diff --git a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h index 579818f10..17cd3ac79 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h +++ b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h @@ -1,5 +1,5 @@ // Copyright 2018-present Barefoot Networks, Inc. -// Copyright 2022-2023 Intel Corporation +// Copyright 2022-2023,2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef STRATUM_HAL_LIB_TDI_ES2K_CHASSIS_MANAGER_H_ @@ -19,6 +19,7 @@ #include "stratum/hal/lib/common/writer_interface.h" #include "stratum/hal/lib/tdi/tdi_global_vars.h" #include "stratum/hal/lib/tdi/tdi_port_manager.h" +#include "stratum/hal/lib/tdi/tdi_virtual_port_manager.h" #include "stratum/lib/channel/channel.h" namespace stratum { @@ -26,6 +27,7 @@ namespace hal { namespace tdi { class Es2kPortManager; +class Es2kVirtualPortManager; // Lock which protects chassis state across the entire switch. extern absl::Mutex chassis_lock; @@ -71,7 +73,9 @@ class Es2kChassisManager { // Factory function for creating the instance of the class. static std::unique_ptr CreateInstance( - OperationMode mode, Es2kPortManager* es2k_port_manager); + OperationMode mode, + Es2kPortManager* es2k_port_manager, + Es2kVirtualPortManager* es2k_virtual_port_manager); // Es2kChassisManager is neither copyable nor movable. Es2kChassisManager(const Es2kChassisManager&) = delete; @@ -111,7 +115,9 @@ class Es2kChassisManager { // Private constructor. Use CreateInstance() to create an instance of this // class. - Es2kChassisManager(OperationMode mode, Es2kPortManager* es2k_port_manager); + Es2kChassisManager(OperationMode mode, + Es2kPortManager* es2k_port_manager, + Es2kVirtualPortManager* es2k_virtual_port_manager); ::util::StatusOr GetPortConfig(uint64 node_id, uint32 port_id) const @@ -253,6 +259,9 @@ class Es2kChassisManager { // Pointer to an Es2kPortManager implementation that wraps the SDE calls. Es2kPortManager* es2k_port_manager_; // not owned by this class. + // Pointer to an Es2kVirtualPortManager implementation that wraps the SDE calls. + Es2kVirtualPortManager* es2k_virtual_port_manager_; // not owned by this class. + friend class Es2kChassisManagerTest; }; diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc new file mode 100644 index 000000000..b2843f1cf --- /dev/null +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc @@ -0,0 +1,198 @@ +// Copyright 2019-present Barefoot Networks, Inc. +// Copyright 2022-2025 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +// ES2K-specific virtual port methods. + +#include "stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h" + +#include +#include + +#include +#include +#include +#include + +#include "absl/memory/memory.h" +#include "absl/synchronization/mutex.h" +#include "absl/time/clock.h" +#include "absl/time/time.h" +#include "stratum/glue/integral_types.h" +#include "stratum/glue/logging.h" +#include "stratum/glue/status/status.h" +#include "stratum/glue/status/status_macros.h" +#include "stratum/glue/status/statusor.h" +#include "stratum/hal/lib/common/common.pb.h" +#include "stratum/hal/lib/common/utils.h" +#include "stratum/hal/lib/tdi/tdi_sde_common.h" +#include "stratum/hal/lib/tdi/tdi_status.h" +#include "stratum/lib/channel/channel.h" + +extern "C" { +#include "ipu_pal/port_intf.h" +#include "ipu_types/ipu_types.h" +} + +namespace stratum { +namespace hal { +namespace tdi { + +Es2kVirtualPortManager* Es2kVirtualPortManager::singleton_ = nullptr; + +namespace { + +// A callback function executed in SDE port state change thread context. +ipu_status_t sde_port_status_callback(ipu_dev_id_t device, + ipu_dev_port_t dev_port, bool up, + void* cookie) { + absl::Time timestamp = absl::Now(); + Es2kVirtualPortManager* es2k_port_manager = Es2kVirtualPortManager::GetSingleton(); + if (!es2k_port_manager) { + LOG(ERROR) << "Es2kVirtualPortManager singleton instance is not initialized."; + return IPU_INTERNAL_ERROR; + } + // Forward the event. + auto status = + es2k_port_manager->OnPortStatusEvent(device, dev_port, up, timestamp); + + return status.ok() ? IPU_SUCCESS : IPU_INTERNAL_ERROR; +} + +} // namespace + +Es2kVirtualPortManager* Es2kVirtualPortManager::CreateSingleton() { + absl::WriterMutexLock l(&init_lock_); + if (!singleton_) { + singleton_ = new Es2kVirtualPortManager(); + } + + return singleton_; +} + +Es2kVirtualPortManager* Es2kVirtualPortManager::GetSingleton() { + absl::ReaderMutexLock l(&init_lock_); + return singleton_; +} + +::util::StatusOr Es2kVirtualPortManager::GetPortState(int device, + int port) { + // Unsupported. Returns PORT_STATE_DOWN if called. + return PORT_STATE_DOWN; +} + +::util::Status Es2kVirtualPortManager::GetPortCounters(int device, int port, + PortCounters* counters) { + uint64_t stats[TDI_PORT_NUM_COUNTERS] = {0}; + + return ::util::OkStatus(); +} + +::util::Status Es2kVirtualPortManager::OnPortStatusEvent(int device, int port, bool up, + absl::Time timestamp) { + // Create PortStatusEvent message. + PortState state = up ? PORT_STATE_UP : PORT_STATE_DOWN; + PortStatusEvent event = {device, port, state, timestamp}; + + { + absl::ReaderMutexLock l(&port_status_event_writer_lock_); + if (!port_status_event_writer_) { + return ::util::OkStatus(); + } + return port_status_event_writer_->Write(event, kWriteTimeout); + } +} + +::util::Status Es2kVirtualPortManager::GetPortInfo(int device, int port, + TargetDatapathId* target_dp_id) { + return ::util::OkStatus(); +} + +// TODO: Check with Sandeep which Add port is applicable or do we really +// need it since we don't add port for MEV +::util::Status Es2kVirtualPortManager::AddPort(int device, int port) { + return ::util::OkStatus(); +} + +::util::Status Es2kVirtualPortManager::AddPort(int device, int port, uint64 speed_bps, + FecMode fec_mode) { + auto port_attrs = absl::make_unique(); + RETURN_IF_TDI_ERROR(ipu_pal_port_add(static_cast(device), + static_cast(port), + port_attrs.get())); + return ::util::OkStatus(); +} + +::util::Status Es2kVirtualPortManager::DeletePort(int device, int port) { + RETURN_IF_TDI_ERROR(ipu_pal_port_del(static_cast(device), + static_cast(port))); + return ::util::OkStatus(); +} + +::util::Status Es2kVirtualPortManager::EnablePort(int device, int port) { + return ::util::OkStatus(); +} + +::util::Status Es2kVirtualPortManager::DisablePort(int device, int port) { + return ::util::OkStatus(); +} + +::util::Status Es2kVirtualPortManager::EnablePortShaping(int device, int port, + TriState enable) { + return ::util::OkStatus(); +} + +::util::Status Es2kVirtualPortManager::SetPortAutonegPolicy(int device, int port, + TriState autoneg) { + return ::util::OkStatus(); +} + +::util::Status Es2kVirtualPortManager::SetPortMtu(int device, int port, int32 mtu) { + return ::util::OkStatus(); +} + +bool Es2kVirtualPortManager::IsValidPort(int device, int port) { return IPU_SUCCESS; } + +::util::Status Es2kVirtualPortManager::SetPortLoopbackMode( + int device, int port, LoopbackState loopback_mode) { + if (loopback_mode == LOOPBACK_STATE_UNKNOWN) { + // Do nothing if we try to set loopback mode to the default one (UNKNOWN). + return ::util::OkStatus(); + } + return ::util::OkStatus(); +} + +// TODO: Check with Sandeep: Is this required? +::util::StatusOr Es2kVirtualPortManager::GetPortIdFromPortKey( + int device, const PortKey& port_key) { + const int port = port_key.port; + RET_CHECK(port >= 0) << "Port ID must be non-negative. Attempted to get port " + << port << " on dev " << device << "."; + + // PortKey uses three possible values for channel: + // > 0: port is channelized (first channel is 1) + // 0: port is not channelized + // < 0: port channel is not important (e.g. for port groups) + // BF SDK expects the first channel to be 0 + // Convert base-1 channel to base-0 channel if port is channelized + // Otherwise, port is already 0 in the non-channelized case + const int channel = + (port_key.channel > 0) ? port_key.channel - 1 : port_key.channel; + RET_CHECK(channel >= 0) << "Channel must be set for port " << port + << " on dev " << device << "."; + + char port_string[MAX_PORT_HDL_STRING_LEN]; + int r = snprintf(port_string, sizeof(port_string), "%d/%d", port, channel); + RET_CHECK(r > 0 && r < sizeof(port_string)) + << "Failed to build port string for port " << port << " channel " + << channel << " on dev " << device << "."; + + ipu_dev_port_t dev_port; + RETURN_IF_TDI_ERROR(ipu_pal_port_str_to_dev_port_map( + static_cast(device), port_string, &dev_port)); + return static_cast(dev_port); +} + +} // namespace tdi +} // namespace hal +} // namespace stratum diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h new file mode 100644 index 000000000..e04760d6a --- /dev/null +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h @@ -0,0 +1,81 @@ +// Copyright 2020-present Open Networking Foundation +// Copyright 2022-2025 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#ifndef STRATUM_HAL_LIB_TDI_ES2K_VIRTUAL_PORT_MANAGER_H_ +#define STRATUM_HAL_LIB_TDI_ES2K_VIRTUAL_PORT_MANAGER_H_ + +#include +#include +#include +#include + +#include "absl/synchronization/mutex.h" +#include "stratum/hal/lib/tdi/tdi_virtual_port_manager.h" + +// Suppress clang errors +#undef LOCKS_EXCLUDED +#define LOCKS_EXCLUDED(...) + +namespace stratum { +namespace hal { +namespace tdi { + +class Es2kVirtualPortManager : public TdiVirtualPortManager { + public: + Es2kVirtualPortManager() {} + virtual ~Es2kVirtualPortManager() {} + + // ---------- Common public methods ---------- + + ::util::Status GetPortInfo(int device, int port, + TargetDatapathId* target_dp_id); + ::util::StatusOr GetPortState(int device, int port); + ::util::Status GetPortCounters(int device, int port, PortCounters* counters); + ::util::StatusOr GetPortIdFromPortKey(int device, + const PortKey& port_key); + bool IsValidPort(int device, int port); + ::util::Status AddPort(int device, int port); + ::util::Status DeletePort(int device, int port); + ::util::Status EnablePort(int device, int port); + ::util::Status DisablePort(int device, int port); + + // ---------- ES2K-specific public methods ---------- + + virtual ::util::Status AddPort(int device, int port, uint64 speed_bps, + FecMode fec_mode); + virtual ::util::Status EnablePortShaping(int device, int port, + TriState enable); + virtual ::util::Status SetPortAutonegPolicy(int device, int port, + TriState autoneg); + virtual ::util::Status SetPortMtu(int device, int port, int32 mtu); + virtual ::util::Status SetPortLoopbackMode(int uint, int port, + LoopbackState loopback_mode); + + // Creates the singleton instance. Expected to be called once to initialize + // the instance. + static Es2kVirtualPortManager* CreateSingleton() LOCKS_EXCLUDED(init_lock_); + + // The following public functions are specific to this class. They are to be + // called by SDE callbacks only. + + // Return the singleton instance to be used in the SDE callbacks. + static Es2kVirtualPortManager* GetSingleton() LOCKS_EXCLUDED(init_lock_); + + // Called whenever a port status event is received from SDK. It forwards the + // port status event to the module who registered a callback by calling + // RegisterPortStatusEventWriter(). + ::util::Status OnPortStatusEvent(int device, int dev_port, bool up, + absl::Time timestamp) + LOCKS_EXCLUDED(port_status_event_writer_lock_); + + protected: + // The singleton instance. + static Es2kVirtualPortManager* singleton_ GUARDED_BY(init_lock_); +}; + +} // namespace tdi +} // namespace hal +} // namespace stratum + +#endif // STRATUM_HAL_LIB_TDI_ES2K_VIRTUAL_PORT_MANAGER_H_ diff --git a/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc b/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc new file mode 100644 index 000000000..21b48b22a --- /dev/null +++ b/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc @@ -0,0 +1,37 @@ +// Copyright 2020-present Open Networking Foundation +// Copyright 2022-2025 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "stratum/hal/lib/tdi/tdi_virtual_port_manager.h" + +#include "absl/synchronization/mutex.h" +#include "absl/time/time.h" +#include "stratum/glue/integral_types.h" +#include "stratum/lib/channel/channel.h" + +namespace stratum { +namespace hal { +namespace tdi { + +constexpr absl::Duration TdiVirtualPortManager::kWriteTimeout; + +ABSL_CONST_INIT absl::Mutex TdiVirtualPortManager::init_lock_(absl::kConstInit); + +TdiVirtualPortManager::TdiVirtualPortManager() : port_status_event_writer_(nullptr) {} + +::util::Status TdiVirtualPortManager::RegisterPortStatusEventWriter( + std::unique_ptr> writer) { + absl::WriterMutexLock l(&port_status_event_writer_lock_); + port_status_event_writer_ = std::move(writer); + return ::util::OkStatus(); +} + +::util::Status TdiVirtualPortManager::UnregisterPortStatusEventWriter() { + absl::WriterMutexLock l(&port_status_event_writer_lock_); + port_status_event_writer_ = nullptr; + return ::util::OkStatus(); +} + +} // namespace tdi +} // namespace hal +} // namespace stratum diff --git a/stratum/hal/lib/tdi/tdi_virtual_port_manager.h b/stratum/hal/lib/tdi/tdi_virtual_port_manager.h new file mode 100644 index 000000000..93fe80bef --- /dev/null +++ b/stratum/hal/lib/tdi/tdi_virtual_port_manager.h @@ -0,0 +1,97 @@ +// Copyright 2020-present Open Networking Foundation +// Copyright 2022-2025 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#ifndef STRATUM_HAL_LIB_TDI_TDI_VIRTUAL_PORT_MANAGER_H_ +#define STRATUM_HAL_LIB_TDI_TDI_VIRTUAL_PORT_MANAGER_H_ + +#include + +#include "absl/time/time.h" +#include "stratum/glue/status/status.h" +#include "stratum/glue/status/statusor.h" +#include "stratum/hal/lib/common/common.pb.h" +#include "stratum/hal/lib/common/utils.h" +#include "stratum/lib/channel/channel.h" + +namespace stratum { +namespace hal { +namespace tdi { + +// TdiVirtualPortManager is a proxy class for per target virtual port management +class TdiVirtualPortManager { + public: + // PortStatusEvent encapsulates the information received on a port status + // event. Port refers to the SDE internal device port ID. + struct PortStatusEvent { + int device; + int port; + PortState state; + absl::Time time_last_changed; + }; + + TdiVirtualPortManager(); + virtual ~TdiVirtualPortManager() {} + + // Registers a writer through which to send any port status events. The + // message contains a tuple (device, port, state), where port refers to the + // SDE internal device port ID. There can only be one writer. + virtual ::util::Status RegisterPortStatusEventWriter( + std::unique_ptr> writer); + + // Unregisters the port status writer. + virtual ::util::Status UnregisterPortStatusEventWriter(); + + // Gets Port Info + virtual ::util::Status GetPortInfo(int device, int port, + TargetDatapathId* target_dp_id) = 0; + + // Gets the operational state of a port. + virtual ::util::StatusOr GetPortState(int device, int port) = 0; + + // Gets the port counters of a port. + virtual ::util::Status GetPortCounters(int device, int port, + PortCounters* counters) = 0; + + // Returns the SDE device port ID for the given PortKey. + virtual ::util::StatusOr GetPortIdFromPortKey( + int device, const PortKey& port_key) = 0; + + // Checks if a port is valid. + virtual bool IsValidPort(int device, int port) = 0; + + // Adds a new port. + virtual ::util::Status AddPort(int device, int port) = 0; + + // Deletes a port. + virtual ::util::Status DeletePort(int device, int port) = 0; + + // Enables a port. + virtual ::util::Status EnablePort(int device, int port) = 0; + + // Disables a port. + virtual ::util::Status DisablePort(int device, int port) = 0; + + protected: + // RW mutex lock for protecting the singleton instance initialization and + // reading it back from other threads. Unlike other singleton classes, we + // use RW lock as we need the pointer to class to be returned. + static absl::Mutex init_lock_; + + // Timeout for Write() operations on port status events. + static constexpr absl::Duration kWriteTimeout = absl::InfiniteDuration(); + + // RW Mutex to protect the port status writer. + mutable absl::Mutex port_status_event_writer_lock_; + + // Writer to forward the port status change message to. It is registered + // by chassis manager to receive port status change events. + std::unique_ptr> port_status_event_writer_ + GUARDED_BY(port_status_event_writer_lock_); +}; + +} // namespace tdi +} // namespace hal +} // namespace stratum + +#endif // STRATUM_HAL_LIB_TDI_TDI_VIRTUAL_PORT_MANAGER_H_ From 916c00ee6e4371f9b3481e9fb50df08ffcec2738 Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Wed, 29 Jan 2025 07:35:08 -0800 Subject: [PATCH 04/11] Support for oper-status and mac-address and flow through SwitchInterface to es2k_vport_mgr Signed-off-by: Sabeel Ansari --- stratum/hal/lib/common/common.proto | 22 +-- .../hal/lib/tdi/es2k/es2k_chassis_manager.cc | 51 ++++++- .../hal/lib/tdi/es2k/es2k_chassis_manager.h | 15 ++- stratum/hal/lib/tdi/es2k/es2k_switch.cc | 15 ++- .../lib/tdi/es2k/es2k_virtual_port_manager.cc | 125 ++++-------------- .../lib/tdi/es2k/es2k_virtual_port_manager.h | 29 +--- .../hal/lib/tdi/tdi_virtual_port_manager.cc | 3 +- .../hal/lib/tdi/tdi_virtual_port_manager.h | 30 ----- .../lib/yang/yang_parse_tree_virtual_port.cc | 59 ++++++++- 9 files changed, 156 insertions(+), 193 deletions(-) diff --git a/stratum/hal/lib/common/common.proto b/stratum/hal/lib/common/common.proto index 87e6a713c..e8ee83606 100644 --- a/stratum/hal/lib/common/common.proto +++ b/stratum/hal/lib/common/common.proto @@ -1564,15 +1564,14 @@ message IPsecOffloadInfo { int32 spi = 1; } -// VirtualPortInfo is used in DataRequest and DataResponse to retrieve the -// values from target. message VirtualPortInfo { - uint32 global_resource_id = 1; - uint32 vsi = 2; - OperStatus oper_status = 3; + oneof value { + uint32 vsi = 1; + // OperStatus oper_status = 2; + // MacAddress mac_address = 3; + } } - // DataRequest is a message used internally to request data about a component // or a set of components through SwitchInterface. It is specifically used in // ConfigMonitoringService, as part of gNMI Get/Subscribe RPC implementation. @@ -1603,6 +1602,11 @@ message DataRequest { message IPsecOffloadInfo { int32 spi = 1; } + // Defines data required to get vport. + // Req will only contain global_resource_id to index on + message VirtualPort { + uint32 global_resource_id = 1; + } oneof request { Port oper_status = 1; Port admin_status = 2; @@ -1627,8 +1631,9 @@ message DataRequest { Port sdn_port_id = 22; Port target_dp_id = 23; IPsecOffloadInfo ipsec_offload_info = 24; - VirtualPortInfo vport_vsi = 25; - VirtualPortInfo vport_oper_status = 26; + VirtualPort vport_vsi = 25; + VirtualPort vport_oper_status = 26; + VirtualPort vport_mac_address = 27; } } repeated Request requests = 1; @@ -1676,7 +1681,6 @@ message DataResponse { PacketDirValue packet_dir = 35; IPsecOffloadInfo ipsec_offload_info = 36; VirtualPortInfo vport_vsi = 37; - VirtualPortInfo vport_oper_status = 38; } } diff --git a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc index 42888d6c0..26920c141 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc @@ -38,9 +38,9 @@ constexpr int Es2kChassisManager::kMaxPortStatusEventDepth; /* static */ constexpr int Es2kChassisManager::kMaxXcvrEventDepth; -Es2kChassisManager::Es2kChassisManager(OperationMode mode, - Es2kPortManager* es2k_port_manager, - Es2kVirtualPortManager* es2k_virtual_port_manager) +Es2kChassisManager::Es2kChassisManager( + OperationMode mode, Es2kPortManager* es2k_port_manager, + Es2kVirtualPortManager* es2k_virtual_port_manager) : mode_(mode), initialized_(false), port_status_event_channel_(nullptr), @@ -720,6 +720,45 @@ ::util::StatusOr Es2kChassisManager::GetPortData( return resp; } +::util::StatusOr Es2kChassisManager::GetVirtualPortData( + const DataRequest::Request& request) { + if (!initialized_) { + return MAKE_ERROR(ERR_NOT_INITIALIZED) << "Not initialized!"; + } + DataResponse resp; + using Request = DataRequest::Request; + switch (request.request_case()) { + case Request::kVportVsi: { + ASSIGN_OR_RETURN(auto vsi, es2k_virtual_port_manager_->GetVSI( + request.vport_vsi().global_resource_id())); + resp.mutable_vport_vsi()->set_vsi(vsi); + break; + } + case Request::kVportOperStatus: { + ASSIGN_OR_RETURN(auto oper_status, + es2k_virtual_port_manager_->GetPortState( + request.vport_oper_status().global_resource_id())); + resp.mutable_oper_status()->set_state(oper_status); + break; + } + case Request::kVportMacAddress: { + ASSIGN_OR_RETURN(auto mac_address, + es2k_virtual_port_manager_->GetMacAddress( + request.vport_oper_status().global_resource_id())); + resp.mutable_mac_address()->set_mac_address(mac_address); + break; + } + default: + return MAKE_ERROR(ERR_UNIMPLEMENTED) + << "DataRequest field " + << request.descriptor() + ->FindFieldByNumber(request.request_case()) + ->name() + << " is not supported yet!"; + } + return resp; +} + ::util::StatusOr Es2kChassisManager::GetPortState( uint64 node_id, uint32 port_id) const { if (!initialized_) { @@ -867,11 +906,9 @@ ::util::Status Es2kChassisManager::ReplayChassisConfig(uint64 node_id) { } std::unique_ptr Es2kChassisManager::CreateInstance( - OperationMode mode, - Es2kPortManager* es2k_port_manager, + OperationMode mode, Es2kPortManager* es2k_port_manager, Es2kVirtualPortManager* es2k_virtual_port_manager) { - return absl::WrapUnique(new Es2kChassisManager(mode, - es2k_port_manager, + return absl::WrapUnique(new Es2kChassisManager(mode, es2k_port_manager, es2k_virtual_port_manager)); } diff --git a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h index 17cd3ac79..898570960 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h +++ b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h @@ -54,6 +54,9 @@ class Es2kChassisManager { virtual ::util::StatusOr GetPortData( const DataRequest::Request& request) SHARED_LOCKS_REQUIRED(chassis_lock); + virtual ::util::StatusOr GetVirtualPortData( + const DataRequest::Request& request) SHARED_LOCKS_REQUIRED(chassis_lock); + virtual ::util::StatusOr GetPortTimeLastChanged(uint64 node_id, uint32 port_id) SHARED_LOCKS_REQUIRED(chassis_lock); @@ -73,8 +76,7 @@ class Es2kChassisManager { // Factory function for creating the instance of the class. static std::unique_ptr CreateInstance( - OperationMode mode, - Es2kPortManager* es2k_port_manager, + OperationMode mode, Es2kPortManager* es2k_port_manager, Es2kVirtualPortManager* es2k_virtual_port_manager); // Es2kChassisManager is neither copyable nor movable. @@ -115,8 +117,7 @@ class Es2kChassisManager { // Private constructor. Use CreateInstance() to create an instance of this // class. - Es2kChassisManager(OperationMode mode, - Es2kPortManager* es2k_port_manager, + Es2kChassisManager(OperationMode mode, Es2kPortManager* es2k_port_manager, Es2kVirtualPortManager* es2k_virtual_port_manager); ::util::StatusOr GetPortConfig(uint64 node_id, @@ -259,8 +260,10 @@ class Es2kChassisManager { // Pointer to an Es2kPortManager implementation that wraps the SDE calls. Es2kPortManager* es2k_port_manager_; // not owned by this class. - // Pointer to an Es2kVirtualPortManager implementation that wraps the SDE calls. - Es2kVirtualPortManager* es2k_virtual_port_manager_; // not owned by this class. + // Pointer to an Es2kVirtualPortManager implementation that wraps the SDE + // calls. + Es2kVirtualPortManager* + es2k_virtual_port_manager_; // not owned by this class. friend class Es2kChassisManagerTest; }; diff --git a/stratum/hal/lib/tdi/es2k/es2k_switch.cc b/stratum/hal/lib/tdi/es2k/es2k_switch.cc index cfccd6863..c4e707533 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_switch.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_switch.cc @@ -246,13 +246,14 @@ ::util::Status Es2kSwitch::RetrieveValue(uint64 node_id, } // VirtualPort data request case DataRequest::Request::kVportVsi: - case DataRequest::Request::kVportOperStatus: { -// auto vport_data = chassis_manager_->GetPortData(req); -// if (!vport_data.ok()) { -// status.Update(vport_data.status()); -// } else { -// resp = vport_data.ConsumeValueOrDie(); -// } + case DataRequest::Request::kVportOperStatus: + case DataRequest::Request::kVportMacAddress: { + auto vport_data = chassis_manager_->GetVirtualPortData(req); + if (!vport_data.ok()) { + status.Update(vport_data.status()); + } else { + resp = vport_data.ConsumeValueOrDie(); + } break; } default: diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc index b2843f1cf..91c83c72c 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc @@ -47,9 +47,11 @@ ipu_status_t sde_port_status_callback(ipu_dev_id_t device, ipu_dev_port_t dev_port, bool up, void* cookie) { absl::Time timestamp = absl::Now(); - Es2kVirtualPortManager* es2k_port_manager = Es2kVirtualPortManager::GetSingleton(); + Es2kVirtualPortManager* es2k_port_manager = + Es2kVirtualPortManager::GetSingleton(); if (!es2k_port_manager) { - LOG(ERROR) << "Es2kVirtualPortManager singleton instance is not initialized."; + LOG(ERROR) + << "Es2kVirtualPortManager singleton instance is not initialized."; return IPU_INTERNAL_ERROR; } // Forward the event. @@ -75,21 +77,30 @@ Es2kVirtualPortManager* Es2kVirtualPortManager::GetSingleton() { return singleton_; } -::util::StatusOr Es2kVirtualPortManager::GetPortState(int device, - int port) { - // Unsupported. Returns PORT_STATE_DOWN if called. - return PORT_STATE_DOWN; +::util::StatusOr Es2kVirtualPortManager::GetVSI( + uint32 global_resource_id) { + // TODO: Retrieve vport VSI from SDE + uint32 vsi = 432; + return vsi; } -::util::Status Es2kVirtualPortManager::GetPortCounters(int device, int port, - PortCounters* counters) { - uint64_t stats[TDI_PORT_NUM_COUNTERS] = {0}; +::util::StatusOr Es2kVirtualPortManager::GetPortState( + uint32 global_resource_id) { + // TODO: Retrieve vport oper-status from SDE + return PORT_STATE_DOWN; +} - return ::util::OkStatus(); +// Stratum's common.proto uses uint64 for MacAddress +::util::StatusOr Es2kVirtualPortManager::GetMacAddress( + uint32 global_resource_id) { + // TODO: Retrieve vport mac-address from SDE + uint64 kDummyMacAddress = 0x112233445566ull; + return kDummyMacAddress; } -::util::Status Es2kVirtualPortManager::OnPortStatusEvent(int device, int port, bool up, - absl::Time timestamp) { +::util::Status Es2kVirtualPortManager::OnPortStatusEvent(int device, int port, + bool up, + absl::Time timestamp) { // Create PortStatusEvent message. PortState state = up ? PORT_STATE_UP : PORT_STATE_DOWN; PortStatusEvent event = {device, port, state, timestamp}; @@ -103,96 +114,6 @@ ::util::Status Es2kVirtualPortManager::OnPortStatusEvent(int device, int port, b } } -::util::Status Es2kVirtualPortManager::GetPortInfo(int device, int port, - TargetDatapathId* target_dp_id) { - return ::util::OkStatus(); -} - -// TODO: Check with Sandeep which Add port is applicable or do we really -// need it since we don't add port for MEV -::util::Status Es2kVirtualPortManager::AddPort(int device, int port) { - return ::util::OkStatus(); -} - -::util::Status Es2kVirtualPortManager::AddPort(int device, int port, uint64 speed_bps, - FecMode fec_mode) { - auto port_attrs = absl::make_unique(); - RETURN_IF_TDI_ERROR(ipu_pal_port_add(static_cast(device), - static_cast(port), - port_attrs.get())); - return ::util::OkStatus(); -} - -::util::Status Es2kVirtualPortManager::DeletePort(int device, int port) { - RETURN_IF_TDI_ERROR(ipu_pal_port_del(static_cast(device), - static_cast(port))); - return ::util::OkStatus(); -} - -::util::Status Es2kVirtualPortManager::EnablePort(int device, int port) { - return ::util::OkStatus(); -} - -::util::Status Es2kVirtualPortManager::DisablePort(int device, int port) { - return ::util::OkStatus(); -} - -::util::Status Es2kVirtualPortManager::EnablePortShaping(int device, int port, - TriState enable) { - return ::util::OkStatus(); -} - -::util::Status Es2kVirtualPortManager::SetPortAutonegPolicy(int device, int port, - TriState autoneg) { - return ::util::OkStatus(); -} - -::util::Status Es2kVirtualPortManager::SetPortMtu(int device, int port, int32 mtu) { - return ::util::OkStatus(); -} - -bool Es2kVirtualPortManager::IsValidPort(int device, int port) { return IPU_SUCCESS; } - -::util::Status Es2kVirtualPortManager::SetPortLoopbackMode( - int device, int port, LoopbackState loopback_mode) { - if (loopback_mode == LOOPBACK_STATE_UNKNOWN) { - // Do nothing if we try to set loopback mode to the default one (UNKNOWN). - return ::util::OkStatus(); - } - return ::util::OkStatus(); -} - -// TODO: Check with Sandeep: Is this required? -::util::StatusOr Es2kVirtualPortManager::GetPortIdFromPortKey( - int device, const PortKey& port_key) { - const int port = port_key.port; - RET_CHECK(port >= 0) << "Port ID must be non-negative. Attempted to get port " - << port << " on dev " << device << "."; - - // PortKey uses three possible values for channel: - // > 0: port is channelized (first channel is 1) - // 0: port is not channelized - // < 0: port channel is not important (e.g. for port groups) - // BF SDK expects the first channel to be 0 - // Convert base-1 channel to base-0 channel if port is channelized - // Otherwise, port is already 0 in the non-channelized case - const int channel = - (port_key.channel > 0) ? port_key.channel - 1 : port_key.channel; - RET_CHECK(channel >= 0) << "Channel must be set for port " << port - << " on dev " << device << "."; - - char port_string[MAX_PORT_HDL_STRING_LEN]; - int r = snprintf(port_string, sizeof(port_string), "%d/%d", port, channel); - RET_CHECK(r > 0 && r < sizeof(port_string)) - << "Failed to build port string for port " << port << " channel " - << channel << " on dev " << device << "."; - - ipu_dev_port_t dev_port; - RETURN_IF_TDI_ERROR(ipu_pal_port_str_to_dev_port_map( - static_cast(device), port_string, &dev_port)); - return static_cast(dev_port); -} - } // namespace tdi } // namespace hal } // namespace stratum diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h index e04760d6a..8dd40763b 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h @@ -26,31 +26,10 @@ class Es2kVirtualPortManager : public TdiVirtualPortManager { Es2kVirtualPortManager() {} virtual ~Es2kVirtualPortManager() {} - // ---------- Common public methods ---------- - - ::util::Status GetPortInfo(int device, int port, - TargetDatapathId* target_dp_id); - ::util::StatusOr GetPortState(int device, int port); - ::util::Status GetPortCounters(int device, int port, PortCounters* counters); - ::util::StatusOr GetPortIdFromPortKey(int device, - const PortKey& port_key); - bool IsValidPort(int device, int port); - ::util::Status AddPort(int device, int port); - ::util::Status DeletePort(int device, int port); - ::util::Status EnablePort(int device, int port); - ::util::Status DisablePort(int device, int port); - - // ---------- ES2K-specific public methods ---------- - - virtual ::util::Status AddPort(int device, int port, uint64 speed_bps, - FecMode fec_mode); - virtual ::util::Status EnablePortShaping(int device, int port, - TriState enable); - virtual ::util::Status SetPortAutonegPolicy(int device, int port, - TriState autoneg); - virtual ::util::Status SetPortMtu(int device, int port, int32 mtu); - virtual ::util::Status SetPortLoopbackMode(int uint, int port, - LoopbackState loopback_mode); + ::util::StatusOr GetVSI(uint32 global_resource_id); + ::util::StatusOr GetPortState(uint32 global_resource_id); + // Stratum's common.proto uses uint64 for MacAddress + ::util::StatusOr GetMacAddress(uint32 global_resource_id); // Creates the singleton instance. Expected to be called once to initialize // the instance. diff --git a/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc b/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc index 21b48b22a..e13e62ee3 100644 --- a/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc +++ b/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc @@ -17,7 +17,8 @@ constexpr absl::Duration TdiVirtualPortManager::kWriteTimeout; ABSL_CONST_INIT absl::Mutex TdiVirtualPortManager::init_lock_(absl::kConstInit); -TdiVirtualPortManager::TdiVirtualPortManager() : port_status_event_writer_(nullptr) {} +TdiVirtualPortManager::TdiVirtualPortManager() + : port_status_event_writer_(nullptr) {} ::util::Status TdiVirtualPortManager::RegisterPortStatusEventWriter( std::unique_ptr> writer) { diff --git a/stratum/hal/lib/tdi/tdi_virtual_port_manager.h b/stratum/hal/lib/tdi/tdi_virtual_port_manager.h index 93fe80bef..cd1e1ae22 100644 --- a/stratum/hal/lib/tdi/tdi_virtual_port_manager.h +++ b/stratum/hal/lib/tdi/tdi_virtual_port_manager.h @@ -42,36 +42,6 @@ class TdiVirtualPortManager { // Unregisters the port status writer. virtual ::util::Status UnregisterPortStatusEventWriter(); - // Gets Port Info - virtual ::util::Status GetPortInfo(int device, int port, - TargetDatapathId* target_dp_id) = 0; - - // Gets the operational state of a port. - virtual ::util::StatusOr GetPortState(int device, int port) = 0; - - // Gets the port counters of a port. - virtual ::util::Status GetPortCounters(int device, int port, - PortCounters* counters) = 0; - - // Returns the SDE device port ID for the given PortKey. - virtual ::util::StatusOr GetPortIdFromPortKey( - int device, const PortKey& port_key) = 0; - - // Checks if a port is valid. - virtual bool IsValidPort(int device, int port) = 0; - - // Adds a new port. - virtual ::util::Status AddPort(int device, int port) = 0; - - // Deletes a port. - virtual ::util::Status DeletePort(int device, int port) = 0; - - // Enables a port. - virtual ::util::Status EnablePort(int device, int port) = 0; - - // Disables a port. - virtual ::util::Status DisablePort(int device, int port) = 0; - protected: // RW mutex lock for protecting the singleton instance initialization and // reading it back from other threads. Unlike other singleton classes, we diff --git a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc index a8ec4f3aa..a4948fcd3 100644 --- a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc +++ b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc @@ -29,6 +29,8 @@ void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { // Create a data retrieval request. DataRequest req; auto* request = req.add_requests()->mutable_vport_vsi(); + request->set_global_resource_id(0); // TODO sabeel + // In-place definition of method retrieving data from generic response // and saving into 'resp' local variable. uint32 resp{}; @@ -54,13 +56,54 @@ void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { //////////////////////////////////////////////////////////////////////////////// // /virtual-ports/virtual-port/state/oper-status void SetUpVirtualPortFetchOperStatus(TreeNode* node, YangParseTree* tree) { + auto poll_functor = [tree](const GnmiEvent& event, const ::gnmi::Path& path, + GnmiSubscribeStream* stream) { + DataRequest req; + auto* request = req.add_requests()->mutable_vport_oper_status(); + request->set_global_resource_id(0); // TODO sabeel - // -- return unsupported func - auto poll_functor = UnsupportedFunc(); - node->SetOnTimerHandler(poll_functor) - ->SetOnPollHandler(poll_functor) - ->SetOnChangeHandler(poll_functor); + uint32 resp{}; + DataResponseWriter writer([&resp](const DataResponse& in) { + if (!in.has_oper_status()) return false; + resp = in.oper_status().state(); + return true; + }); + tree->GetSwitchInterface() + ->RetrieveValue(/*node_id*/ 0, req, &writer, /* details= */ nullptr) + .IgnoreError(); + return SendResponse(GetResponse(path, resp), stream); + }; + auto on_change_functor = UnsupportedFunc(); + node->SetOnPollHandler(poll_functor) + ->SetOnTimerHandler(poll_functor) + ->SetOnChangeHandler(on_change_functor); +} +//////////////////////////////////////////////////////////////////////////////// +// /virtual-ports/virtual-port/state/mac-address +void SetUpVirtualPortFetchMacAddress(TreeNode* node, YangParseTree* tree) { + auto poll_functor = [tree](const GnmiEvent& event, const ::gnmi::Path& path, + GnmiSubscribeStream* stream) { + DataRequest req; + auto* request = req.add_requests()->mutable_vport_mac_address(); + request->set_global_resource_id(0); // TODO sabeel + + uint32 resp{}; + DataResponseWriter writer([&resp](const DataResponse& in) { + if (!in.has_mac_address()) return false; + resp = in.mac_address().mac_address(); + return true; + }); + tree->GetSwitchInterface() + ->RetrieveValue(/*node_id*/ 0, req, &writer, /* details= */ nullptr) + .IgnoreError(); + return SendResponse(GetResponse(path, MacAddressToYangString(resp)), + stream); + }; + auto on_change_functor = UnsupportedFunc(); + node->SetOnPollHandler(poll_functor) + ->SetOnTimerHandler(poll_functor) + ->SetOnChangeHandler(on_change_functor); } } // namespace @@ -73,8 +116,12 @@ void YangParseTreePaths::AddSubtreeVirtualPort(YangParseTree* tree) { TreeNode* node = tree->AddNode(GetPath("virtual-ports")("virtual-port")("state")("vsi")()); SetUpVirtualPortFetchVSI(node, tree); - node = tree->AddNode(GetPath("virtual-ports")("virtual-port")("state")("oper-status")()); + node = tree->AddNode( + GetPath("virtual-ports")("virtual-port")("state")("oper-status")()); SetUpVirtualPortFetchOperStatus(node, tree); + node = tree->AddNode( + GetPath("virtual-ports")("virtual-port")("state")("mac-address")()); + SetUpVirtualPortFetchMacAddress(node, tree); } } // namespace hal From 1827910ee9b5528a92fd2ad844b607c5c28f80ec Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Thu, 30 Jan 2025 12:38:43 -0800 Subject: [PATCH 05/11] Adding a get-with-val handler and new functor support Signed-off-by: Sabeel Ansari --- .../lib/common/config_monitoring_service.cc | 16 +++++++ stratum/hal/lib/common/gnmi_events.h | 4 ++ stratum/hal/lib/common/gnmi_publisher.cc | 47 +++++++++++++++++++ stratum/hal/lib/common/gnmi_publisher.h | 23 ++++++++- stratum/hal/lib/yang/yang_parse_tree.h | 28 +++++++++++ .../lib/yang/yang_parse_tree_virtual_port.cc | 47 +++++++++++++++++-- 6 files changed, 159 insertions(+), 6 deletions(-) diff --git a/stratum/hal/lib/common/config_monitoring_service.cc b/stratum/hal/lib/common/config_monitoring_service.cc index 36905c1b2..a75d98de2 100644 --- a/stratum/hal/lib/common/config_monitoring_service.cc +++ b/stratum/hal/lib/common/config_monitoring_service.cc @@ -373,6 +373,22 @@ ::grpc::Status ConfigMonitoringService::DoGet(::grpc::ServerContext* context, }); // Check if the path is supported. ::util::Status status; + + // In some cases such as vports yang tree nodes, we use a single node leaf + // to process for all vports. Instead of using a SubscriptionHandler and + // calling HandlePoll(), this will use a simple GET and pass the key + // from the yangpath so that the functor can use that data for interacting + // with SDE/TDI layer and access the correct vport info. + std::vector keys; + if (gnmi_publisher_.IsPathSupportedVirtualPorts(path, keys)) { + if (!(status = gnmi_publisher_.HandleGet(path, keys, &stream)).ok()) { + return ::grpc::Status(ToGrpcCode(status.CanonicalCode()), + status.error_message()); + } + return ::grpc::Status::OK; + } + // else (not vport)...continue with subscribe + handlePoll() + if ((status = gnmi_publisher_.SubscribePoll(path, &stream, &h)).ok()) { // Get the value(s) represented by the path. if (!(status = gnmi_publisher_.HandlePoll(h)).ok()) { diff --git a/stratum/hal/lib/common/gnmi_events.h b/stratum/hal/lib/common/gnmi_events.h index 314104a09..ed17399be 100644 --- a/stratum/hal/lib/common/gnmi_events.h +++ b/stratum/hal/lib/common/gnmi_events.h @@ -613,6 +613,10 @@ using GnmiDeleteWithValHandler = std::function<::util::Status( const ::gnmi::Path& path, const std::vector& val, CopyOnWriteChassisConfig* config)>; +using GnmiGetWithValHandler = std::function<::util::Status( + const ::gnmi::Path& path, const std::vector& val, + GnmiSubscribeStream* stream)>; + // A class used to keep information about a subscription. class EventHandlerRecord { public: diff --git a/stratum/hal/lib/common/gnmi_publisher.cc b/stratum/hal/lib/common/gnmi_publisher.cc index a5c21efb2..930cd3cc9 100644 --- a/stratum/hal/lib/common/gnmi_publisher.cc +++ b/stratum/hal/lib/common/gnmi_publisher.cc @@ -132,6 +132,25 @@ ::util::Status GnmiPublisher::HandleEvent( return ::util::OkStatus(); } +::util::Status GnmiPublisher::HandleGet(const ::gnmi::Path& path, + const std::vector& val, + GnmiSubscribeStream* stream) { + absl::WriterMutexLock l(&access_lock_); + + // Map the input path to the supported one - walk the tree of known elements + // element by element starting from the root and if the element is found the + // move to the next one. If not found, return an error. + const TreeNode* node = parse_tree_.FindNodeOrNull(path); + if (node == nullptr) { + // Ooops... This path is not supported. + return MAKE_ERROR(ERR_INVALID_PARAM) + << "The path (" << path.ShortDebugString() << ") is unsupported!"; + } + + // Call the GetWithVal handler and pass the keys + return node->GetOnGetWithValHandler()(path, val, stream); +} + ::util::Status GnmiPublisher::HandlePoll(const SubscriptionHandle& handle) { absl::WriterMutexLock l(&access_lock_); @@ -377,5 +396,33 @@ bool GnmiPublisher::IsPathSupportedIPsec(const ::gnmi::Path& path, return true; } +bool GnmiPublisher::IsPathSupportedVirtualPorts( + const ::gnmi::Path& path, std::vector& keys) const { + std::vector supported_path; + supported_path.push_back("virtual-ports"); + supported_path.push_back("virtual-port"); + + int element = 0; + std::vector::iterator iter; + for (iter = supported_path.begin(); iter != supported_path.end(); ++iter) { + if (path.elem(element).name() != *iter) { + return false; + } + + // This block extracts the key from the path + if (element == 1) { // virtual-port + // get the key + auto* search1 = + gtl::FindOrNull(path.elem(element).key(), "global-resource-id"); + if (search1 != nullptr) { + keys.push_back(*search1); + } + } + + ++element; + } + return true; +} + } // namespace hal } // namespace stratum diff --git a/stratum/hal/lib/common/gnmi_publisher.h b/stratum/hal/lib/common/gnmi_publisher.h index 9cdae36cb..9f10b56dc 100644 --- a/stratum/hal/lib/common/gnmi_publisher.h +++ b/stratum/hal/lib/common/gnmi_publisher.h @@ -96,6 +96,14 @@ class GnmiPublisher { ::util::Status HandleChange(const GnmiEvent& event) LOCKS_EXCLUDED(access_lock_); + // A simple GET routine to process gNMI requests without making a + // subscription and poll handle calls + // The second argument allows the yangpath keys to be passed to the functor + virtual ::util::Status HandleGet(const ::gnmi::Path& path, + const std::vector& val, + GnmiSubscribeStream* stream) + LOCKS_EXCLUDED(access_lock_); + virtual ::util::Status HandlePoll(const SubscriptionHandle& handle) LOCKS_EXCLUDED(access_lock_); @@ -144,13 +152,24 @@ class GnmiPublisher { // stateless and scale is too high to maintain tree nodes in memory -- tens of // millions of entries). Instead, a single tree node is maintained without any // keys that services all gnmi SET/DELETE requests. The tree node is - // initialized to to be at /ipsec-offload/sad/sad-entr/config. The contents of - // the message will contain the key, which is subsequently handled at lower + // initialized to to be at /ipsec-offload/sad/sad-entry/config. The contents + // of the message will contain the key, which is subsequently handled at lower // layers. virtual bool IsPathSupportedIPsec(const ::gnmi::Path& path, std::vector& keys) const LOCKS_EXCLUDED(access_lock_); + // virtual-ports is a special use-case, since yang tree nodes are not + // initialized and maintained for each key of yang list. + // Instead, a single tree node (for each leaf node type) is maintained without + // any keys that services all gnmi SET/GET requests. The tree node is + // initialized to to be at /virtual-ports/virtual-port/... The contents of + // the message will contain the key, which is subsequently handled at lower + // layers. + virtual bool IsPathSupportedVirtualPorts(const ::gnmi::Path& path, + std::vector& keys) const + LOCKS_EXCLUDED(access_lock_); + private: // ReaderArgs encapsulates the arguments for a Channel reader thread. template diff --git a/stratum/hal/lib/yang/yang_parse_tree.h b/stratum/hal/lib/yang/yang_parse_tree.h index 11f170a4f..643e7b6b2 100644 --- a/stratum/hal/lib/yang/yang_parse_tree.h +++ b/stratum/hal/lib/yang/yang_parse_tree.h @@ -41,6 +41,9 @@ using TreeNodeDeleteHandler = std::function<::util::Status( using TreeNodeDeleteWithValHandler = std::function<::util::Status( const ::gnmi::Path& path, const std::vector& val, CopyOnWriteChassisConfig* config)>; +using TreeNodeGetWithValHandler = std::function<::util::Status( + const ::gnmi::Path& path, const std::vector& val, + GnmiSubscribeStream* stream)>; using EventHandlerRecordPtr = std::weak_ptr; using TreeNodeEventRegistration = @@ -121,6 +124,14 @@ class TreeNode { return this; } + // Overrides the default-not-supported handler procedure called when + // a get request is processed with a user-specified one. + TreeNode* SetOnGetWithValHandler(const TreeNodeGetWithValHandler& handler) { + on_get_with_val_handler_ = handler; + // supports_on_poll_ = true; // TODO(5abeel): do we need a new type? + return this; + } + // Overrides the default-process-whole-sub-tree handler procedure called when // a timer event is processed with a user-specified one. TreeNode* SetOnTimerHandler(const TreeNodeEventHandler& handler) { @@ -250,6 +261,14 @@ class TreeNode { }; } + // Returns a functor that will execute handlers of this node. + GnmiGetWithValHandler GetOnGetWithValHandler() const { + return [this](const ::gnmi::Path& path, const std::vector& val, + GnmiSubscribeStream* stream) { + return on_get_with_val_handler_(path, val, stream); + }; + } + // Returns a functor that will execute handlers of this node and its children. GnmiEventHandler GetOnTimerHandler() const { return [this](const GnmiEvent& event, GnmiSubscribeStream* stream) { @@ -381,6 +400,15 @@ class TreeNode { return MAKE_ERROR() << "unsupported mode: DELETE(-with-val) for: '" << path.ShortDebugString() << "'"; }; + // Special delete handler (developed for vport feature) with a + // vector argument + TreeNodeGetWithValHandler on_get_with_val_handler_ = + [](const ::gnmi::Path&, const std::vector&, + GnmiSubscribeStream* stream) { + // Intermediate node. No real processing but needs to + // return OK so its children are processed. + return ::util::OkStatus(); + }; const TreeNode* parent_; std::string name_; // Some nodes are mapped to ::gnmi::PathElem 'name' key value. This variable diff --git a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc index a4948fcd3..f3cdc3058 100644 --- a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc +++ b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc @@ -24,11 +24,17 @@ namespace { //////////////////////////////////////////////////////////////////////////////// // /virtual-ports/virtual-port/state/vsi void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { +#if 0 auto poll_functor = [tree](const GnmiEvent& event, const ::gnmi::Path& path, GnmiSubscribeStream* stream) { // Create a data retrieval request. DataRequest req; auto* request = req.add_requests()->mutable_vport_vsi(); + + ::gnmi::Path* path_ptr = const_cast<::gnmi::Path*>(&path); + + std::cout << ">> SABEEL2 path=" << path_ptr->DebugString() << std::endl; + request->set_global_resource_id(0); // TODO sabeel // In-place definition of method retrieving data from generic response @@ -47,10 +53,43 @@ void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { .IgnoreError(); return SendResponse(GetResponse(path, resp), stream); }; - auto on_change_functor = UnsupportedFunc(); - node->SetOnPollHandler(poll_functor) - ->SetOnTimerHandler(poll_functor) - ->SetOnChangeHandler(on_change_functor); +#endif + + auto get_functor = [tree](const ::gnmi::Path& path, + const std::vector& val, + GnmiSubscribeStream* stream) { + // Create a data retrieval request. + DataRequest req; + auto* request = req.add_requests()->mutable_vport_vsi(); + ::gnmi::Path* path_ptr = const_cast<::gnmi::Path*>(&path); + + // std::cout << "path=" << path_ptr->DebugString() << std::endl; + uint32 glort_id = static_cast( + std::stoul(val.at(0))); // only one will be present at index 0 + request->set_global_resource_id(glort_id); + + // In-place definition of method retrieving data from generic response + // and saving into 'resp' local variable. + uint32 resp{}; + DataResponseWriter writer([&resp](const DataResponse& in) { + if (!in.has_vport_vsi()) return false; + resp = in.vport_vsi().vsi(); + return true; + }); + // Query the switch. The returned status is ignored as there is no way to + // notify the controller that something went wrong. The error is logged when + // it is created. + tree->GetSwitchInterface() + ->RetrieveValue(/*node_id*/ 0, req, &writer, /* details= */ nullptr) + .IgnoreError(); + return SendResponse(GetResponse(path, resp), stream); + }; + + auto unsupported_functor = UnsupportedFunc(); + node->SetOnPollHandler(unsupported_functor) + ->SetOnTimerHandler(unsupported_functor) + ->SetOnGetWithValHandler(get_functor) + ->SetOnChangeHandler(unsupported_functor); } //////////////////////////////////////////////////////////////////////////////// From 2f154bc43f4295602a20807c80d7c753d4802fcb Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Thu, 30 Jan 2025 12:44:28 -0800 Subject: [PATCH 06/11] Update OperStatus and MacAddress retrievals to use get-with-val functor Signed-off-by: Sabeel Ansari --- .../lib/yang/yang_parse_tree_virtual_port.cc | 77 ++++++++----------- 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc index f3cdc3058..b27f6a151 100644 --- a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc +++ b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc @@ -24,37 +24,6 @@ namespace { //////////////////////////////////////////////////////////////////////////////// // /virtual-ports/virtual-port/state/vsi void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { -#if 0 - auto poll_functor = [tree](const GnmiEvent& event, const ::gnmi::Path& path, - GnmiSubscribeStream* stream) { - // Create a data retrieval request. - DataRequest req; - auto* request = req.add_requests()->mutable_vport_vsi(); - - ::gnmi::Path* path_ptr = const_cast<::gnmi::Path*>(&path); - - std::cout << ">> SABEEL2 path=" << path_ptr->DebugString() << std::endl; - - request->set_global_resource_id(0); // TODO sabeel - - // In-place definition of method retrieving data from generic response - // and saving into 'resp' local variable. - uint32 resp{}; - DataResponseWriter writer([&resp](const DataResponse& in) { - if (!in.has_vport_vsi()) return false; - resp = in.vport_vsi().vsi(); - return true; - }); - // Query the switch. The returned status is ignored as there is no way to - // notify the controller that something went wrong. The error is logged when - // it is created. - tree->GetSwitchInterface() - ->RetrieveValue(/*node_id*/ 0, req, &writer, /* details= */ nullptr) - .IgnoreError(); - return SendResponse(GetResponse(path, resp), stream); - }; -#endif - auto get_functor = [tree](const ::gnmi::Path& path, const std::vector& val, GnmiSubscribeStream* stream) { @@ -95,11 +64,16 @@ void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { //////////////////////////////////////////////////////////////////////////////// // /virtual-ports/virtual-port/state/oper-status void SetUpVirtualPortFetchOperStatus(TreeNode* node, YangParseTree* tree) { - auto poll_functor = [tree](const GnmiEvent& event, const ::gnmi::Path& path, - GnmiSubscribeStream* stream) { + auto get_functor = [tree](const ::gnmi::Path& path, + const std::vector& val, + GnmiSubscribeStream* stream) { DataRequest req; - auto* request = req.add_requests()->mutable_vport_oper_status(); - request->set_global_resource_id(0); // TODO sabeel + auto* request = req.add_requests()->mutable_vport_vsi(); + ::gnmi::Path* path_ptr = const_cast<::gnmi::Path*>(&path); + + uint32 glort_id = static_cast( + std::stoul(val.at(0))); // only one will be present at index 0 + request->set_global_resource_id(glort_id); uint32 resp{}; DataResponseWriter writer([&resp](const DataResponse& in) { @@ -112,20 +86,27 @@ void SetUpVirtualPortFetchOperStatus(TreeNode* node, YangParseTree* tree) { .IgnoreError(); return SendResponse(GetResponse(path, resp), stream); }; - auto on_change_functor = UnsupportedFunc(); - node->SetOnPollHandler(poll_functor) - ->SetOnTimerHandler(poll_functor) - ->SetOnChangeHandler(on_change_functor); + + auto unsupported_functor = UnsupportedFunc(); + node->SetOnPollHandler(unsupported_functor) + ->SetOnTimerHandler(unsupported_functor) + ->SetOnGetWithValHandler(get_functor) + ->SetOnChangeHandler(unsupported_functor); } //////////////////////////////////////////////////////////////////////////////// // /virtual-ports/virtual-port/state/mac-address void SetUpVirtualPortFetchMacAddress(TreeNode* node, YangParseTree* tree) { - auto poll_functor = [tree](const GnmiEvent& event, const ::gnmi::Path& path, - GnmiSubscribeStream* stream) { + auto get_functor = [tree](const ::gnmi::Path& path, + const std::vector& val, + GnmiSubscribeStream* stream) { DataRequest req; - auto* request = req.add_requests()->mutable_vport_mac_address(); - request->set_global_resource_id(0); // TODO sabeel + auto* request = req.add_requests()->mutable_vport_vsi(); + ::gnmi::Path* path_ptr = const_cast<::gnmi::Path*>(&path); + + uint32 glort_id = static_cast( + std::stoul(val.at(0))); // only one will be present at index 0 + request->set_global_resource_id(glort_id); uint32 resp{}; DataResponseWriter writer([&resp](const DataResponse& in) { @@ -139,10 +120,12 @@ void SetUpVirtualPortFetchMacAddress(TreeNode* node, YangParseTree* tree) { return SendResponse(GetResponse(path, MacAddressToYangString(resp)), stream); }; - auto on_change_functor = UnsupportedFunc(); - node->SetOnPollHandler(poll_functor) - ->SetOnTimerHandler(poll_functor) - ->SetOnChangeHandler(on_change_functor); + + auto unsupported_functor = UnsupportedFunc(); + node->SetOnPollHandler(unsupported_functor) + ->SetOnTimerHandler(unsupported_functor) + ->SetOnGetWithValHandler(get_functor) + ->SetOnChangeHandler(unsupported_functor); } } // namespace From d0238fdbbb6d5c3be987d9ea94b4bed8285f3891 Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Fri, 31 Jan 2025 09:43:11 -0800 Subject: [PATCH 07/11] Integration with TDI layer Signed-off-by: Sabeel Ansari --- stratum/hal/bin/tdi/es2k/es2k_main.cc | 13 +++-- .../hal/lib/tdi/es2k/es2k_chassis_manager.cc | 2 +- .../lib/tdi/es2k/es2k_virtual_port_manager.cc | 57 ++++++++++++++++--- .../lib/tdi/es2k/es2k_virtual_port_manager.h | 12 ++++ stratum/hal/lib/tdi/tdi_constants.h | 8 ++- .../hal/lib/tdi/tdi_fixed_function_manager.cc | 28 ++++++++- .../hal/lib/tdi/tdi_fixed_function_manager.h | 9 ++- .../lib/yang/yang_parse_tree_virtual_port.cc | 23 ++++---- 8 files changed, 124 insertions(+), 28 deletions(-) diff --git a/stratum/hal/bin/tdi/es2k/es2k_main.cc b/stratum/hal/bin/tdi/es2k/es2k_main.cc index 78ebe4aad..4dca72851 100644 --- a/stratum/hal/bin/tdi/es2k/es2k_main.cc +++ b/stratum/hal/bin/tdi/es2k/es2k_main.cc @@ -24,6 +24,7 @@ #include "stratum/hal/lib/tdi/es2k/es2k_port_manager.h" #include "stratum/hal/lib/tdi/es2k/es2k_sde_wrapper.h" #include "stratum/hal/lib/tdi/es2k/es2k_switch.h" +#include "stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h" #include "stratum/hal/lib/tdi/tdi_action_profile_manager.h" #include "stratum/hal/lib/tdi/tdi_counter_manager.h" #include "stratum/hal/lib/tdi/tdi_fixed_function_manager.h" @@ -31,7 +32,6 @@ #include "stratum/hal/lib/tdi/tdi_packetio_manager.h" #include "stratum/hal/lib/tdi/tdi_pre_manager.h" #include "stratum/hal/lib/tdi/tdi_table_manager.h" -#include "stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h" #include "stratum/lib/macros.h" #include "stratum/lib/security/auth_policy_checker.h" #include "stratum/lib/security/credentials_manager.h" @@ -145,9 +145,14 @@ ::util::Status Main(absl::Notification* ready_sync, auto virtual_port_manager = Es2kVirtualPortManager::CreateSingleton(); - auto chassis_manager = Es2kChassisManager::CreateInstance(mode, - port_manager, - virtual_port_manager); + auto chassis_manager = Es2kChassisManager::CreateInstance( + mode, port_manager, virtual_port_manager); + + // Es2kVirtualPortManager needs reference to SetTdiSdeInterface & + // TdiFixedFunctionManager + virtual_port_manager->SetTdiSdeInterface(sde_wrapper); + virtual_port_manager->SetTdiFixedFunctionManager( + fixed_function_manager.get()); auto ipsec_manager = TdiIpsecManager::CreateInstance( sde_wrapper, fixed_function_manager.get()); diff --git a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc index 26920c141..9c95dbe82 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc @@ -744,7 +744,7 @@ ::util::StatusOr Es2kChassisManager::GetVirtualPortData( case Request::kVportMacAddress: { ASSIGN_OR_RETURN(auto mac_address, es2k_virtual_port_manager_->GetMacAddress( - request.vport_oper_status().global_resource_id())); + request.vport_mac_address().global_resource_id())); resp.mutable_mac_address()->set_mac_address(mac_address); break; } diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc index 91c83c72c..791800e35 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc @@ -25,6 +25,7 @@ #include "stratum/glue/status/statusor.h" #include "stratum/hal/lib/common/common.pb.h" #include "stratum/hal/lib/common/utils.h" +#include "stratum/hal/lib/tdi/tdi_constants.h" #include "stratum/hal/lib/tdi/tdi_sde_common.h" #include "stratum/hal/lib/tdi/tdi_status.h" #include "stratum/lib/channel/channel.h" @@ -34,12 +35,16 @@ extern "C" { #include "ipu_types/ipu_types.h" } +#define VPORT_STATE_TABLE_NAME \ + "openconfig-virtual-ports.virtual-ports.virtual-port.state" + namespace stratum { namespace hal { namespace tdi { Es2kVirtualPortManager* Es2kVirtualPortManager::singleton_ = nullptr; +#if 0 namespace { // A callback function executed in SDE port state change thread context. @@ -63,6 +68,8 @@ ipu_status_t sde_port_status_callback(ipu_dev_id_t device, } // namespace +#endif + Es2kVirtualPortManager* Es2kVirtualPortManager::CreateSingleton() { absl::WriterMutexLock l(&init_lock_); if (!singleton_) { @@ -77,25 +84,59 @@ Es2kVirtualPortManager* Es2kVirtualPortManager::GetSingleton() { return singleton_; } +void Es2kVirtualPortManager::SetTdiSdeInterface(TdiSdeInterface* tdi_sde_intf) { + tdi_sde_interface_ = tdi_sde_intf; +} + +void Es2kVirtualPortManager::SetTdiFixedFunctionManager( + TdiFixedFunctionManager* tdi_fixed_func_mgr) { + tdi_fixed_function_manager_ = tdi_fixed_func_mgr; +} + ::util::StatusOr Es2kVirtualPortManager::GetVSI( uint32 global_resource_id) { - // TODO: Retrieve vport VSI from SDE - uint32 vsi = 432; - return vsi; + uint64 data; + ASSIGN_OR_RETURN(auto session, tdi_sde_interface_->CreateSession()); + auto status = tdi_fixed_function_manager_->FetchVportTableData( + session, VPORT_STATE_TABLE_NAME, global_resource_id, kVsi, &data); + if (!status.ok()) { + return MAKE_ERROR(ERR_AT_LEAST_ONE_OPER_FAILED) + << "One or more read operations failed."; + } + return static_cast(data); } ::util::StatusOr Es2kVirtualPortManager::GetPortState( uint32 global_resource_id) { - // TODO: Retrieve vport oper-status from SDE - return PORT_STATE_DOWN; + uint64 data; + ASSIGN_OR_RETURN(auto session, tdi_sde_interface_->CreateSession()); + auto status = tdi_fixed_function_manager_->FetchVportTableData( + session, VPORT_STATE_TABLE_NAME, global_resource_id, kOperStatus, &data); + if (!status.ok()) { + return MAKE_ERROR(ERR_AT_LEAST_ONE_OPER_FAILED) + << "One or more read operations failed."; + } + return static_cast(data); } // Stratum's common.proto uses uint64 for MacAddress ::util::StatusOr Es2kVirtualPortManager::GetMacAddress( uint32 global_resource_id) { - // TODO: Retrieve vport mac-address from SDE - uint64 kDummyMacAddress = 0x112233445566ull; - return kDummyMacAddress; + uint64 data; + ASSIGN_OR_RETURN(auto session, tdi_sde_interface_->CreateSession()); + auto status = tdi_fixed_function_manager_->FetchVportTableData( + session, VPORT_STATE_TABLE_NAME, global_resource_id, kMacAddress, &data); + if (!status.ok()) { + return MAKE_ERROR(ERR_AT_LEAST_ONE_OPER_FAILED) + << "One or more read operations failed."; + } + + // Return mac-address with correct byte order + uint64 swapped_mac = ((data & 0xFF) << 40) | ((data & 0xFF00) << 24) | + ((data & 0xFF0000) << 8) | ((data & 0xFF000000) >> 8) | + ((data & 0xFF00000000) >> 24) | + ((data & 0xFF0000000000) >> 40); + return swapped_mac; } ::util::Status Es2kVirtualPortManager::OnPortStatusEvent(int device, int port, diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h index 8dd40763b..6912eae53 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h @@ -11,6 +11,8 @@ #include #include "absl/synchronization/mutex.h" +#include "stratum/hal/lib/tdi/tdi_fixed_function_manager.h" +#include "stratum/hal/lib/tdi/tdi_sde_interface.h" #include "stratum/hal/lib/tdi/tdi_virtual_port_manager.h" // Suppress clang errors @@ -26,6 +28,9 @@ class Es2kVirtualPortManager : public TdiVirtualPortManager { Es2kVirtualPortManager() {} virtual ~Es2kVirtualPortManager() {} + void SetTdiSdeInterface(TdiSdeInterface* tdi_sde_intf); + void SetTdiFixedFunctionManager(TdiFixedFunctionManager* tdi_fixed_func_mgr); + ::util::StatusOr GetVSI(uint32 global_resource_id); ::util::StatusOr GetPortState(uint32 global_resource_id); // Stratum's common.proto uses uint64 for MacAddress @@ -51,6 +56,13 @@ class Es2kVirtualPortManager : public TdiVirtualPortManager { protected: // The singleton instance. static Es2kVirtualPortManager* singleton_ GUARDED_BY(init_lock_); + + private: + // Pointer to TdiSdeInterface implementation. + TdiSdeInterface* tdi_sde_interface_; // not owned by this class. + + // Pointer to FixedFunctionManager. (not owned by this class) + TdiFixedFunctionManager* tdi_fixed_function_manager_; }; } // namespace tdi diff --git a/stratum/hal/lib/tdi/tdi_constants.h b/stratum/hal/lib/tdi/tdi_constants.h index f0f2a67d3..60e2ca3ea 100644 --- a/stratum/hal/lib/tdi/tdi_constants.h +++ b/stratum/hal/lib/tdi/tdi_constants.h @@ -1,5 +1,5 @@ // Copyright 2020-present Open Networking Foundation -// Copyright 2022-2023 Intel Corporation +// Copyright 2022-2023,2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef STRATUM_HAL_LIB_TDI_TDI_CONSTANTS_H_ @@ -62,6 +62,12 @@ constexpr char kIpsecSaLtHard[] = "sa-lifetime-hard"; constexpr char kIpsecSaLtSoft[] = "sa-lifetime-soft"; constexpr char kIpsecFetchSpi[] = "rx-spi"; +// vport related consts used in fixed functions +constexpr char kGlobalResourceId[] = "global-resource-id"; +constexpr char kVsi[] = "vsi"; +constexpr char kOperStatus[] = "oper-status"; +constexpr char kMacAddress[] = "mac-address"; + // TNA specific limits constexpr uint16 kMaxCloneSessionId = 1015; constexpr uint16 kMaxMulticastGroupId = 65535; diff --git a/stratum/hal/lib/tdi/tdi_fixed_function_manager.cc b/stratum/hal/lib/tdi/tdi_fixed_function_manager.cc index 243e4d30e..4cd1b5c5a 100644 --- a/stratum/hal/lib/tdi/tdi_fixed_function_manager.cc +++ b/stratum/hal/lib/tdi/tdi_fixed_function_manager.cc @@ -1,4 +1,4 @@ -// Copyright 2023 Intel Corporation +// Copyright 2023,2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "stratum/hal/lib/tdi/tdi_fixed_function_manager.h" @@ -57,6 +57,10 @@ TdiFixedFunctionManager::CreateInstance(OperationMode mode, new TdiFixedFunctionManager(mode, tdi_sde_interface, device)); } +////////////////////////////////// +// IPsec fixed-function TDI calls +////////////////////////////////// + ::util::Status TdiFixedFunctionManager::InitNotificationTableWithCallback( std::string table_name, void (*ipsec_notif_cb)(uint32_t, uint32_t, bool, uint8_t, char*, bool, @@ -169,6 +173,28 @@ ::util::Status TdiFixedFunctionManager::BuildSadbTableData( return ::util::OkStatus(); } +////////////////////////////////////////// +// Virtual-ports fixed-function TDI calls +////////////////////////////////////////// +::util::Status TdiFixedFunctionManager::FetchVportTableData( + std::shared_ptr session, + std::string table_name, uint32 global_resource_id, const char* param_name, + uint64* data) { + absl::ReaderMutexLock l(&lock_); + + ASSIGN_OR_RETURN(uint32 table_id, tdi_sde_interface_->GetTableId(table_name)); + ASSIGN_OR_RETURN(auto table_key, + tdi_sde_interface_->CreateTableKey(table_id)); + RETURN_IF_ERROR(table_key->SetExact(kGlobalResourceId, global_resource_id)); + ASSIGN_OR_RETURN(auto table_data, + tdi_sde_interface_->CreateTableData(table_id, 0)); + RETURN_IF_ERROR(tdi_sde_interface_->GetTableEntry( + device_, session, table_id, table_key.get(), table_data.get())); + RETURN_IF_ERROR(table_data->GetParam(std::string(param_name), data)); + + return ::util::OkStatus(); +} + } // namespace tdi } // namespace hal } // namespace stratum diff --git a/stratum/hal/lib/tdi/tdi_fixed_function_manager.h b/stratum/hal/lib/tdi/tdi_fixed_function_manager.h index 74fe11d5f..5c4ae23e2 100644 --- a/stratum/hal/lib/tdi/tdi_fixed_function_manager.h +++ b/stratum/hal/lib/tdi/tdi_fixed_function_manager.h @@ -1,4 +1,4 @@ -// Copyright 2023 Intel Corporation +// Copyright 2023,2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef STRATUM_HAL_LIB_TDI_TDI_FIXED_FUNCTION_MANAGER_H_ @@ -9,6 +9,7 @@ #include "stratum/glue/status/statusor.h" #include "stratum/hal/lib/common/common.pb.h" #include "stratum/hal/lib/tdi/tdi.pb.h" +#include "stratum/hal/lib/tdi/tdi_constants.h" #include "stratum/hal/lib/tdi/tdi_sde_interface.h" namespace stratum { @@ -35,6 +36,12 @@ class TdiFixedFunctionManager { std::shared_ptr session, std::string table_name, uint32* spi) LOCKS_EXCLUDED(lock_); + // Fetch value from the TDI table + ::util::Status FetchVportTableData( + std::shared_ptr session, + std::string table_name, uint32 global_resource_id, const char* param_name, + uint64* data) LOCKS_EXCLUDED(lock_); + // Creates a Fixed function table manager instance. static std::unique_ptr CreateInstance( OperationMode mode, TdiSdeInterface* tdi_sde_interface, int device); diff --git a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc index b27f6a151..e49a2c403 100644 --- a/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc +++ b/stratum/hal/lib/yang/yang_parse_tree_virtual_port.cc @@ -32,14 +32,13 @@ void SetUpVirtualPortFetchVSI(TreeNode* node, YangParseTree* tree) { auto* request = req.add_requests()->mutable_vport_vsi(); ::gnmi::Path* path_ptr = const_cast<::gnmi::Path*>(&path); - // std::cout << "path=" << path_ptr->DebugString() << std::endl; - uint32 glort_id = static_cast( + uint32 global_resource_id = static_cast( std::stoul(val.at(0))); // only one will be present at index 0 - request->set_global_resource_id(glort_id); + request->set_global_resource_id(global_resource_id); // In-place definition of method retrieving data from generic response // and saving into 'resp' local variable. - uint32 resp{}; + uint64 resp{}; DataResponseWriter writer([&resp](const DataResponse& in) { if (!in.has_vport_vsi()) return false; resp = in.vport_vsi().vsi(); @@ -68,14 +67,14 @@ void SetUpVirtualPortFetchOperStatus(TreeNode* node, YangParseTree* tree) { const std::vector& val, GnmiSubscribeStream* stream) { DataRequest req; - auto* request = req.add_requests()->mutable_vport_vsi(); + auto* request = req.add_requests()->mutable_vport_oper_status(); ::gnmi::Path* path_ptr = const_cast<::gnmi::Path*>(&path); - uint32 glort_id = static_cast( + uint32 global_resource_id = static_cast( std::stoul(val.at(0))); // only one will be present at index 0 - request->set_global_resource_id(glort_id); + request->set_global_resource_id(global_resource_id); - uint32 resp{}; + uint64 resp{}; DataResponseWriter writer([&resp](const DataResponse& in) { if (!in.has_oper_status()) return false; resp = in.oper_status().state(); @@ -101,14 +100,14 @@ void SetUpVirtualPortFetchMacAddress(TreeNode* node, YangParseTree* tree) { const std::vector& val, GnmiSubscribeStream* stream) { DataRequest req; - auto* request = req.add_requests()->mutable_vport_vsi(); + auto* request = req.add_requests()->mutable_vport_mac_address(); ::gnmi::Path* path_ptr = const_cast<::gnmi::Path*>(&path); - uint32 glort_id = static_cast( + uint32 global_resource_id = static_cast( std::stoul(val.at(0))); // only one will be present at index 0 - request->set_global_resource_id(glort_id); + request->set_global_resource_id(global_resource_id); - uint32 resp{}; + uint64 resp{}; DataResponseWriter writer([&resp](const DataResponse& in) { if (!in.has_mac_address()) return false; resp = in.mac_address().mac_address(); From c548c797ff8a41ca9c3ca750da736ce553ead9f3 Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Fri, 31 Jan 2025 10:29:04 -0800 Subject: [PATCH 08/11] Update copyright dates Signed-off-by: Sabeel Ansari --- stratum/hal/lib/common/common.proto | 2 -- stratum/hal/lib/common/config_monitoring_service.cc | 2 +- stratum/hal/lib/common/gnmi_publisher.cc | 2 +- stratum/hal/lib/common/gnmi_publisher.h | 2 +- stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc | 2 +- stratum/hal/lib/tdi/es2k/es2k_switch.cc | 2 +- 6 files changed, 5 insertions(+), 7 deletions(-) diff --git a/stratum/hal/lib/common/common.proto b/stratum/hal/lib/common/common.proto index e8ee83606..89fa41c08 100644 --- a/stratum/hal/lib/common/common.proto +++ b/stratum/hal/lib/common/common.proto @@ -1567,8 +1567,6 @@ message IPsecOffloadInfo { message VirtualPortInfo { oneof value { uint32 vsi = 1; - // OperStatus oper_status = 2; - // MacAddress mac_address = 3; } } diff --git a/stratum/hal/lib/common/config_monitoring_service.cc b/stratum/hal/lib/common/config_monitoring_service.cc index a75d98de2..830879764 100644 --- a/stratum/hal/lib/common/config_monitoring_service.cc +++ b/stratum/hal/lib/common/config_monitoring_service.cc @@ -1,6 +1,6 @@ // Copyright 2018 Google LLC // Copyright 2018-present Open Networking Foundation -// Copyright 2021-2024 Intel Corporation. +// Copyright 2021-2025 Intel Corporation. // SPDX-License-Identifier: Apache-2.0 #include "stratum/hal/lib/common/config_monitoring_service.h" diff --git a/stratum/hal/lib/common/gnmi_publisher.cc b/stratum/hal/lib/common/gnmi_publisher.cc index 930cd3cc9..3c612350d 100644 --- a/stratum/hal/lib/common/gnmi_publisher.cc +++ b/stratum/hal/lib/common/gnmi_publisher.cc @@ -1,6 +1,6 @@ // Copyright 2018 Google LLC // Copyright 2018-present Open Networking Foundation -// Copyright 2023-2024 Intel Corporation +// Copyright 2023-2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "stratum/hal/lib/common/gnmi_publisher.h" diff --git a/stratum/hal/lib/common/gnmi_publisher.h b/stratum/hal/lib/common/gnmi_publisher.h index 9f10b56dc..893b8d4e3 100644 --- a/stratum/hal/lib/common/gnmi_publisher.h +++ b/stratum/hal/lib/common/gnmi_publisher.h @@ -1,6 +1,6 @@ // Copyright 2018 Google LLC // Copyright 2018-present Open Networking Foundation -// Copyright 2023 Intel Corporation +// Copyright 2023,2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef STRATUM_HAL_LIB_COMMON_GNMI_PUBLISHER_H_ diff --git a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc index 9c95dbe82..792125d97 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.cc @@ -1,5 +1,5 @@ // Copyright 2018-present Barefoot Networks, Inc. -// Copyright 2022-2023 Intel Corporation +// Copyright 2022-2023,2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h" diff --git a/stratum/hal/lib/tdi/es2k/es2k_switch.cc b/stratum/hal/lib/tdi/es2k/es2k_switch.cc index c4e707533..3a579aa8c 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_switch.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_switch.cc @@ -1,5 +1,5 @@ // Copyright 2020-present Open Networking Foundation -// Copyright 2022-2024 Intel Corporation +// Copyright 2022-2025 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "stratum/hal/lib/tdi/es2k/es2k_switch.h" From 7f03c5728b4688aa8c53a9f9544902549912036f Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Fri, 31 Jan 2025 10:32:10 -0800 Subject: [PATCH 09/11] Remove unused code Signed-off-by: Sabeel Ansari --- .../lib/tdi/es2k/es2k_virtual_port_manager.cc | 42 ------------------- .../lib/tdi/es2k/es2k_virtual_port_manager.h | 7 ---- 2 files changed, 49 deletions(-) diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc index 791800e35..0465a4d05 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc @@ -44,32 +44,6 @@ namespace tdi { Es2kVirtualPortManager* Es2kVirtualPortManager::singleton_ = nullptr; -#if 0 -namespace { - -// A callback function executed in SDE port state change thread context. -ipu_status_t sde_port_status_callback(ipu_dev_id_t device, - ipu_dev_port_t dev_port, bool up, - void* cookie) { - absl::Time timestamp = absl::Now(); - Es2kVirtualPortManager* es2k_port_manager = - Es2kVirtualPortManager::GetSingleton(); - if (!es2k_port_manager) { - LOG(ERROR) - << "Es2kVirtualPortManager singleton instance is not initialized."; - return IPU_INTERNAL_ERROR; - } - // Forward the event. - auto status = - es2k_port_manager->OnPortStatusEvent(device, dev_port, up, timestamp); - - return status.ok() ? IPU_SUCCESS : IPU_INTERNAL_ERROR; -} - -} // namespace - -#endif - Es2kVirtualPortManager* Es2kVirtualPortManager::CreateSingleton() { absl::WriterMutexLock l(&init_lock_); if (!singleton_) { @@ -139,22 +113,6 @@ ::util::StatusOr Es2kVirtualPortManager::GetMacAddress( return swapped_mac; } -::util::Status Es2kVirtualPortManager::OnPortStatusEvent(int device, int port, - bool up, - absl::Time timestamp) { - // Create PortStatusEvent message. - PortState state = up ? PORT_STATE_UP : PORT_STATE_DOWN; - PortStatusEvent event = {device, port, state, timestamp}; - - { - absl::ReaderMutexLock l(&port_status_event_writer_lock_); - if (!port_status_event_writer_) { - return ::util::OkStatus(); - } - return port_status_event_writer_->Write(event, kWriteTimeout); - } -} - } // namespace tdi } // namespace hal } // namespace stratum diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h index 6912eae53..6e74f4afb 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h @@ -46,13 +46,6 @@ class Es2kVirtualPortManager : public TdiVirtualPortManager { // Return the singleton instance to be used in the SDE callbacks. static Es2kVirtualPortManager* GetSingleton() LOCKS_EXCLUDED(init_lock_); - // Called whenever a port status event is received from SDK. It forwards the - // port status event to the module who registered a callback by calling - // RegisterPortStatusEventWriter(). - ::util::Status OnPortStatusEvent(int device, int dev_port, bool up, - absl::Time timestamp) - LOCKS_EXCLUDED(port_status_event_writer_lock_); - protected: // The singleton instance. static Es2kVirtualPortManager* singleton_ GUARDED_BY(init_lock_); From 0680231a5280a7a149c93e37bc919e5077eadc57 Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Fri, 31 Jan 2025 10:53:31 -0800 Subject: [PATCH 10/11] Remove TdiVirtualPortManager since its unused Signed-off-by: Sabeel Ansari --- stratum/hal/lib/tdi/CMakeLists.txt | 4 +- .../hal/lib/tdi/es2k/es2k_chassis_manager.h | 1 - .../lib/tdi/es2k/es2k_virtual_port_manager.cc | 2 + .../lib/tdi/es2k/es2k_virtual_port_manager.h | 8 ++- .../hal/lib/tdi/tdi_virtual_port_manager.cc | 38 ----------- .../hal/lib/tdi/tdi_virtual_port_manager.h | 67 ------------------- 6 files changed, 9 insertions(+), 111 deletions(-) delete mode 100644 stratum/hal/lib/tdi/tdi_virtual_port_manager.cc delete mode 100644 stratum/hal/lib/tdi/tdi_virtual_port_manager.h diff --git a/stratum/hal/lib/tdi/CMakeLists.txt b/stratum/hal/lib/tdi/CMakeLists.txt index 092068fea..6e6ee8e9d 100644 --- a/stratum/hal/lib/tdi/CMakeLists.txt +++ b/stratum/hal/lib/tdi/CMakeLists.txt @@ -1,6 +1,6 @@ # Build file for //stratum/hal/lib/tdi # -# Copyright 2022-2025 Intel Corporation +# Copyright 2022-2024 Intel Corporation # SPDX-License-Identifier: Apache 2.0 # @@ -48,8 +48,6 @@ add_library(stratum_tdi_common_o OBJECT tdi_sde_wrapper.h tdi_table_manager.cc tdi_table_manager.h - tdi_virtual_port_manager.cc - tdi_virtual_port_manager.h utils.cc utils.h ) diff --git a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h index 898570960..2b0f5e97e 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h +++ b/stratum/hal/lib/tdi/es2k/es2k_chassis_manager.h @@ -19,7 +19,6 @@ #include "stratum/hal/lib/common/writer_interface.h" #include "stratum/hal/lib/tdi/tdi_global_vars.h" #include "stratum/hal/lib/tdi/tdi_port_manager.h" -#include "stratum/hal/lib/tdi/tdi_virtual_port_manager.h" #include "stratum/lib/channel/channel.h" namespace stratum { diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc index 0465a4d05..61b6b026c 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc @@ -44,6 +44,8 @@ namespace tdi { Es2kVirtualPortManager* Es2kVirtualPortManager::singleton_ = nullptr; +ABSL_CONST_INIT absl::Mutex Es2kVirtualPortManager::init_lock_(absl::kConstInit); + Es2kVirtualPortManager* Es2kVirtualPortManager::CreateSingleton() { absl::WriterMutexLock l(&init_lock_); if (!singleton_) { diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h index 6e74f4afb..59b8c70a8 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.h @@ -13,7 +13,6 @@ #include "absl/synchronization/mutex.h" #include "stratum/hal/lib/tdi/tdi_fixed_function_manager.h" #include "stratum/hal/lib/tdi/tdi_sde_interface.h" -#include "stratum/hal/lib/tdi/tdi_virtual_port_manager.h" // Suppress clang errors #undef LOCKS_EXCLUDED @@ -23,7 +22,7 @@ namespace stratum { namespace hal { namespace tdi { -class Es2kVirtualPortManager : public TdiVirtualPortManager { +class Es2kVirtualPortManager { public: Es2kVirtualPortManager() {} virtual ~Es2kVirtualPortManager() {} @@ -47,6 +46,11 @@ class Es2kVirtualPortManager : public TdiVirtualPortManager { static Es2kVirtualPortManager* GetSingleton() LOCKS_EXCLUDED(init_lock_); protected: + // RW mutex lock for protecting the singleton instance initialization and + // reading it back from other threads. Unlike other singleton classes, we + // use RW lock as we need the pointer to class to be returned. + static absl::Mutex init_lock_; + // The singleton instance. static Es2kVirtualPortManager* singleton_ GUARDED_BY(init_lock_); diff --git a/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc b/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc deleted file mode 100644 index e13e62ee3..000000000 --- a/stratum/hal/lib/tdi/tdi_virtual_port_manager.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020-present Open Networking Foundation -// Copyright 2022-2025 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#include "stratum/hal/lib/tdi/tdi_virtual_port_manager.h" - -#include "absl/synchronization/mutex.h" -#include "absl/time/time.h" -#include "stratum/glue/integral_types.h" -#include "stratum/lib/channel/channel.h" - -namespace stratum { -namespace hal { -namespace tdi { - -constexpr absl::Duration TdiVirtualPortManager::kWriteTimeout; - -ABSL_CONST_INIT absl::Mutex TdiVirtualPortManager::init_lock_(absl::kConstInit); - -TdiVirtualPortManager::TdiVirtualPortManager() - : port_status_event_writer_(nullptr) {} - -::util::Status TdiVirtualPortManager::RegisterPortStatusEventWriter( - std::unique_ptr> writer) { - absl::WriterMutexLock l(&port_status_event_writer_lock_); - port_status_event_writer_ = std::move(writer); - return ::util::OkStatus(); -} - -::util::Status TdiVirtualPortManager::UnregisterPortStatusEventWriter() { - absl::WriterMutexLock l(&port_status_event_writer_lock_); - port_status_event_writer_ = nullptr; - return ::util::OkStatus(); -} - -} // namespace tdi -} // namespace hal -} // namespace stratum diff --git a/stratum/hal/lib/tdi/tdi_virtual_port_manager.h b/stratum/hal/lib/tdi/tdi_virtual_port_manager.h deleted file mode 100644 index cd1e1ae22..000000000 --- a/stratum/hal/lib/tdi/tdi_virtual_port_manager.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2020-present Open Networking Foundation -// Copyright 2022-2025 Intel Corporation -// SPDX-License-Identifier: Apache-2.0 - -#ifndef STRATUM_HAL_LIB_TDI_TDI_VIRTUAL_PORT_MANAGER_H_ -#define STRATUM_HAL_LIB_TDI_TDI_VIRTUAL_PORT_MANAGER_H_ - -#include - -#include "absl/time/time.h" -#include "stratum/glue/status/status.h" -#include "stratum/glue/status/statusor.h" -#include "stratum/hal/lib/common/common.pb.h" -#include "stratum/hal/lib/common/utils.h" -#include "stratum/lib/channel/channel.h" - -namespace stratum { -namespace hal { -namespace tdi { - -// TdiVirtualPortManager is a proxy class for per target virtual port management -class TdiVirtualPortManager { - public: - // PortStatusEvent encapsulates the information received on a port status - // event. Port refers to the SDE internal device port ID. - struct PortStatusEvent { - int device; - int port; - PortState state; - absl::Time time_last_changed; - }; - - TdiVirtualPortManager(); - virtual ~TdiVirtualPortManager() {} - - // Registers a writer through which to send any port status events. The - // message contains a tuple (device, port, state), where port refers to the - // SDE internal device port ID. There can only be one writer. - virtual ::util::Status RegisterPortStatusEventWriter( - std::unique_ptr> writer); - - // Unregisters the port status writer. - virtual ::util::Status UnregisterPortStatusEventWriter(); - - protected: - // RW mutex lock for protecting the singleton instance initialization and - // reading it back from other threads. Unlike other singleton classes, we - // use RW lock as we need the pointer to class to be returned. - static absl::Mutex init_lock_; - - // Timeout for Write() operations on port status events. - static constexpr absl::Duration kWriteTimeout = absl::InfiniteDuration(); - - // RW Mutex to protect the port status writer. - mutable absl::Mutex port_status_event_writer_lock_; - - // Writer to forward the port status change message to. It is registered - // by chassis manager to receive port status change events. - std::unique_ptr> port_status_event_writer_ - GUARDED_BY(port_status_event_writer_lock_); -}; - -} // namespace tdi -} // namespace hal -} // namespace stratum - -#endif // STRATUM_HAL_LIB_TDI_TDI_VIRTUAL_PORT_MANAGER_H_ From 4d85fa85924038dfc6f9f35b967ad789594b0190 Mon Sep 17 00:00:00 2001 From: Sabeel Ansari Date: Fri, 31 Jan 2025 11:08:23 -0800 Subject: [PATCH 11/11] clang-format fix Signed-off-by: Sabeel Ansari --- stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc index 61b6b026c..392a801f6 100644 --- a/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc +++ b/stratum/hal/lib/tdi/es2k/es2k_virtual_port_manager.cc @@ -44,7 +44,8 @@ namespace tdi { Es2kVirtualPortManager* Es2kVirtualPortManager::singleton_ = nullptr; -ABSL_CONST_INIT absl::Mutex Es2kVirtualPortManager::init_lock_(absl::kConstInit); +ABSL_CONST_INIT absl::Mutex Es2kVirtualPortManager::init_lock_( + absl::kConstInit); Es2kVirtualPortManager* Es2kVirtualPortManager::CreateSingleton() { absl::WriterMutexLock l(&init_lock_);