Skip to content

Commit

Permalink
[Buffer Orch] Support removing buffer port profile list (sonic-net#2371)
Browse files Browse the repository at this point in the history
Signed-off-by: Stephen Sun <stephens@nvidia.com>

What I did
Support removing an entry from BUFFER_PORT_INGRESS/EGRESS_PROFILE_LIST table.
To remove it, set the list as empty.
Add mock test to verify the change

How I verified it
Mock test and manual test
  • Loading branch information
stephenxs authored Jul 20, 2022
1 parent 419ab1b commit 33c420d
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 34 deletions.
94 changes: 62 additions & 32 deletions orchagent/bufferorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -987,28 +987,43 @@ task_process_status BufferOrch::processIngressBufferProfileList(KeyOpFieldsValue

vector<string> port_names = tokenize(key, list_item_delimiter);
vector<sai_object_id_t> profile_list;
sai_attribute_t attr;
attr.id = SAI_PORT_ATTR_QOS_INGRESS_BUFFER_PROFILE_LIST;

string profile_name_list;
ref_resolve_status resolve_status = resolveFieldRefArray(m_buffer_type_maps, buffer_profile_list_field_name,
buffer_to_ref_table_map.at(buffer_profile_list_field_name), tuple,
profile_list, profile_name_list);
if (ref_resolve_status::success != resolve_status)
if (op == SET_COMMAND)
{
if(ref_resolve_status::not_resolved == resolve_status)
string profile_name_list;
ref_resolve_status resolve_status = resolveFieldRefArray(m_buffer_type_maps, buffer_profile_list_field_name,
buffer_to_ref_table_map.at(buffer_profile_list_field_name), tuple,
profile_list, profile_name_list);
if (ref_resolve_status::success != resolve_status)
{
SWSS_LOG_INFO("Missing or invalid ingress buffer profile reference specified for:%s", key.c_str());
return task_process_status::task_need_retry;
if(ref_resolve_status::not_resolved == resolve_status)
{
SWSS_LOG_INFO("Missing or invalid ingress buffer profile reference specified for:%s", key.c_str());
return task_process_status::task_need_retry;
}
SWSS_LOG_ERROR("Failed resolving ingress buffer profile reference specified for:%s", key.c_str());
return task_process_status::task_failed;
}
SWSS_LOG_ERROR("Failed resolving ingress buffer profile reference specified for:%s", key.c_str());
return task_process_status::task_failed;
}

setObjectReference(m_buffer_type_maps, APP_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME, key, buffer_profile_list_field_name, profile_name_list);
setObjectReference(m_buffer_type_maps, APP_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME, key, buffer_profile_list_field_name, profile_name_list);

attr.value.objlist.count = (uint32_t)profile_list.size();
attr.value.objlist.list = profile_list.data();
}
else if (op == DEL_COMMAND)
{
SWSS_LOG_NOTICE("%s has been removed from BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE", key.c_str());
removeObject(m_buffer_type_maps, APP_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME, key);
attr.value.objlist.count = 0;
attr.value.objlist.list = profile_list.data();
}
else
{
SWSS_LOG_ERROR("Unknown command %s when handling BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE key %s", op.c_str(), key.c_str());
}

sai_attribute_t attr;
attr.id = SAI_PORT_ATTR_QOS_INGRESS_BUFFER_PROFILE_LIST;
attr.value.objlist.count = (uint32_t)profile_list.size();
attr.value.objlist.list = profile_list.data();
for (string port_name : port_names)
{
if (!gPortsOrch->getPort(port_name, port))
Expand Down Expand Up @@ -1043,28 +1058,43 @@ task_process_status BufferOrch::processEgressBufferProfileList(KeyOpFieldsValues
SWSS_LOG_DEBUG("processing:%s", key.c_str());
vector<string> port_names = tokenize(key, list_item_delimiter);
vector<sai_object_id_t> profile_list;
sai_attribute_t attr;
attr.id = SAI_PORT_ATTR_QOS_EGRESS_BUFFER_PROFILE_LIST;

string profile_name_list;
ref_resolve_status resolve_status = resolveFieldRefArray(m_buffer_type_maps, buffer_profile_list_field_name,
buffer_to_ref_table_map.at(buffer_profile_list_field_name), tuple,
profile_list, profile_name_list);
if (ref_resolve_status::success != resolve_status)
if (op == SET_COMMAND)
{
if(ref_resolve_status::not_resolved == resolve_status)
string profile_name_list;
ref_resolve_status resolve_status = resolveFieldRefArray(m_buffer_type_maps, buffer_profile_list_field_name,
buffer_to_ref_table_map.at(buffer_profile_list_field_name), tuple,
profile_list, profile_name_list);
if (ref_resolve_status::success != resolve_status)
{
SWSS_LOG_INFO("Missing or invalid egress buffer profile reference specified for:%s", key.c_str());
return task_process_status::task_need_retry;
if(ref_resolve_status::not_resolved == resolve_status)
{
SWSS_LOG_INFO("Missing or invalid egress buffer profile reference specified for:%s", key.c_str());
return task_process_status::task_need_retry;
}
SWSS_LOG_ERROR("Failed resolving egress buffer profile reference specified for:%s", key.c_str());
return task_process_status::task_failed;
}
SWSS_LOG_ERROR("Failed resolving egress buffer profile reference specified for:%s", key.c_str());
return task_process_status::task_failed;
}

setObjectReference(m_buffer_type_maps, APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME, key, buffer_profile_list_field_name, profile_name_list);
setObjectReference(m_buffer_type_maps, APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME, key, buffer_profile_list_field_name, profile_name_list);

attr.value.objlist.count = (uint32_t)profile_list.size();
attr.value.objlist.list = profile_list.data();
}
else if (op == DEL_COMMAND)
{
SWSS_LOG_NOTICE("%s has been removed from BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE", key.c_str());
removeObject(m_buffer_type_maps, APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME, key);
attr.value.objlist.count = 0;
attr.value.objlist.list = profile_list.data();
}
else
{
SWSS_LOG_ERROR("Unknown command %s when handling BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE key %s", op.c_str(), key.c_str());
}

sai_attribute_t attr;
attr.id = SAI_PORT_ATTR_QOS_EGRESS_BUFFER_PROFILE_LIST;
attr.value.objlist.count = (uint32_t)profile_list.size();
attr.value.objlist.list = profile_list.data();
for (string port_name : port_names)
{
if (!gPortsOrch->getPort(port_name, port))
Expand Down
145 changes: 143 additions & 2 deletions tests/mock_tests/bufferorch_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,52 @@ namespace bufferorch_test
{
using namespace std;

sai_port_api_t ut_sai_port_api;
sai_port_api_t *pold_sai_port_api;

shared_ptr<swss::DBConnector> m_app_db;
shared_ptr<swss::DBConnector> m_config_db;
shared_ptr<swss::DBConnector> m_state_db;
shared_ptr<swss::DBConnector> m_chassis_app_db;

uint32_t _ut_stub_expected_profile_count;
uint32_t _ut_stub_port_profile_list_add_count;
uint32_t _ut_stub_port_profile_list_del_count;
sai_port_attr_t _ut_stub_expected_profile_list_type;
sai_status_t _ut_stub_sai_set_port_attribute(
_In_ sai_object_id_t port_id,
_In_ const sai_attribute_t *attr)
{
if (attr[0].id == _ut_stub_expected_profile_list_type)
{
if (_ut_stub_expected_profile_count == attr[0].value.objlist.count)
{
if (_ut_stub_expected_profile_count != 0)
{
_ut_stub_port_profile_list_add_count++;
}
else
{
_ut_stub_port_profile_list_del_count++;
}
}
}
return pold_sai_port_api->set_port_attribute(port_id, attr);
}

void _hook_sai_port_api()
{
ut_sai_port_api = *sai_port_api;
pold_sai_port_api = sai_port_api;
ut_sai_port_api.set_port_attribute = _ut_stub_sai_set_port_attribute;
sai_port_api = &ut_sai_port_api;
}

void _unhook_sai_port_api()
{
sai_port_api = pold_sai_port_api;
}

struct BufferOrchTest : public ::testing::Test
{
BufferOrchTest()
Expand Down Expand Up @@ -211,13 +252,13 @@ namespace bufferorch_test
{
{"size", "1024000"},
{"mode", "dynamic"},
{"type", "egress"}
{"type", "ingress"}
});
bufferPoolTable.set("ingress_lossy_pool",
{
{"size", "1024000"},
{"mode", "dynamic"},
{"type", "egress"}
{"type", "ingress"}
});
bufferProfileTable.set("ingress_lossless_profile",
{
Expand Down Expand Up @@ -346,6 +387,7 @@ namespace bufferorch_test

TEST_F(BufferOrchTest, BufferOrchTestReferencingObjRemoveThenAdd)
{
_hook_sai_port_api();
vector<string> ts;
std::deque<KeyOpFieldsValuesTuple> entries;
Table bufferProfileListTable = Table(m_app_db.get(), APP_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME);
Expand All @@ -354,7 +396,11 @@ namespace bufferorch_test
{"profile_list", "ingress_lossy_profile,ingress_lossless_profile"}
});
gBufferOrch->addExistingData(&bufferProfileListTable);
auto sai_port_profile_list_create_count = _ut_stub_port_profile_list_add_count;
_ut_stub_expected_profile_count = 2;
_ut_stub_expected_profile_list_type = SAI_PORT_ATTR_QOS_INGRESS_BUFFER_PROFILE_LIST;
static_cast<Orch *>(gBufferOrch)->doTask();
ASSERT_EQ(++sai_port_profile_list_create_count, _ut_stub_port_profile_list_add_count);
CheckDependency(APP_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME, "Ethernet0", "profile_list",
APP_BUFFER_PROFILE_TABLE_NAME, "ingress_lossy_profile,ingress_lossless_profile");

Expand Down Expand Up @@ -405,5 +451,100 @@ namespace bufferorch_test
ASSERT_EQ(ts[2], "BUFFER_PROFILE_TABLE:ingress_lossy_profile|DEL");
ASSERT_EQ(ts[3], "BUFFER_PROFILE_TABLE:ingress_lossy_profile|SET|pool:ingress_lossy_pool|size:0|dynamic_th:0");
ts.clear();

// Remove ingress port profile list
entries.push_back({"Ethernet0", "DEL", {}});
consumer = dynamic_cast<Consumer *>(gBufferOrch->getExecutor(APP_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME));
consumer->addToSync(entries);
entries.clear();
// Drain BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE table
_ut_stub_expected_profile_count = 0;
auto sai_port_profile_list_remove_count = _ut_stub_port_profile_list_del_count;
static_cast<Orch *>(gBufferOrch)->doTask();
ASSERT_EQ(++sai_port_profile_list_remove_count, _ut_stub_port_profile_list_del_count);
// Drain BUFFER_PROFILE_TABLE del operation
static_cast<Orch *>(gBufferOrch)->doTask();
// Drain BUFFER_POOL_TABLE del operation
static_cast<Orch *>(gBufferOrch)->doTask();
// Drain the rest create operations
static_cast<Orch *>(gBufferOrch)->doTask();
static_cast<Orch *>(gBufferOrch)->dumpPendingTasks(ts);
// As an side-effect, all pending notifications should be drained
ASSERT_TRUE(ts.empty());

// To satisfy the coverage requirement
bufferProfileListTable.set("Ethernet0",
{
{"profile_list", "ingress_no_exist_profile"}
});
gBufferOrch->addExistingData(&bufferProfileListTable);
static_cast<Orch *>(gBufferOrch)->doTask();
static_cast<Orch *>(gBufferOrch)->dumpPendingTasks(ts);
ASSERT_EQ(ts[0], "BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE:Ethernet0|SET|profile_list:ingress_no_exist_profile");
ts.clear();

_unhook_sai_port_api();
}

TEST_F(BufferOrchTest, BufferOrchTestCreateAndRemoveEgressProfileList)
{
_hook_sai_port_api();
vector<string> ts;
std::deque<KeyOpFieldsValuesTuple> entries;
Table bufferPoolTable = Table(m_app_db.get(), APP_BUFFER_POOL_TABLE_NAME);
Table bufferProfileTable = Table(m_app_db.get(), APP_BUFFER_PROFILE_TABLE_NAME);
Table bufferProfileListTable = Table(m_app_db.get(), APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME);

// To satisfy the coverage requirement
bufferProfileListTable.set("Ethernet0",
{
{"profile_list", "egress_lossless_profile"}
});

gBufferOrch->addExistingData(&bufferProfileListTable);
static_cast<Orch *>(gBufferOrch)->doTask();
static_cast<Orch *>(gBufferOrch)->dumpPendingTasks(ts);
ASSERT_EQ(ts[0], "BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE:Ethernet0|SET|profile_list:egress_lossless_profile");
ts.clear();

bufferPoolTable.set("egress_lossless_pool",
{
{"size", "1024000"},
{"mode", "dynamic"},
{"type", "egress"}
});
bufferProfileTable.set("egress_lossless_profile",
{
{"pool", "egress_lossless_pool"},
{"size", "0"},
{"dynamic_th", "0"}
});

gBufferOrch->addExistingData(&bufferPoolTable);
gBufferOrch->addExistingData(&bufferProfileTable);

auto sai_port_profile_list_create_count = _ut_stub_port_profile_list_add_count;
_ut_stub_expected_profile_count = 1;
_ut_stub_expected_profile_list_type = SAI_PORT_ATTR_QOS_EGRESS_BUFFER_PROFILE_LIST;
static_cast<Orch *>(gBufferOrch)->doTask();
ASSERT_EQ(++sai_port_profile_list_create_count, _ut_stub_port_profile_list_add_count);
CheckDependency(APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME, "Ethernet0", "profile_list",
APP_BUFFER_PROFILE_TABLE_NAME, "egress_lossless_profile");

// Remove egress port profile list
entries.push_back({"Ethernet0", "DEL", {}});
auto consumer = dynamic_cast<Consumer *>(gBufferOrch->getExecutor(APP_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME));
consumer->addToSync(entries);
entries.clear();
// Drain BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE table
_ut_stub_expected_profile_count = 0;
auto sai_port_profile_list_remove_count = _ut_stub_port_profile_list_del_count;
static_cast<Orch *>(gBufferOrch)->doTask();
ASSERT_EQ(++sai_port_profile_list_remove_count, _ut_stub_port_profile_list_del_count);

static_cast<Orch *>(gBufferOrch)->dumpPendingTasks(ts);
ASSERT_TRUE(ts.empty());

_unhook_sai_port_api();
}
}

0 comments on commit 33c420d

Please sign in to comment.