@@ -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+
128133static 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+
20662254AclRuleMirror::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
35383727void 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 {
0 commit comments