Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[aclorch]: add support for acl rule to match out port #810

Merged
merged 7 commits into from
Jan 29, 2020
Merged
Show file tree
Hide file tree
Changes from 5 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
11 changes: 9 additions & 2 deletions orchagent/aclorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,13 @@ bool AclTable::create()
table_attrs.push_back(attr);
}

if (type == ACL_TABLE_L3)
shine4chen marked this conversation as resolved.
Show resolved Hide resolved
shine4chen marked this conversation as resolved.
Show resolved Hide resolved
{
attr.id = SAI_ACL_TABLE_ATTR_FIELD_OUT_PORTS;
attr.value.booldata = true;
table_attrs.push_back(attr);
shine4chen marked this conversation as resolved.
Show resolved Hide resolved
}

sai_status_t status = sai_acl_api->create_acl_table(&m_oid, gSwitchId, (uint32_t)table_attrs.size(), table_attrs.data());

if (status == SAI_STATUS_SUCCESS)
Expand Down Expand Up @@ -2135,12 +2142,12 @@ void AclOrch::doTask(Consumer &consumer)

string table_name = consumer.getTableName();

if (table_name == CFG_ACL_TABLE_TABLE_NAME)
if (table_name == CFG_ACL_TABLE_TABLE_NAME || table_name == APP_ACL_TABLE_TABLE_NAME)
{
unique_lock<mutex> lock(m_countersMutex);
doAclTableTask(consumer);
}
else if (table_name == CFG_ACL_RULE_TABLE_NAME)
else if (table_name == CFG_ACL_RULE_TABLE_NAME || table_name == APP_ACL_RULE_TABLE_NAME)
{
unique_lock<mutex> lock(m_countersMutex);
doAclRuleTask(consumer);
Expand Down
6 changes: 5 additions & 1 deletion orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,14 @@ bool OrchDaemon::init()

TableConnector confDbAclTable(m_configDb, CFG_ACL_TABLE_TABLE_NAME);
TableConnector confDbAclRuleTable(m_configDb, CFG_ACL_RULE_TABLE_NAME);
TableConnector appDbAclTable(m_applDb, APP_ACL_TABLE_TABLE_NAME);
TableConnector appDbAclRuleTable(m_applDb, APP_ACL_RULE_TABLE_NAME);

vector<TableConnector> acl_table_connectors = {
confDbAclTable,
confDbAclRuleTable
confDbAclRuleTable,
appDbAclTable,
appDbAclRuleTable
};

vector<string> dtel_tables = {
Expand Down
199 changes: 199 additions & 0 deletions tests/test_acl_mclag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
from swsscommon import swsscommon
import time
import re
import json

class TestMclagAcl(object):
def setup_db(self, dvs):
self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0)
self.adb = swsscommon.DBConnector(1, dvs.redis_sock, 0)

def create_entry(self, tbl, key, pairs):
fvs = swsscommon.FieldValuePairs(pairs)
tbl.set(key, fvs)
time.sleep(1)

def remove_entry(self, tbl, key):
tbl._del(key)
time.sleep(1)

def create_entry_tbl(self, db, table, key, pairs):
tbl = swsscommon.Table(db, table)
self.create_entry(tbl, key, pairs)

def remove_entry_tbl(self, db, table, key):
tbl = swsscommon.Table(db, table)
self.remove_entry(tbl, key)

def create_entry_pst(self, db, table, key, pairs):
tbl = swsscommon.ProducerStateTable(db, table)
self.create_entry(tbl, key, pairs)

def remove_entry_pst(self, db, table, key):
tbl = swsscommon.ProducerStateTable(db, table)
self.remove_entry(tbl, key)

def get_acl_table_id(self, dvs):
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE")
keys = tbl.getKeys()

for k in dvs.asicdb.default_acl_tables:
assert k in keys

acl_tables = [k for k in keys if k not in dvs.asicdb.default_acl_tables]
if len(acl_tables) == 1:
return acl_tables[0]
else:
return None

def verify_acl_group_num(self, expt):
atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP")
acl_table_groups = atbl.getKeys()
assert len(acl_table_groups) == expt

for k in acl_table_groups:
(status, fvs) = atbl.get(k)
assert status == True
for fv in fvs:
if fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE":
assert fv[1] == "SAI_ACL_STAGE_INGRESS"
elif fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST":
assert fv[1] == "1:SAI_ACL_BIND_POINT_TYPE_PORT"
elif fv[0] == "SAI_ACL_TABLE_GROUP_ATTR_TYPE":
assert fv[1] == "SAI_ACL_TABLE_GROUP_TYPE_PARALLEL"
else:
assert False

def verify_acl_group_member(self, acl_group_ids, acl_table_id):
atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP_MEMBER")
keys = atbl.getKeys()

member_groups = []
for k in keys:
(status, fvs) = atbl.get(k)
assert status == True
assert len(fvs) == 3
for fv in fvs:
if fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID":
assert fv[1] in acl_group_ids
member_groups.append(fv[1])
elif fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID":
assert fv[1] == acl_table_id
elif fv[0] == "SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY":
assert True
else:
assert False

assert set(member_groups) == set(acl_group_ids)

def verify_acl_port_binding(self, dvs, bind_ports):
atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP")
acl_table_groups = atbl.getKeys()
assert len(acl_table_groups) == len(bind_ports)

atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT")
port_groups = []
for p in [dvs.asicdb.portnamemap[portname] for portname in bind_ports]:
(status, fvs) = atbl.get(p)
for fv in fvs:
if fv[0] == "SAI_PORT_ATTR_INGRESS_ACL":
assert fv[1] in acl_table_groups
port_groups.append(fv[1])

assert len(port_groups) == len(bind_ports)
assert set(port_groups) == set(acl_table_groups)

def test_AclTableCreation(self, dvs, testlog):
"""
hmset ACL_TABLE_TABLE:mclag policy_desc "Mclag egress port isolate acl" type L3 ports Ethernet0,Ethernet4
"""
self.setup_db(dvs)

# create ACL_TABLE_TABLE in app db
bind_ports = ["Ethernet0", "Ethernet4"]
self.create_entry_pst(
self.pdb,
"ACL_TABLE_TABLE", "mclag",
[
("policy_desc", "Mclag egress port isolate acl"),
("type", "L3"),
("ports", ",".join(bind_ports)),
]
)

# check acl table in asic db
acl_table_id = self.get_acl_table_id(dvs)
assert acl_table_id is not None

# check acl table group in asic db
self.verify_acl_group_num(2)

# get acl table group ids and verify the id numbers
atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_TABLE_GROUP")
acl_group_ids = atbl.getKeys()
assert len(acl_group_ids) == 2

# check acl table group member
self.verify_acl_group_member(acl_group_ids, acl_table_id)

# check port binding
self.verify_acl_port_binding(dvs, bind_ports)

def test_AclRuleOutPorts(self, dvs, testlog):
"""
hmset ACL_RULE_TABLE:mclag:mclag IP_TYPE ANY PACKET_ACTION DROP OUT_PORTS Ethernet8,Ethernet12
"""
self.setup_db(dvs)

# create acl rule
bind_ports = ["Ethernet8", "Ethernet12"]
self.create_entry_pst(
self.pdb,
"ACL_RULE_TABLE", "mclag:mclag",
[
("IP_TYPE", "ANY"),
("PACKET_ACTION", "DROP"),
("OUT_PORTS", ",".join(bind_ports)),
]
)

# check acl rule table in asic db
acl_table_id = self.get_acl_table_id(dvs)

atbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ACL_ENTRY")
keys = atbl.getKeys()

acl_entry = [k for k in keys if k not in dvs.asicdb.default_acl_entries]
assert len(acl_entry) == 1

(status, fvs) = atbl.get(acl_entry[0])
assert status == True

value = dict(fvs)
assert value["SAI_ACL_ENTRY_ATTR_TABLE_ID"] == acl_table_id
assert value["SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION"] == "SAI_PACKET_ACTION_DROP"
assert value["SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE"] == "SAI_ACL_IP_TYPE_ANY&mask:0xffffffffffffffff"
out_ports = value["SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS"]
assert out_ports.startswith("2:")
assert dvs.asicdb.portnamemap["Ethernet8"] in out_ports
assert dvs.asicdb.portnamemap["Ethernet12"] in out_ports

# remove acl rule
self.remove_entry_pst(
self.pdb,
"ACL_RULE_TABLE", "mclag:mclag"
)

# check acl rule in asic db
(status, fvs) = atbl.get(acl_entry[0])
assert status == False

# remove acl
self.remove_entry_pst(
self.pdb,
"ACL_TABLE_TABLE", "mclag:mclag"
)

# check acl in asic db
acl_table_id = self.get_acl_table_id(dvs)
assert acl_table_id is None