diff --git a/.gitignore b/.gitignore index bfba27230560..c2522ba71178 100644 --- a/.gitignore +++ b/.gitignore @@ -85,3 +85,5 @@ tests/mock_tests/tests.trs tests/test-suite.log tests/tests.log tests/tests.trs +orchagent/p4orch/tests/**/*gcda +orchagent/p4orch/tests/**/*gcno diff --git a/configure.ac b/configure.ac index 81ee0a50176a..5e5ce44171af 100644 --- a/configure.ac +++ b/configure.ac @@ -138,6 +138,7 @@ AC_CONFIG_FILES([ swssconfig/Makefile cfgmgr/Makefile tests/Makefile + orchagent/p4orch/tests/Makefile ]) # If no SAI library is installed, compile with SAIVS and run unit tests diff --git a/orchagent/Makefile.am b/orchagent/Makefile.am index 7225917e4da9..248c190f11ef 100644 --- a/orchagent/Makefile.am +++ b/orchagent/Makefile.am @@ -95,6 +95,18 @@ orchagent_SOURCES = \ orchagent_SOURCES += flex_counter/flex_counter_manager.cpp flex_counter/flex_counter_stat_manager.cpp flex_counter/flow_counter_handler.cpp orchagent_SOURCES += debug_counter/debug_counter.cpp debug_counter/drop_counter.cpp +orchagent_SOURCES += p4orch/p4orch.cpp \ + p4orch/p4orch_util.cpp \ + p4orch/p4oidmapper.cpp \ + p4orch/router_interface_manager.cpp \ + p4orch/neighbor_manager.cpp \ + p4orch/next_hop_manager.cpp \ + p4orch/route_manager.cpp \ + p4orch/acl_util.cpp \ + p4orch/acl_table_manager.cpp \ + p4orch/acl_rule_manager.cpp \ + p4orch/wcmp_manager.cpp \ + p4orch/mirror_session_manager.cpp orchagent_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) orchagent_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) diff --git a/orchagent/acltable.h b/orchagent/acltable.h index 081170984f90..3ec7f1a757e0 100644 --- a/orchagent/acltable.h +++ b/orchagent/acltable.h @@ -19,8 +19,9 @@ extern "C" { #define ACL_TABLE_TYPE_BPOINT_TYPES "BIND_POINTS" #define ACL_TABLE_TYPE_ACTIONS "ACTIONS" -#define STAGE_INGRESS "INGRESS" -#define STAGE_EGRESS "EGRESS" +#define STAGE_INGRESS "INGRESS" +#define STAGE_EGRESS "EGRESS" +#define STAGE_PRE_INGRESS "PRE_INGRESS" #define TABLE_TYPE_L3 "L3" #define TABLE_TYPE_L3V6 "L3V6" @@ -39,7 +40,31 @@ typedef enum { ACL_STAGE_UNKNOWN, ACL_STAGE_INGRESS, - ACL_STAGE_EGRESS + ACL_STAGE_EGRESS, + ACL_STAGE_PRE_INGRESS } acl_stage_type_t; typedef std::unordered_map acl_stage_type_lookup_t; +typedef std::map acl_stage_lookup_t; +typedef std::map acl_stage_to_switch_attr_lookup_t; + +struct AclTableGroupMember +{ + sai_object_id_t m_group_oid; + sai_object_id_t m_group_member_oid; + uint32_t m_priority; + AclTableGroupMember() : m_group_oid(SAI_NULL_OBJECT_ID), m_group_member_oid(SAI_NULL_OBJECT_ID), m_priority(0) + {} +}; + +static const acl_stage_lookup_t aclStageLookup = { + {STAGE_INGRESS, SAI_ACL_STAGE_INGRESS}, + {STAGE_EGRESS, SAI_ACL_STAGE_EGRESS}, + {STAGE_PRE_INGRESS, SAI_ACL_STAGE_PRE_INGRESS}, +}; + +static const acl_stage_to_switch_attr_lookup_t aclStageToSwitchAttrLookup = { + {SAI_ACL_STAGE_INGRESS, SAI_SWITCH_ATTR_INGRESS_ACL}, + {SAI_ACL_STAGE_EGRESS, SAI_SWITCH_ATTR_EGRESS_ACL}, + {SAI_ACL_STAGE_PRE_INGRESS, SAI_SWITCH_ATTR_PRE_INGRESS_ACL}, +}; diff --git a/orchagent/copporch.cpp b/orchagent/copporch.cpp index d193e215c34e..8a58ae73a084 100644 --- a/orchagent/copporch.cpp +++ b/orchagent/copporch.cpp @@ -1079,16 +1079,20 @@ bool CoppOrch::getAttribsFromTrapGroup (vector &fv_tuple, genetlink_attribs.push_back(attr); attr.id = SAI_HOSTIF_ATTR_NAME; + auto size = sizeof(attr.value.chardata); strncpy(attr.value.chardata, fvValue(*i).c_str(), - sizeof(attr.value.chardata)); + size - 1); + attr.value.chardata[size - 1] = '\0'; genetlink_attribs.push_back(attr); } else if (fvField(*i) == copp_genetlink_mcgrp_name) { attr.id = SAI_HOSTIF_ATTR_GENETLINK_MCGRP_NAME; + auto size = sizeof(attr.value.chardata); strncpy(attr.value.chardata, fvValue(*i).c_str(), - sizeof(attr.value.chardata)); + size - 1); + attr.value.chardata[size - 1] = '\0'; genetlink_attribs.push_back(attr); } else diff --git a/orchagent/copporch.h b/orchagent/copporch.h index 096979ebb8e1..d774db64bab3 100644 --- a/orchagent/copporch.h +++ b/orchagent/copporch.h @@ -65,6 +65,16 @@ class CoppOrch : public Orch CoppOrch(swss::DBConnector* db, std::string tableName); void generateHostIfTrapCounterIdList(); void clearHostIfTrapCounterIdList(); + + inline object_map getTrapGroupMap() + { + return m_trap_group_map; + } + + inline TrapGroupHostIfMap getTrapGroupHostIfMap() + { + return m_trap_group_hostif_map; + } protected: object_map m_trap_group_map; diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 0fee695c4e18..ff1d8afb18c9 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -48,6 +48,7 @@ MlagOrch *gMlagOrch; IsoGrpOrch *gIsoGrpOrch; MACsecOrch *gMacsecOrch; CoppOrch *gCoppOrch; +P4Orch *gP4Orch; BfdOrch *gBfdOrch; Srv6Orch *gSrv6Orch; @@ -91,6 +92,9 @@ bool OrchDaemon::init() SWSS_LOG_ENTER(); string platform = getenv("platform") ? getenv("platform") : ""; + + gCrmOrch = new CrmOrch(m_configDb, CFG_CRM_TABLE_NAME); + TableConnector stateDbSwitchTable(m_stateDb, "SWITCH_CAPABILITY"); TableConnector app_switch_table(m_applDb, APP_SWITCH_TABLE_NAME); TableConnector conf_asic_sensors(m_configDb, CFG_ASIC_SENSORS_TABLE_NAME); @@ -118,7 +122,6 @@ bool OrchDaemon::init() { APP_MCLAG_FDB_TABLE_NAME, FdbOrch::fdborch_pri} }; - gCrmOrch = new CrmOrch(m_configDb, CFG_CRM_TABLE_NAME); gPortsOrch = new PortsOrch(m_applDb, m_stateDb, ports_tables, m_chassisAppDb); TableConnector stateDbFdb(m_stateDb, STATE_FDB_TABLE_NAME); TableConnector stateMclagDbFdb(m_stateDb, STATE_MCLAG_REMOTE_FDB_TABLE_NAME); @@ -603,6 +606,10 @@ bool OrchDaemon::init() m_orchList.push_back(&CounterCheckOrch::getInstance(m_configDb)); + vector p4rt_tables = {APP_P4RT_TABLE_NAME}; + gP4Orch = new P4Orch(m_applDb, p4rt_tables, vrf_orch, gCoppOrch); + m_orchList.push_back(gP4Orch); + if (WarmStart::isWarmStart()) { bool suc = warmRestoreAndSyncUp(); diff --git a/orchagent/orchdaemon.h b/orchagent/orchdaemon.h index aca8c2869705..ea49affbfc1b 100644 --- a/orchagent/orchdaemon.h +++ b/orchagent/orchdaemon.h @@ -40,6 +40,7 @@ #include "mlagorch.h" #include "muxorch.h" #include "macsecorch.h" +#include "p4orch/p4orch.h" #include "bfdorch.h" #include "srv6orch.h" diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 16b4922bc939..843ffbd7f1cf 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -163,6 +163,8 @@ class PortsOrch : public Orch, public Subject bool getPortIPG(sai_object_id_t port_id, uint32_t &ipg); bool setPortIPG(sai_object_id_t port_id, uint32_t ipg); + bool getPortOperStatus(const Port& port, sai_port_oper_status_t& status) const; + private: unique_ptr m_counterTable; unique_ptr
m_counterLagTable; @@ -322,7 +324,6 @@ class PortsOrch : public Orch, public Subject task_process_status setPortInterfaceType(sai_object_id_t id, sai_port_interface_type_t interface_type); task_process_status setPortAdvInterfaceTypes(sai_object_id_t id, std::vector &interface_types); - bool getPortOperStatus(const Port& port, sai_port_oper_status_t& status) const; void updatePortOperStatus(Port &port, sai_port_oper_status_t status); bool getPortOperSpeed(const Port& port, sai_uint32_t& speed) const; @@ -363,4 +364,3 @@ class PortsOrch : public Orch, public Subject }; #endif /* SWSS_PORTSORCH_H */ - diff --git a/orchagent/saihelper.cpp b/orchagent/saihelper.cpp index 8db9676f394f..3b409f7217f0 100644 --- a/orchagent/saihelper.cpp +++ b/orchagent/saihelper.cpp @@ -57,6 +57,7 @@ sai_qos_map_api_t* sai_qos_map_api; sai_buffer_api_t* sai_buffer_api; sai_acl_api_t* sai_acl_api; sai_hash_api_t* sai_hash_api; +sai_udf_api_t* sai_udf_api; sai_mirror_api_t* sai_mirror_api; sai_fdb_api_t* sai_fdb_api; sai_dtel_api_t* sai_dtel_api; @@ -186,6 +187,7 @@ void initSaiApi() sai_api_query(SAI_API_SCHEDULER_GROUP, (void **)&sai_scheduler_group_api); sai_api_query(SAI_API_ACL, (void **)&sai_acl_api); sai_api_query(SAI_API_HASH, (void **)&sai_hash_api); + sai_api_query(SAI_API_UDF, (void **)&sai_udf_api); sai_api_query(SAI_API_DTEL, (void **)&sai_dtel_api); sai_api_query(SAI_API_SAMPLEPACKET, (void **)&sai_samplepacket_api); sai_api_query(SAI_API_DEBUG_COUNTER, (void **)&sai_debug_counter_api); @@ -223,6 +225,7 @@ void initSaiApi() sai_log_set(SAI_API_SCHEDULER_GROUP, SAI_LOG_LEVEL_NOTICE); sai_log_set(SAI_API_ACL, SAI_LOG_LEVEL_NOTICE); sai_log_set(SAI_API_HASH, SAI_LOG_LEVEL_NOTICE); + sai_log_set(SAI_API_UDF, SAI_LOG_LEVEL_NOTICE); sai_log_set(SAI_API_DTEL, SAI_LOG_LEVEL_NOTICE); sai_log_set(SAI_API_SAMPLEPACKET, SAI_LOG_LEVEL_NOTICE); sai_log_set(SAI_API_DEBUG_COUNTER, SAI_LOG_LEVEL_NOTICE); diff --git a/orchagent/switchorch.cpp b/orchagent/switchorch.cpp index daeace8b08a5..1251a956e33b 100644 --- a/orchagent/switchorch.cpp +++ b/orchagent/switchorch.cpp @@ -2,17 +2,21 @@ #include #include "switchorch.h" +#include "crmorch.h" #include "converter.h" #include "notifier.h" #include "notificationproducer.h" #include "macaddress.h" +#include "return_code.h" using namespace std; using namespace swss; extern sai_object_id_t gSwitchId; extern sai_switch_api_t *sai_switch_api; +extern sai_acl_api_t *sai_acl_api; extern MacAddress gVxlanMacAddress; +extern CrmOrch *gCrmOrch; const map switch_attribute_map = { @@ -57,6 +61,92 @@ SwitchOrch::SwitchOrch(DBConnector *db, vector& connectors, Tabl Orch::addExecutor(executorT); } +void SwitchOrch::initAclGroupsBindToSwitch() +{ + // Create an ACL group per stage, INGRESS, EGRESS and PRE_INGRESS + for (auto stage_it : aclStageLookup) + { + sai_object_id_t group_oid; + auto status = createAclGroup(fvValue(stage_it), &group_oid); + if (!status.ok()) + { + status.prepend("Failed to create ACL group for stage " + fvField(stage_it) + ": "); + SWSS_LOG_THROW("%s", status.message().c_str()); + } + SWSS_LOG_NOTICE("Created ACL group for stage %s", fvField(stage_it).c_str()); + m_aclGroups[fvValue(stage_it)] = group_oid; + status = bindAclGroupToSwitch(fvValue(stage_it), group_oid); + if (!status.ok()) + { + status.prepend("Failed to bind ACL group to stage " + fvField(stage_it) + ": "); + SWSS_LOG_THROW("%s", status.message().c_str()); + } + } +} + +const std::map &SwitchOrch::getAclGroupOidsBindingToSwitch() +{ + return m_aclGroups; +} + +ReturnCode SwitchOrch::createAclGroup(const sai_acl_stage_t &group_stage, sai_object_id_t *acl_grp_oid) +{ + SWSS_LOG_ENTER(); + + std::vector acl_grp_attrs; + sai_attribute_t acl_grp_attr; + acl_grp_attr.id = SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE; + acl_grp_attr.value.s32 = group_stage; + acl_grp_attrs.push_back(acl_grp_attr); + + acl_grp_attr.id = SAI_ACL_TABLE_GROUP_ATTR_TYPE; + acl_grp_attr.value.s32 = SAI_ACL_TABLE_GROUP_TYPE_PARALLEL; + acl_grp_attrs.push_back(acl_grp_attr); + + acl_grp_attr.id = SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST; + std::vector bpoint_list; + bpoint_list.push_back(SAI_ACL_BIND_POINT_TYPE_SWITCH); + acl_grp_attr.value.s32list.count = (uint32_t)bpoint_list.size(); + acl_grp_attr.value.s32list.list = bpoint_list.data(); + acl_grp_attrs.push_back(acl_grp_attr); + + CHECK_ERROR_AND_LOG_AND_RETURN(sai_acl_api->create_acl_table_group( + acl_grp_oid, gSwitchId, (uint32_t)acl_grp_attrs.size(), acl_grp_attrs.data()), + "Failed to create ACL group for stage " << group_stage); + if (group_stage == SAI_ACL_STAGE_INGRESS || group_stage == SAI_ACL_STAGE_PRE_INGRESS || + group_stage == SAI_ACL_STAGE_EGRESS) + { + gCrmOrch->incCrmAclUsedCounter(CrmResourceType::CRM_ACL_GROUP, (sai_acl_stage_t)group_stage, + SAI_ACL_BIND_POINT_TYPE_SWITCH); + } + SWSS_LOG_INFO("Suceeded to create ACL group %s in stage %d ", sai_serialize_object_id(*acl_grp_oid).c_str(), + group_stage); + return ReturnCode(); +} + +ReturnCode SwitchOrch::bindAclGroupToSwitch(const sai_acl_stage_t &group_stage, const sai_object_id_t &acl_grp_oid) +{ + SWSS_LOG_ENTER(); + + auto switch_attr_it = aclStageToSwitchAttrLookup.find(group_stage); + if (switch_attr_it == aclStageToSwitchAttrLookup.end()) + { + LOG_ERROR_AND_RETURN(ReturnCode(StatusCode::SWSS_RC_INVALID_PARAM) + << "Failed to set ACL group(" << acl_grp_oid << ") to the SWITCH bind point at stage " + << group_stage); + } + sai_attribute_t attr; + attr.id = switch_attr_it->second; + attr.value.oid = acl_grp_oid; + auto sai_status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); + if (sai_status != SAI_STATUS_SUCCESS) + { + LOG_ERROR_AND_RETURN(ReturnCode(sai_status) << "[SAI] Failed to set_switch_attribute with attribute.id=" + << attr.id << " and acl group oid=" << acl_grp_oid); + } + return ReturnCode(); +} + void SwitchOrch::doCfgSensorsTableTask(Consumer &consumer) { SWSS_LOG_ENTER(); diff --git a/orchagent/switchorch.h b/orchagent/switchorch.h index 46d165bd48a4..8c3789f52350 100644 --- a/orchagent/switchorch.h +++ b/orchagent/switchorch.h @@ -1,5 +1,6 @@ #pragma once +#include "acltable.h" #include "orch.h" #include "timer.h" @@ -29,6 +30,13 @@ class SwitchOrch : public Orch bool setAgingFDB(uint32_t sec); void set_switch_capability(const std::vector& values); bool querySwitchDscpToTcCapability(sai_object_type_t sai_object, sai_attr_id_t attr_id); + + // Return reference to ACL group created for each stage and the bind point is + // the switch + const std::map &getAclGroupOidsBindingToSwitch(); + // Initialize the ACL groups bind to Switch + void initAclGroupsBindToSwitch(); + private: void doTask(Consumer &consumer); void doTask(swss::SelectableTimer &timer); @@ -38,10 +46,20 @@ class SwitchOrch : public Orch void querySwitchTpidCapability(); sai_status_t setSwitchTunnelVxlanParams(swss::FieldValueTuple &val); + // Create the default ACL group for the given stage, bind point is + // SAI_ACL_BIND_POINT_TYPE_SWITCH and group type is + // SAI_ACL_TABLE_GROUP_TYPE_PARALLEL. + ReturnCode createAclGroup(const sai_acl_stage_t &group_stage, sai_object_id_t *acl_grp_oid); + + // Bind the ACL group to switch for the given stage. + // Set the SAI_SWITCH_ATTR_{STAGE}_ACL with the group oid. + ReturnCode bindAclGroupToSwitch(const sai_acl_stage_t &group_stage, const sai_object_id_t &acl_grp_oid); + swss::NotificationConsumer* m_restartCheckNotificationConsumer; void doTask(swss::NotificationConsumer& consumer); swss::DBConnector *m_db; swss::Table m_switchTable; + std::map m_aclGroups; sai_object_id_t m_switchTunnelId; // ASIC temperature sensors diff --git a/tests/mock_tests/Makefile.am b/tests/mock_tests/Makefile.am index 51df17f7299f..11cd00670ef0 100644 --- a/tests/mock_tests/Makefile.am +++ b/tests/mock_tests/Makefile.am @@ -1,5 +1,6 @@ FLEX_CTR_DIR = $(top_srcdir)/orchagent/flex_counter DEBUG_CTR_DIR = $(top_srcdir)/orchagent/debug_counter +P4_ORCH_DIR = $(top_srcdir)/orchagent/p4orch INCLUDES = -I $(FLEX_CTR_DIR) -I $(DEBUG_CTR_DIR) -I $(top_srcdir)/lib @@ -89,6 +90,18 @@ tests_SOURCES = aclorch_ut.cpp \ tests_SOURCES += $(FLEX_CTR_DIR)/flex_counter_manager.cpp $(FLEX_CTR_DIR)/flex_counter_stat_manager.cpp $(FLEX_CTR_DIR)/flow_counter_handler.cpp tests_SOURCES += $(DEBUG_CTR_DIR)/debug_counter.cpp $(DEBUG_CTR_DIR)/drop_counter.cpp +tests_SOURCES += $(P4_ORCH_DIR)/p4orch.cpp \ + $(P4_ORCH_DIR)/p4orch_util.cpp \ + $(P4_ORCH_DIR)/p4oidmapper.cpp \ + $(P4_ORCH_DIR)/router_interface_manager.cpp \ + $(P4_ORCH_DIR)/neighbor_manager.cpp \ + $(P4_ORCH_DIR)/next_hop_manager.cpp \ + $(P4_ORCH_DIR)/route_manager.cpp \ + $(P4_ORCH_DIR)/acl_util.cpp \ + $(P4_ORCH_DIR)/acl_table_manager.cpp \ + $(P4_ORCH_DIR)/acl_rule_manager.cpp \ + $(P4_ORCH_DIR)/wcmp_manager.cpp \ + $(P4_ORCH_DIR)/mirror_session_manager.cpp tests_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_GTEST) $(CFLAGS_SAI) tests_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_GTEST) $(CFLAGS_SAI) -I$(top_srcdir)/orchagent diff --git a/tests/mock_tests/aclorch_ut.cpp b/tests/mock_tests/aclorch_ut.cpp index c0d7399570c4..295fed20baa6 100644 --- a/tests/mock_tests/aclorch_ut.cpp +++ b/tests/mock_tests/aclorch_ut.cpp @@ -342,6 +342,9 @@ namespace aclorch_test gVirtualRouterId = attr.value.oid; + ASSERT_EQ(gCrmOrch, nullptr); + gCrmOrch = new CrmOrch(m_config_db.get(), CFG_CRM_TABLE_NAME); + TableConnector stateDbSwitchTable(m_state_db.get(), "SWITCH_CAPABILITY"); TableConnector conf_asic_sensors(m_config_db.get(), CFG_ASIC_SENSORS_TABLE_NAME); TableConnector app_switch_table(m_app_db.get(), APP_SWITCH_TABLE_NAME); @@ -369,9 +372,6 @@ namespace aclorch_test ASSERT_EQ(gPortsOrch, nullptr); gPortsOrch = new PortsOrch(m_app_db.get(), m_state_db.get(), ports_tables, m_chassis_app_db.get()); - ASSERT_EQ(gCrmOrch, nullptr); - gCrmOrch = new CrmOrch(m_config_db.get(), CFG_CRM_TABLE_NAME); - ASSERT_EQ(gVrfOrch, nullptr); gVrfOrch = new VRFOrch(m_app_db.get(), APP_VRF_TABLE_NAME, m_state_db.get(), STATE_VRF_OBJECT_TABLE_NAME); diff --git a/tests/mock_tests/mock_orchagent_main.h b/tests/mock_tests/mock_orchagent_main.h index 181ebac88973..321f3d15d251 100644 --- a/tests/mock_tests/mock_orchagent_main.h +++ b/tests/mock_tests/mock_orchagent_main.h @@ -61,3 +61,4 @@ extern sai_next_hop_api_t *sai_next_hop_api; extern sai_hostif_api_t *sai_hostif_api; extern sai_buffer_api_t *sai_buffer_api; extern sai_queue_api_t *sai_queue_api; +extern sai_udf_api_t* sai_udf_api;