From 1091da45acfa4dd344cb0dd29d7ff51e20a1e9c9 Mon Sep 17 00:00:00 2001 From: Vivek Reddy Date: Thu, 12 Feb 2026 10:10:34 +0200 Subject: [PATCH 1/2] [DASH] Set HA_FLOW_OWNER attribute only if supported Signed-off-by: Vivek Reddy --- orchagent/dash/dashorch.cpp | 60 ++++++++++++++++++++++++++++--------- orchagent/dash/dashorch.h | 3 ++ 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/orchagent/dash/dashorch.cpp b/orchagent/dash/dashorch.cpp index bf84b2d4adb..41a555d9bfd 100644 --- a/orchagent/dash/dashorch.cpp +++ b/orchagent/dash/dashorch.cpp @@ -99,6 +99,32 @@ bool DashOrch::hasApplianceEntry() return !appliance_entries_.empty(); } +bool DashOrch::isHaFlowOwnerAttrSupported() +{ + SWSS_LOG_ENTER(); + + std::call_once(m_ha_flow_owner_attr_once_flag, [this]() { + sai_attr_capability_t capability; + sai_status_t status = sai_query_attribute_capability( + gSwitchId, + (sai_object_type_t)SAI_OBJECT_TYPE_ENI, + SAI_ENI_ATTR_IS_HA_FLOW_OWNER, + &capability); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Could not query SAI_ENI_ATTR_IS_HA_FLOW_OWNER capability: %d", status); + m_ha_flow_owner_attr_supported = false; + } + else + { + m_ha_flow_owner_attr_supported = capability.set_implemented || capability.create_implemented; + } + }); + + return m_ha_flow_owner_attr_supported; +} + bool DashOrch::addApplianceEntry(const string& appliance_id, const dash::appliance::Appliance &entry) { SWSS_LOG_ENTER(); @@ -650,25 +676,31 @@ bool DashOrch::addEniObject(const string& eni, EniEntry& entry) eni_attrs.push_back(eni_attr); SWSS_LOG_INFO("Setting HA Scope ID %" PRIx64 " for ENI %s", ha_scope_entry.ha_scope_id, eni.c_str()); - // Set HA flow owner based on HA role - eni_attr.id = SAI_ENI_ATTR_IS_HA_FLOW_OWNER; - if (ha_scope_entry.metadata.ha_role() == dash::types::HA_ROLE_ACTIVE || ha_scope_entry.metadata.ha_role() == dash::types::HA_ROLE_STANDALONE) - { - eni_attr.value.booldata = true; - SWSS_LOG_INFO("Setting HA flow owner to true (ACTIVE) for ENI %s", eni.c_str()); - } - else if (ha_scope_entry.metadata.ha_role() == dash::types::HA_ROLE_STANDBY) + if (isHaFlowOwnerAttrSupported()) { - eni_attr.value.booldata = false; - SWSS_LOG_INFO("Setting HA flow owner to false (STANDBY) for ENI %s", eni.c_str()); + eni_attr.id = SAI_ENI_ATTR_IS_HA_FLOW_OWNER; + if (ha_scope_entry.metadata.ha_role() == dash::types::HA_ROLE_ACTIVE || ha_scope_entry.metadata.ha_role() == dash::types::HA_ROLE_STANDALONE) + { + eni_attr.value.booldata = true; + SWSS_LOG_INFO("Setting HA flow owner to true (ACTIVE) for ENI %s", eni.c_str()); + } + else if (ha_scope_entry.metadata.ha_role() == dash::types::HA_ROLE_STANDBY) + { + eni_attr.value.booldata = false; + SWSS_LOG_INFO("Setting HA flow owner to false (STANDBY) for ENI %s", eni.c_str()); + } + else + { + // For other roles (DEAD, SWITCHING_TO_ACTIVE), default to false + eni_attr.value.booldata = false; + SWSS_LOG_INFO("Setting HA flow owner to false (role: %s) for ENI %s", dash::types::HaRole_Name(ha_scope_entry.metadata.ha_role()).c_str(), eni.c_str()); + } + eni_attrs.push_back(eni_attr); } else { - // For other roles (DEAD, SWITCHING_TO_ACTIVE), default to false - eni_attr.value.booldata = false; - SWSS_LOG_INFO("Setting HA flow owner to false (role: %s) for ENI %s", dash::types::HaRole_Name(ha_scope_entry.metadata.ha_role()).c_str(), eni.c_str()); + SWSS_LOG_INFO("SAI_ENI_ATTR_IS_HA_FLOW_OWNER not supported, skipping for ENI %s", eni.c_str()); } - eni_attrs.push_back(eni_attr); } else { diff --git a/orchagent/dash/dashorch.h b/orchagent/dash/dashorch.h index 4ac36cb7788..7c65b2fd865 100644 --- a/orchagent/dash/dashorch.h +++ b/orchagent/dash/dashorch.h @@ -102,6 +102,7 @@ class DashOrch : public ZmqOrch bool removeQosEntry(const std::string& qos_name); bool setEniRoute(const std::string& eni, const dash::eni_route::EniRoute& entry); bool removeEniRoute(const std::string& eni); + bool isHaFlowOwnerAttrSupported(); private: @@ -172,6 +173,8 @@ class DashOrch : public ZmqOrch std::shared_ptr m_counter_db; std::shared_ptr m_asic_db; DashHaOrch* m_dash_ha_orch = nullptr; + bool m_ha_flow_owner_attr_supported = false; + std::once_flag m_ha_flow_owner_attr_once_flag; void addEniMapEntry(sai_object_id_t oid, const std::string& name); void removeEniMapEntry(sai_object_id_t oid, const std::string& name); From 4e3e668685b85503b72a3b76755bfd7add05dfed Mon Sep 17 00:00:00 2001 From: Vivek Reddy Date: Wed, 18 Feb 2026 04:58:19 +0200 Subject: [PATCH 2/2] [DASH] Set ADMIN_STATE attribute only if supported Signed-off-by: Vivek Reddy --- orchagent/dash/dashhaorch.cpp | 44 +++++++++++++++++++++++++++++++---- orchagent/dash/dashhaorch.h | 5 ++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/orchagent/dash/dashhaorch.cpp b/orchagent/dash/dashhaorch.cpp index 5d1d6e493a4..c7344c260d1 100644 --- a/orchagent/dash/dashhaorch.cpp +++ b/orchagent/dash/dashhaorch.cpp @@ -163,6 +163,33 @@ bool DashHaOrch::register_ha_scope_notifier() return true; } +bool DashHaOrch::isHaScopeAdminStateAttrSupported() +{ + SWSS_LOG_ENTER(); + + std::call_once(m_ha_scope_admin_state_attr_once_flag, [this]() { + sai_attr_capability_t capability; + sai_status_t status = sai_query_attribute_capability( + gSwitchId, + (sai_object_type_t)SAI_OBJECT_TYPE_HA_SCOPE, + SAI_HA_SCOPE_ATTR_ADMIN_STATE, + &capability); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_WARN("Could not query SAI_HA_SCOPE_ATTR_ADMIN_STATE capability: %d", status); + m_ha_scope_admin_state_attr_supported = false; + } + else + { + m_ha_scope_admin_state_attr_supported = + capability.set_implemented || capability.create_implemented; + } + }); + + return m_ha_scope_admin_state_attr_supported; +} + std::string DashHaOrch::getHaSetObjectKey(const sai_object_id_t ha_set_oid) { SWSS_LOG_ENTER(); @@ -499,10 +526,13 @@ bool DashHaOrch::addHaScopeEntry(const std::string &key, const dash::ha_scope::H ha_role_attr.value.u16 = to_sai(entry.ha_role()); ha_scope_attrs.push_back(ha_role_attr); - sai_attribute_t disabled_attr = {}; - disabled_attr.id = SAI_HA_SCOPE_ATTR_ADMIN_STATE; - disabled_attr.value.booldata = !entry.disabled(); - ha_scope_attrs.push_back(disabled_attr); + if (isHaScopeAdminStateAttrSupported()) + { + sai_attribute_t disabled_attr = {}; + disabled_attr.id = SAI_HA_SCOPE_ATTR_ADMIN_STATE; + disabled_attr.value.booldata = !entry.disabled(); + ha_scope_attrs.push_back(disabled_attr); + } if (entry.has_vip_v4() && entry.vip_v4().has_ipv4()) { @@ -729,6 +759,12 @@ bool DashHaOrch::setHaScopeDisabled(const std::string &key, bool disabled) { SWSS_LOG_ENTER(); + if (!isHaScopeAdminStateAttrSupported()) + { + m_ha_scope_entries[key].metadata.set_disabled(disabled); + return true; + } + sai_object_id_t ha_scope_id = m_ha_scope_entries[key].ha_scope_id; sai_attribute_t ha_scope_attr; diff --git a/orchagent/dash/dashhaorch.h b/orchagent/dash/dashhaorch.h index c0732fb3455..d9c33c3c733 100644 --- a/orchagent/dash/dashhaorch.h +++ b/orchagent/dash/dashhaorch.h @@ -1,6 +1,7 @@ #ifndef DASHHAORCH_H #define DASHHAORCH_H #include +#include #include "dbconnector.h" #include "dashorch.h" @@ -71,6 +72,7 @@ class DashHaOrch : public ZmqOrch bool setHaScopeFlowReconcileRequest(const std::string &key); bool setHaScopeActivateRoleRequest(const std::string &key); bool setHaScopeDisabled(const std::string &key, bool disabled); + bool isHaScopeAdminStateAttrSupported(); bool setEniHaScopeId(const sai_object_id_t eni_id, const sai_object_id_t ha_scope_id); bool register_ha_set_notifier(); bool register_ha_scope_notifier(); @@ -107,6 +109,9 @@ class DashHaOrch : public ZmqOrch swss::NotificationConsumer* m_haSetNotificationConsumer; swss::NotificationConsumer* m_haScopeNotificationConsumer; + bool m_ha_scope_admin_state_attr_supported = false; + std::once_flag m_ha_scope_admin_state_attr_once_flag; + public: const HaSetTable& getHaSetEntries() const { return m_ha_set_entries; }; const HaScopeTable& getHaScopeEntries() const { return m_ha_scope_entries; };