Skip to content

Commit 98a16cf

Browse files
authored
[ACL] Write ACL table/rule creation status into STATE_DB (sonic-net#2662)
* Add status for ACL_TABLE and ACL_RULE in STATE_DB
1 parent a2c9a61 commit 98a16cf

File tree

4 files changed

+305
-6
lines changed

4 files changed

+305
-6
lines changed

orchagent/aclorch.cpp

+100
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,14 @@ static map<sai_acl_counter_attr_t, sai_acl_counter_attr_t> aclCounterLookup =
415415
{SAI_ACL_COUNTER_ATTR_ENABLE_PACKET_COUNT, SAI_ACL_COUNTER_ATTR_PACKETS},
416416
};
417417

418+
static map<AclObjectStatus, string> aclObjectStatusLookup =
419+
{
420+
{AclObjectStatus::ACTIVE, "Active"},
421+
{AclObjectStatus::INACTIVE, "Inactive"},
422+
{AclObjectStatus::PENDING_CREATION, "Pending creation"},
423+
{AclObjectStatus::PENDING_REMOVAL, "Pending removal"}
424+
};
425+
418426
static sai_acl_table_attr_t AclEntryFieldToAclTableField(sai_acl_entry_attr_t attr)
419427
{
420428
if (!IS_ATTR_ID_IN_RANGE(attr, ACL_ENTRY, FIELD))
@@ -3006,6 +3014,10 @@ void AclOrch::init(vector<TableConnector>& connectors, PortsOrch *portOrch, Mirr
30063014
{
30073015
SWSS_LOG_ENTER();
30083016

3017+
// Clear ACL_TABLE and ACL_RULE status from STATE_DB
3018+
removeAllAclTableStatus();
3019+
removeAllAclRuleStatus();
3020+
30093021
// TODO: Query SAI to get mirror table capabilities
30103022
// Right now, verified platforms that support mirroring IPv6 packets are
30113023
// Broadcom and Mellanox. Virtual switch is also supported for testing
@@ -3509,6 +3521,8 @@ AclOrch::AclOrch(vector<TableConnector>& connectors, DBConnector* stateDb, Switc
35093521
PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch, DTelOrch *dtelOrch) :
35103522
Orch(connectors),
35113523
m_aclStageCapabilityTable(stateDb, STATE_ACL_STAGE_CAPABILITY_TABLE_NAME),
3524+
m_aclTableStateTable(stateDb, STATE_ACL_TABLE_TABLE_NAME),
3525+
m_aclRuleStateTable(stateDb, STATE_ACL_RULE_TABLE_NAME),
35123526
m_switchOrch(switchOrch),
35133527
m_mirrorOrch(mirrorOrch),
35143528
m_neighOrch(neighOrch),
@@ -4332,6 +4346,8 @@ void AclOrch::doAclTableTask(Consumer &consumer)
43324346
{
43334347
SWSS_LOG_NOTICE("Successfully updated existing ACL table %s",
43344348
table_id.c_str());
4349+
// Mark ACL table as ACTIVE
4350+
setAclTableStatus(table_id, AclObjectStatus::ACTIVE);
43354351
it = consumer.m_toSync.erase(it);
43364352
}
43374353
else
@@ -4344,24 +4360,41 @@ void AclOrch::doAclTableTask(Consumer &consumer)
43444360
else
43454361
{
43464362
if (addAclTable(newTable))
4363+
{
4364+
// Mark ACL table as ACTIVE
4365+
setAclTableStatus(table_id, AclObjectStatus::ACTIVE);
43474366
it = consumer.m_toSync.erase(it);
4367+
}
43484368
else
4369+
{
4370+
setAclTableStatus(table_id, AclObjectStatus::PENDING_CREATION);
43494371
it++;
4372+
}
43504373
}
43514374
}
43524375
else
43534376
{
43544377
it = consumer.m_toSync.erase(it);
4378+
// Mark the ACL table as inactive if the configuration is invalid
4379+
setAclTableStatus(table_id, AclObjectStatus::INACTIVE);
43554380
SWSS_LOG_ERROR("Failed to create ACL table %s, invalid configuration",
43564381
table_id.c_str());
43574382
}
43584383
}
43594384
else if (op == DEL_COMMAND)
43604385
{
43614386
if (removeAclTable(table_id))
4387+
{
4388+
// Remove ACL table status from STATE_DB
4389+
removeAclTableStatus(table_id);
43624390
it = consumer.m_toSync.erase(it);
4391+
}
43634392
else
4393+
{
4394+
// Set the status of ACL_TABLE to pending removal if removeAclTable returns error
4395+
setAclTableStatus(table_id, AclObjectStatus::PENDING_REMOVAL);
43644396
it++;
4397+
}
43654398
}
43664399
else
43674400
{
@@ -4501,22 +4534,37 @@ void AclOrch::doAclRuleTask(Consumer &consumer)
45014534
if (bAllAttributesOk && newRule->validate())
45024535
{
45034536
if (addAclRule(newRule, table_id))
4537+
{
4538+
setAclRuleStatus(table_id, rule_id, AclObjectStatus::ACTIVE);
45044539
it = consumer.m_toSync.erase(it);
4540+
}
45054541
else
4542+
{
4543+
setAclRuleStatus(table_id, rule_id, AclObjectStatus::PENDING_CREATION);
45064544
it++;
4545+
}
45074546
}
45084547
else
45094548
{
45104549
it = consumer.m_toSync.erase(it);
4550+
// Mark the rule inactive if the configuration is invalid
4551+
setAclRuleStatus(table_id, rule_id, AclObjectStatus::INACTIVE);
45114552
SWSS_LOG_ERROR("Failed to create ACL rule. Rule configuration is invalid");
45124553
}
45134554
}
45144555
else if (op == DEL_COMMAND)
45154556
{
45164557
if (removeAclRule(table_id, rule_id))
4558+
{
4559+
removeAclRuleStatus(table_id, rule_id);
45174560
it = consumer.m_toSync.erase(it);
4561+
}
45184562
else
4563+
{
4564+
// Mark pending removal status if removeAclRule returns error
4565+
setAclRuleStatus(table_id, rule_id, AclObjectStatus::PENDING_REMOVAL);
45194566
it++;
4567+
}
45204568
}
45214569
else
45224570
{
@@ -4874,3 +4922,55 @@ bool AclOrch::getAclBindPortId(Port &port, sai_object_id_t &port_id)
48744922

48754923
return true;
48764924
}
4925+
4926+
// Set the status of ACL table in STATE_DB
4927+
void AclOrch::setAclTableStatus(string table_name, AclObjectStatus status)
4928+
{
4929+
vector<FieldValueTuple> fvVector;
4930+
fvVector.emplace_back("status", aclObjectStatusLookup[status]);
4931+
m_aclTableStateTable.set(table_name, fvVector);
4932+
}
4933+
4934+
// Remove the status record of given ACL table from STATE_DB
4935+
void AclOrch::removeAclTableStatus(string table_name)
4936+
{
4937+
m_aclTableStateTable.del(table_name);
4938+
}
4939+
4940+
// Set the status of ACL rule in STATE_DB
4941+
void AclOrch::setAclRuleStatus(string table_name, string rule_name, AclObjectStatus status)
4942+
{
4943+
vector<FieldValueTuple> fvVector;
4944+
fvVector.emplace_back("status", aclObjectStatusLookup[status]);
4945+
m_aclRuleStateTable.set(table_name + string("|") + rule_name, fvVector);
4946+
}
4947+
4948+
// Remove the status record of given ACL rule from STATE_DB
4949+
void AclOrch::removeAclRuleStatus(string table_name, string rule_name)
4950+
{
4951+
m_aclRuleStateTable.del(table_name + string("|") + rule_name);
4952+
}
4953+
4954+
// Remove all ACL table status from STATE_DB
4955+
void AclOrch::removeAllAclTableStatus()
4956+
{
4957+
vector<string> keys;
4958+
m_aclTableStateTable.getKeys(keys);
4959+
4960+
for (auto key : keys)
4961+
{
4962+
m_aclTableStateTable.del(key);
4963+
}
4964+
}
4965+
4966+
// Remove all ACL rule status from STATE_DB
4967+
void AclOrch::removeAllAclRuleStatus()
4968+
{
4969+
vector<string> keys;
4970+
m_aclRuleStateTable.getKeys(keys);
4971+
for (auto key : keys)
4972+
{
4973+
m_aclRuleStateTable.del(key);
4974+
}
4975+
}
4976+

orchagent/aclorch.h

+20
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@
101101

102102
#define ACL_COUNTER_FLEX_COUNTER_GROUP "ACL_STAT_COUNTER"
103103

104+
enum AclObjectStatus
105+
{
106+
ACTIVE = 0,
107+
INACTIVE,
108+
PENDING_CREATION,
109+
PENDING_REMOVAL
110+
};
111+
104112
struct AclActionCapabilities
105113
{
106114
set<sai_acl_action_type_t> actionList;
@@ -554,6 +562,15 @@ class AclOrch : public Orch, public Observer
554562

555563
string generateAclRuleIdentifierInCountersDb(const AclRule& rule) const;
556564

565+
void setAclTableStatus(string table_name, AclObjectStatus status);
566+
void setAclRuleStatus(string table_name, string rule_name, AclObjectStatus status);
567+
568+
void removeAclTableStatus(string table_name);
569+
void removeAclRuleStatus(string table_name, string rule_name);
570+
571+
void removeAllAclTableStatus();
572+
void removeAllAclRuleStatus();
573+
557574
map<sai_object_id_t, AclTable> m_AclTables;
558575
// TODO: Move all ACL tables into one map: name -> instance
559576
map<string, AclTable> m_ctrlAclTables;
@@ -564,6 +581,9 @@ class AclOrch : public Orch, public Observer
564581

565582
Table m_aclStageCapabilityTable;
566583

584+
Table m_aclTableStateTable;
585+
Table m_aclRuleStateTable;
586+
567587
map<acl_stage_type_t, string> m_mirrorTableId;
568588
map<acl_stage_type_t, string> m_mirrorV6TableId;
569589

tests/dvslib/dvs_acl.py

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Utilities for interacting with ACLs when writing VS tests."""
22
from typing import Callable, Dict, List
3-
3+
from swsscommon import swsscommon
44

55
class DVSAcl:
66
"""Manage ACL tables and rules on the virtual switch."""
@@ -18,6 +18,9 @@ class DVSAcl:
1818
ADB_ACL_GROUP_MEMBER_TABLE_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER"
1919
ADB_ACL_COUNTER_TABLE_NAME = "ASIC_STATE:SAI_OBJECT_TYPE_ACL_COUNTER"
2020

21+
STATE_DB_ACL_TABLE_TABLE_NAME = "ACL_TABLE_TABLE"
22+
STATE_DB_ACL_RULE_TABLE_NAME = "ACL_RULE_TABLE"
23+
2124
ADB_ACL_STAGE_LOOKUP = {
2225
"ingress": "SAI_ACL_STAGE_INGRESS",
2326
"egress": "SAI_ACL_STAGE_EGRESS"
@@ -740,3 +743,43 @@ def _check_acl_entry_counters_map(self, acl_entry_oid: str):
740743
rule_to_counter_map = self.counters_db.get_entry("ACL_COUNTER_RULE_MAP", "")
741744
counter_to_rule_map = {v: k for k, v in rule_to_counter_map.items()}
742745
assert counter_oid in counter_to_rule_map
746+
747+
def verify_acl_table_status(
748+
self,
749+
acl_table_name,
750+
expected_status
751+
) -> None:
752+
"""Verify that the STATE_DB status of ACL table is as expected.
753+
754+
Args:
755+
acl_table_name: The name of ACL table to check
756+
expected_status: The expected status in STATE_DB
757+
"""
758+
if expected_status:
759+
fvs = self.state_db.wait_for_entry(self.STATE_DB_ACL_TABLE_TABLE_NAME, acl_table_name)
760+
assert len(fvs) > 0
761+
assert (fvs['status'] == expected_status)
762+
else:
763+
self.state_db.wait_for_deleted_entry(self.STATE_DB_ACL_TABLE_TABLE_NAME, acl_table_name)
764+
765+
def verify_acl_rule_status(
766+
self,
767+
acl_table_name,
768+
acl_rule_name,
769+
expected_status
770+
) -> None:
771+
"""Verify that the STATE_DB status of ACL rule is as expected.
772+
773+
Args:
774+
acl_table_name: The name of ACL table to check
775+
acl_rule_name: The name of ACL rule to check
776+
expected_status: The expected status in STATE_DB
777+
"""
778+
key = acl_table_name + "|" + acl_rule_name
779+
if expected_status:
780+
fvs = self.state_db.wait_for_entry(self.STATE_DB_ACL_RULE_TABLE_NAME, key)
781+
assert len(fvs) > 0
782+
assert (fvs['status'] == expected_status)
783+
else:
784+
self.state_db.wait_for_deleted_entry(self.STATE_DB_ACL_TABLE_TABLE_NAME, key)
785+

0 commit comments

Comments
 (0)