Skip to content

Commit d7b7a5d

Browse files
shaygolshaygol
authored andcommitted
Custom ACL Based Metering
- New 'AclRule' subclass: 'AclRulePolicer' - ACL rule table schema update - Unit Tests
1 parent ec2957c commit d7b7a5d

9 files changed

Lines changed: 430 additions & 18 deletions

File tree

doc/swss-schema.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,8 @@ Stores rules associated with a specific ACL table on the switch.
651651
mirror_ingress_action = 1*255VCHAR ; refer to the mirror session
652652
mirror_egress_action = 1*255VCHAR ; refer to the mirror session
653653

654+
policer_action = 1*255VCHAR ; refer to the policer object name
655+
654656
ether_type = h16 ; Ethernet type field
655657

656658
ip_type = ip_types ; options of the l2_protocol_type

orchagent/aclorch.cpp

Lines changed: 205 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ static acl_rule_attr_lookup_t aclOtherActionLookup =
125125
{ ACTION_COUNTER, SAI_ACL_ENTRY_ATTR_ACTION_COUNTER}
126126
};
127127

128+
static acl_rule_attr_lookup_t aclPolicerActionLookup =
129+
{
130+
{ ACTION_POLICER_ACTION, SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER }
131+
};
132+
128133
static acl_packet_action_lookup_t aclPacketActionLookup =
129134
{
130135
{ PACKET_ACTION_FORWARD, SAI_PACKET_ACTION_FORWARD },
@@ -771,6 +776,7 @@ bool AclTableTypeParser::parseAclTableTypeActions(const std::string& value, AclT
771776
auto dtelAction = aclDTelActionLookup.find(action);
772777
auto otherAction = aclOtherActionLookup.find(action);
773778
auto metadataAction = aclMetadataDscpActionLookup.find(action);
779+
auto policerAction = aclPolicerActionLookup.find(action);
774780
if (l3Action != aclL3ActionLookup.end())
775781
{
776782
saiActionAttr = l3Action->second;
@@ -791,6 +797,10 @@ bool AclTableTypeParser::parseAclTableTypeActions(const std::string& value, AclT
791797
{
792798
saiActionAttr = metadataAction->second;
793799
}
800+
if (policerAction != aclPolicerActionLookup.end())
801+
{
802+
saiActionAttr = policerAction->second;
803+
}
794804
else
795805
{
796806
SWSS_LOG_ERROR("Unknown action %s", action.c_str());
@@ -831,6 +841,7 @@ AclRule::AclRule(AclOrch *pAclOrch, string rule, string table, bool createCounte
831841
m_priority(0),
832842
m_createCounter(createCounter)
833843
{
844+
834845
auto tableOid = pAclOrch->getTableById(table);
835846
m_pTable = pAclOrch->getTableByOid(tableOid);
836847
if (!m_pTable)
@@ -1700,7 +1711,14 @@ bool AclRule::getCreateCounter() const
17001711
return m_createCounter;
17011712
}
17021713

1703-
shared_ptr<AclRule> AclRule::makeShared(AclOrch *acl, MirrorOrch *mirror, DTelOrch *dtel, const string& rule, const string& table, const KeyOpFieldsValuesTuple& data, MetaDataMgr * m_metadataMgr)
1714+
shared_ptr<AclRule> AclRule::makeShared(AclOrch *acl,
1715+
MirrorOrch *mirror,
1716+
DTelOrch *dtel,
1717+
PolicerOrch *policer,
1718+
const string& rule,
1719+
const string& table,
1720+
const KeyOpFieldsValuesTuple& data,
1721+
MetaDataMgr * m_metadataMgr)
17041722
{
17051723
shared_ptr<AclRule> aclRule;
17061724

@@ -1729,6 +1747,10 @@ shared_ptr<AclRule> AclRule::makeShared(AclOrch *acl, MirrorOrch *mirror, DTelOr
17291747

17301748
return make_shared<AclRuleDTelWatchListEntry>(acl, dtel, rule, table);
17311749
}
1750+
else if (aclPolicerActionLookup.find(action) != aclPolicerActionLookup.cend())
1751+
{
1752+
return make_shared<AclRulePolicer>(acl, policer, rule, table);
1753+
}
17321754
}
17331755

17341756
if (!aclRule)
@@ -2063,6 +2085,172 @@ void AclRulePacket::onUpdate(SubjectType, void *)
20632085
// Do nothing
20642086
}
20652087

2088+
AclRulePolicer::AclRulePolicer(AclOrch *aclOrch, PolicerOrch *policer, string rule, string table) :
2089+
AclRule(aclOrch, rule, table),
2090+
m_state(false),
2091+
m_pMirrorOrch(policer)
2092+
{
2093+
}
2094+
2095+
bool AclRulePolicer::validateAddAction(string attr_name, string attr_value)
2096+
{
2097+
SWSS_LOG_ENTER();
2098+
2099+
sai_acl_entry_attr_t action;
2100+
2101+
const auto it = aclPolicerActionLookup.find(attr_name);
2102+
if (it != aclPolicerActionLookup.cend())
2103+
{
2104+
action = it->second;
2105+
}
2106+
else
2107+
{
2108+
return false;
2109+
}
2110+
2111+
m_policerName = attr_value;
2112+
2113+
return setAction(action, sai_acl_action_data_t{});
2114+
}
2115+
2116+
bool AclRulePolicer::validate()
2117+
{
2118+
SWSS_LOG_ENTER();
2119+
2120+
if ((m_rangeConfig.empty() && m_matches.empty()) || m_policerName.empty())
2121+
{
2122+
return false;
2123+
}
2124+
2125+
return true;
2126+
}
2127+
2128+
bool AclRulePolicer::createCounter()
2129+
{
2130+
SWSS_LOG_ENTER();
2131+
2132+
if (!AclRule::createCounter())
2133+
{
2134+
SWSS_LOG_ERROR("Failed to create counter for policer rule %s", m_id.c_str());
2135+
return false;
2136+
}
2137+
2138+
return true;
2139+
}
2140+
2141+
bool AclRulePolicer::createRule()
2142+
{
2143+
SWSS_LOG_ENTER();
2144+
2145+
return activate();
2146+
}
2147+
2148+
bool AclRulePolicer::removeRule()
2149+
{
2150+
return deactivate();
2151+
}
2152+
2153+
bool AclRulePolicer::activate()
2154+
{
2155+
SWSS_LOG_ENTER();
2156+
2157+
sai_object_id_t oid = SAI_NULL_OBJECT_ID;
2158+
2159+
if (!m_pPolicerOrch->policerExists(m_policerName))
2160+
{
2161+
SWSS_LOG_ERROR("Policer rule references policer name \"%s\" that does not exist yet", m_policerName.c_str());
2162+
return false;
2163+
}
2164+
2165+
if (!m_pPolicerOrch->getPolicerOid(m_policerName, oid) || (oid == SAI_NULL_OBJECT_ID))
2166+
{
2167+
SWSS_LOG_ERROR("Failed to get policer OID for policer %s", m_policerName.c_str());
2168+
return false;
2169+
}
2170+
2171+
for (auto& it: m_actions)
2172+
{
2173+
auto attr = it.second.getSaiAttr();
2174+
attr.value.aclaction.enable = true;
2175+
attr.value.aclaction.parameter.objlist.list = &oid;
2176+
attr.value.aclaction.parameter.objlist.count = 1;
2177+
setAction(it.first, attr.value.aclaction);
2178+
}
2179+
2180+
if (!hasCounter())
2181+
{
2182+
if (getCreateCounter() && !createCounter())
2183+
{
2184+
SWSS_LOG_ERROR("createCounter failed for Rule %s policer %s", m_id.c_str(), m_policerName.c_str());
2185+
return false;
2186+
}
2187+
}
2188+
2189+
if (!AclRule::createRule())
2190+
{
2191+
return false;
2192+
}
2193+
2194+
if (!m_pPolicerOrch->increaseRefCount(m_policerName))
2195+
{
2196+
SWSS_LOG_ERROR("Failed to increase policer reference count for policer %s", m_policerName.c_str());
2197+
return false;
2198+
}
2199+
2200+
m_state = true;
2201+
2202+
return true;
2203+
}
2204+
2205+
bool AclRulePolicer::deactivate()
2206+
{
2207+
SWSS_LOG_ENTER();
2208+
2209+
if (!m_state)
2210+
{
2211+
return true;
2212+
}
2213+
2214+
if (!AclRule::removeRule())
2215+
{
2216+
return false;
2217+
}
2218+
2219+
if (!m_pPolicerOrch->decreaseRefCount(m_policerName))
2220+
{
2221+
SWSS_LOG_ERROR("Failed to decrease policer reference count for policer %s", m_policerName.c_str());
2222+
return false;
2223+
}
2224+
2225+
m_state = false;
2226+
2227+
return true;
2228+
}
2229+
2230+
bool AclRulePolicer::update(const AclRule& rule)
2231+
{
2232+
SWSS_LOG_ENTER();
2233+
2234+
auto policerRule = dynamic_cast<const AclRulePolicer*>(&rule);
2235+
if (!policerRule)
2236+
{
2237+
SWSS_LOG_ERROR("Cannot update policer rule with a rule of a different type");
2238+
return false;
2239+
}
2240+
2241+
SWSS_LOG_ERROR("Updating policer rule is currently not implemented");
2242+
return false;
2243+
}
2244+
2245+
void AclRulePolicer::onUpdate(SubjectType type, void *cntx)
2246+
{
2247+
SWSS_LOG_ENTER();
2248+
2249+
// Do nothing, since:
2250+
// - PolicerOrch handles policer updates internally and transparently applies them to the policer SAI object.
2251+
// - The existing reference count mechanism in PolicerOrch prevents deletion of referenced policers, ensuring ACL rules remain valid.
2252+
}
2253+
20662254
AclRuleMirror::AclRuleMirror(AclOrch *aclOrch, MirrorOrch *mirror, string rule, string table) :
20672255
AclRule(aclOrch, rule, table),
20682256
m_state(false),
@@ -3533,6 +3721,7 @@ void AclOrch::init(vector<TableConnector>& connectors, PortsOrch *portOrch, Mirr
35333721
// Attach observers
35343722
m_mirrorOrch->attach(this);
35353723
gPortsOrch->attach(this);
3724+
m_policerOrch->attach(this);
35363725
}
35373726

35383727
void AclOrch::initDefaultTableTypes(const string& platform, const string& sub_platform)
@@ -3884,7 +4073,7 @@ void AclOrch::putAclActionCapabilityInDB(acl_stage_type_t stage)
38844073
{
38854074
metadataActionLookup = aclMetadataDscpActionLookup;
38864075
}
3887-
for (const auto& action_map: {aclL3ActionLookup, aclMirrorStageLookup, aclDTelActionLookup, metadataActionLookup})
4076+
for (const auto& action_map: {aclL3ActionLookup, aclMirrorStageLookup, aclDTelActionLookup, metadataActionLookup, aclPolicerActionLookup})
38884077
{
38894078
for (const auto& it: action_map)
38904079
{
@@ -4008,13 +4197,21 @@ void AclOrch::queryAclActionAttrEnumValues(const string &action_name,
40084197
m_switchOrch->set_switch_capability(fvVector);
40094198
}
40104199

4011-
AclOrch::AclOrch(vector<TableConnector>& connectors, DBConnector* stateDb, SwitchOrch *switchOrch,
4012-
PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch, DTelOrch *dtelOrch) :
4200+
AclOrch::AclOrch(vector<TableConnector>& connectors,
4201+
DBConnector* stateDb,
4202+
SwitchOrch *switchOrch,
4203+
PortsOrch *portOrch,
4204+
PolicerOrch *PolicerOrch,
4205+
MirrorOrch *mirrorOrch,
4206+
NeighOrch *neighOrch,
4207+
RouteOrch *routeOrch,
4208+
DTelOrch *dtelOrch) :
40134209
Orch(connectors),
40144210
m_aclStageCapabilityTable(stateDb, STATE_ACL_STAGE_CAPABILITY_TABLE_NAME),
40154211
m_aclTableStateTable(stateDb, STATE_ACL_TABLE_TABLE_NAME),
40164212
m_aclRuleStateTable(stateDb, STATE_ACL_RULE_TABLE_NAME),
40174213
m_switchOrch(switchOrch),
4214+
m_policerOrch(PolicerOrch),
40184215
m_mirrorOrch(mirrorOrch),
40194216
m_neighOrch(neighOrch),
40204217
m_routeOrch(routeOrch),
@@ -4041,6 +4238,8 @@ AclOrch::~AclOrch()
40414238
{
40424239
m_mirrorOrch->detach(this);
40434240

4241+
m_policerOrch->detach(this);
4242+
40444243
if (m_dTelOrch)
40454244
{
40464245
m_dTelOrch->detach(this);
@@ -4263,7 +4462,7 @@ EgressSetDscpTableStatus AclOrch::addEgrSetDscpTable(string table_id, AclTable &
42634462
if (!isAclMetaDataSupported())
42644463
{
42654464
SWSS_LOG_ERROR("Platform does not support MARK_META/MARK_METAV6 tables.");
4266-
return EgressSetDscpTableStatus::EGRESS_SET_DSCP_TABLE_NOT_SUPPORTED;
4465+
return EgressSetDscpTableStatus::EGRESS_SET_DSCP_TABLE_NOT_SUPPORTED;
42674466
}
42684467
AclTable egrSetDscpTable(this);
42694468

@@ -5384,7 +5583,7 @@ void AclOrch::doAclRuleTask(Consumer &consumer)
53845583

53855584
try
53865585
{
5387-
newRule = AclRule::makeShared(this, m_mirrorOrch, m_dTelOrch, rule_id, table_id, t, &m_metaDataMgr);
5586+
newRule = AclRule::makeShared(this, m_mirrorOrch, m_dTelOrch, m_policerOrch, rule_id, table_id, t, &m_metaDataMgr);
53885587
}
53895588
catch (exception &e)
53905589
{

orchagent/aclorch.h

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#define ACTION_PACKET_ACTION "PACKET_ACTION"
6262
#define ACTION_REDIRECT_ACTION "REDIRECT_ACTION"
6363
#define ACTION_DO_NOT_NAT_ACTION "DO_NOT_NAT_ACTION"
64+
#define ACTION_POLICER_ACTION "POLICER_ACTION"
6465
#define ACTION_MIRROR_ACTION "MIRROR_ACTION"
6566
#define ACTION_MIRROR_INGRESS_ACTION "MIRROR_INGRESS_ACTION"
6667
#define ACTION_MIRROR_EGRESS_ACTION "MIRROR_EGRESS_ACTION"
@@ -317,12 +318,13 @@ class AclRule
317318

318319
const vector<AclRangeConfig>& getRangeConfig() const;
319320
static shared_ptr<AclRule> makeShared(AclOrch *acl,
320-
MirrorOrch *mirror,
321-
DTelOrch *dtel,
322-
const string& rule,
323-
const string& table,
324-
const KeyOpFieldsValuesTuple&,
325-
MetaDataMgr * m_metadataMgr);
321+
MirrorOrch *mirror,
322+
DTelOrch *dtel,
323+
PolicerOrch *policer,
324+
const string& rule,
325+
const string& table,
326+
const KeyOpFieldsValuesTuple&,
327+
MetaDataMgr * m_metadataMgr);
326328
virtual ~AclRule() {}
327329

328330
protected:
@@ -380,6 +382,30 @@ class AclRulePacket: public AclRule
380382
sai_object_id_t getRedirectObjectId(const string& redirect_param);
381383
};
382384

385+
class AclRulePolicer: public AclRule
386+
{
387+
public:
388+
AclRulePolicer (AclOrch *m_pAclOrch, PolicerOrch *policer, string rule, string table);
389+
390+
bool validateAddAction(string attr_name, string attr_value);
391+
bool validate();
392+
bool createCounter();
393+
bool createRule();
394+
bool removeRule();
395+
void onUpdate(SubjectType, void *) override;
396+
397+
bool activate();
398+
bool deactivate();
399+
400+
bool update(const AclRule& updatedRule) override;
401+
402+
protected:
403+
protected:
404+
bool m_state {false};
405+
string m_policerName;
406+
PolicerOrch *m_pPolicerOrch {nullptr};
407+
};
408+
383409
class AclRuleMirror: public AclRule
384410
{
385411
public:
@@ -528,6 +554,7 @@ class AclOrch : public Orch, public Observer
528554
DBConnector *m_stateDb,
529555
SwitchOrch *m_switchOrch,
530556
PortsOrch *portOrch,
557+
PolicerOrch *policerOrch,
531558
MirrorOrch *mirrorOrch,
532559
NeighOrch *neighOrch,
533560
RouteOrch *routeOrch,
@@ -546,6 +573,7 @@ class AclOrch : public Orch, public Observer
546573

547574
// FIXME: Add getters for them? I'd better to add a common directory of orch objects and use it everywhere
548575
MirrorOrch *m_mirrorOrch;
576+
PolicerOrch *m_policerOrch;
549577
NeighOrch *m_neighOrch;
550578
RouteOrch *m_routeOrch;
551579
DTelOrch *m_dTelOrch;

orchagent/orchdaemon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ bool OrchDaemon::init()
464464
}
465465

466466
gAclOrch = new AclOrch(acl_table_connectors, m_stateDb,
467-
gSwitchOrch, gPortsOrch, gMirrorOrch, gNeighOrch, gRouteOrch, dtel_orch);
467+
gSwitchOrch, gPortsOrch, gPolicerOrch, gMirrorOrch, gNeighOrch, gRouteOrch, dtel_orch);
468468

469469
vector<string> mlag_tables = {
470470
{ CFG_MCLAG_TABLE_NAME },

0 commit comments

Comments
 (0)