Skip to content

Commit

Permalink
[aclorch] Add support for creating ingress and egress MIRROR tables c…
Browse files Browse the repository at this point in the history
…oncurrently (sonic-net#1286)

Signed-off-by: Danny Allen <daall@microsoft.com>
  • Loading branch information
daall authored May 27, 2020
1 parent 69a980e commit a9dbc83
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 39 deletions.
80 changes: 47 additions & 33 deletions orchagent/aclorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2213,6 +2213,12 @@ void AclOrch::init(vector<TableConnector>& connectors, PortsOrch *portOrch, Mirr

queryAclActionCapability();

for (auto stage: {ACL_STAGE_INGRESS, ACL_STAGE_EGRESS})
{
m_mirrorTableId[stage] = "";
m_mirrorV6TableId[stage] = "";
}

// Attach observers
m_mirrorOrch->attach(this);
gPortsOrch->attach(this);
Expand Down Expand Up @@ -2666,6 +2672,7 @@ bool AclOrch::addAclTable(AclTable &newTable)
}

sai_object_id_t table_oid = getTableById(table_id);
auto table_stage = newTable.stage;

if (table_oid != SAI_NULL_OBJECT_ID)
{
Expand All @@ -2685,19 +2692,23 @@ bool AclOrch::addAclTable(AclTable &newTable)
if (table_type == ACL_TABLE_MIRROR || table_type == ACL_TABLE_MIRRORV6)
{
string mirror_type;
if ((table_type == ACL_TABLE_MIRROR && !m_mirrorTableId.empty()))
if (table_type == ACL_TABLE_MIRROR && !m_mirrorTableId[table_stage].empty())
{
mirror_type = TABLE_TYPE_MIRROR;
}

if (table_type == ACL_TABLE_MIRRORV6 && !m_mirrorV6TableId.empty())
if (table_type == ACL_TABLE_MIRRORV6 && !m_mirrorV6TableId[table_stage].empty())
{
mirror_type = TABLE_TYPE_MIRRORV6;
}

if (!mirror_type.empty())
{
SWSS_LOG_ERROR("Mirror table %s has already been created", mirror_type.c_str());
string stage_str = table_stage == ACL_STAGE_INGRESS ? "INGRESS" : "EGRESS";
SWSS_LOG_ERROR(
"Mirror table %s (%s) has already been created",
mirror_type.c_str(),
stage_str.c_str());
return false;
}
}
Expand All @@ -2706,23 +2717,22 @@ bool AclOrch::addAclTable(AclTable &newTable)
// 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())) {

(!m_mirrorTableId[table_stage].empty() ||
!m_mirrorV6TableId[table_stage].empty())) {
string orig_table_name;

// If v4 table is created, mark v6 table is created
if (!m_mirrorTableId.empty())
if (!m_mirrorTableId[table_stage].empty())
{
orig_table_name = m_mirrorTableId;
m_mirrorV6TableId = newTable.id;
orig_table_name = m_mirrorTableId[table_stage];
m_mirrorV6TableId[table_stage] = newTable.id;
}
// If v6 table is created, mark v4 table is created
else
{
orig_table_name = m_mirrorV6TableId;
m_mirrorTableId = newTable.id;
orig_table_name = m_mirrorV6TableId[table_stage];
m_mirrorTableId[table_stage] = newTable.id;
}

SWSS_LOG_NOTICE("Created ACL table %s as a sibling of %s",
Expand All @@ -2741,11 +2751,11 @@ bool AclOrch::addAclTable(AclTable &newTable)
// Mark the existence of the mirror table
if (newTable.type == ACL_TABLE_MIRROR)
{
m_mirrorTableId = table_id;
m_mirrorTableId[table_stage] = table_id;
}
else if (newTable.type == ACL_TABLE_MIRRORV6)
{
m_mirrorV6TableId = table_id;
m_mirrorV6TableId[table_stage] = table_id;
}

return true;
Expand Down Expand Up @@ -2774,29 +2784,30 @@ bool AclOrch::removeAclTable(string table_id)

if (deleteUnbindAclTable(table_oid) == SAI_STATUS_SUCCESS)
{
sai_acl_stage_t stage = (m_AclTables[table_oid].stage == ACL_STAGE_INGRESS) ? SAI_ACL_STAGE_INGRESS : SAI_ACL_STAGE_EGRESS;
gCrmOrch->decCrmAclUsedCounter(CrmResourceType::CRM_ACL_TABLE, stage, SAI_ACL_BIND_POINT_TYPE_PORT, table_oid);
auto stage = m_AclTables[table_oid].stage;
sai_acl_stage_t sai_stage = (stage == ACL_STAGE_INGRESS) ? SAI_ACL_STAGE_INGRESS : SAI_ACL_STAGE_EGRESS;
gCrmOrch->decCrmAclUsedCounter(CrmResourceType::CRM_ACL_TABLE, sai_stage, SAI_ACL_BIND_POINT_TYPE_PORT, table_oid);

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)
if (m_mirrorTableId[stage] == table_id)
{
m_mirrorTableId.clear();
m_mirrorTableId[stage].clear();
if (m_isCombinedMirrorV6Table)
{
m_mirrorV6TableId.clear();
m_mirrorV6TableId[stage].clear();
}
}
else if (table_id == m_mirrorV6TableId)
else if (m_mirrorV6TableId[stage] == table_id)
{
m_mirrorV6TableId.clear();
m_mirrorV6TableId[stage].clear();
if (m_isCombinedMirrorV6Table)
{
m_mirrorTableId.clear();
m_mirrorTableId[stage].clear();
}
}

Expand Down Expand Up @@ -3042,9 +3053,10 @@ void AclOrch::doAclRuleTask(Consumer &consumer)
}

auto type = m_AclTables[table_oid].type;
auto stage = m_AclTables[table_oid].stage;
if (type == ACL_TABLE_MIRROR || type == ACL_TABLE_MIRRORV6)
{
type = table_id == m_mirrorTableId ? ACL_TABLE_MIRROR : ACL_TABLE_MIRRORV6;
type = table_id == m_mirrorTableId[stage] ? ACL_TABLE_MIRROR : ACL_TABLE_MIRRORV6;
}


Expand Down Expand Up @@ -3212,18 +3224,20 @@ 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
for (auto stage: {ACL_STAGE_INGRESS, ACL_STAGE_EGRESS}) {
if (m_isCombinedMirrorV6Table &&
(table_id == m_mirrorTableId[stage] || table_id == m_mirrorV6TableId[stage]))
{
return getTableById(m_mirrorTableId);
// If the table is v4, the corresponding v6 table is already created
if (table_id == m_mirrorTableId[stage])
{
return getTableById(m_mirrorV6TableId[stage]);
}
// If the table is v6, the corresponding v4 table is already created
else
{
return getTableById(m_mirrorTableId[stage]);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions orchagent/aclorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,8 @@ class AclOrch : public Orch, public Observer
static DBConnector m_db;
static Table m_countersTable;

string m_mirrorTableId;
string m_mirrorV6TableId;
map<acl_stage_type_t, string> m_mirrorTableId;
map<acl_stage_type_t, string> m_mirrorV6TableId;

acl_capabilities_t m_aclCapabilities;
acl_action_enum_values_capabilities_t m_aclEnumActionCapabilities;
Expand Down
62 changes: 58 additions & 4 deletions tests/test_mirror_ipv6_separate.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,15 @@ def get_mirror_session_state(self, name):
assert len(fvs) > 0
return { fv[0]: fv[1] for fv in fvs }

def create_acl_table(self, table, interfaces, type):
def create_acl_table(self, table, interfaces, type, stage=None):
attrs = [("policy_desc", "mirror_test"),
("type", type),
("ports", ",".join(interfaces))]
if stage:
attrs.append(("stage", stage))

tbl = swsscommon.Table(self.cdb, "ACL_TABLE")
fvs = swsscommon.FieldValuePairs([("policy_desc", "mirror_test"),
("type", type),
("ports", ",".join(interfaces))])
fvs = swsscommon.FieldValuePairs(attrs)
tbl.set(table, fvs)
time.sleep(1)

Expand Down Expand Up @@ -268,6 +272,56 @@ def test_MirrorV6TableCreation(self, dvs, testlog):
# Delete the V6 table
self.remove_acl_table(acl_table_v6)

def test_CreateMirrorIngressAndEgress(self, dvs, testlog):
self.setup_db(dvs)
asic_db = dvs.get_asic_db()

ingress_table = "INGRESS_TABLE"
duplicate_ingress_table = "INGRESS_TABLE_2"
ports = ["Ethernet0", "Ethernet4"]

# Create the table
self.create_acl_table(ingress_table, ports, "MIRROR")

# Check that the table has been created
table_ids = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE",
len(asic_db.default_acl_tables) + 1)
table_entries = [oid for oid in table_ids if oid not in asic_db.default_acl_tables]
original_entry = table_entries[0]

# Attempt to create another MIRROR table with ingress ACLs
self.create_acl_table(duplicate_ingress_table, ports, "MIRROR")

# Check that there is still only one table, and that it is the original table
table_ids = asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE",
len(asic_db.default_acl_tables) + 1)
table_entries = [oid for oid in table_ids if oid not in asic_db.default_acl_tables]
assert table_entries[0] == original_entry

egress_table = "EGRESS_TABLE"
duplicate_egress_table = "EGRESS_TABLE_2"

# Create the egress table
self.create_acl_table(egress_table, ports, "MIRROR", "egress")

# Check that there are two tables
asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE",
len(asic_db.default_acl_tables) + 2)

# Attempt to create another MIRROR table with egress ACLs
self.create_acl_table(duplicate_egress_table, ports, "MIRROR", "egress")

# Check that there are still only two tables
asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE",
len(asic_db.default_acl_tables) + 2)

self.remove_acl_table(ingress_table)
self.remove_acl_table(egress_table)
self.remove_acl_table(duplicate_ingress_table)
self.remove_acl_table(duplicate_egress_table)

asic_db.wait_for_n_keys("ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE", len(asic_db.default_acl_tables))

# 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
Expand Down

0 comments on commit a9dbc83

Please sign in to comment.