Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/swss-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,8 @@ Stores rules associated with a specific ACL table on the switch.
mirror_ingress_action = 1*255VCHAR ; refer to the mirror session
mirror_egress_action = 1*255VCHAR ; refer to the mirror session

policer_action = 1*255VCHAR ; refer to the policer object name

ether_type = h16 ; Ethernet type field

ip_type = ip_types ; options of the l2_protocol_type
Expand Down
212 changes: 206 additions & 6 deletions orchagent/aclorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ static acl_rule_attr_lookup_t aclOtherActionLookup =
{ ACTION_COUNTER, SAI_ACL_ENTRY_ATTR_ACTION_COUNTER}
};

static acl_rule_attr_lookup_t aclPolicerActionLookup =
{
{ ACTION_POLICER_ACTION, SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER }
};

static acl_packet_action_lookup_t aclPacketActionLookup =
{
{ PACKET_ACTION_FORWARD, SAI_PACKET_ACTION_FORWARD },
Expand Down Expand Up @@ -807,6 +812,7 @@ bool AclTableTypeParser::parseAclTableTypeActions(const std::string& value, AclT
auto dtelAction = aclDTelActionLookup.find(action);
auto otherAction = aclOtherActionLookup.find(action);
auto metadataAction = aclMetadataDscpActionLookup.find(action);
auto policerAction = aclPolicerActionLookup.find(action);
if (l3Action != aclL3ActionLookup.end())
{
saiActionAttr = l3Action->second;
Expand All @@ -827,6 +833,10 @@ bool AclTableTypeParser::parseAclTableTypeActions(const std::string& value, AclT
{
saiActionAttr = metadataAction->second;
}
if (policerAction != aclPolicerActionLookup.end())
{
saiActionAttr = policerAction->second;
}
else
{
SWSS_LOG_ERROR("Unknown action %s", action.c_str());
Expand Down Expand Up @@ -867,6 +877,7 @@ AclRule::AclRule(AclOrch *pAclOrch, string rule, string table, bool createCounte
m_priority(0),
m_createCounter(createCounter)
{

auto tableOid = pAclOrch->getTableById(table);
m_pTable = pAclOrch->getTableByOid(tableOid);
if (!m_pTable)
Expand Down Expand Up @@ -1753,7 +1764,14 @@ bool AclRule::getCreateCounter() const
return m_createCounter;
}

shared_ptr<AclRule> AclRule::makeShared(AclOrch *acl, MirrorOrch *mirror, DTelOrch *dtel, const string& rule, const string& table, const KeyOpFieldsValuesTuple& data, MetaDataMgr * m_metadataMgr)
shared_ptr<AclRule> AclRule::makeShared(AclOrch *acl,
MirrorOrch *mirror,
DTelOrch *dtel,
PolicerOrch *policer,
const string& rule,
const string& table,
const KeyOpFieldsValuesTuple& data,
MetaDataMgr * m_metadataMgr)
{
shared_ptr<AclRule> aclRule;

Expand Down Expand Up @@ -1782,6 +1800,10 @@ shared_ptr<AclRule> AclRule::makeShared(AclOrch *acl, MirrorOrch *mirror, DTelOr

return make_shared<AclRuleDTelWatchListEntry>(acl, dtel, rule, table);
}
else if (aclPolicerActionLookup.find(action) != aclPolicerActionLookup.cend())
{
return make_shared<AclRulePolicer>(acl, policer, rule, table);
}
}

if (!aclRule)
Expand Down Expand Up @@ -2133,6 +2155,174 @@ void AclRulePacket::onUpdate(SubjectType, void *)
// Do nothing
}

AclRulePolicer::AclRulePolicer(AclOrch *aclOrch, PolicerOrch *policer, string rule, string table) :
AclRule(aclOrch, rule, table),
m_state(false),
m_pPolicerOrch(policer)
{
}

bool AclRulePolicer::validateAddAction(string attr_name, string attr_value)
{
SWSS_LOG_ENTER();

sai_acl_entry_attr_t action;

const auto it = aclPolicerActionLookup.find(attr_name);
if (it != aclPolicerActionLookup.cend())
{
action = it->second;
}
else
{
return false;
}

m_policerName = attr_value;

return setAction(action, sai_acl_action_data_t{});
}

bool AclRulePolicer::validate()
{
SWSS_LOG_ENTER();

if ((m_rangeConfig.empty() && m_matches.empty()) || m_policerName.empty())
{
return false;
}

return true;
}

bool AclRulePolicer::createCounter()
{
SWSS_LOG_ENTER();

if (!AclRule::createCounter())
{
SWSS_LOG_ERROR("Failed to create counter for policer rule %s", m_id.c_str());
return false;
}

return true;
}

bool AclRulePolicer::createRule()
{
SWSS_LOG_ENTER();

return activate();
}

bool AclRulePolicer::removeRule()
{
SWSS_LOG_ENTER();

return deactivate();
}

bool AclRulePolicer::activate()
{
SWSS_LOG_ENTER();

sai_object_id_t oid = SAI_NULL_OBJECT_ID;

if (!m_pPolicerOrch->policerExists(m_policerName))
{
SWSS_LOG_ERROR("Policer rule references policer name \"%s\" that does not exist yet", m_policerName.c_str());
return false;
}

if (!m_pPolicerOrch->getPolicerOid(m_policerName, oid) || (oid == SAI_NULL_OBJECT_ID))
{
SWSS_LOG_ERROR("Failed to get policer OID for policer %s", m_policerName.c_str());
return false;
}

for (auto& it: m_actions)
{
auto attr = it.second.getSaiAttr();
attr.value.aclaction.enable = true;
attr.value.aclaction.parameter.objlist.list = &oid;
attr.value.aclaction.parameter.objlist.count = 1;
setAction(it.first, attr.value.aclaction);
}

if (!hasCounter())
{
if (getCreateCounter() && !createCounter())
{
SWSS_LOG_ERROR("createCounter failed for Rule %s policer %s", m_id.c_str(), m_policerName.c_str());
return false;
}
}

if (!AclRule::createRule())
{
return false;
}

if (!m_pPolicerOrch->increaseRefCount(m_policerName))
{
SWSS_LOG_ERROR("Failed to increase policer reference count for policer %s", m_policerName.c_str());
return false;
}

m_state = true;

return true;
}

bool AclRulePolicer::deactivate()
{
SWSS_LOG_ENTER();

if (!m_state)
{
return true;
}

if (!AclRule::removeRule())
{
return false;
}

if (!m_pPolicerOrch->decreaseRefCount(m_policerName))
{
SWSS_LOG_ERROR("Failed to decrease policer reference count for policer %s", m_policerName.c_str());
return false;
}

m_state = false;

return true;
}

bool AclRulePolicer::update(const AclRule& rule)
{
SWSS_LOG_ENTER();

auto policerRule = dynamic_cast<const AclRulePolicer*>(&rule);
if (!policerRule)
{
SWSS_LOG_ERROR("Cannot update policer rule with a rule of a different type");
return false;
}

SWSS_LOG_ERROR("Updating policer rule is currently not implemented");
return false;
}

void AclRulePolicer::onUpdate(SubjectType type, void *cntx)
{
SWSS_LOG_ENTER();

// Do nothing, since:
// - PolicerOrch handles policer updates internally and transparently applies them to the policer SAI object.
// - The existing reference count mechanism in PolicerOrch prevents deletion of referenced policers, ensuring ACL rules remain valid.
}

AclRuleMirror::AclRuleMirror(AclOrch *aclOrch, MirrorOrch *mirror, string rule, string table) :
AclRule(aclOrch, rule, table),
m_state(false),
Expand Down Expand Up @@ -3954,7 +4144,7 @@ void AclOrch::putAclActionCapabilityInDB(acl_stage_type_t stage)
{
metadataActionLookup = aclMetadataDscpActionLookup;
}
for (const auto& action_map: {aclL3ActionLookup, aclMirrorStageLookup, aclDTelActionLookup, metadataActionLookup})
for (const auto& action_map: {aclL3ActionLookup, aclMirrorStageLookup, aclDTelActionLookup, metadataActionLookup, aclPolicerActionLookup})
{
for (const auto& it: action_map)
{
Expand Down Expand Up @@ -4078,13 +4268,21 @@ void AclOrch::queryAclActionAttrEnumValues(const string &action_name,
m_switchOrch->set_switch_capability(fvVector);
}

AclOrch::AclOrch(vector<TableConnector>& connectors, DBConnector* stateDb, SwitchOrch *switchOrch,
PortsOrch *portOrch, MirrorOrch *mirrorOrch, NeighOrch *neighOrch, RouteOrch *routeOrch, DTelOrch *dtelOrch) :
AclOrch::AclOrch(vector<TableConnector>& connectors,
DBConnector* stateDb,
SwitchOrch *switchOrch,
PortsOrch *portOrch,
PolicerOrch *PolicerOrch,
MirrorOrch *mirrorOrch,
NeighOrch *neighOrch,
RouteOrch *routeOrch,
DTelOrch *dtelOrch) :
Orch(connectors),
m_aclStageCapabilityTable(stateDb, STATE_ACL_STAGE_CAPABILITY_TABLE_NAME),
m_aclTableStateTable(stateDb, STATE_ACL_TABLE_TABLE_NAME),
m_aclRuleStateTable(stateDb, STATE_ACL_RULE_TABLE_NAME),
m_switchOrch(switchOrch),
m_policerOrch(PolicerOrch),
m_mirrorOrch(mirrorOrch),
m_neighOrch(neighOrch),
m_routeOrch(routeOrch),
Expand Down Expand Up @@ -4333,7 +4531,7 @@ EgressSetDscpTableStatus AclOrch::addEgrSetDscpTable(string table_id, AclTable &
if (!isAclMetaDataSupported())
{
SWSS_LOG_ERROR("Platform does not support MARK_META/MARK_METAV6 tables.");
return EgressSetDscpTableStatus::EGRESS_SET_DSCP_TABLE_NOT_SUPPORTED;
return EgressSetDscpTableStatus::EGRESS_SET_DSCP_TABLE_NOT_SUPPORTED;
}
AclTable egrSetDscpTable(this);

Expand Down Expand Up @@ -5454,7 +5652,7 @@ void AclOrch::doAclRuleTask(Consumer &consumer)

try
{
newRule = AclRule::makeShared(this, m_mirrorOrch, m_dTelOrch, rule_id, table_id, t, &m_metaDataMgr);
newRule = AclRule::makeShared(this, m_mirrorOrch, m_dTelOrch, m_policerOrch, rule_id, table_id, t, &m_metaDataMgr);
}
catch (exception &e)
{
Expand Down Expand Up @@ -5938,13 +6136,15 @@ bool AclOrch::getAclBindPortId(Port &port, sai_object_id_t &port_id)
void AclOrch::setAclTableStatus(string table_name, AclObjectStatus status)
{
vector<FieldValueTuple> fvVector;
SWSS_LOG_NOTICE("changing table '%s' status to '%s'", table_name.c_str(), aclObjectStatusLookup[status].c_str());
fvVector.emplace_back("status", aclObjectStatusLookup[status]);
m_aclTableStateTable.set(table_name, fvVector);
}

// Remove the status record of given ACL table from STATE_DB
void AclOrch::removeAclTableStatus(string table_name)
{
SWSS_LOG_NOTICE("removing ACL table '%s' status", table_name.c_str());
m_aclTableStateTable.del(table_name);
}

Expand Down
28 changes: 28 additions & 0 deletions orchagent/aclorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#define ACTION_PACKET_ACTION "PACKET_ACTION"
#define ACTION_REDIRECT_ACTION "REDIRECT_ACTION"
#define ACTION_DO_NOT_NAT_ACTION "DO_NOT_NAT_ACTION"
#define ACTION_POLICER_ACTION "POLICER_ACTION"
#define ACTION_MIRROR_ACTION "MIRROR_ACTION"
#define ACTION_MIRROR_INGRESS_ACTION "MIRROR_INGRESS_ACTION"
#define ACTION_MIRROR_EGRESS_ACTION "MIRROR_EGRESS_ACTION"
Expand Down Expand Up @@ -336,6 +337,7 @@ class AclRule

const vector<AclRangeConfig>& getRangeConfig() const;
static shared_ptr<AclRule> makeShared(AclOrch *acl,
PolicerOrch *policer,
MirrorOrch *mirror,
DTelOrch *dtel,
const string& rule,
Expand Down Expand Up @@ -400,6 +402,30 @@ class AclRulePacket: public AclRule
sai_object_id_t getRedirectObjectId(const string& redirect_param);
};

class AclRulePolicer: public AclRule
{
public:
AclRulePolicer (AclOrch *m_pAclOrch, PolicerOrch *m_pPolicerOrch, string rule, string table);

bool validateAddAction(string attr_name, string attr_value);
bool validate();
bool createCounter();
bool createRule();
bool removeRule();
void onUpdate(SubjectType, void *) override;

bool activate();
bool deactivate();

bool update(const AclRule& updatedRule) override;

protected:
protected:
bool m_state {false};
string m_policerName;
PolicerOrch *m_pPolicerOrch {nullptr};
};

class AclRuleMirror: public AclRule
{
public:
Expand Down Expand Up @@ -548,6 +574,7 @@ class AclOrch : public Orch, public Observer
DBConnector *m_stateDb,
SwitchOrch *m_switchOrch,
PortsOrch *portOrch,
PolicerOrch *policerOrch,
MirrorOrch *mirrorOrch,
NeighOrch *neighOrch,
RouteOrch *routeOrch,
Expand All @@ -566,6 +593,7 @@ class AclOrch : public Orch, public Observer

// FIXME: Add getters for them? I'd better to add a common directory of orch objects and use it everywhere
MirrorOrch *m_mirrorOrch;
PolicerOrch *m_policerOrch;
NeighOrch *m_neighOrch;
RouteOrch *m_routeOrch;
DTelOrch *m_dTelOrch;
Expand Down
2 changes: 1 addition & 1 deletion orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ bool OrchDaemon::init()
}

gAclOrch = new AclOrch(acl_table_connectors, m_stateDb,
gSwitchOrch, gPortsOrch, gMirrorOrch, gNeighOrch, gRouteOrch, dtel_orch);
gSwitchOrch, gPortsOrch, gPolicerOrch, gMirrorOrch, gNeighOrch, gRouteOrch, dtel_orch);

vector<string> mlag_tables = {
{ CFG_MCLAG_TABLE_NAME },
Expand Down
Loading
Loading