Skip to content

Commit

Permalink
[pfc]: Add egress drop by creating egress ACL table and rule (sonic-n…
Browse files Browse the repository at this point in the history
…et#397)

* Egress drop by creating egress acl table and rule
* Separate acl stage type from aclorch and reference in portsorch

Signed-off-by: Sihui Han <[email protected]>
  • Loading branch information
sihuihan88 authored and Shuotian Cheng committed Nov 30, 2017
1 parent 57a98ac commit 6f0eee3
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 40 deletions.
1 change: 1 addition & 0 deletions orchagent/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ orchagent_SOURCES = \
switchorch.cpp \
pfcwdorch.cpp \
pfcactionhandler.cpp \
acltable.h \
aclorch.h \
bufferorch.h \
copporch.h \
Expand Down
62 changes: 52 additions & 10 deletions orchagent/aclorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ static acl_table_type_lookup_t aclTableTypeLookUp =
{ TABLE_TYPE_MIRROR, ACL_TABLE_MIRROR }
};

static acl_stage_type_lookup_t aclStageLookUp =
{
{TABLE_INGRESS, ACL_STAGE_INGRESS },
{TABLE_EGRESS, ACL_STAGE_EGRESS }
};

static acl_ip_type_lookup_t aclIpTypeLookup =
{
{ IP_TYPE_ANY, SAI_ACL_IP_TYPE_ANY },
Expand Down Expand Up @@ -858,8 +864,15 @@ bool AclTable::create()
{
SWSS_LOG_ENTER();

if (stage == ACL_STAGE_UNKNOWN)
{
SWSS_LOG_ERROR("Unknown ACL stage for ACL table %s", id.c_str());
return false;
}

sai_attribute_t attr;
vector<sai_attribute_t> table_attrs;

int32_t range_types_list[] =
{ SAI_ACL_RANGE_TYPE_L4_DST_PORT_RANGE,
SAI_ACL_RANGE_TYPE_L4_SRC_PORT_RANGE
Expand All @@ -872,10 +885,6 @@ bool AclTable::create()
attr.value.s32list.list = bpoint_list.data();
table_attrs.push_back(attr);

attr.id = SAI_ACL_TABLE_ATTR_ACL_STAGE;
attr.value.s32 = SAI_ACL_STAGE_INGRESS;
table_attrs.push_back(attr);

attr.id = SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE;
attr.value.booldata = true;
table_attrs.push_back(attr);
Expand Down Expand Up @@ -912,18 +921,25 @@ bool AclTable::create()
attr.value.booldata = true;
table_attrs.push_back(attr);

if(stage == ACL_STAGE_INGRESS)
{
attr.id = SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE;
attr.value.s32list.count = (uint32_t)(sizeof(range_types_list) / sizeof(range_types_list[0]));
attr.value.s32list.list = range_types_list;
table_attrs.push_back(attr);
}

attr.id = SAI_ACL_TABLE_ATTR_ACL_STAGE;
attr.value.s32 = stage == ACL_STAGE_INGRESS ? SAI_ACL_STAGE_INGRESS : SAI_ACL_STAGE_EGRESS;
table_attrs.push_back(attr);

if (type == ACL_TABLE_MIRROR)
{
attr.id = SAI_ACL_TABLE_ATTR_FIELD_DSCP;
attr.value.booldata = true;
table_attrs.push_back(attr);
}

attr.id = SAI_ACL_TABLE_ATTR_FIELD_ACL_RANGE_TYPE;
attr.value.s32list.count = (uint32_t)(sizeof(range_types_list) / sizeof(range_types_list[0]));
attr.value.s32list.list = range_types_list;
table_attrs.push_back(attr);

sai_status_t status = sai_acl_api->create_acl_table(&m_oid, gSwitchId, (uint32_t)table_attrs.size(), table_attrs.data());
return status == SAI_STATUS_SUCCESS;
}
Expand All @@ -935,7 +951,7 @@ bool AclTable::bind(sai_object_id_t portOid)
assert(ports.find(portOid) != ports.end());

sai_object_id_t group_member_oid;
if (!gPortsOrch->bindAclTable(portOid, m_oid, group_member_oid))
if (!gPortsOrch->bindAclTable(portOid, m_oid, group_member_oid, stage))
{
return false;
}
Expand Down Expand Up @@ -1424,6 +1440,13 @@ void AclOrch::doAclTableTask(Consumer &consumer)
SWSS_LOG_ERROR("Failed to process table ports for table %s", table_id.c_str());
}
}
else if (attr_name == TABLE_STAGE)
{
if (!processAclTableStage(attr_value, newTable.stage))
{
SWSS_LOG_ERROR("Failed to process table stage for table %s", table_id.c_str());
}
}
else
{
SWSS_LOG_ERROR("Unknown table attribute '%s'", attr_name.c_str());
Expand Down Expand Up @@ -1613,6 +1636,25 @@ bool AclOrch::processAclTableType(string type, acl_table_type_t &table_type)
return true;
}

