Skip to content

Commit

Permalink
[policerorch]: Add the capability to update policer rate/size (#1017)
Browse files Browse the repository at this point in the history
Monitor the changes in the configuration databaes and update
the corresponding rate/size for the policers

Signed-off-by: Shu0T1an ChenG <[email protected]>
  • Loading branch information
stcheng authored and yxieca committed Aug 14, 2019
1 parent f44029d commit bec6d63
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 21 deletions.
76 changes: 55 additions & 21 deletions orchagent/policerorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,8 @@ void PolicerOrch::doTask(Consumer &consumer)

if (op == SET_COMMAND)
{
if (m_syncdPolicers.find(key) != m_syncdPolicers.end())
{
SWSS_LOG_ERROR("Policer %s already exists", key.c_str());
it = consumer.m_toSync.erase(it);
continue;
}
// Mark the opeartion as an 'update', if the policer exists.
bool update = m_syncdPolicers.find(key) != m_syncdPolicers.end();

vector<sai_attribute_t> attrs;
bool meter_type = false, mode = false;
Expand Down Expand Up @@ -211,26 +207,64 @@ void PolicerOrch::doTask(Consumer &consumer)
attrs.push_back(attr);
}

if (!meter_type || !mode)
// Create a new policer
if (!update)
{
SWSS_LOG_ERROR("Failed to create policer %s,\
missing madatory fields", key.c_str());
}
if (!meter_type || !mode)
{
SWSS_LOG_ERROR("Failed to create policer %s,\
missing mandatory fields", key.c_str());
}

sai_object_id_t policer_id;
sai_status_t status = sai_policer_api->create_policer(
&policer_id, gSwitchId, (uint32_t)attrs.size(), attrs.data());
if (status != SAI_STATUS_SUCCESS)
sai_object_id_t policer_id;
sai_status_t status = sai_policer_api->create_policer(
&policer_id, gSwitchId, (uint32_t)attrs.size(), attrs.data());
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to create policer %s, rv:%d",
key.c_str(), status);
it++;
continue;
}

SWSS_LOG_NOTICE("Created policer %s", key.c_str());
m_syncdPolicers[key] = policer_id;
m_policerRefCounts[key] = 0;
}
// Update an existing policer
else
{
SWSS_LOG_ERROR("Failed to create policer %s, rv:%d",
key.c_str(), status);
it++;
continue;
auto policer_id = m_syncdPolicers[key];

// The update operation has limitations that it could only update
// the rate and the size accordingly.
// SR_TCM: CIR, CBS, PBS
// TR_TCM: CIR, CBS, PIR, PBS
// STORM_CONTROL: CIR, CBS
for (auto & attr: attrs)
{
if (attr.id != SAI_POLICER_ATTR_CBS &&
attr.id != SAI_POLICER_ATTR_CIR &&
attr.id != SAI_POLICER_ATTR_PBS &&
attr.id != SAI_POLICER_ATTR_PIR)
{
continue;
}

sai_status_t status = sai_policer_api->set_policer_attribute(
policer_id, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to update policer %s attribute, rv:%d",
key.c_str(), status);
it++;
continue;
}
}

SWSS_LOG_NOTICE("Update policer %s attributes", key.c_str());
}

SWSS_LOG_NOTICE("Created policer %s", key.c_str());
m_syncdPolicers[key] = policer_id;
m_policerRefCounts[key] = 0;
it = consumer.m_toSync.erase(it);
}
else if (op == DEL_COMMAND)
Expand Down
73 changes: 73 additions & 0 deletions tests/test_policer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import platform
import pytest
import time

from swsscommon import swsscommon

class TestPolicer(object):
def test_PolicerBasic(self, dvs, testlog):
dvs.setup_db()
policer = "POLICER"

# create policer
tbl = swsscommon.Table(dvs.cdb, "POLICER")
fvs = swsscommon.FieldValuePairs([("meter_type", "packets"),
("mode", "sr_tcm"),
("cir", "600"),
("cbs", "600"),
("red_packet_action", "drop")])
tbl.set(policer, fvs)
time.sleep(1)

# check asic database
tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER")
policer_entries = tbl.getKeys()
assert len(policer_entries) == 1

(status, fvs) = tbl.get(policer_entries[0])
assert status == True
assert len(fvs) == 5
for fv in fvs:
if fv[0] == "SAI_POLICER_ATTR_CBS":
assert fv[1] == "600"
if fv[0] == "SAI_POLICER_ATTR_CIR":
assert fv[1] == "600"
if fv[0] == "SAI_POLICER_ATTR_RED_PACKET_ACTION":
assert fv[1] == "SAI_PACKET_ACTION_DROP"
if fv[0] == "SAI_POLICER_ATTR_MODE":
assert fv[1] == "SAI_POLICER_MODE_SR_TCM"
if fv[0] == "SAI_POLICER_ATTR_METER_TYPE":
assert fv[1] == "SAI_METER_TYPE_PACKETS"

# update cir
tbl = swsscommon.Table(dvs.cdb, "POLICER")
fvs = swsscommon.FieldValuePairs([("cir", "800")])
tbl.set(policer, fvs)
time.sleep(1)

# check asic database
tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER")
(status, fvs) = tbl.get(policer_entries[0])
assert status == True
assert len(fvs) == 5
for fv in fvs:
if fv[0] == "SAI_POLICER_ATTR_CBS":
assert fv[1] == "600"
if fv[0] == "SAI_POLICER_ATTR_CIR":
assert fv[1] == "800" # updated
if fv[0] == "SAI_POLICER_ATTR_RED_PACKET_ACTION":
assert fv[1] == "SAI_PACKET_ACTION_DROP"
if fv[0] == "SAI_POLICER_ATTR_MODE":
assert fv[1] == "SAI_POLICER_MODE_SR_TCM"
if fv[0] == "SAI_POLICER_ATTR_METER_TYPE":
assert fv[1] == "SAI_METER_TYPE_PACKETS"

# remove policer
tbl = swsscommon.Table(dvs.cdb, "POLICER")
tbl._del(policer)
time.sleep(1)

# check asic database
tbl = swsscommon.Table(dvs.adb, "ASIC_STATE:SAI_OBJECT_TYPE_POLICER")
policer_entries = tbl.getKeys()
assert len(policer_entries) == 0

0 comments on commit bec6d63

Please sign in to comment.