Skip to content

Commit 95d3f6d

Browse files
bingwang-msyxieca
authored andcommitted
[ACL] Write ACL table/rule creation status into STATE_DB (#2662)
* Add status for ACL_TABLE and ACL_RULE in STATE_DB
1 parent 8853c75 commit 95d3f6d

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
@@ -380,6 +380,14 @@ static map<sai_acl_counter_attr_t, sai_acl_counter_attr_t> aclCounterLookup =
380380
{SAI_ACL_COUNTER_ATTR_ENABLE_PACKET_COUNT, SAI_ACL_COUNTER_ATTR_PACKETS},
381381
};
382382

383+
static map<AclObjectStatus, string> aclObjectStatusLookup =
384+
{
385+
{AclObjectStatus::ACTIVE, "Active"},
386+
{AclObjectStatus::INACTIVE, "Inactive"},
387+
{AclObjectStatus::PENDING_CREATION, "Pending creation"},
388+
{AclObjectStatus::PENDING_REMOVAL, "Pending removal"}
389+
};
390+
383391
static sai_acl_table_attr_t AclEntryFieldToAclTableField(sai_acl_entry_attr_t attr)
384392
{
385393
if (!IS_ATTR_ID_IN_RANGE(attr, ACL_ENTRY, FIELD))
@@ -2911,6 +2919,10 @@ void AclOrch::init(vector<TableConnector>& connectors, PortsOrch *portOrch, Mirr
29112919
{
29122920
SWSS_LOG_ENTER();
29132921

2922+
// Clear ACL_TABLE and ACL_RULE status from STATE_DB
2923+
removeAllAclTableStatus();
2924+
removeAllAclRuleStatus();
2925+
29142926
// TODO: Query SAI to get mirror table capabilities
29152927
// Right now, verified platforms that support mirroring IPv6 packets are
29162928
// Broadcom and Mellanox. Virtual switch is also supported for testing
@@ -3416,6 +3428,8 @@ AclOrch::AclOrch(vector<TableConnector>& connectors, DBConnector* stateDb, Switc
34163428
PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch, DTelOrch *dtelOrch) :
34173429
Orch(connectors),
34183430
m_aclStageCapabilityTable(stateDb, STATE_ACL_STAGE_CAPABILITY_TABLE_NAME),
3431+
m_aclTableStateTable(stateDb, STATE_ACL_TABLE_TABLE_NAME),
3432+
m_aclRuleStateTable(stateDb, STATE_ACL_RULE_TABLE_NAME),
34193433
m_switchOrch(switchOrch),
34203434
m_mirrorOrch(mirrorOrch),
34213435
m_neighOrch(neighOrch),
@@ -4239,6 +4253,8 @@ void AclOrch::doAclTableTask(Consumer &consumer)
42394253
{
42404254
SWSS_LOG_NOTICE("Successfully updated existing ACL table %s",
42414255
table_id.c_str());
4256+
// Mark ACL table as ACTIVE
4257+
setAclTableStatus(table_id, AclObjectStatus::ACTIVE);
42424258
it = consumer.m_toSync.erase(it);
42434259
}
42444260
else
@@ -4251,24 +4267,41 @@ void AclOrch::doAclTableTask(Consumer &consumer)
42514267
else
42524268
{
42534269
if (addAclTable(newTable))
4270+
{
4271+
// Mark ACL table as ACTIVE
4272+
setAclTableStatus(table_id, AclObjectStatus::ACTIVE);
42544273
it = consumer.m_toSync.erase(it);
4274+
}
42554275
else
4276+
{
4277+
setAclTableStatus(table_id, AclObjectStatus::PENDING_CREATION);
42564278
it++;
4279+
}
42574280
}
42584281
}
42594282
else
42604283
{
42614284
it = consumer.m_toSync.erase(it);
4285+
// Mark the ACL table as inactive if the configuration is invalid
4286+
setAclTableStatus(table_id, AclObjectStatus::INACTIVE);
42624287
SWSS_LOG_ERROR("Failed to create ACL table %s, invalid configuration",
42634288
table_id.c_str());
42644289
}
42654290
}
42664291
else if (op == DEL_COMMAND)
42674292
{
42684293
if (removeAclTable(table_id))
4294+
{
4295+
// Remove ACL table status from STATE_DB
4296+
removeAclTableStatus(table_id);
42694297
it = consumer.m_toSync.erase(it);
4298+
}
42704299
else
4300+
{
4301+
// Set the status of ACL_TABLE to pending removal if removeAclTable returns error
4302+
setAclTableStatus(table_id, AclObjectStatus::PENDING_REMOVAL);
42714303
it++;
4304+
}
42724305
}
42734306
else
42744307
{
@@ -4408,22 +4441,37 @@ void AclOrch::doAclRuleTask(Consumer &consumer)
44084441
if (bAllAttributesOk && newRule->validate())
44094442
{
44104443
if (addAclRule(newRule, table_id))
4444+
{
4445+
setAclRuleStatus(table_id, rule_id, AclObjectStatus::ACTIVE);
44114446
it = consumer.m_toSync.erase(it);
4447+
}
44124448
else
4449+
{
4450+
setAclRuleStatus(table_id, rule_id, AclObjectStatus::PENDING_CREATION);
44134451
it++;
4452+
}
44144453
}
44154454
else
44164455
{
44174456
it = consumer.m_toSync.erase(it);
4457+
// Mark the rule inactive if the configuration is invalid
4458+
setAclRuleStatus(table_id, rule_id, AclObjectStatus::INACTIVE);
44184459
SWSS_LOG_ERROR("Failed to create ACL rule. Rule configuration is invalid");
44194460
}
44204461
}
44214462
else if (op == DEL_COMMAND)
44224463
{
44234464
if (removeAclRule(table_id, rule_id))
4465+
{
4466+
removeAclRuleStatus(table_id, rule_id);
44244467
it = consumer.m_toSync.erase(it);
4468+
}
44254469
else
4470+
{
4471+
// Mark pending removal status if removeAclRule returns error
4472+
setAclRuleStatus(table_id, rule_id, AclObjectStatus::PENDING_REMOVAL);
44264473
it++;
4474+
}
44274475
}
44284476
else
44294477
{
@@ -4781,3 +4829,55 @@ bool AclOrch::getAclBindPortId(Port &port, sai_object_id_t &port_id)
47814829

47824830
return true;
47834831
}
4832+
4833+
// Set the status of ACL table in STATE_DB
4834+
void AclOrch::setAclTableStatus(string table_name, AclObjectStatus status)
4835+
{
4836+
vector<FieldValueTuple> fvVector;
4837+
fvVector.emplace_back("status", aclObjectStatusLookup[status]);
4838+
m_aclTableStateTable.set(table_name, fvVector);
4839+
}
4840+
4841+
// Remove the status record of given ACL table from STATE_DB
4842+
void AclOrch::removeAclTableStatus(string table_name)
4843+
{
4844+
m_aclTableStateTable.del(table_name);
4845+
}
4846+
4847+
// Set the status of ACL rule in STATE_DB
4848+
void AclOrch::setAclRuleStatus(string table_name, string rule_name, AclObjectStatus status)
4849+
{
4850+
vector<FieldValueTuple> fvVector;
4851+
fvVector.emplace_back("status", aclObjectStatusLookup[status]);
4852+
m_aclRuleStateTable.set(table_name + string("|") + rule_name, fvVector);
4853+
}
4854+
4855+
// Remove the status record of given ACL rule from STATE_DB
4856+
void AclOrch::removeAclRuleStatus(string table_name, string rule_name)
4857+
{
4858+
m_aclRuleStateTable.del(table_name + string("|") + rule_name);
4859+
}
4860+
4861+
// Remove all ACL table status from STATE_DB
4862+
void AclOrch::removeAllAclTableStatus()
4863+
{
4864+
vector<string> keys;
4865+
m_aclTableStateTable.getKeys(keys);
4866+
4867+
for (auto key : keys)
4868+
{
4869+
m_aclTableStateTable.del(key);
4870+
}
4871+
}
4872+
4873+
// Remove all ACL rule status from STATE_DB
4874+
void AclOrch::removeAllAclRuleStatus()
4875+
{
4876+
vector<string> keys;
4877+
m_aclRuleStateTable.getKeys(keys);
4878+
for (auto key : keys)
4879+
{
4880+
m_aclRuleStateTable.del(key);
4881+
}
4882+
}
4883+

orchagent/aclorch.h

+20
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@
9999

100100
#define ACL_COUNTER_FLEX_COUNTER_GROUP "ACL_STAT_COUNTER"
101101

102+
enum AclObjectStatus
103+
{
104+
ACTIVE = 0,
105+
INACTIVE,
106+
PENDING_CREATION,
107+
PENDING_REMOVAL
108+
};
109+
102110
struct AclActionCapabilities
103111
{
104112
set<sai_acl_action_type_t> actionList;
@@ -549,6 +557,15 @@ class AclOrch : public Orch, public Observer
549557

550558
string generateAclRuleIdentifierInCountersDb(const AclRule& rule) const;
551559

560+
void setAclTableStatus(string table_name, AclObjectStatus status);
561+
void setAclRuleStatus(string table_name, string rule_name, AclObjectStatus status);
562+
563+
void removeAclTableStatus(string table_name);
564+
void removeAclRuleStatus(string table_name, string rule_name);
565+
566+
void removeAllAclTableStatus();
567+
void removeAllAclRuleStatus();
568+
552569
map<sai_object_id_t, AclTable> m_AclTables;
553570
// TODO: Move all ACL tables into one map: name -> instance
554571
map<string, AclTable> m_ctrlAclTables;
@@ -559,6 +576,9 @@ class AclOrch : public Orch, public Observer
559576

560577
Table m_aclStageCapabilityTable;
561578

579+
Table m_aclTableStateTable;
580+
Table m_aclRuleStateTable;
581+
562582
map<acl_stage_type_t, string> m_mirrorTableId;
563583
map<acl_stage_type_t, string> m_mirrorV6TableId;
564584

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)