bool AclOrch::processAclTableStage(string stage, acl_stage_type_t &acl_stage)
{
SWSS_LOG_ENTER();

auto iter = aclStageLookUp.find(toUpper(stage));

if (iter == aclStageLookUp.end())
{
acl_stage = ACL_STAGE_UNKNOWN;
return false;
}

acl_stage = iter->second;

return true;
}



sai_object_id_t AclOrch::getTableById(string table_id)
{
SWSS_LOG_ENTER();
Expand Down
5 changes: 4 additions & 1 deletion orchagent/aclorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ class AclTable {
string id;
string description;
acl_table_type_t type;
acl_stage_type_t stage;

// Map port oid to group member oid
std::map<sai_object_id_t, sai_object_id_t> ports;
// Map rule name to rule data
Expand All @@ -227,6 +229,7 @@ class AclTable {
AclTable()
: type(ACL_TABLE_UNKNOWN)
, m_oid(SAI_NULL_OBJECT_ID)
, stage(ACL_STAGE_INGRESS)
{}

sai_object_id_t getOid() { return m_oid; }
Expand Down Expand Up @@ -302,7 +305,7 @@ class AclOrch : public Orch, public Observer
sai_status_t deleteUnbindAclTable(sai_object_id_t table_oid);

bool processAclTableType(string type, acl_table_type_t &table_type);

bool processAclTableStage(string stage, acl_stage_type_t &acl_stage);
bool processPorts(string portsList, std::function<void (sai_object_id_t)> inserter);
bool validateAclTable(AclTable &aclTable);

Expand Down
30 changes: 30 additions & 0 deletions orchagent/acltable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef SWSS_ACLTABLE_H
#define SWSS_ACLTABLE_H

extern "C" {
#include "sai.h"
}

#include <set>
#include <string>
#include <vector>
#include <map>

using namespace std;

/* TODO: move all acltable and aclrule implementation out of aclorch */

#define TABLE_INGRESS "INGRESS"
#define TABLE_EGRESS "EGRESS"
#define TABLE_STAGE "STAGE"

typedef enum
{
ACL_STAGE_UNKNOWN,
ACL_STAGE_INGRESS,
ACL_STAGE_EGRESS
} acl_stage_type_t;

typedef map<string, acl_stage_type_t> acl_stage_type_lookup_t;

#endif /* SWSS_ACLTABLE_H */
44 changes: 32 additions & 12 deletions orchagent/pfcactionhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,31 @@ PfcWdAclHandler::PfcWdAclHandler(sai_object_id_t port, sai_object_id_t queue,

// There is one handler instance per queue ID
string queuestr = to_string(queueId);
m_strTable = "Table_PfcWdAclHandler_" + queuestr;
m_strIngressTable = "IngressTable_PfcWdAclHandler_" + queuestr;
m_strEgressTable = "EgressTable_PfcWdAclHandler_" + queuestr;
m_strRule = "Rule_PfcWdAclHandler_" + queuestr;

auto found = m_aclTables.find(m_strTable);
auto found = m_aclTables.find(m_strIngressTable);
if (found == m_aclTables.end())
{
// First time of handling PFC for this queue, create ACL table, and bind
createPfcAclTable(port);
shared_ptr<AclRuleL3> newRule = make_shared<AclRuleL3>(gAclOrch, m_strRule, m_strTable, table_type);
createPfcAclRule(newRule, queueId);
createPfcAclTable(port, m_strIngressTable, true);
shared_ptr<AclRuleL3> newRule = make_shared<AclRuleL3>(gAclOrch, m_strRule, m_strIngressTable, table_type);
createPfcAclRule(newRule, queueId, m_strIngressTable);
}
else
{
// Otherwise just bind ACL table with the port
found->second.bind(port);
}

found = m_aclTables.find(m_strEgressTable);
if (found == m_aclTables.end())
{
// First time of handling PFC for this queue, create ACL table, and bind
createPfcAclTable(port, m_strEgressTable, false);
shared_ptr<AclRuleL3> newRule = make_shared<AclRuleL3>(gAclOrch, m_strRule, m_strEgressTable, table_type);
createPfcAclRule(newRule, queueId, m_strEgressTable);
}
else
{
Expand All @@ -165,7 +180,10 @@ PfcWdAclHandler::~PfcWdAclHandler(void)
{
SWSS_LOG_ENTER();

auto found = m_aclTables.find(m_strTable);
auto found = m_aclTables.find(m_strIngressTable);
found->second.unbind(getPort());

found = m_aclTables.find(m_strEgressTable);
found->second.unbind(getPort());
}

Expand All @@ -180,23 +198,25 @@ void PfcWdAclHandler::clear()
}
}

void PfcWdAclHandler::createPfcAclTable(sai_object_id_t port)
void PfcWdAclHandler::createPfcAclTable(sai_object_id_t port, string strTable, bool ingress)
{
SWSS_LOG_ENTER();

auto inserted = m_aclTables.emplace(piecewise_construct,
std::forward_as_tuple(m_strTable),
std::forward_as_tuple(strTable),
std::forward_as_tuple());

assert(inserted.second);

AclTable& aclTable = inserted.first->second;
aclTable.type = ACL_TABLE_L3;
aclTable.link(port);
aclTable.id = m_strTable;
gAclOrch->addAclTable(aclTable, m_strTable);
aclTable.id = strTable;
aclTable.stage = ingress ? ACL_STAGE_INGRESS : ACL_STAGE_EGRESS;
gAclOrch->addAclTable(aclTable, strTable);
}

void PfcWdAclHandler::createPfcAclRule(shared_ptr<AclRuleL3> rule, uint8_t queueId)
void PfcWdAclHandler::createPfcAclRule(shared_ptr<AclRuleL3> rule, uint8_t queueId, string strTable)
{
SWSS_LOG_ENTER();

Expand All @@ -214,7 +234,7 @@ void PfcWdAclHandler::createPfcAclRule(shared_ptr<AclRuleL3> rule, uint8_t queue
attr_value = PACKET_ACTION_DROP;
rule->validateAddAction(attr_name, attr_value);

gAclOrch->addAclRule(rule, m_strTable);
gAclOrch->addAclRule(rule, strTable);
}

std::map<std::string, AclTable> PfcWdAclHandler::m_aclTables;
Expand Down
7 changes: 4 additions & 3 deletions orchagent/pfcactionhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,11 @@ class PfcWdAclHandler: public PfcWdActionHandler
// class shared dict: ACL table name -> ACL table
static std::map<std::string, AclTable> m_aclTables;

string m_strTable;
string m_strIngressTable;
string m_strEgressTable;
string m_strRule;
void createPfcAclTable(sai_object_id_t port);
void createPfcAclRule(shared_ptr<AclRuleL3> rule, uint8_t queueId);
void createPfcAclTable(sai_object_id_t port, string strTable, bool ingress);
void createPfcAclRule(shared_ptr<AclRuleL3> rule, uint8_t queueId, string strTable);
};

// Pfc queue that implements forward action by disabling PFC on queue
Expand Down
3 changes: 2 additions & 1 deletion orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ class Port
sai_object_id_t m_hif_id = 0;
sai_object_id_t m_lag_id = 0;
sai_object_id_t m_lag_member_id = 0;
sai_object_id_t m_acl_table_group_id = 0;
sai_object_id_t m_ingress_acl_table_group_id = 0;
sai_object_id_t m_egress_acl_table_group_id = 0;
vlan_members_t m_vlan_members;
std::set<std::string> m_members;
std::vector<sai_object_id_t> m_queue_ids;
Expand Down
40 changes: 30 additions & 10 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,8 +396,16 @@ bool PortsOrch::setPortFec(sai_object_id_t id, sai_port_fec_mode_t mode)
return true;
}

bool PortsOrch::bindAclTable(sai_object_id_t id, sai_object_id_t table_oid, sai_object_id_t &group_member_oid)
bool PortsOrch::bindAclTable(sai_object_id_t id, sai_object_id_t table_oid, sai_object_id_t &group_member_oid, acl_stage_type_t acl_stage)
{
SWSS_LOG_ENTER();

if (acl_stage == ACL_STAGE_UNKNOWN)
{
SWSS_LOG_ERROR("Unknown Acl stage for Acl table %lx", table_oid);
return false;
}

sai_status_t status;
sai_object_id_t groupOid;

Expand All @@ -409,16 +417,25 @@ bool PortsOrch::bindAclTable(sai_object_id_t id, sai_object_id_t table_oid, sai_

auto &port = m_portList.find(p.m_alias)->second;

// If port ACL table group does not exist, create one
if (port.m_acl_table_group_id == 0)
if (acl_stage == ACL_STAGE_INGRESS && port.m_ingress_acl_table_group_id != 0)
{
groupOid = port.m_ingress_acl_table_group_id;
}
else if (acl_stage == ACL_STAGE_EGRESS && port.m_egress_acl_table_group_id != 0)
{
groupOid = port.m_egress_acl_table_group_id;
}
else if (acl_stage == ACL_STAGE_INGRESS or acl_stage == ACL_STAGE_EGRESS)
{
bool ingress = acl_stage == ACL_STAGE_INGRESS ? true : false;
// If port ACL table group does not exist, create one
sai_object_id_t bp_list[] = { SAI_ACL_BIND_POINT_TYPE_PORT };

vector<sai_attribute_t> group_attrs;
sai_attribute_t group_attr;

group_attr.id = SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE;
group_attr.value.s32 = SAI_ACL_STAGE_INGRESS; // TODO: double check
group_attr.value.s32 = ingress ? SAI_ACL_STAGE_INGRESS : SAI_ACL_STAGE_EGRESS;
group_attrs.push_back(group_attr);

group_attr.id = SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST;
Expand All @@ -437,11 +454,18 @@ bool PortsOrch::bindAclTable(sai_object_id_t id, sai_object_id_t table_oid, sai_
return false;
}

port.m_acl_table_group_id = groupOid;
if (ingress)
{
port.m_ingress_acl_table_group_id = groupOid;
}
else
{
port.m_egress_acl_table_group_id = groupOid;
}

// Bind this ACL group to port OID
sai_attribute_t port_attr;
port_attr.id = SAI_PORT_ATTR_INGRESS_ACL;
port_attr.id = ingress ? SAI_PORT_ATTR_INGRESS_ACL : SAI_PORT_ATTR_EGRESS_ACL;
port_attr.value.oid = groupOid;

status = sai_port_api->set_port_attribute(port.m_port_id, &port_attr);
Expand All @@ -454,10 +478,6 @@ bool PortsOrch::bindAclTable(sai_object_id_t id, sai_object_id_t table_oid, sai_

SWSS_LOG_NOTICE("Create ACL table group and bind port %s to it", port.m_alias.c_str());
}
else
{
groupOid = port.m_acl_table_group_id;
}

// Create an ACL group member with table_oid and groupOid
vector<sai_attribute_t> member_attrs;
Expand Down
Loading

0 comments on commit 6f0eee3

Please sign in to comment.