From 429b21284eb3104e5481e33696ddd518af0db06f Mon Sep 17 00:00:00 2001 From: Shuotian Cheng Date: Sun, 28 Apr 2019 11:25:55 -0700 Subject: [PATCH 1/6] [mirrororch]: Fix comments typo (#863) Signed-off-by: Shu0T1an ChenG --- orchagent/mirrororch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orchagent/mirrororch.cpp b/orchagent/mirrororch.cpp index 120eb7b17a2..e295ecb7c74 100644 --- a/orchagent/mirrororch.cpp +++ b/orchagent/mirrororch.cpp @@ -566,7 +566,7 @@ bool MirrorOrch::activateSession(const string& name, MirrorEntry& session) MirrorSessionUpdate update = { name, true }; notify(SUBJECT_TYPE_MIRROR_SESSION_CHANGE, static_cast(&update)); - SWSS_LOG_NOTICE("Activate mirror session %s", name.c_str()); + SWSS_LOG_NOTICE("Activated mirror session %s", name.c_str()); return true; } @@ -593,7 +593,7 @@ bool MirrorOrch::deactivateSession(const string& name, MirrorEntry& session) // Store whole state into StateDB, since it is far from that frequent it's durable setSessionState(name, session); - SWSS_LOG_NOTICE("Deactive mirror session %s", name.c_str()); + SWSS_LOG_NOTICE("Deactivated mirror session %s", name.c_str()); return true; } From 4606d6cb86c4241b9f03fb0f7f030b7a0a371e77 Mon Sep 17 00:00:00 2001 From: Shuotian Cheng Date: Mon, 29 Apr 2019 09:46:09 -0700 Subject: [PATCH 2/6] [aclorch]: Add MIRRORv6 and MIRRORv4v6 support for ACL table (#825) Enable both IPv4 and IPv6 source and destination IP match and mirror functionality in SONiC. Signed-off-by: Shu0T1an ChenG --- orchagent/aclorch.cpp | 298 ++++++++++++++++-- orchagent/aclorch.h | 52 +++- orchagent/orchdaemon.cpp | 5 +- tests/test_mirror_ipv6_combined.py | 484 +++++++++++++++++++++++++++++ tests/test_mirror_ipv6_separate.py | 478 ++++++++++++++++++++++++++++ 5 files changed, 1270 insertions(+), 47 deletions(-) create mode 100644 tests/test_mirror_ipv6_combined.py create mode 100644 tests/test_mirror_ipv6_separate.py diff --git a/orchagent/aclorch.cpp b/orchagent/aclorch.cpp index d79f8213c6d..675897592c6 100644 --- a/orchagent/aclorch.cpp +++ b/orchagent/aclorch.cpp @@ -85,6 +85,7 @@ static acl_table_type_lookup_t aclTableTypeLookUp = { TABLE_TYPE_L3, ACL_TABLE_L3 }, { TABLE_TYPE_L3V6, ACL_TABLE_L3V6 }, { TABLE_TYPE_MIRROR, ACL_TABLE_MIRROR }, + { TABLE_TYPE_MIRRORV6, ACL_TABLE_MIRRORV6 }, { TABLE_TYPE_CTRLPLANE, ACL_TABLE_CTRLPLANE }, { TABLE_TYPE_DTEL_FLOW_WATCHLIST, ACL_TABLE_DTEL_FLOW_WATCHLIST }, { TABLE_TYPE_DTEL_DROP_WATCHLIST, ACL_TABLE_DTEL_DROP_WATCHLIST } @@ -589,12 +590,17 @@ shared_ptr AclRule::makeShared(acl_table_type_t type, AclOrch *acl, Mir throw runtime_error("ACL rule action is not found in rule " + rule); } - if (type != ACL_TABLE_L3 && type != ACL_TABLE_L3V6 && type != ACL_TABLE_MIRROR && type != ACL_TABLE_DTEL_FLOW_WATCHLIST && type != ACL_TABLE_DTEL_DROP_WATCHLIST) + if (type != ACL_TABLE_L3 && + type != ACL_TABLE_L3V6 && + type != ACL_TABLE_MIRROR && + type != ACL_TABLE_MIRRORV6 && + type != ACL_TABLE_DTEL_FLOW_WATCHLIST && + type != ACL_TABLE_DTEL_DROP_WATCHLIST) { - throw runtime_error("Unknown table type."); + throw runtime_error("Unknown table type"); } - /* Mirror rules can exist in both tables*/ + /* Mirror rules can exist in both tables */ if (action == ACTION_MIRROR_ACTION) { return make_shared(acl, mirror, rule, table, type); @@ -948,6 +954,37 @@ bool AclRuleMirror::validateAddMatch(string attr_name, string attr_value) return false; } + /* + * Type of Tables and Supported Match Types (Configuration) + * |--------------------------------------------------| + * | Match Type | TABLE_MIRROR | TABLE_MIRRORV6 | + * |--------------------------------------------------| + * | MATCH_SRC_IP | √ | | + * | MATCH_DST_IP | √ | | + * |--------------------------------------------------| + * | MATCH_SRC_IPV6 | | √ | + * | MATCH_DST_IPV6 | | √ | + * |--------------------------------------------------| + * | MARTCH_ETHERTYPE | √ | | + * |--------------------------------------------------| + */ + + if (m_tableType == ACL_TABLE_MIRROR && + (attr_name == MATCH_SRC_IPV6 || attr_name == MATCH_DST_IPV6)) + { + SWSS_LOG_ERROR("%s match is not supported for the table of type MIRROR", + attr_name.c_str()); + return false; + } + + if (m_tableType == ACL_TABLE_MIRRORV6 && + (attr_name == MATCH_SRC_IP || attr_name == MATCH_DST_IP || attr_name == MATCH_ETHER_TYPE)) + { + SWSS_LOG_ERROR("%s match is not supported for the table of type MIRRORV6", + attr_name.c_str()); + return false; + } + return AclRule::validateAddMatch(attr_name, attr_value); } @@ -1118,9 +1155,12 @@ bool AclTable::create() return status == SAI_STATUS_SUCCESS; } - attr.id = SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE; - attr.value.booldata = true; - table_attrs.push_back(attr); + if (type != ACL_TABLE_MIRRORV6) + { + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE; + attr.value.booldata = true; + table_attrs.push_back(attr); + } attr.id = SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE; attr.value.booldata = true; @@ -1130,7 +1170,47 @@ bool AclTable::create() attr.value.booldata = true; table_attrs.push_back(attr); - if (type == ACL_TABLE_L3V6) + /* + * Type of Tables and Supported Match Types (ASIC database) + * |-----------------------------------------------------------------| + * | | TABLE_MIRROR | TABLE_MIRROR | TABLE_MIRRORV6 | + * | Match Type |----------------------------------------------| + * | | combined | separated | + * |-----------------------------------------------------------------| + * | MATCH_SRC_IP | √ | √ | | + * | MATCH_DST_IP | √ | √ | | + * |-----------------------------------------------------------------| + * | MATCH_SRC_IPV6 | √ | | √ | + * | MATCH_DST_IPV6 | √ | | √ | + * |-----------------------------------------------------------------| + * | MARTCH_ETHERTYPE | √ | √ | | + * |-----------------------------------------------------------------| + */ + + if (type == ACL_TABLE_MIRROR) + { + attr.id = SAI_ACL_TABLE_ATTR_FIELD_SRC_IP; + attr.value.booldata = true; + table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_DST_IP; + attr.value.booldata = true; + table_attrs.push_back(attr); + + // If the switch supports v6 and requires one single table + if (m_pAclOrch->m_mirrorTableCapabilities[ACL_TABLE_MIRRORV6] && + m_pAclOrch->m_isCombinedMirrorV6Table) + { + attr.id = SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6; + attr.value.booldata = true; + table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6; + attr.value.booldata = true; + table_attrs.push_back(attr); + } + } + else if (type == ACL_TABLE_L3V6 || type == ACL_TABLE_MIRRORV6) // v6 only { attr.id = SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6; attr.value.booldata = true; @@ -1140,7 +1220,7 @@ bool AclTable::create() attr.value.booldata = true; table_attrs.push_back(attr); } - else + else // v4 only { attr.id = SAI_ACL_TABLE_ATTR_FIELD_SRC_IP; attr.value.booldata = true; @@ -1780,6 +1860,65 @@ void AclOrch::init(vector& connectors, PortsOrch *portOrch, Mirr { SWSS_LOG_ENTER(); + // TODO: Query SAI to get mirror table capabilities + // Right now, verified platforms that support mirroring IPv6 packets are + // Broadcom and Mellanox. Virtual switch is also supported for testing + // purposes. + string platform = getenv("platform") ? getenv("platform") : ""; + if (platform == BRCM_PLATFORM_SUBSTRING || + platform == MLNX_PLATFORM_SUBSTRING) + { + m_mirrorTableCapabilities = + { + { ACL_TABLE_MIRROR, true }, + { ACL_TABLE_MIRRORV6, true }, + }; + } + else + { + m_mirrorTableCapabilities = + { + { ACL_TABLE_MIRROR, true }, + { ACL_TABLE_MIRRORV6, false }, + }; + } + + SWSS_LOG_NOTICE("%s switch capability:", platform.c_str()); + SWSS_LOG_NOTICE(" ACL_TABLE_MIRROR: %s", + m_mirrorTableCapabilities[ACL_TABLE_MIRROR] ? "yes" : "no"); + SWSS_LOG_NOTICE(" ACL_TABLE_MIRRORV6: %s", + m_mirrorTableCapabilities[ACL_TABLE_MIRRORV6] ? "yes" : "no"); + + // In Broadcom platform, V4 and V6 rules are stored in the same table + if (platform == BRCM_PLATFORM_SUBSTRING) { + m_isCombinedMirrorV6Table = true; + } + + // In Mellanox platform, V4 and V6 rules are stored in different tables + if (platform == MLNX_PLATFORM_SUBSTRING) { + m_isCombinedMirrorV6Table = false; + } + + // Store the capabilities in state database + // TODO: Move this part of the code into syncd + vector fvVector; + for (auto const& it : m_mirrorTableCapabilities) + { + string value = it.second ? "true" : "false"; + switch (it.first) + { + case ACL_TABLE_MIRROR: + fvVector.emplace_back(TABLE_TYPE_MIRROR, value); + break; + case ACL_TABLE_MIRRORV6: + fvVector.emplace_back(TABLE_TYPE_MIRRORV6, value); + break; + default: + break; + } + } + m_switchTable.set("switch", fvVector); + sai_attribute_t attrs[2]; attrs[0].id = SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY; attrs[1].id = SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY; @@ -1809,20 +1948,10 @@ void AclOrch::init(vector& connectors, PortsOrch *portOrch, Mirr timer->start(); } -AclOrch::AclOrch(vector& connectors, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch) : - Orch(connectors), - m_mirrorOrch(mirrorOrch), - m_neighOrch(neighOrch), - m_routeOrch(routeOrch), - m_dTelOrch(NULL) -{ - SWSS_LOG_ENTER(); - - init(connectors, portOrch, mirrorOrch, neighOrch, routeOrch); -} - -AclOrch::AclOrch(vector& connectors, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch, DTelOrch *dtelOrch) : +AclOrch::AclOrch(vector& connectors, TableConnector switchTable, + PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch, DTelOrch *dtelOrch) : Orch(connectors), + m_switchTable(switchTable.first, switchTable.second), m_mirrorOrch(mirrorOrch), m_neighOrch(neighOrch), m_routeOrch(routeOrch), @@ -1835,9 +1964,8 @@ AclOrch::AclOrch(vector& connectors, PortsOrch *portOrch, Mirror if (m_dTelOrch) { m_dTelOrch->attach(this); + createDTelWatchListTables(); } - - createDTelWatchListTables(); } AclOrch::~AclOrch() @@ -1937,11 +2065,51 @@ bool AclOrch::addAclTable(AclTable &newTable, string table_id) } } + // Check if a separate mirror table is needed or not based on the platform + if (newTable.type == ACL_TABLE_MIRROR || newTable.type == ACL_TABLE_MIRRORV6) + { + + if (m_isCombinedMirrorV6Table && + (!m_mirrorTableId.empty() || !m_mirrorV6TableId.empty())) { + + string orig_table_name; + + // If v4 table is created, mark v6 table is created + if (!m_mirrorTableId.empty()) + { + orig_table_name = m_mirrorTableId; + m_mirrorV6TableId = newTable.id; + } + // If v6 table is created, mark v4 table is created + else + { + orig_table_name = m_mirrorV6TableId; + m_mirrorTableId = newTable.id; + } + + SWSS_LOG_NOTICE("Created ACL table %s as a sibling of %s", + newTable.id.c_str(), orig_table_name.c_str()); + + return true; + } + } + if (createBindAclTable(newTable, table_oid)) { m_AclTables[table_oid] = newTable; SWSS_LOG_NOTICE("Created ACL table %s oid:%lx", newTable.id.c_str(), table_oid); + + // Mark the existence of the mirror table + if (newTable.type == ACL_TABLE_MIRROR) + { + m_mirrorTableId = table_id; + } + else if (newTable.type == ACL_TABLE_MIRRORV6) + { + m_mirrorV6TableId = table_id; + } + return true; } else @@ -1974,6 +2142,26 @@ bool AclOrch::removeAclTable(string table_id) SWSS_LOG_NOTICE("Successfully deleted ACL table %s", table_id.c_str()); m_AclTables.erase(table_oid); + // Clear mirror table information + // If the v4 and v6 ACL mirror tables are combined together, + // remove both of them. + if (table_id == m_mirrorTableId) + { + m_mirrorTableId.clear(); + if (m_isCombinedMirrorV6Table) + { + m_mirrorV6TableId.clear(); + } + } + else if (table_id == m_mirrorV6TableId) + { + m_mirrorV6TableId.clear(); + if (m_isCombinedMirrorV6Table) + { + m_mirrorTableId.clear(); + } + } + return true; } else @@ -2007,6 +2195,11 @@ bool AclOrch::removeAclRule(string table_id, string rule_id) return m_AclTables[table_oid].remove(rule_id); } +bool AclOrch::isCombinedMirrorV6Table() +{ + return m_isCombinedMirrorV6Table; +} + void AclOrch::doAclTableTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -2024,9 +2217,10 @@ void AclOrch::doAclTableTask(Consumer &consumer) if (op == SET_COMMAND) { - AclTable newTable; + AclTable newTable(this); bool bAllAttributesOk = true; + // Scan all attributes for (auto itp : kfvFieldsValues(t)) { newTable.id = table_id; @@ -2133,12 +2327,15 @@ void AclOrch::doAclRuleTask(Consumer &consumer) { bool bAllAttributesOk = true; shared_ptr newRule; + + // Get the ACL table OID sai_object_id_t table_oid = getTableById(table_id); /* ACL table is not yet created or ACL table is a control plane table */ /* TODO: Remove ACL_TABLE_UNKNOWN as a table with this type cannot be successfully created */ if (table_oid == SAI_NULL_OBJECT_ID || m_AclTables[table_oid].type == ACL_TABLE_UNKNOWN) { + /* Skip the control plane rules */ if (m_ctrlAclTables.find(table_id) != m_ctrlAclTables.end()) { @@ -2152,7 +2349,14 @@ void AclOrch::doAclRuleTask(Consumer &consumer) continue; } - newRule = AclRule::makeShared(m_AclTables[table_oid].type, this, m_mirrorOrch, m_dTelOrch, rule_id, table_id, t); + auto type = m_AclTables[table_oid].type; + if (type == ACL_TABLE_MIRROR || type == ACL_TABLE_MIRRORV6) + { + type = table_id == m_mirrorTableId ? ACL_TABLE_MIRROR : ACL_TABLE_MIRRORV6; + } + + + newRule = AclRule::makeShared(type, this, m_mirrorOrch, m_dTelOrch, rule_id, table_id, t); for (const auto& itr : kfvFieldsValues(t)) { @@ -2254,14 +2458,34 @@ bool AclOrch::processAclTableType(string type, acl_table_type_t &table_type) { SWSS_LOG_ENTER(); - auto tt = aclTableTypeLookUp.find(to_upper(type)); + auto iter = aclTableTypeLookUp.find(to_upper(type)); - if (tt == aclTableTypeLookUp.end()) + if (iter == aclTableTypeLookUp.end()) { return false; } - table_type = tt->second; + table_type = iter->second; + + // Mirror table check procedure + if (table_type == ACL_TABLE_MIRROR || table_type == ACL_TABLE_MIRRORV6) + { + // Check the switch capability + if (!m_mirrorTableCapabilities[table_type]) + { + SWSS_LOG_ERROR("Mirror table type %s is not supported", type.c_str()); + return false; + } + + // Check the existence of current mirror tables + // Note: only one table per type could be created + if ((table_type == ACL_TABLE_MIRROR && !m_mirrorTableId.empty()) || + (table_type == ACL_TABLE_MIRRORV6 && !m_mirrorV6TableId.empty())) + { + SWSS_LOG_ERROR("Mirror table table_type %s has already been created", type.c_str()); + return false; + } + } return true; } @@ -2295,6 +2519,22 @@ sai_object_id_t AclOrch::getTableById(string table_id) } } + // Check if the table is a mirror table and a sibling mirror table is created + if (m_isCombinedMirrorV6Table && + (table_id == m_mirrorTableId || table_id == m_mirrorV6TableId)) + { + // If the table is v4, the corresponding v6 table is already created + if (table_id == m_mirrorTableId) + { + return getTableById(m_mirrorV6TableId); + } + // If the table is v6, the corresponding v4 table is already created + else + { + return getTableById(m_mirrorTableId); + } + } + return SAI_NULL_OBJECT_ID; } @@ -2538,7 +2778,7 @@ sai_status_t AclOrch::deleteDTelWatchListTables() { SWSS_LOG_ENTER(); - AclTable flowWLTable, dropWLTable; + AclTable flowWLTable(this), dropWLTable(this); sai_object_id_t table_oid; string table_id = TABLE_TYPE_DTEL_FLOW_WATCHLIST; diff --git a/orchagent/aclorch.h b/orchagent/aclorch.h index 1be9704508e..4e18924f7c0 100644 --- a/orchagent/aclorch.h +++ b/orchagent/aclorch.h @@ -24,13 +24,14 @@ #define TABLE_PORTS "PORTS" #define TABLE_SERVICES "SERVICES" -#define TABLE_TYPE_L3 "L3" -#define TABLE_TYPE_L3V6 "L3V6" -#define TABLE_TYPE_MIRROR "MIRROR" -#define TABLE_TYPE_PFCWD "PFCWD" -#define TABLE_TYPE_CTRLPLANE "CTRLPLANE" -#define TABLE_TYPE_DTEL_FLOW_WATCHLIST "DTEL_FLOW_WATCHLIST" -#define TABLE_TYPE_DTEL_DROP_WATCHLIST "DTEL_DROP_WATCHLIST" +#define TABLE_TYPE_L3 "L3" +#define TABLE_TYPE_L3V6 "L3V6" +#define TABLE_TYPE_MIRROR "MIRROR" +#define TABLE_TYPE_MIRRORV6 "MIRRORV6" +#define TABLE_TYPE_PFCWD "PFCWD" +#define TABLE_TYPE_CTRLPLANE "CTRLPLANE" +#define TABLE_TYPE_DTEL_FLOW_WATCHLIST "DTEL_FLOW_WATCHLIST" +#define TABLE_TYPE_DTEL_DROP_WATCHLIST "DTEL_DROP_WATCHLIST" #define RULE_PRIORITY "PRIORITY" #define MATCH_IN_PORTS "IN_PORTS" @@ -55,8 +56,8 @@ #define MATCH_INNER_L4_SRC_PORT "INNER_L4_SRC_PORT" #define MATCH_INNER_L4_DST_PORT "INNER_L4_DST_PORT" -#define ACTION_PACKET_ACTION "PACKET_ACTION" -#define ACTION_MIRROR_ACTION "MIRROR_ACTION" +#define ACTION_PACKET_ACTION "PACKET_ACTION" +#define ACTION_MIRROR_ACTION "MIRROR_ACTION" #define ACTION_DTEL_FLOW_OP "FLOW_OP" #define ACTION_DTEL_INT_SESSION "INT_SESSION" #define ACTION_DTEL_DROP_REPORT_ENABLE "DROP_REPORT_ENABLE" @@ -95,6 +96,7 @@ typedef enum ACL_TABLE_L3, ACL_TABLE_L3V6, ACL_TABLE_MIRROR, + ACL_TABLE_MIRRORV6, ACL_TABLE_PFCWD, ACL_TABLE_CTRLPLANE, ACL_TABLE_DTEL_FLOW_WATCHLIST, @@ -301,6 +303,7 @@ class AclRuleDTelDropWatchListEntry: public AclRule class AclTable { sai_object_id_t m_oid; + AclOrch *m_pAclOrch; public: string id; string description; @@ -317,7 +320,15 @@ class AclTable { set pendingPortSet; AclTable() - : type(ACL_TABLE_UNKNOWN) + : m_pAclOrch(NULL) + , type(ACL_TABLE_UNKNOWN) + , m_oid(SAI_NULL_OBJECT_ID) + , stage(ACL_STAGE_INGRESS) + {} + + AclTable(AclOrch *aclOrch) + : m_pAclOrch(aclOrch) + , type(ACL_TABLE_UNKNOWN) , m_oid(SAI_NULL_OBJECT_ID) , stage(ACL_STAGE_INGRESS) {} @@ -363,8 +374,8 @@ inline void split(string str, Iterable& out, char delim = ' ') class AclOrch : public Orch, public Observer { public: - AclOrch(vector& connectors, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch); - AclOrch(vector& connectors, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch, DTelOrch *m_dTelOrch); + AclOrch(vector& connectors, TableConnector switchTable, + PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch, DTelOrch *m_dTelOrch = NULL); ~AclOrch(); void update(SubjectType, void *); @@ -375,6 +386,8 @@ class AclOrch : public Orch, public Observer return m_countersTable; } + Table m_switchTable; + // FIXME: Add getters for them? I'd better to add a common directory of orch objects and use it everywhere MirrorOrch *m_mirrorOrch; NeighOrch *m_neighOrch; @@ -386,6 +399,11 @@ class AclOrch : public Orch, public Observer bool addAclRule(shared_ptr aclRule, string table_id); bool removeAclRule(string table_id, string rule_id); + bool isCombinedMirrorV6Table(); + + bool m_isCombinedMirrorV6Table = true; + map m_mirrorTableCapabilities; + private: void doTask(Consumer &consumer); void doAclTableTask(Consumer &consumer); @@ -393,6 +411,8 @@ class AclOrch : public Orch, public Observer void doTask(SelectableTimer &timer); void init(vector& connectors, PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch); + void queryMirrorTableCapability(); + static void collectCountersThread(AclOrch *pAclOrch); bool createBindAclTable(AclTable &aclTable, sai_object_id_t &table_oid); @@ -406,7 +426,6 @@ class AclOrch : public Orch, public Observer sai_status_t createDTelWatchListTables(); sai_status_t deleteDTelWatchListTables(); - //vector m_AclTables; map m_AclTables; // TODO: Move all ACL tables into one map: name -> instance map m_ctrlAclTables; @@ -414,8 +433,11 @@ class AclOrch : public Orch, public Observer static mutex m_countersMutex; static condition_variable m_sleepGuard; static bool m_bCollectCounters; - static swss::DBConnector m_db; - static swss::Table m_countersTable; + static DBConnector m_db; + static Table m_countersTable; + + string m_mirrorTableId; + string m_mirrorV6TableId; }; #endif /* SWSS_ACLORCH_H */ diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 998343716b1..189f5b53ad2 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -187,10 +187,9 @@ bool OrchDaemon::init() { dtel_orch = new DTelOrch(m_configDb, dtel_tables, gPortsOrch); m_orchList.push_back(dtel_orch); - gAclOrch = new AclOrch(acl_table_connectors, gPortsOrch, mirror_orch, gNeighOrch, gRouteOrch, dtel_orch); - } else { - gAclOrch = new AclOrch(acl_table_connectors, gPortsOrch, mirror_orch, gNeighOrch, gRouteOrch); } + TableConnector stateDbSwitchTable(m_stateDb, "SWITCH_CAPABILITY"); + gAclOrch = new AclOrch(acl_table_connectors, stateDbSwitchTable, gPortsOrch, mirror_orch, gNeighOrch, gRouteOrch, dtel_orch); m_orchList.push_back(gFdbOrch); m_orchList.push_back(mirror_orch); diff --git a/tests/test_mirror_ipv6_combined.py b/tests/test_mirror_ipv6_combined.py new file mode 100644 index 00000000000..f97315836a1 --- /dev/null +++ b/tests/test_mirror_ipv6_combined.py @@ -0,0 +1,484 @@ +# This test suite covers the functionality of mirror feature in SwSS + +import platform +import pytest +import time +from distutils.version import StrictVersion + +from swsscommon import swsscommon + +DVS_FAKE_PLATFORM = "broadcom" + + +class TestMirror(object): + def setup_db(self, dvs): + self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) + + def setup_mirrorv6_mode(self, mode): + tbl = swsscommon.Table(self.sdb, "SWITCH_CAPABILITY") + fvs = swsscommon.FieldValuePairs([("mirror_v6_table_mode", mode)]) + tbl.set("switch", fvs) + time.sleep(1) + + def set_interface_status(self, interface, admin_status): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL" + elif interface.startswith("Vlan"): + tbl_name = "VLAN" + else: + tbl_name = "PORT" + tbl = swsscommon.Table(self.cdb, tbl_name) + fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) + tbl.set(interface, fvs) + time.sleep(1) + + def add_ip_address(self, interface, ip): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL_INTERFACE" + elif interface.startswith("Vlan"): + tbl_name = "VLAN_INTERFACE" + else: + tbl_name = "INTERFACE" + tbl = swsscommon.Table(self.cdb, tbl_name) + fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) + tbl.set(interface + "|" + ip, fvs) + time.sleep(1) + + def remove_ip_address(self, interface, ip): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL_INTERFACE" + elif interface.startswith("Vlan"): + tbl_name = "VLAN_INTERFACE" + else: + tbl_name = "INTERFACE" + tbl = swsscommon.Table(self.cdb, tbl_name) + tbl._del(interface + "|" + ip) + time.sleep(1) + + def add_neighbor(self, interface, ip, mac): + tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") + fvs = swsscommon.FieldValuePairs([("neigh", mac), + ("family", "IPv4")]) + tbl.set(interface + ":" + ip, fvs) + time.sleep(1) + + def remove_neighbor(self, interface, ip): + tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") + tbl._del(interface + ":" + ip) + time.sleep(1) + + def add_route(self, dvs, prefix, nexthop): + dvs.runcmd("ip route add " + prefix + " via " + nexthop) + time.sleep(1) + + def remove_route(self, dvs, prefix): + dvs.runcmd("ip route del " + prefix) + time.sleep(1) + + def create_mirror_session(self, name, src, dst, gre, dscp, ttl, queue): + tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") + fvs = swsscommon.FieldValuePairs([("src_ip", src), + ("dst_ip", dst), + ("gre_type", gre), + ("dscp", dscp), + ("ttl", ttl), + ("queue", queue)]) + tbl.set(name, fvs) + time.sleep(1) + + def remove_mirror_session(self, name): + tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") + tbl._del(name) + time.sleep(1) + + def get_mirror_session_status(self, name): + return self.get_mirror_session_state(name)["status"] + + def get_mirror_session_state(self, name): + tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION") + (status, fvs) = tbl.get(name) + assert status == True + assert len(fvs) > 0 + return { fv[0]: fv[1] for fv in fvs } + + def create_acl_table(self, table, interfaces, type): + tbl = swsscommon.Table(self.cdb, "ACL_TABLE") + fvs = swsscommon.FieldValuePairs([("policy_desc", "mirror_test"), + ("type", type), + ("ports", ",".join(interfaces))]) + tbl.set(table, fvs) + time.sleep(1) + + def remove_acl_table(self, table): + tbl = swsscommon.Table(self.cdb, "ACL_TABLE") + tbl._del(table) + time.sleep(1) + + def create_mirror_acl_ipv4_rule(self, table, rule, session): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + fvs = swsscommon.FieldValuePairs([("priority", "1000"), + ("mirror_action", session), + ("SRC_IP", "10.0.0.0/32"), + ("DST_IP", "20.0.0.0/23")]) + tbl.set(table + "|" + rule, fvs) + time.sleep(1) + + def create_mirror_acl_ipv6_rule(self, table, rule, session): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + fvs = swsscommon.FieldValuePairs([("priority", "1000"), + ("mirror_action", session), + ("SRC_IPV6", "2777::0/64"), + ("DST_IPV6", "3666::0/128")]) + tbl.set(table + "|" + rule, fvs) + time.sleep(1) + + def remove_mirror_acl_rule(self, table, rule): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + tbl._del(table + "|" + rule) + time.sleep(1) + + # Test case - create a MIRROR table and a MIRRORV6 table in combined mode + # 0. predefine the VS capability: combined + # 1. create a mirror session + # 2. create two ACL tables that support both IPv4 and IPv6 + # 3. create two ACL rules with both IPv4 and IPv6 source and destination IP + # verify the ACL rules are created successfully + # 4. remove all the configurations + def test_AclBindMirrorV6Combined(self, dvs, testlog): + """ + This test verifies IPv6 rules cannot be inserted into MIRROR table + """ + self.setup_db(dvs) + + self.setup_mirrorv6_mode("combined") + + session = "MIRROR_SESSION" + acl_table = "MIRROR_TABLE" + acl_table_v6 = "MIRROR_TABLE_V6" + acl_rule_1 = "MIRROR_RULE_1" + acl_rule_2 = "MIRROR_RULE_2" + + # bring up port; assign ip; create neighbor; create route + self.set_interface_status("Ethernet32", "up") + self.add_ip_address("Ethernet32", "20.0.0.0/31") + self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "4.4.4.4", "20.0.0.1") + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") + assert self.get_mirror_session_state(session)["status"] == "active" + + # assert mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 1 + mirror_session_oid = tbl.getKeys()[0] + + # create acl table ipv4 + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") + + # assert acl table is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") + table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] + assert len(table_entries) == 1 + + # create acl table ipv6 + self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") + + # assert acl table is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") + table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] + assert len(table_entries) == 1 + + table_id = table_entries[0] + + # create acl rule with IPv4 addresses + self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) + + # assert acl rule ipv4 is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 1 + + rule_id_v4 = rule_entries[0] + + # assert acl rule is assocaited with table ipv4 + (status, fvs) = tbl.get(rule_id_v4) + assert status == True + for fv in fvs: + if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": + assert fv[1] == table_id + + # create acl rule with IPv6 addresses + self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) + + # assert acl rule ipv6 is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 2 + + rule_id_v6 = rule_entries[1] if rule_entries[0] == rule_id_v4 else rule_entries[0] + + # assert acl rule is associated with table ipv6 + (status, fvs) = tbl.get(rule_id_v6) + assert status == True + for fv in fvs: + if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": + assert fv[1] == table_id + + # remove acl rule + self.remove_mirror_acl_rule(acl_table, acl_rule_1) + self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) + + # remove acl table + self.remove_acl_table(acl_table) + self.remove_acl_table(acl_table_v6) + + # remove mirror session + self.remove_mirror_session(session) + + # assert no mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 0 + + # remove route; remove neighbor; remove ip; bring down port + self.remove_route(dvs, "4.4.4.4") + self.remove_neighbor("Ethernet32", "20.0.0.1") + self.remove_ip_address("Ethernet32", "20.0.0.0/31") + self.set_interface_status("Ethernet32", "down") + + + # Test case - intervene rule creation in table creation + # 0. predefine the VS platform: mellanox platform + # 1. create a mirror session + # 2. create the ipv4 ACL table + # 3. create the ipv4 ACL rule + # 4. create the ipv6 ACL table + # 5. create the ipv6 ACL rule + # 6. verify two rules are inserted successfully + def test_AclBindMirrorV6Reorder1(self, dvs, testlog): + """ + This test verifies IPv6 rules cannot be inserted into MIRROR table + """ + self.setup_db(dvs) + + session = "MIRROR_SESSION" + acl_table = "MIRROR_TABLE" + acl_table_v6 = "MIRROR_TABLE_V6" + acl_rule_1 = "MIRROR_RULE_1" + acl_rule_2 = "MIRROR_RULE_2" + + # bring up port; assign ip; create neighbor; create route + self.set_interface_status("Ethernet32", "up") + self.add_ip_address("Ethernet32", "20.0.0.0/31") + self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "4.4.4.4", "20.0.0.1") + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") + assert self.get_mirror_session_state(session)["status"] == "active" + + # assert mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 1 + mirror_session_oid = tbl.getKeys()[0] + + # create acl table ipv4 + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") + + # create acl rule with IPv4 addresses + self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) + + # create acl table ipv6 + self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") + + # create acl rule with IPv6 addresses + self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) + + # assert acl rules are created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 2 + + # remove acl rule + self.remove_mirror_acl_rule(acl_table, acl_rule_1) + self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) + + # remove acl table + self.remove_acl_table(acl_table) + self.remove_acl_table(acl_table_v6) + + # remove mirror session + self.remove_mirror_session(session) + + # assert no mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 0 + + # remove route; remove neighbor; remove ip; bring down port + self.remove_route(dvs, "4.4.4.4") + self.remove_neighbor("Ethernet32", "20.0.0.1") + self.remove_ip_address("Ethernet32", "20.0.0.0/31") + self.set_interface_status("Ethernet32", "down") + + + # Test case - intervene rule creation in table creation + # 0. predefine the VS platform: mellanox platform + # 1. create a mirror session + # 2. create the ipv4 ACL table + # 3. create the ipv6 ACL rule + # 4. create the ipv6 ACL table + # 5. create the ipv4 ACL rule + # 6. verify two rules are inserted successfully + def test_AclBindMirrorV6Reorder2(self, dvs, testlog): + """ + This test verifies IPv6 rules cannot be inserted into MIRROR table + """ + self.setup_db(dvs) + + session = "MIRROR_SESSION" + acl_table = "MIRROR_TABLE" + acl_table_v6 = "MIRROR_TABLE_V6" + acl_rule_1 = "MIRROR_RULE_1" + acl_rule_2 = "MIRROR_RULE_2" + + # bring up port; assign ip; create neighbor; create route + self.set_interface_status("Ethernet32", "up") + self.add_ip_address("Ethernet32", "20.0.0.0/31") + self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "4.4.4.4", "20.0.0.1") + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") + assert self.get_mirror_session_state(session)["status"] == "active" + + # assert mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 1 + mirror_session_oid = tbl.getKeys()[0] + + # create acl table ipv4 + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") + + # create acl rule with IPv6 addresses + self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) + + # assert acl rule is not created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 0 + + # create acl table ipv6 + self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") + + # create acl rule with IPv4 addresses + self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) + + # assert acl rules are created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 2 + + # remove acl rule + self.remove_mirror_acl_rule(acl_table, acl_rule_1) + self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) + + # remove acl table + self.remove_acl_table(acl_table) + self.remove_acl_table(acl_table_v6) + + # remove mirror session + self.remove_mirror_session(session) + + # assert no mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 0 + + # remove route; remove neighbor; remove ip; bring down port + self.remove_route(dvs, "4.4.4.4") + self.remove_neighbor("Ethernet32", "20.0.0.1") + self.remove_ip_address("Ethernet32", "20.0.0.0/31") + self.set_interface_status("Ethernet32", "down") + + + # Test case - create ACL rules associated with wrong table + # 0. predefine the VS platform: mellanox platform + # 1. create a mirror session + # 2. create the ipv4 ACL table + # 3. create the ipv6 ACL rule associated with ipv4 table + # 4. create the ipv6 ACL table + # 5. create the ipv4 ACL rule associated with ipv6 table + # 6. verify two rules are inserted successfully + def test_AclBindMirrorV6WrongConfig(self, dvs, testlog): + """ + This test verifies IPv6 rules cannot be inserted into MIRROR table + """ + self.setup_db(dvs) + + session = "MIRROR_SESSION" + acl_table = "MIRROR_TABLE" + acl_table_v6 = "MIRROR_TABLE_V6" + acl_rule_1 = "MIRROR_RULE_1" + acl_rule_2 = "MIRROR_RULE_2" + + # bring up port; assign ip; create neighbor; create route + self.set_interface_status("Ethernet32", "up") + self.add_ip_address("Ethernet32", "20.0.0.0/31") + self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "4.4.4.4", "20.0.0.1") + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") + assert self.get_mirror_session_state(session)["status"] == "active" + + # assert mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 1 + mirror_session_oid = tbl.getKeys()[0] + + # create acl table ipv4 + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") + + # create WRONG acl rule with IPv6 addresses + self.create_mirror_acl_ipv6_rule(acl_table, acl_rule_2, session) + + # assert acl rule is not created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 0 + + # create acl table ipv6 + self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") + + # create WRONG acl rule with IPv4 addresses + self.create_mirror_acl_ipv4_rule(acl_table_v6, acl_rule_1, session) + + # assert acl rules are created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 0 + + # remove acl rule + self.remove_mirror_acl_rule(acl_table, acl_rule_1) + self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) + + # remove acl table + self.remove_acl_table(acl_table) + self.remove_acl_table(acl_table_v6) + + # remove mirror session + self.remove_mirror_session(session) + + # assert no mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 0 + + # remove route; remove neighbor; remove ip; bring down port + self.remove_route(dvs, "4.4.4.4") + self.remove_neighbor("Ethernet32", "20.0.0.1") + self.remove_ip_address("Ethernet32", "20.0.0.0/31") + self.set_interface_status("Ethernet32", "down") + + diff --git a/tests/test_mirror_ipv6_separate.py b/tests/test_mirror_ipv6_separate.py new file mode 100644 index 00000000000..839e79c018a --- /dev/null +++ b/tests/test_mirror_ipv6_separate.py @@ -0,0 +1,478 @@ +# This test suite covers the functionality of mirror feature in SwSS + +import platform +import pytest +import time +from distutils.version import StrictVersion + +from swsscommon import swsscommon + +DVS_FAKE_PLATFORM = "mellanox" + + +class TestMirror(object): + def setup_db(self, dvs): + self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) + + def set_interface_status(self, interface, admin_status): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL" + elif interface.startswith("Vlan"): + tbl_name = "VLAN" + else: + tbl_name = "PORT" + tbl = swsscommon.Table(self.cdb, tbl_name) + fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) + tbl.set(interface, fvs) + time.sleep(1) + + def add_ip_address(self, interface, ip): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL_INTERFACE" + elif interface.startswith("Vlan"): + tbl_name = "VLAN_INTERFACE" + else: + tbl_name = "INTERFACE" + tbl = swsscommon.Table(self.cdb, tbl_name) + fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) + tbl.set(interface + "|" + ip, fvs) + time.sleep(1) + + def remove_ip_address(self, interface, ip): + if interface.startswith("PortChannel"): + tbl_name = "PORTCHANNEL_INTERFACE" + elif interface.startswith("Vlan"): + tbl_name = "VLAN_INTERFACE" + else: + tbl_name = "INTERFACE" + tbl = swsscommon.Table(self.cdb, tbl_name) + tbl._del(interface + "|" + ip) + time.sleep(1) + + def add_neighbor(self, interface, ip, mac): + tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") + fvs = swsscommon.FieldValuePairs([("neigh", mac), + ("family", "IPv4")]) + tbl.set(interface + ":" + ip, fvs) + time.sleep(1) + + def remove_neighbor(self, interface, ip): + tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") + tbl._del(interface + ":" + ip) + time.sleep(1) + + def add_route(self, dvs, prefix, nexthop): + dvs.runcmd("ip route add " + prefix + " via " + nexthop) + time.sleep(1) + + def remove_route(self, dvs, prefix): + dvs.runcmd("ip route del " + prefix) + time.sleep(1) + + def create_mirror_session(self, name, src, dst, gre, dscp, ttl, queue): + tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") + fvs = swsscommon.FieldValuePairs([("src_ip", src), + ("dst_ip", dst), + ("gre_type", gre), + ("dscp", dscp), + ("ttl", ttl), + ("queue", queue)]) + tbl.set(name, fvs) + time.sleep(1) + + def remove_mirror_session(self, name): + tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") + tbl._del(name) + time.sleep(1) + + def get_mirror_session_status(self, name): + return self.get_mirror_session_state(name)["status"] + + def get_mirror_session_state(self, name): + tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION") + (status, fvs) = tbl.get(name) + assert status == True + assert len(fvs) > 0 + return { fv[0]: fv[1] for fv in fvs } + + def create_acl_table(self, table, interfaces, type): + tbl = swsscommon.Table(self.cdb, "ACL_TABLE") + fvs = swsscommon.FieldValuePairs([("policy_desc", "mirror_test"), + ("type", type), + ("ports", ",".join(interfaces))]) + tbl.set(table, fvs) + time.sleep(1) + + def remove_acl_table(self, table): + tbl = swsscommon.Table(self.cdb, "ACL_TABLE") + tbl._del(table) + time.sleep(1) + + def create_mirror_acl_ipv4_rule(self, table, rule, session): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + fvs = swsscommon.FieldValuePairs([("priority", "1000"), + ("mirror_action", session), + ("SRC_IP", "10.0.0.0/32"), + ("DST_IP", "20.0.0.0/23")]) + tbl.set(table + "|" + rule, fvs) + time.sleep(1) + + def create_mirror_acl_ipv6_rule(self, table, rule, session): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + fvs = swsscommon.FieldValuePairs([("priority", "1000"), + ("mirror_action", session), + ("SRC_IPV6", "2777::0/64"), + ("DST_IPV6", "3666::0/128")]) + tbl.set(table + "|" + rule, fvs) + time.sleep(1) + + def remove_mirror_acl_rule(self, table, rule): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + tbl._del(table + "|" + rule) + time.sleep(1) + + + # Test case - create a MIRROR table and a MIRRORV6 table in separated mode + # 0. predefine the VS platform: mellanox platform + # 1. create a mirror session + # 2. create two ACL tables that support IPv4 and IPv6 separatedly + # 3. create two ACL rules with both IPv4 and IPv6 source and destination IP + # verify the ACL rules are created successfully + # 4. remove all the configurations + def test_AclBindMirrorSeparated(self, dvs, testlog): + """ + This test verifies IPv6 rules cannot be inserted into MIRROR table + """ + self.setup_db(dvs) + + session = "MIRROR_SESSION" + acl_table = "MIRROR_TABLE" + acl_table_v6 = "MIRROR_TABLE_V6" + acl_rule_1 = "MIRROR_RULE_1" + acl_rule_2 = "MIRROR_RULE_2" + + # bring up port; assign ip; create neighbor; create route + self.set_interface_status("Ethernet32", "up") + self.add_ip_address("Ethernet32", "20.0.0.0/31") + self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "4.4.4.4", "20.0.0.1") + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") + assert self.get_mirror_session_state(session)["status"] == "active" + + # assert mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 1 + mirror_session_oid = tbl.getKeys()[0] + + # create acl table ipv4 + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") + + # assert acl table ipv4 is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") + table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] + assert len(table_entries) == 1 + + table_id_v4 = table_entries[0] + + # create acl table ipv6 + self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") + + # assert acl table ipv6 is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") + table_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_tables] + assert len(table_entries) == 2 + + table_id_v6 = table_entries[1] if table_entries[0] == table_id_v4 else table_entries[0] + + # create acl rule with IPv4 addresses + self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) + + # assert acl rule ipv4 is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 1 + + rule_id_v4 = rule_entries[0] + + # assert acl rule is assocaited with table ipv4 + (status, fvs) = tbl.get(rule_id_v4) + assert status == True + for fv in fvs: + if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": + assert fv[1] == table_id_v4 + + # create acl rule with IPv6 addresses + self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) + + # assert acl rule ipv6 is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 2 + + rule_id_v6 = rule_entries[1] if rule_entries[0] == rule_id_v4 else rule_entries[0] + + # assert acl rule is associated with table ipv6 + (status, fvs) = tbl.get(rule_id_v6) + assert status == True + for fv in fvs: + if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": + assert fv[1] == table_id_v6 + + # remove acl rule + self.remove_mirror_acl_rule(acl_table, acl_rule_1) + self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) + + # remove acl table + self.remove_acl_table(acl_table) + self.remove_acl_table(acl_table_v6) + + # remove mirror session + self.remove_mirror_session(session) + + # assert no mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 0 + + # remove route; remove neighbor; remove ip; bring down port + self.remove_route(dvs, "4.4.4.4") + self.remove_neighbor("Ethernet32", "20.0.0.1") + self.remove_ip_address("Ethernet32", "20.0.0.0/31") + self.set_interface_status("Ethernet32", "down") + + # Test case - intervene rule creation in table creation + # 0. predefine the VS platform: mellanox platform + # 1. create a mirror session + # 2. create the ipv4 ACL table + # 3. create the ipv4 ACL rule + # 4. create the ipv6 ACL table + # 5. create the ipv6 ACL rule + # 6. verify two rules are inserted successfully + def test_AclBindMirrorV6Reorder1(self, dvs, testlog): + """ + This test verifies IPv6 rules cannot be inserted into MIRROR table + """ + self.setup_db(dvs) + + session = "MIRROR_SESSION" + acl_table = "MIRROR_TABLE" + acl_table_v6 = "MIRROR_TABLE_V6" + acl_rule_1 = "MIRROR_RULE_1" + acl_rule_2 = "MIRROR_RULE_2" + + # bring up port; assign ip; create neighbor; create route + self.set_interface_status("Ethernet32", "up") + self.add_ip_address("Ethernet32", "20.0.0.0/31") + self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "4.4.4.4", "20.0.0.1") + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") + assert self.get_mirror_session_state(session)["status"] == "active" + + # assert mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 1 + mirror_session_oid = tbl.getKeys()[0] + + # create acl table ipv4 + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") + + # create acl rule with IPv4 addresses + self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) + + # create acl table ipv6 + self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") + + # create acl rule with IPv6 addresses + self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) + + # assert acl rules are created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 2 + + # remove acl rule + self.remove_mirror_acl_rule(acl_table, acl_rule_1) + self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) + + # remove acl table + self.remove_acl_table(acl_table) + self.remove_acl_table(acl_table_v6) + + # remove mirror session + self.remove_mirror_session(session) + + # assert no mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 0 + + # remove route; remove neighbor; remove ip; bring down port + self.remove_route(dvs, "4.4.4.4") + self.remove_neighbor("Ethernet32", "20.0.0.1") + self.remove_ip_address("Ethernet32", "20.0.0.0/31") + self.set_interface_status("Ethernet32", "down") + + + # Test case - intervene rule creation in table creation + # 0. predefine the VS platform: mellanox platform + # 1. create a mirror session + # 2. create the ipv4 ACL table + # 3. create the ipv6 ACL rule + # 4. create the ipv6 ACL table + # 5. create the ipv4 ACL rule + # 6. verify two rules are inserted successfully + def test_AclBindMirrorV6Reorder2(self, dvs, testlog): + """ + This test verifies IPv6 rules cannot be inserted into MIRROR table + """ + self.setup_db(dvs) + + session = "MIRROR_SESSION" + acl_table = "MIRROR_TABLE" + acl_table_v6 = "MIRROR_TABLE_V6" + acl_rule_1 = "MIRROR_RULE_1" + acl_rule_2 = "MIRROR_RULE_2" + + # bring up port; assign ip; create neighbor; create route + self.set_interface_status("Ethernet32", "up") + self.add_ip_address("Ethernet32", "20.0.0.0/31") + self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "4.4.4.4", "20.0.0.1") + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") + assert self.get_mirror_session_state(session)["status"] == "active" + + # assert mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 1 + mirror_session_oid = tbl.getKeys()[0] + + # create acl table ipv4 + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") + + # create acl rule with IPv6 addresses + self.create_mirror_acl_ipv6_rule(acl_table_v6, acl_rule_2, session) + + # assert acl rule is not created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 0 + + # create acl table ipv6 + self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") + + # create acl rule with IPv4 addresses + self.create_mirror_acl_ipv4_rule(acl_table, acl_rule_1, session) + + # assert acl rules are created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 2 + + # remove acl rule + self.remove_mirror_acl_rule(acl_table, acl_rule_1) + self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) + + # remove acl table + self.remove_acl_table(acl_table) + self.remove_acl_table(acl_table_v6) + + # remove mirror session + self.remove_mirror_session(session) + + # assert no mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 0 + + # remove route; remove neighbor; remove ip; bring down port + self.remove_route(dvs, "4.4.4.4") + self.remove_neighbor("Ethernet32", "20.0.0.1") + self.remove_ip_address("Ethernet32", "20.0.0.0/31") + self.set_interface_status("Ethernet32", "down") + + + # Test case - create ACL rules associated with wrong table + # 0. predefine the VS platform: mellanox platform + # 1. create a mirror session + # 2. create the ipv4 ACL table + # 3. create the ipv6 ACL rule associated with ipv4 table + # 4. create the ipv6 ACL table + # 5. create the ipv4 ACL rule associated with ipv6 table + # 6. verify two rules are inserted successfully + def test_AclBindMirrorV6WrongConfig(self, dvs, testlog): + """ + This test verifies IPv6 rules cannot be inserted into MIRROR table + """ + self.setup_db(dvs) + + session = "MIRROR_SESSION" + acl_table = "MIRROR_TABLE" + acl_table_v6 = "MIRROR_TABLE_V6" + acl_rule_1 = "MIRROR_RULE_1" + acl_rule_2 = "MIRROR_RULE_2" + + # bring up port; assign ip; create neighbor; create route + self.set_interface_status("Ethernet32", "up") + self.add_ip_address("Ethernet32", "20.0.0.0/31") + self.add_neighbor("Ethernet32", "20.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "4.4.4.4", "20.0.0.1") + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "4.4.4.4", "0x6558", "8", "100", "0") + assert self.get_mirror_session_state(session)["status"] == "active" + + # assert mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 1 + mirror_session_oid = tbl.getKeys()[0] + + # create acl table ipv4 + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"], "MIRROR") + + # create WRONG acl rule with IPv6 addresses + self.create_mirror_acl_ipv6_rule(acl_table, acl_rule_2, session) + + # assert acl rule is not created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 0 + + # create acl table ipv6 + self.create_acl_table(acl_table_v6, ["Ethernet0", "Ethernet4"], "MIRRORV6") + + # create WRONG acl rule with IPv4 addresses + self.create_mirror_acl_ipv4_rule(acl_table_v6, acl_rule_1, session) + + # assert acl rules are created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 0 + + # remove acl rule + self.remove_mirror_acl_rule(acl_table, acl_rule_1) + self.remove_mirror_acl_rule(acl_table_v6, acl_rule_2) + + # remove acl table + self.remove_acl_table(acl_table) + self.remove_acl_table(acl_table_v6) + + # remove mirror session + self.remove_mirror_session(session) + + # assert no mirror session in asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + assert len(tbl.getKeys()) == 0 + + # remove route; remove neighbor; remove ip; bring down port + self.remove_route(dvs, "4.4.4.4") + self.remove_neighbor("Ethernet32", "20.0.0.1") + self.remove_ip_address("Ethernet32", "20.0.0.0/31") + self.set_interface_status("Ethernet32", "down") + + From 5609ee93c59ff2876b4e5be791884c29220a8656 Mon Sep 17 00:00:00 2001 From: Shuotian Cheng Date: Wed, 8 May 2019 09:14:15 -0700 Subject: [PATCH 3/6] [aclorch]: Add ICMP type/code match for v4/v6 (#868) Support the following matches: SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE SAI_ACL_TABLE_ATTR_FIELD_ICMP_CODE SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_CODE Signed-off-by: Shu0T1an ChenG --- orchagent/aclorch.cpp | 133 ++++++++++++++++++++++++++--------- orchagent/aclorch.h | 4 ++ tests/test_acl.py | 158 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 246 insertions(+), 49 deletions(-) diff --git a/orchagent/aclorch.cpp b/orchagent/aclorch.cpp index 675897592c6..44f827854bc 100644 --- a/orchagent/aclorch.cpp +++ b/orchagent/aclorch.cpp @@ -46,6 +46,10 @@ acl_rule_attr_lookup_t aclMatchLookup = { MATCH_IP_TYPE, SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE }, { MATCH_DSCP, SAI_ACL_ENTRY_ATTR_FIELD_DSCP }, { MATCH_TC, SAI_ACL_ENTRY_ATTR_FIELD_TC }, + { MATCH_ICMP_TYPE, SAI_ACL_ENTRY_ATTR_FIELD_ICMP_TYPE }, + { MATCH_ICMP_CODE, SAI_ACL_ENTRY_ATTR_FIELD_ICMP_CODE }, + { MATCH_ICMPV6_TYPE, SAI_ACL_ENTRY_ATTR_FIELD_ICMPV6_TYPE }, + { MATCH_ICMPV6_CODE, SAI_ACL_ENTRY_ATTR_FIELD_ICMPV6_CODE }, { MATCH_L4_SRC_PORT_RANGE, (sai_acl_entry_attr_t)SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE }, { MATCH_L4_DST_PORT_RANGE, (sai_acl_entry_attr_t)SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE }, { MATCH_TUNNEL_VNI, SAI_ACL_ENTRY_ATTR_FIELD_TUNNEL_VNI }, @@ -334,6 +338,12 @@ bool AclRule::validateAddMatch(string attr_name, string attr_value) value.aclfield.data.u8 = to_uint(attr_value); value.aclfield.mask.u8 = 0xFF; } + else if (attr_name == MATCH_ICMP_TYPE || attr_name == MATCH_ICMP_CODE || + attr_name == MATCH_ICMPV6_TYPE || attr_name == MATCH_ICMPV6_CODE) + { + value.aclfield.data.u8 = to_uint(attr_value); + value.aclfield.mask.u8 = 0xFF; + } else if (attr_name == MATCH_TUNNEL_VNI) { value.aclfield.data.u32 = to_uint(attr_value); @@ -850,12 +860,19 @@ bool AclRuleL3::validateAddMatch(string attr_name, string attr_value) { if (attr_name == MATCH_DSCP) { - SWSS_LOG_ERROR("DSCP match is not supported for the tables of type L3"); + SWSS_LOG_ERROR("DSCP match is not supported for table type L3"); return false; } + if (attr_name == MATCH_SRC_IPV6 || attr_name == MATCH_DST_IPV6) { - SWSS_LOG_ERROR("IPv6 address match is not supported for the tables of type L3"); + SWSS_LOG_ERROR("IPv6 address match is not supported for table type L3"); + return false; + } + + if (attr_name == MATCH_ICMPV6_TYPE || attr_name == MATCH_ICMPV6_CODE) + { + SWSS_LOG_ERROR("ICMPv6 match is not supported for table type L3"); return false; } @@ -906,12 +923,19 @@ bool AclRuleL3V6::validateAddMatch(string attr_name, string attr_value) { if (attr_name == MATCH_DSCP) { - SWSS_LOG_ERROR("DSCP match is not supported for the tables of type L3V6"); + SWSS_LOG_ERROR("DSCP match is not supported for table type L3V6"); return false; } + if (attr_name == MATCH_SRC_IP || attr_name == MATCH_DST_IP) { - SWSS_LOG_ERROR("IPv4 address match is not supported for the tables of type L3V6"); + SWSS_LOG_ERROR("IPv4 address match is not supported for table type L3V6"); + return false; + } + + if (attr_name == MATCH_ICMP_TYPE || attr_name == MATCH_ICMP_CODE) + { + SWSS_LOG_ERROR("ICMPv4 match is not supported for table type L3V6"); return false; } @@ -956,21 +980,28 @@ bool AclRuleMirror::validateAddMatch(string attr_name, string attr_value) /* * Type of Tables and Supported Match Types (Configuration) - * |--------------------------------------------------| - * | Match Type | TABLE_MIRROR | TABLE_MIRRORV6 | - * |--------------------------------------------------| - * | MATCH_SRC_IP | √ | | - * | MATCH_DST_IP | √ | | - * |--------------------------------------------------| - * | MATCH_SRC_IPV6 | | √ | - * | MATCH_DST_IPV6 | | √ | - * |--------------------------------------------------| - * | MARTCH_ETHERTYPE | √ | | - * |--------------------------------------------------| + * |---------------------------------------------------| + * | Match Type | TABLE_MIRROR | TABLE_MIRRORV6 | + * |---------------------------------------------------| + * | MATCH_SRC_IP | √ | | + * | MATCH_DST_IP | √ | | + * |---------------------------------------------------| + * | MATCH_ICMP_TYPE | √ | | + * | MATCH_ICMP_CODE | √ | | + * |---------------------------------------------------| + * | MATCH_ICMPV6_TYPE | | √ | + * | MATCH_ICMPV6_CODE | | √ | + * |---------------------------------------------------| + * | MATCH_SRC_IPV6 | | √ | + * | MATCH_DST_IPV6 | | √ | + * |---------------------------------------------------| + * | MARTCH_ETHERTYPE | √ | | + * |---------------------------------------------------| */ if (m_tableType == ACL_TABLE_MIRROR && - (attr_name == MATCH_SRC_IPV6 || attr_name == MATCH_DST_IPV6)) + (attr_name == MATCH_SRC_IPV6 || attr_name == MATCH_DST_IPV6 || + attr_name == MATCH_ICMPV6_TYPE || attr_name == MATCH_ICMPV6_CODE)) { SWSS_LOG_ERROR("%s match is not supported for the table of type MIRROR", attr_name.c_str()); @@ -978,9 +1009,11 @@ bool AclRuleMirror::validateAddMatch(string attr_name, string attr_value) } if (m_tableType == ACL_TABLE_MIRRORV6 && - (attr_name == MATCH_SRC_IP || attr_name == MATCH_DST_IP || attr_name == MATCH_ETHER_TYPE)) + (attr_name == MATCH_SRC_IP || attr_name == MATCH_DST_IP || + attr_name == MATCH_ICMP_TYPE || attr_name == MATCH_ICMP_CODE || + attr_name == MATCH_ETHER_TYPE)) { - SWSS_LOG_ERROR("%s match is not supported for the table of type MIRRORV6", + SWSS_LOG_ERROR("%s match is not supported for the table of type MIRRORv6", attr_name.c_str()); return false; } @@ -1172,19 +1205,25 @@ bool AclTable::create() /* * Type of Tables and Supported Match Types (ASIC database) - * |-----------------------------------------------------------------| - * | | TABLE_MIRROR | TABLE_MIRROR | TABLE_MIRRORV6 | - * | Match Type |----------------------------------------------| - * | | combined | separated | - * |-----------------------------------------------------------------| - * | MATCH_SRC_IP | √ | √ | | - * | MATCH_DST_IP | √ | √ | | - * |-----------------------------------------------------------------| - * | MATCH_SRC_IPV6 | √ | | √ | - * | MATCH_DST_IPV6 | √ | | √ | - * |-----------------------------------------------------------------| - * | MARTCH_ETHERTYPE | √ | √ | | - * |-----------------------------------------------------------------| + * |------------------------------------------------------------------| + * | | TABLE_MIRROR | TABLE_MIRROR | TABLE_MIRRORV6 | + * | Match Type |----------------------------------------------| + * | | combined | separated | + * |------------------------------------------------------------------| + * | MATCH_SRC_IP | √ | √ | | + * | MATCH_DST_IP | √ | √ | | + * |------------------------------------------------------------------| + * | MATCH_ICMP_TYPE | √ | √ | | + * | MATCH_ICMP_CODE | √ | √ | | + * |------------------------------------------------------------------| + * | MATCH_SRC_IPV6 | √ | | √ | + * | MATCH_DST_IPV6 | √ | | √ | + * |------------------------------------------------------------------| + * | MATCH_ICMPV6_TYPE | √ | | √ | + * | MATCH_ICMPV6_CODE | √ | | √ | + * |------------------------------------------------------------------| + * | MARTCH_ETHERTYPE | √ | √ | | + * |------------------------------------------------------------------| */ if (type == ACL_TABLE_MIRROR) @@ -1197,6 +1236,14 @@ bool AclTable::create() attr.value.booldata = true; table_attrs.push_back(attr); + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE; + attr.value.booldata = true; + table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ICMP_CODE; + attr.value.booldata = true; + table_attrs.push_back(attr); + // If the switch supports v6 and requires one single table if (m_pAclOrch->m_mirrorTableCapabilities[ACL_TABLE_MIRRORV6] && m_pAclOrch->m_isCombinedMirrorV6Table) @@ -1208,6 +1255,14 @@ bool AclTable::create() attr.id = SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6; attr.value.booldata = true; table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE; + attr.value.booldata = true; + table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_CODE; + attr.value.booldata = true; + table_attrs.push_back(attr); } } else if (type == ACL_TABLE_L3V6 || type == ACL_TABLE_MIRRORV6) // v6 only @@ -1219,6 +1274,14 @@ bool AclTable::create() attr.id = SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6; attr.value.booldata = true; table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_TYPE; + attr.value.booldata = true; + table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ICMPV6_CODE; + attr.value.booldata = true; + table_attrs.push_back(attr); } else // v4 only { @@ -1229,6 +1292,14 @@ bool AclTable::create() attr.id = SAI_ACL_TABLE_ATTR_FIELD_DST_IP; attr.value.booldata = true; table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ICMP_TYPE; + attr.value.booldata = true; + table_attrs.push_back(attr); + + attr.id = SAI_ACL_TABLE_ATTR_FIELD_ICMP_CODE; + attr.value.booldata = true; + table_attrs.push_back(attr); } attr.id = SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT; diff --git a/orchagent/aclorch.h b/orchagent/aclorch.h index 4e18924f7c0..46151476e49 100644 --- a/orchagent/aclorch.h +++ b/orchagent/aclorch.h @@ -50,6 +50,10 @@ #define MATCH_L4_SRC_PORT_RANGE "L4_SRC_PORT_RANGE" #define MATCH_L4_DST_PORT_RANGE "L4_DST_PORT_RANGE" #define MATCH_TC "TC" +#define MATCH_ICMP_TYPE "ICMP_TYPE" +#define MATCH_ICMP_CODE "ICMP_CODE" +#define MATCH_ICMPV6_TYPE "ICMPV6_TYPE" +#define MATCH_ICMPV6_CODE "ICMPV6_CODE" #define MATCH_TUNNEL_VNI "TUNNEL_VNI" #define MATCH_INNER_ETHER_TYPE "INNER_ETHER_TYPE" #define MATCH_INNER_IP_PROTOCOL "INNER_IP_PROTOCOL" diff --git a/tests/test_acl.py b/tests/test_acl.py index 7d57645bd87..197026d548f 100644 --- a/tests/test_acl.py +++ b/tests/test_acl.py @@ -4,13 +4,33 @@ import json class TestAcl(object): - def get_acl_table_id(self, dvs, adb): - atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") - keys = atbl.getKeys() + def setup_db(self, dvs): + self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) + + def create_acl_table(self, table, type, ports): + tbl = swsscommon.Table(self.cdb, "ACL_TABLE") + fvs = swsscommon.FieldValuePairs([("policy_desc", "test"), + ("type", type), + ("ports", ",".join(ports))]) + tbl.set(table, fvs) + time.sleep(1) + + def remove_acl_table(self, table): + tbl = swsscommon.Table(self.cdb, "ACL_TABLE") + tbl._del(table) + time.sleep(1) + + def get_acl_table_id(self, dvs): + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") + keys = tbl.getKeys() + for k in dvs.asicdb.default_acl_tables: assert k in keys - acl_tables = [k for k in keys if k not in dvs.asicdb.default_acl_tables] + acl_tables = [k for k in keys if k not in dvs.asicdb.default_acl_tables] assert len(acl_tables) == 1 return acl_tables[0] @@ -105,6 +125,7 @@ def verify_acl_port_binding(self, dvs, adb, bind_ports): assert set(port_groups) == set(acl_table_groups) def test_AclTableCreation(self, dvs, testlog): + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -116,7 +137,7 @@ def test_AclTableCreation(self, dvs, testlog): time.sleep(1) # check acl table in asic db - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) assert test_acl_table_id # check acl table group in asic db @@ -138,6 +159,7 @@ def test_AclRuleL4SrcPort(self, dvs, testlog): hmset ACL_RULE|test|acl_test_rule priority 55 PACKET_ACTION FORWARD L4_SRC_PORT 65000 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -148,7 +170,7 @@ def test_AclRuleL4SrcPort(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -189,6 +211,7 @@ def test_AclRuleInOutPorts(self, dvs, testlog): hmset ACL_RULE|test|acl_test_rule priority 55 PACKET_ACTION FORWARD IN_PORTS Ethernet0,Ethernet4 OUT_PORTS Ethernet8,Ethernet12 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -202,7 +225,7 @@ def test_AclRuleInOutPorts(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -246,6 +269,7 @@ def test_AclRuleInOutPorts(self, dvs, testlog): def test_AclTableDeletion(self, dvs, testlog): + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -262,6 +286,7 @@ def test_AclTableDeletion(self, dvs, testlog): def test_V6AclTableCreation(self, dvs, testlog): + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -274,7 +299,7 @@ def test_V6AclTableCreation(self, dvs, testlog): time.sleep(1) # check acl table in asic db - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table group in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP") @@ -338,6 +363,7 @@ def test_V6AclRuleIPv6Any(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule1 priority 1000 PACKET_ACTION FORWARD IPv6Any """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -348,7 +374,7 @@ def test_V6AclRuleIPv6Any(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -389,6 +415,7 @@ def test_V6AclRuleIPv6AnyDrop(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule2 priority 1002 PACKET_ACTION DROP IPv6Any """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -399,7 +426,7 @@ def test_V6AclRuleIPv6AnyDrop(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -440,6 +467,7 @@ def test_V6AclRuleIpProtocol(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule3 priority 1003 PACKET_ACTION DROP IP_PROTOCOL 6 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -450,7 +478,7 @@ def test_V6AclRuleIpProtocol(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -491,6 +519,7 @@ def test_V6AclRuleSrcIPv6(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule4 priority 1004 PACKET_ACTION DROP SRC_IPV6 2777::0/64 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -501,7 +530,7 @@ def test_V6AclRuleSrcIPv6(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -542,6 +571,7 @@ def test_V6AclRuleDstIPv6(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule5 priority 1005 PACKET_ACTION DROP DST_IPV6 2002::2/128 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -552,7 +582,7 @@ def test_V6AclRuleDstIPv6(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -593,6 +623,7 @@ def test_V6AclRuleL4SrcPort(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule6 priority 1006 PACKET_ACTION DROP L4_SRC_PORT 65000 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -603,7 +634,7 @@ def test_V6AclRuleL4SrcPort(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -644,6 +675,7 @@ def test_V6AclRuleL4DstPort(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule7 priority 1007 PACKET_ACTION DROP L4_DST_PORT 65001 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -654,7 +686,7 @@ def test_V6AclRuleL4DstPort(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -695,6 +727,7 @@ def test_V6AclRuleTCPFlags(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule8 priority 1008 PACKET_ACTION DROP TCP_FLAGS 0x7/0x3f """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -705,7 +738,7 @@ def test_V6AclRuleTCPFlags(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -746,6 +779,7 @@ def test_V6AclRuleL4SrcPortRange(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule9 priority 1009 PACKET_ACTION DROP L4_SRC_PORT_RANGE 1-100 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -756,7 +790,7 @@ def test_V6AclRuleL4SrcPortRange(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -811,6 +845,7 @@ def test_V6AclRuleL4DstPortRange(self, dvs, testlog): hmset ACL_RULE|test-aclv6|test_rule10 priority 1010 PACKET_ACTION DROP L4_DST_PORT_RANGE 101-200 """ + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -821,7 +856,7 @@ def test_V6AclRuleL4DstPortRange(self, dvs, testlog): time.sleep(1) - test_acl_table_id = self.get_acl_table_id(dvs, adb) + test_acl_table_id = self.get_acl_table_id(dvs) # check acl table in asic db atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") @@ -873,6 +908,7 @@ def test_V6AclRuleL4DstPortRange(self, dvs, testlog): def test_V6AclTableDeletion(self, dvs, testlog): + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -903,6 +939,7 @@ def check_rule_existence(self, entry, rules, verifs): return False def test_InsertAclRuleBetweenPriorities(self, dvs, testlog): + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -1001,6 +1038,7 @@ def test_InsertAclRuleBetweenPriorities(self, dvs, testlog): assert len(keys) >= 1 def test_RulesWithDiffMaskLengths(self, dvs, testlog): + self.setup_db(dvs) db = swsscommon.DBConnector(4, dvs.redis_sock, 0) adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) @@ -1084,3 +1122,87 @@ def test_RulesWithDiffMaskLengths(self, dvs, testlog): atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE") keys = atbl.getKeys() assert len(keys) >= 1 + + def create_acl_rule(self, table, rule, field, value): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + fvs = swsscommon.FieldValuePairs([("priority", "666"), + ("PACKET_ACTION", "FORWARD"), + (field, value)]) + tbl.set(table + "|" + rule, fvs) + time.sleep(1) + + def remove_acl_rule(self, table, rule): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + tbl._del(table + "|" + rule) + time.sleep(1) + + def verify_acl_rule(self, dvs, field, value): + acl_table_id = self.get_acl_table_id(dvs) + + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + acl_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(acl_entries) == 1 + + (status, fvs) = tbl.get(acl_entries[0]) + assert status == True + assert len(fvs) == 6 + for fv in fvs: + if fv[0] == "SAI_ACL_ENTRY_ATTR_TABLE_ID": + assert fv[1] == acl_table_id + elif fv[0] == "SAI_ACL_ENTRY_ATTR_ADMIN_STATE": + assert fv[1] == "true" + elif fv[0] == "SAI_ACL_ENTRY_ATTR_PRIORITY": + assert fv[1] == "666" + elif fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_COUNTER": + assert True + elif fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION": + assert fv[1] == "SAI_PACKET_ACTION_FORWARD" + elif fv[0] == field: + assert fv[1] == value + else: + assert False + + + def test_AclRuleIcmp(self, dvs, testlog): + self.setup_db(dvs) + + acl_table = "TEST_TABLE" + acl_rule = "TEST_RULE" + + self.create_acl_table(acl_table, "L3", ["Ethernet0", "Ethernet4"]) + + self.create_acl_rule(acl_table, acl_rule, "ICMP_TYPE", "8") + + self.verify_acl_rule(dvs, "SAI_ACL_ENTRY_ATTR_FIELD_ICMP_TYPE", "8&mask:0xff") + + self.remove_acl_rule(acl_table, acl_rule) + + self.create_acl_rule(acl_table, acl_rule, "ICMP_CODE", "9") + + self.verify_acl_rule(dvs, "SAI_ACL_ENTRY_ATTR_FIELD_ICMP_CODE", "9&mask:0xff") + + self.remove_acl_rule(acl_table, acl_rule) + + self.remove_acl_table(acl_table) + + def test_AclRuleIcmpV6(self, dvs, testlog): + self.setup_db(dvs) + + acl_table = "TEST_TABLE" + acl_rule = "TEST_RULE" + + self.create_acl_table(acl_table, "L3V6", ["Ethernet0", "Ethernet4"]) + + self.create_acl_rule(acl_table, acl_rule, "ICMPV6_TYPE", "8") + + self.verify_acl_rule(dvs, "SAI_ACL_ENTRY_ATTR_FIELD_ICMPV6_TYPE", "8&mask:0xff") + + self.remove_acl_rule(acl_table, acl_rule) + + self.create_acl_rule(acl_table, acl_rule, "ICMPV6_CODE", "9") + + self.verify_acl_rule(dvs, "SAI_ACL_ENTRY_ATTR_FIELD_ICMPV6_CODE", "9&mask:0xff") + + self.remove_acl_rule(acl_table, acl_rule) + + self.remove_acl_table(acl_table) From 9f6e794890bf65a6bb8ce82ae4c2d67b0c5c13a9 Mon Sep 17 00:00:00 2001 From: Shuotian Cheng Date: Thu, 9 May 2019 10:04:57 -0700 Subject: [PATCH 4/6] [Makefile]: Remove header files from source files (#883) Signed-off-by: Shu0T1an ChenG --- orchagent/Makefile.am | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/orchagent/Makefile.am b/orchagent/Makefile.am index 0b7f9265fae..178e1078aae 100644 --- a/orchagent/Makefile.am +++ b/orchagent/Makefile.am @@ -48,39 +48,7 @@ orchagent_SOURCES = \ vnetorch.cpp \ dtelorch.cpp \ flexcounterorch.cpp \ - watermarkorch.cpp \ - acltable.h \ - aclorch.h \ - bufferorch.h \ - copporch.h \ - directory.h \ - fdborch.h \ - intfsorch.h \ - mirrororch.h \ - neighorch.h \ - notifications.h \ - observer.h \ - orch.h \ - orchdaemon.h \ - pfcactionhandler.h \ - pfcwdorch.h \ - port.h \ - portsorch.h \ - qosorch.h \ - routeorch.h \ - saihelper.h \ - switchorch.h \ - swssnet.h \ - tunneldecaporch.h \ - crmorch.h \ - request_parser.h \ - vrforch.h \ - dtelorch.h \ - countercheckorch.h \ - vxlanorch.h \ - vnetorch.h \ - flexcounterorch.h \ - watermarkorch.h + watermarkorch.cpp orchagent_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) orchagent_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) From e34d1d7514fbbad10fff18682b2a8b33a65253b1 Mon Sep 17 00:00:00 2001 From: Shuotian Cheng Date: Wed, 22 May 2019 18:27:16 -0700 Subject: [PATCH 5/6] [policerorch]: Add PolicerOrch to bundle with mirror session (#889) Now that we could create a policer for the mirror session to throttle the mirroring traffic. configuration: POLICER|NAME: meter_type:packets|bytes mode:sr_tcm|tr_tcm|storm_control cir|DIGITS cbs|DIGITS pir|DIGITS pbs|DIGITS corlor_source:aware|blind red_action:drop yellow_action:drop green_action:drop MIRROR_SESSION|NAME: policer:policer_name Signed-off-by: Shu0T1an ChenG --- orchagent/Makefile.am | 3 +- orchagent/copporch.cpp | 10 +- orchagent/mirrororch.cpp | 38 ++++- orchagent/mirrororch.h | 5 +- orchagent/orchdaemon.cpp | 6 +- orchagent/orchdaemon.h | 1 + orchagent/policerorch.cpp | 268 +++++++++++++++++++++++++++++++++++ orchagent/policerorch.h | 29 ++++ tests/test_mirror_policer.py | 239 +++++++++++++++++++++++++++++++ 9 files changed, 588 insertions(+), 11 deletions(-) create mode 100644 orchagent/policerorch.cpp create mode 100644 orchagent/policerorch.h create mode 100644 tests/test_mirror_policer.py diff --git a/orchagent/Makefile.am b/orchagent/Makefile.am index 178e1078aae..a2c20a85356 100644 --- a/orchagent/Makefile.am +++ b/orchagent/Makefile.am @@ -48,7 +48,8 @@ orchagent_SOURCES = \ vnetorch.cpp \ dtelorch.cpp \ flexcounterorch.cpp \ - watermarkorch.cpp + watermarkorch.cpp \ + policerorch.cpp orchagent_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) orchagent_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_SAI) diff --git a/orchagent/copporch.cpp b/orchagent/copporch.cpp index ea68dd0cbaf..85fa5bf9248 100644 --- a/orchagent/copporch.cpp +++ b/orchagent/copporch.cpp @@ -17,23 +17,23 @@ extern sai_switch_api_t* sai_switch_api; extern sai_object_id_t gSwitchId; extern PortsOrch* gPortsOrch; -map policer_meter_map = { +static map policer_meter_map = { {"packets", SAI_METER_TYPE_PACKETS}, {"bytes", SAI_METER_TYPE_BYTES} }; -map policer_mode_map = { +static map policer_mode_map = { {"sr_tcm", SAI_POLICER_MODE_SR_TCM}, {"tr_tcm", SAI_POLICER_MODE_TR_TCM}, {"storm", SAI_POLICER_MODE_STORM_CONTROL} }; -map policer_color_aware_map = { +static map policer_color_aware_map = { {"aware", SAI_POLICER_COLOR_SOURCE_AWARE}, {"blind", SAI_POLICER_COLOR_SOURCE_BLIND} }; -map trap_id_map = { +static map trap_id_map = { {"stp", SAI_HOSTIF_TRAP_TYPE_STP}, {"lacp", SAI_HOSTIF_TRAP_TYPE_LACP}, {"eapol", SAI_HOSTIF_TRAP_TYPE_EAPOL}, @@ -71,7 +71,7 @@ map trap_id_map = { {"udld", SAI_HOSTIF_TRAP_TYPE_UDLD} }; -map packet_action_map = { +static map packet_action_map = { {"drop", SAI_PACKET_ACTION_DROP}, {"forward", SAI_PACKET_ACTION_FORWARD}, {"copy", SAI_PACKET_ACTION_COPY}, diff --git a/orchagent/mirrororch.cpp b/orchagent/mirrororch.cpp index e295ecb7c74..135e3464e26 100644 --- a/orchagent/mirrororch.cpp +++ b/orchagent/mirrororch.cpp @@ -24,6 +24,7 @@ #define MIRROR_SESSION_MONITOR_PORT "monitor_port" #define MIRROR_SESSION_ROUTE_PREFIX "route_prefix" #define MIRROR_SESSION_VLAN_HEADER_VALID "vlan_header_valid" +#define MIRROR_SESSION_POLICER "policer" #define MIRROR_SESSION_DEFAULT_VLAN_PRI 0 #define MIRROR_SESSION_DEFAULT_VLAN_CFI 0 @@ -60,12 +61,13 @@ MirrorEntry::MirrorEntry(const string& platform) : } MirrorOrch::MirrorOrch(TableConnector stateDbConnector, TableConnector confDbConnector, - PortsOrch *portOrch, RouteOrch *routeOrch, NeighOrch *neighOrch, FdbOrch *fdbOrch) : + PortsOrch *portOrch, RouteOrch *routeOrch, NeighOrch *neighOrch, FdbOrch *fdbOrch, PolicerOrch *policerOrch) : Orch(confDbConnector.first, confDbConnector.second), m_portsOrch(portOrch), m_routeOrch(routeOrch), m_neighOrch(neighOrch), m_fdbOrch(fdbOrch), + m_policerOrch(policerOrch), m_mirrorTable(stateDbConnector.first, stateDbConnector.second) { m_portsOrch->attach(this); @@ -239,6 +241,18 @@ void MirrorOrch::createEntry(const string& key, const vector& d { entry.queue = to_uint(fvValue(i)); } + else if (fvField(i) == MIRROR_SESSION_POLICER) + { + if (!m_policerOrch->policerExists(fvValue(i))) + { + SWSS_LOG_ERROR("Failed to get policer %s", + fvValue(i).c_str()); + return; + } + + m_policerOrch->increaseRefCount(fvValue(i)); + entry.policer = fvValue(i); + } else { SWSS_LOG_ERROR("Failed to parse session %s configuration. Unknown attribute %s.\n", key.c_str(), fvField(i).c_str()); @@ -292,6 +306,11 @@ void MirrorOrch::deleteEntry(const string& name) deactivateSession(name, session); } + if (!session.policer.empty()) + { + m_policerOrch->decreaseRefCount(session.policer); + } + m_syncdMirrors.erase(sessionIter); SWSS_LOG_NOTICE("Removed mirror session %s", name.c_str()); @@ -387,7 +406,8 @@ bool MirrorOrch::getNeighborInfo(const string& name, MirrorEntry& session) } case Port::VLAN: { - SWSS_LOG_NOTICE("vlan id is %d", session.neighborInfo.port.m_vlan_info.vlan_id); + SWSS_LOG_NOTICE("Get mirror session destination IP neighbor VLAN %d", + session.neighborInfo.port.m_vlan_info.vlan_id); Port member; if (!m_fdbOrch->getPort(session.neighborInfo.mac, session.neighborInfo.port.m_vlan_info.vlan_id, member)) { @@ -550,6 +570,20 @@ bool MirrorOrch::activateSession(const string& name, MirrorEntry& session) attr.value.u16 = session.greType; attrs.push_back(attr); + if (!session.policer.empty()) + { + sai_object_id_t oid = SAI_NULL_OBJECT_ID; + if (!m_policerOrch->getPolicerOid(session.policer, oid)) + { + SWSS_LOG_ERROR("Faield to get policer %s", session.policer.c_str()); + return false; + } + + attr.id = SAI_MIRROR_SESSION_ATTR_POLICER; + attr.value.oid = oid; + attrs.push_back(attr); + } + status = sai_mirror_api-> create_mirror_session(&session.sessionId, gSwitchId, (uint32_t)attrs.size(), attrs.data()); if (status != SAI_STATUS_SUCCESS) diff --git a/orchagent/mirrororch.h b/orchagent/mirrororch.h index 076f6b20260..765b24cb5f5 100644 --- a/orchagent/mirrororch.h +++ b/orchagent/mirrororch.h @@ -7,6 +7,7 @@ #include "neighorch.h" #include "routeorch.h" #include "fdborch.h" +#include "policerorch.h" #include "ipaddress.h" #include "ipaddresses.h" @@ -30,6 +31,7 @@ struct MirrorEntry uint8_t dscp; uint8_t ttl; uint8_t queue; + string policer; struct { @@ -65,7 +67,7 @@ class MirrorOrch : public Orch, public Observer, public Subject { public: MirrorOrch(TableConnector appDbConnector, TableConnector confDbConnector, - PortsOrch *portOrch, RouteOrch *routeOrch, NeighOrch *neighOrch, FdbOrch *fdbOrch); + PortsOrch *portOrch, RouteOrch *routeOrch, NeighOrch *neighOrch, FdbOrch *fdbOrch, PolicerOrch *policerOrch); void update(SubjectType, void *); bool sessionExists(const string&); @@ -79,6 +81,7 @@ class MirrorOrch : public Orch, public Observer, public Subject RouteOrch *m_routeOrch; NeighOrch *m_neighOrch; FdbOrch *m_fdbOrch; + PolicerOrch *m_policerOrch; Table m_mirrorTable; diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 189f5b53ad2..8edfd992378 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -120,9 +120,11 @@ bool OrchDaemon::init() }; gBufferOrch = new BufferOrch(m_configDb, buffer_tables); + PolicerOrch *policer_orch = new PolicerOrch(m_configDb, "POLICER"); + TableConnector stateDbMirrorSession(m_stateDb, APP_MIRROR_SESSION_TABLE_NAME); TableConnector confDbMirrorSession(m_configDb, CFG_MIRROR_SESSION_TABLE_NAME); - MirrorOrch *mirror_orch = new MirrorOrch(stateDbMirrorSession, confDbMirrorSession, gPortsOrch, gRouteOrch, gNeighOrch, gFdbOrch); + MirrorOrch *mirror_orch = new MirrorOrch(stateDbMirrorSession, confDbMirrorSession, gPortsOrch, gRouteOrch, gNeighOrch, gFdbOrch, policer_orch); TableConnector confDbAclTable(m_configDb, CFG_ACL_TABLE_NAME); TableConnector confDbAclRuleTable(m_configDb, CFG_ACL_RULE_TABLE_NAME); @@ -155,7 +157,7 @@ bool OrchDaemon::init() * when iterating ConsumerMap. * That is ensured implicitly by the order of map key, "LAG_TABLE" is smaller than "VLAN_TABLE" in lexicographic order. */ - m_orchList = { gSwitchOrch, gCrmOrch, gBufferOrch, gPortsOrch, gIntfsOrch, gNeighOrch, gRouteOrch, copp_orch, tunnel_decap_orch, qos_orch, wm_orch }; + m_orchList = { gSwitchOrch, gCrmOrch, gBufferOrch, gPortsOrch, gIntfsOrch, gNeighOrch, gRouteOrch, copp_orch, tunnel_decap_orch, qos_orch, wm_orch, policer_orch }; bool initialize_dtel = false; diff --git a/orchagent/orchdaemon.h b/orchagent/orchdaemon.h index 09342088b1e..14d43fb2c1a 100644 --- a/orchagent/orchdaemon.h +++ b/orchagent/orchdaemon.h @@ -26,6 +26,7 @@ #include "countercheckorch.h" #include "flexcounterorch.h" #include "watermarkorch.h" +#include "policerorch.h" #include "directory.h" using namespace swss; diff --git a/orchagent/policerorch.cpp b/orchagent/policerorch.cpp new file mode 100644 index 00000000000..aea221cb489 --- /dev/null +++ b/orchagent/policerorch.cpp @@ -0,0 +1,268 @@ +#include "sai.h" +#include "policerorch.h" + +#include "converter.h" + +using namespace std; +using namespace swss; + +extern sai_policer_api_t* sai_policer_api; + +extern sai_object_id_t gSwitchId; +extern PortsOrch* gPortsOrch; + +static const string meter_type_field = "METER_TYPE"; +static const string mode_field = "MODE"; +static const string color_source_field = "COLOR_SOURCE"; +static const string cbs_field = "CBS"; +static const string cir_field = "CIR"; +static const string pbs_field = "PBS"; +static const string pir_field = "PIR"; +static const string green_packet_action_field = "GREEN_PACKET_ACTION"; +static const string red_packet_action_field = "RED_PACKET_ACTION"; +static const string yellow_packet_action_field = "YELLOW_PACKET_ACTION"; + +static const map meter_type_map = { + {"PACKETS", SAI_METER_TYPE_PACKETS}, + {"BYTES", SAI_METER_TYPE_BYTES} +}; + +static const map policer_mode_map = { + {"SR_TCM", SAI_POLICER_MODE_SR_TCM}, + {"TR_TCM", SAI_POLICER_MODE_TR_TCM}, + {"STORM_CONTROL", SAI_POLICER_MODE_STORM_CONTROL} +}; + +static const map policer_color_source_map = { + {"AWARE", SAI_POLICER_COLOR_SOURCE_AWARE}, + {"BLIND", SAI_POLICER_COLOR_SOURCE_BLIND} +}; + +static const map packet_action_map = { + {"DROP", SAI_PACKET_ACTION_DROP}, + {"FORWARD", SAI_PACKET_ACTION_FORWARD}, + {"COPY", SAI_PACKET_ACTION_COPY}, + {"COPY_CANCEL", SAI_PACKET_ACTION_COPY_CANCEL}, + {"TRAP", SAI_PACKET_ACTION_TRAP}, + {"LOG", SAI_PACKET_ACTION_LOG}, + {"DENY", SAI_PACKET_ACTION_DENY}, + {"TRANSIT", SAI_PACKET_ACTION_TRANSIT} +}; + +bool PolicerOrch::policerExists(const string &name) +{ + SWSS_LOG_ENTER(); + + return m_syncdPolicers.find(name) != m_syncdPolicers.end(); +} + +bool PolicerOrch::getPolicerOid(const string &name, sai_object_id_t &oid) +{ + SWSS_LOG_ENTER(); + + if (policerExists(name)) + { + oid = m_syncdPolicers[name]; + SWSS_LOG_NOTICE("Get policer %s oid:%lx", name.c_str(), oid); + return true; + } + + return false; +} + +bool PolicerOrch::increaseRefCount(const string &name) +{ + SWSS_LOG_ENTER(); + + if (!policerExists(name)) + { + SWSS_LOG_WARN("Policer %s does not exist", name.c_str()); + return false; + } + + ++m_policerRefCounts[name]; + + SWSS_LOG_INFO("Policer %s reference count is increased to %d", + name.c_str(), m_policerRefCounts[name]); + return true; +} + +bool PolicerOrch::decreaseRefCount(const string &name) +{ + SWSS_LOG_ENTER(); + + if (!policerExists(name)) + { + SWSS_LOG_WARN("Policer %s does not exist", name.c_str()); + return false; + } + + --m_policerRefCounts[name]; + + SWSS_LOG_INFO("Policer %s reference count is decreased to %d", + name.c_str(), m_policerRefCounts[name]); + return true; +} + +PolicerOrch::PolicerOrch(DBConnector* db, string tableName) : + Orch(db, tableName) +{ + SWSS_LOG_ENTER(); +} + +void PolicerOrch::doTask(Consumer &consumer) +{ + SWSS_LOG_ENTER(); + + if (!gPortsOrch->isPortReady()) + { + return; + } + + auto it = consumer.m_toSync.begin(); + while (it != consumer.m_toSync.end()) + { + auto tuple = it->second; + + auto key = kfvKey(tuple); + auto op = kfvOp(tuple); + + if (op == SET_COMMAND) + { + if (m_syncdPolicers.find(key) != m_syncdPolicers.end()) + { + SWSS_LOG_ERROR("Policer %s already exists", key.c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + vector attrs; + bool meter_type = false, mode = false; + + for (auto i = kfvFieldsValues(tuple).begin(); + i != kfvFieldsValues(tuple).end(); ++i) + { + auto field = to_upper(fvField(*i)); + auto value = to_upper(fvValue(*i)); + + SWSS_LOG_DEBUG("attribute: %s value: %s", field.c_str(), value.c_str()); + + sai_attribute_t attr; + + if (field == meter_type_field) + { + attr.id = SAI_POLICER_ATTR_METER_TYPE; + attr.value.s32 = (sai_meter_type_t) meter_type_map.at(value); + meter_type = true; + } + else if (field == mode_field) + { + attr.id = SAI_POLICER_ATTR_MODE; + attr.value.s32 = (sai_policer_mode_t) policer_mode_map.at(value); + mode = true; + } + else if (field == color_source_field) + { + attr.id = SAI_POLICER_ATTR_COLOR_SOURCE; + attr.value.s32 = policer_color_source_map.at(value); + } + else if (field == cbs_field) + { + attr.id = SAI_POLICER_ATTR_CBS; + attr.value.u64 = stoul(value); + } + else if (field == cir_field) + { + attr.id = SAI_POLICER_ATTR_CIR; + attr.value.u64 = stoul(value); + } + else if (field == pbs_field) + { + attr.id = SAI_POLICER_ATTR_PBS; + attr.value.u64 = stoul(value); + } + else if (field == pir_field) + { + attr.id = SAI_POLICER_ATTR_PIR; + attr.value.u64 = stoul(value); + } + else if (field == red_packet_action_field) + { + attr.id = SAI_POLICER_ATTR_RED_PACKET_ACTION; + attr.value.s32 = packet_action_map.at(value); + } + else if (field == green_packet_action_field) + { + attr.id = SAI_POLICER_ATTR_GREEN_PACKET_ACTION; + attr.value.s32 = packet_action_map.at(value); + } + else if (field == yellow_packet_action_field) + { + attr.id = SAI_POLICER_ATTR_YELLOW_PACKET_ACTION; + attr.value.s32 = packet_action_map.at(value); + } + else + { + SWSS_LOG_ERROR("Unknown policer attribute %s specified", + field.c_str()); + continue; + } + + attrs.push_back(attr); + } + + if (!meter_type || !mode) + { + SWSS_LOG_ERROR("Failed to create policer %s,\ + missing madatory fields", key.c_str()); + } + + sai_object_id_t policer_id; + sai_status_t status = sai_policer_api->create_policer( + &policer_id, gSwitchId, (uint32_t)attrs.size(), attrs.data()); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to create policer %s, rv:%d", + key.c_str(), status); + it++; + continue; + } + + SWSS_LOG_NOTICE("Created policer %s", key.c_str()); + m_syncdPolicers[key] = policer_id; + m_policerRefCounts[key] = 0; + it = consumer.m_toSync.erase(it); + } + else if (op == DEL_COMMAND) + { + if (m_syncdPolicers.find(key) == m_syncdPolicers.end()) + { + SWSS_LOG_ERROR("Policer %s does not exists", key.c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + if (m_policerRefCounts[key] > 0) + { + SWSS_LOG_INFO("Policer %s is still referenced", key.c_str()); + it++; + continue; + } + + sai_status_t status = sai_policer_api->remove_policer( + m_syncdPolicers.at(key)); + if (status == SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to remove policer %s, rv:%d", + key.c_str(), status); + it++; + continue; + } + + SWSS_LOG_NOTICE("Removed policer %s", key.c_str()); + m_syncdPolicers.erase(key); + m_policerRefCounts.erase(key); + it = consumer.m_toSync.erase(it); + } + } +} diff --git a/orchagent/policerorch.h b/orchagent/policerorch.h new file mode 100644 index 00000000000..d735da03b79 --- /dev/null +++ b/orchagent/policerorch.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +#include "orch.h" +#include "portsorch.h" + +using namespace std; + +typedef map PolicerTable; +typedef map PolicerRefCountTable; + +class PolicerOrch : public Orch +{ +public: + PolicerOrch(DBConnector* db, string tableName); + + bool policerExists(const string &name); + bool getPolicerOid(const string &name, sai_object_id_t &oid); + + bool increaseRefCount(const string &name); + bool decreaseRefCount(const string &name); +private: + virtual void doTask(Consumer& consumer); + + PolicerTable m_syncdPolicers; + PolicerRefCountTable m_policerRefCounts; +}; diff --git a/tests/test_mirror_policer.py b/tests/test_mirror_policer.py new file mode 100644 index 00000000000..3226fbb1661 --- /dev/null +++ b/tests/test_mirror_policer.py @@ -0,0 +1,239 @@ +# This test suite covers the functionality of mirror feature in SwSS + +import platform +import pytest +import time +from distutils.version import StrictVersion + +from swsscommon import swsscommon + + +class TestMirror(object): + def setup_db(self, dvs): + self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0) + self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0) + self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0) + self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0) + + def set_port_status(self, port, admin_status): + tbl = swsscommon.Table(self.cdb, "PORT") + fvs = swsscommon.FieldValuePairs([("admin_status", "up")]) + tbl.set(port, fvs) + time.sleep(1) + + def add_ip_address(self, interface, ip): + tbl = swsscommon.Table(self.cdb, "INTERFACE") + fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) + tbl.set(interface + "|" + ip, fvs) + time.sleep(1) + + def remove_ip_address(self, interface, ip): + tbl = swsscommon.Table(self.cdb, "INTERFACE") + tbl._del(interface + "|" + ip) + time.sleep(1) + + def add_neighbor(self, interface, ip, mac): + tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") + fvs = swsscommon.FieldValuePairs([("neigh", mac), + ("family", "IPv4")]) + tbl.set(interface + ":" + ip, fvs) + time.sleep(1) + + def remove_neighbor(self, interface, ip): + tbl = swsscommon.ProducerStateTable(self.pdb, "NEIGH_TABLE") + tbl._del(interface + ":" + ip) + time.sleep(1) + + def add_route(self, dvs, prefix, nexthop): + dvs.runcmd("ip route add " + prefix + " via " + nexthop) + time.sleep(1) + + def remove_route(self, dvs, prefix): + dvs.runcmd("ip route del " + prefix) + time.sleep(1) + + def create_mirror_session(self, name, src, dst, gre, dscp, ttl, queue, policer): + tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") + fvs = swsscommon.FieldValuePairs([("src_ip", src), + ("dst_ip", dst), + ("gre_type", gre), + ("dscp", dscp), + ("ttl", ttl), + ("queue", queue), + ("policer", policer)]) + tbl.set(name, fvs) + time.sleep(1) + + def remove_mirror_session(self, name): + tbl = swsscommon.Table(self.cdb, "MIRROR_SESSION") + tbl._del(name) + time.sleep(1) + + def create_policer(self, name): + tbl = swsscommon.Table(self.cdb, "POLICER") + fvs = swsscommon.FieldValuePairs([("meter_type", "packets"), + ("mode", "sr_tcm"), + ("cir", "600"), + ("cbs", "600"), + ("red_packet_action", "drop")]) + tbl.set(name, fvs) + time.sleep(1) + + def remove_policer(self, name): + tbl = swsscommon.Table(self.cdb, "POLICER") + tbl._del(name) + time.sleep(1) + + def test_MirrorPolicer(self, dvs, testlog): + self.setup_db(dvs) + + session = "MIRROR_SESSION" + policer= "POLICER" + + # create policer + self.create_policer(policer) + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "2.2.2.2", "0x6558", "8", "100", "0", policer) + self.set_port_status("Ethernet16", "up") + self.add_ip_address("Ethernet16", "10.0.0.0/31") + self.add_neighbor("Ethernet16", "10.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "2.2.2.2", "10.0.0.1") + + # check asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER") + policer_entries = tbl.getKeys() + assert len(policer_entries) == 1 + policer_oid = policer_entries[0] + + # check asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + mirror_entries = tbl.getKeys() + assert len(mirror_entries) == 1 + + (status, fvs) = tbl.get(mirror_entries[0]) + assert status == True + assert len(fvs) == 12 + for fv in fvs: + if fv[0] == "SAI_MIRROR_SESSION_ATTR_MONITOR_PORT": + assert dvs.asicdb.portoidmap[fv[1]] == "Ethernet16" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TYPE": + assert fv[1] == "SAI_MIRROR_SESSION_TYPE_ENHANCED_REMOTE" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE": + assert fv[1] == "SAI_ERSPAN_ENCAPSULATION_TYPE_MIRROR_L3_GRE_TUNNEL" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION": + assert fv[1] == "4" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TOS": + assert fv[1] == "32" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_TTL": + assert fv[1] == "100" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS": + assert fv[1] == "3.3.3.3" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS": + assert fv[1] == "2.2.2.2" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS": + assert fv[1] == dvs.runcmd("bash -c \"ip link show eth0 | grep ether | awk '{print $2}'\"")[1].strip().upper() + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS": + assert fv[1] == "02:04:06:08:10:12" + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE": + assert fv[1] == "25944" # 0x6558 + elif fv[0] == "SAI_MIRROR_SESSION_ATTR_POLICER": + assert fv[1] == policer_oid + else: + assert False + + # remove mirror session + self.remove_route(dvs, "2.2.2.2") + self.remove_neighbor("Ethernet16", "10.0.0.1") + self.remove_ip_address("Ethernet16", "10.0.0.0/31") + self.set_port_status("Ethernet16", "down") + self.remove_mirror_session(session) + + # remove policer + self.remove_policer(policer) + + + def create_acl_table(self, table, interfaces): + tbl = swsscommon.Table(self.cdb, "ACL_TABLE") + fvs = swsscommon.FieldValuePairs([("policy_desc", "mirror_test"), + ("type", "mirror"), + ("ports", ",".join(interfaces))]) + tbl.set(table, fvs) + time.sleep(1) + + def remove_acl_table(self, table): + tbl = swsscommon.Table(self.cdb, "ACL_TABLE") + tbl._del(table) + time.sleep(1) + + def create_mirror_acl_dscp_rule(self, table, rule, dscp, session): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + fvs = swsscommon.FieldValuePairs([("priority", "1000"), + ("mirror_action", session), + ("DSCP", dscp)]) + tbl.set(table + "|" + rule, fvs) + time.sleep(1) + + def remove_mirror_acl_dscp_rule(self, table, rule): + tbl = swsscommon.Table(self.cdb, "ACL_RULE") + tbl._del(table + "|" + rule) + time.sleep(1) + + def test_MirrorPolicerWithAcl(self, dvs, testlog): + self.setup_db(dvs) + + session = "MIRROR_SESSION" + policer= "POLICER" + acl_table = "MIRROR_TABLE" + acl_rule = "MIRROR_RULE" + + # create policer + self.create_policer(policer) + + # create mirror session + self.create_mirror_session(session, "3.3.3.3", "2.2.2.2", "0x6558", "8", "100", "0", policer) + self.set_port_status("Ethernet16", "up") + self.add_ip_address("Ethernet16", "10.0.0.0/31") + self.add_neighbor("Ethernet16", "10.0.0.1", "02:04:06:08:10:12") + self.add_route(dvs, "2.2.2.2", "10.0.0.1") + + # check asic database + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION") + mirror_entries = tbl.getKeys() + assert len(mirror_entries) == 1 + mirror_oid = mirror_entries[0] + + # create acl table + self.create_acl_table(acl_table, ["Ethernet0", "Ethernet4"]) + + # create acl rule with dscp value and mask + self.create_mirror_acl_dscp_rule(acl_table, acl_rule, "8/56", session) + + # assert acl rule is created + tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY") + rule_entries = [k for k in tbl.getKeys() if k not in dvs.asicdb.default_acl_entries] + assert len(rule_entries) == 1 + + (status, fvs) = tbl.get(rule_entries[0]) + assert status == True + for fv in fvs: + if fv[0] == "SAI_ACL_ENTRY_ATTR_FIELD_DSCP": + assert fv[1] == "8&mask:0x38" + if fv[0] == "SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS": + assert fv[1] == "1:" + mirror_oid + + # remove acl rule + self.remove_mirror_acl_dscp_rule(acl_table, acl_rule) + + # remove acl table + self.remove_acl_table(acl_table) + + # remove mirror session + self.remove_route(dvs, "2.2.2.2") + self.remove_neighbor("Ethernet16", "10.0.0.1") + self.remove_ip_address("Ethernet16", "10.0.0.0/31") + self.set_port_status("Ethernet16", "down") + self.remove_mirror_session(session) + + # remove policer + self.remove_policer(policer) From a0274cc4b3ee31cb6c6113fbd583fca57489c8bb Mon Sep 17 00:00:00 2001 From: Shuotian Cheng Date: Thu, 30 May 2019 12:34:06 -0700 Subject: [PATCH 6/6] [vstest]: Update the mirror session state table name (#917) Due to the change c033b2380419fe36dfc3b5e055bbe0376cc8f4e7 Fix MIRROR_SESSION table macro name (#802) Signed-off-by: Shu0T1an ChenG --- tests/test_mirror.py | 2 +- tests/test_mirror_ipv6_combined.py | 2 +- tests/test_mirror_ipv6_separate.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_mirror.py b/tests/test_mirror.py index d1a29840406..38c94f6a664 100644 --- a/tests/test_mirror.py +++ b/tests/test_mirror.py @@ -90,7 +90,7 @@ def get_mirror_session_status(self, name): return self.get_mirror_session_state(name)["status"] def get_mirror_session_state(self, name): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION") + tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") (status, fvs) = tbl.get(name) assert status == True assert len(fvs) > 0 diff --git a/tests/test_mirror_ipv6_combined.py b/tests/test_mirror_ipv6_combined.py index f97315836a1..988d41b76f6 100644 --- a/tests/test_mirror_ipv6_combined.py +++ b/tests/test_mirror_ipv6_combined.py @@ -98,7 +98,7 @@ def get_mirror_session_status(self, name): return self.get_mirror_session_state(name)["status"] def get_mirror_session_state(self, name): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION") + tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") (status, fvs) = tbl.get(name) assert status == True assert len(fvs) > 0 diff --git a/tests/test_mirror_ipv6_separate.py b/tests/test_mirror_ipv6_separate.py index 839e79c018a..97bf4df8dd2 100644 --- a/tests/test_mirror_ipv6_separate.py +++ b/tests/test_mirror_ipv6_separate.py @@ -92,7 +92,7 @@ def get_mirror_session_status(self, name): return self.get_mirror_session_state(name)["status"] def get_mirror_session_state(self, name): - tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION") + tbl = swsscommon.Table(self.sdb, "MIRROR_SESSION_TABLE") (status, fvs) = tbl.get(name) assert status == True assert len(fvs) > 0