Skip to content

Commit

Permalink
[qosorch]: Optimizations of qosorch (sonic-net#488)
Browse files Browse the repository at this point in the history
* Get the switch attribute SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_CHILDS_PER_SCHEDULER_GROUP just once

* Compress scheduler group creation time in 2.5 times

* Inprove style
  • Loading branch information
pavel-shirshov authored Apr 27, 2018
1 parent edafa34 commit f939b95
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 76 deletions.
177 changes: 101 additions & 76 deletions orchagent/qosorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -875,106 +875,131 @@ task_process_status QosOrch::handleSchedulerTable(Consumer& consumer)
return task_process_status::task_success;
}

bool QosOrch::applySchedulerToQueueSchedulerGroup(Port &port, size_t queue_ind, sai_object_id_t scheduler_profile_id)
sai_object_id_t QosOrch::getSchedulerGroup(const Port &port, const sai_object_id_t queue_id)
{
SWSS_LOG_ENTER();
sai_attribute_t attr;
sai_status_t sai_status;
sai_object_id_t queue_id;
vector<sai_object_id_t> groups;
vector<sai_object_id_t> child_groups;
uint32_t groups_count = 0;

if (port.m_queue_ids.size() <= queue_ind)
{
SWSS_LOG_ERROR("Invalid queue index specified:%zd", queue_ind);
return false;
}
queue_id = port.m_queue_ids[queue_ind];

/* Get max child groups count */
attr.id = SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_CHILDS_PER_SCHEDULER_GROUP;
sai_status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to get number of childs per scheduler group for port:%s", port.m_alias.c_str());
return false;
}
child_groups.resize(attr.value.u32);

/* Get max sched groups count */
attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_SCHEDULER_GROUPS;
sai_status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr);
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to get number of scheduler groups for port:%s", port.m_alias.c_str());
return false;
}

/* Get total groups list on the port */
groups_count = attr.value.u32;
groups.resize(groups_count);

attr.id = SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST;
attr.value.objlist.list = groups.data();
attr.value.objlist.count = groups_count;
sai_status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr);
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to get scheduler group list for port:%s", port.m_alias.c_str());
return false;
}
sai_attribute_t attr;
sai_status_t sai_status;

/* Lookup groups to which queue belongs */
for (uint32_t ii = 0; ii < groups_count ; ii++)
const auto it = m_scheduler_group_port_info.find(port.m_port_id);
if (it == m_scheduler_group_port_info.end())
{
uint32_t child_count = 0;

attr.id = SAI_SCHEDULER_GROUP_ATTR_CHILD_COUNT;//Number of queues/groups childs added to scheduler group
sai_status = sai_scheduler_group_api->get_scheduler_group_attribute(groups[ii], 1, &attr);
child_count = attr.value.u32;
/* Get max sched groups count */
attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_SCHEDULER_GROUPS;
sai_status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr);
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to get child count for scheduler group:0x%lx of port:%s", groups[ii], port.m_alias.c_str());
return false;
SWSS_LOG_ERROR("Failed to get number of scheduler groups for port:%s", port.m_alias.c_str());
return SAI_NULL_OBJECT_ID;
}

// skip this iteration if there're no children in this group
if (child_count == 0)
{
continue;
}
/* Get total groups list on the port */
uint32_t groups_count = attr.value.u32;
std::vector<sai_object_id_t> groups(groups_count);

attr.id = SAI_SCHEDULER_GROUP_ATTR_CHILD_LIST;
attr.value.objlist.list = child_groups.data();
attr.value.objlist.count = child_count;
sai_status = sai_scheduler_group_api->get_scheduler_group_attribute(groups[ii], 1, &attr);
attr.id = SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST;
attr.value.objlist.list = groups.data();
attr.value.objlist.count = groups_count;
sai_status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr);
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to get child list for scheduler group:0x%lx of port:%s", groups[ii], port.m_alias.c_str());
return false;
SWSS_LOG_ERROR("Failed to get scheduler group list for port:%s", port.m_alias.c_str());
return SAI_NULL_OBJECT_ID;
}

for (uint32_t jj = 0; jj < child_count; jj++)
m_scheduler_group_port_info[port.m_port_id] = {
.groups = std::move(groups),
.child_groups = std::vector<std::vector<sai_object_id_t>>(groups_count)
};
}

/* Lookup groups to which queue belongs */
const auto& groups = m_scheduler_group_port_info[port.m_port_id].groups;
for (uint32_t ii = 0; ii < groups.size() ; ii++)
{
const auto& group_id = groups[ii];
const auto& child_groups_per_group = m_scheduler_group_port_info[port.m_port_id].child_groups[ii];
if (child_groups_per_group.empty())
{
if (child_groups[jj] != queue_id)
attr.id = SAI_SCHEDULER_GROUP_ATTR_CHILD_COUNT;//Number of queues/groups childs added to scheduler group
sai_status = sai_scheduler_group_api->get_scheduler_group_attribute(group_id, 1, &attr);
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to get child count for scheduler group:0x%lx of port:%s", group_id, port.m_alias.c_str());
return SAI_NULL_OBJECT_ID;
}

uint32_t child_count = attr.value.u32;
vector<sai_object_id_t> child_groups(child_count);

// skip this iteration if there're no children in this group
if (child_count == 0)
{
continue;
}

attr.id = SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID;
attr.value.oid = scheduler_profile_id;
sai_status = sai_scheduler_group_api->set_scheduler_group_attribute(groups[ii], &attr);
attr.id = SAI_SCHEDULER_GROUP_ATTR_CHILD_LIST;
attr.value.objlist.list = child_groups.data();
attr.value.objlist.count = child_count;
sai_status = sai_scheduler_group_api->get_scheduler_group_attribute(group_id, 1, &attr);
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed applying scheduler profile:0x%lx to scheduler group:0x%lx, port:%s", scheduler_profile_id, groups[ii], port.m_alias.c_str());
return false;
SWSS_LOG_ERROR("Failed to get child list for scheduler group:0x%lx of port:%s", group_id, port.m_alias.c_str());
return SAI_NULL_OBJECT_ID;
}

m_scheduler_group_port_info[port.m_port_id].child_groups[ii] = std::move(child_groups);
}

for (const auto& child_group_id: child_groups_per_group)
{
if (child_group_id == queue_id)
{
return group_id;
}
SWSS_LOG_DEBUG("port:%s, scheduler_profile_id:0x%lx applied to scheduler group:0x%lx", port.m_alias.c_str(), scheduler_profile_id, groups[ii]);
return true;
}
}
return false;

return SAI_NULL_OBJECT_ID;
}

bool QosOrch::applySchedulerToQueueSchedulerGroup(Port &port, size_t queue_ind, sai_object_id_t scheduler_profile_id)
{
SWSS_LOG_ENTER();

if (port.m_queue_ids.size() <= queue_ind)
{
SWSS_LOG_ERROR("Invalid queue index specified:%zd", queue_ind);
return false;
}

const sai_object_id_t queue_id = port.m_queue_ids[queue_ind];

const sai_object_id_t group_id = getSchedulerGroup(port, queue_id);
if(group_id == SAI_NULL_OBJECT_ID)
{
SWSS_LOG_ERROR("Failed to find a scheduler group for port: %s queue: %lu", port.m_alias.c_str(), queue_ind);
return false;
}

/* Apply scheduler profile to all port groups */
sai_attribute_t attr;
sai_status_t sai_status;

attr.id = SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID;
attr.value.oid = scheduler_profile_id;

sai_status = sai_scheduler_group_api->set_scheduler_group_attribute(group_id, &attr);
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed applying scheduler profile:0x%lx to scheduler group:0x%lx, port:%s", scheduler_profile_id, group_id, port.m_alias.c_str());
return false;
}

SWSS_LOG_DEBUG("port:%s, scheduler_profile_id:0x%lx applied to scheduler group:0x%lx", port.m_alias.c_str(), scheduler_profile_id, group_id);

return true;
}

bool QosOrch::applyWredProfileToQueue(Port &port, size_t queue_ind, sai_object_id_t sai_wred_profile)
Expand Down
12 changes: 12 additions & 0 deletions orchagent/qosorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#define SWSS_QOSORCH_H

#include <map>
#include <unordered_map>
#include <unordered_set>
#include "orch.h"
#include "portsorch.h"

Expand Down Expand Up @@ -132,6 +134,8 @@ class QosOrch : public Orch
task_process_status handleQueueTable(Consumer& consumer);
task_process_status handleWredProfileTable(Consumer& consumer);

sai_object_id_t getSchedulerGroup(const Port &port, const sai_object_id_t queue_id);

bool applyMapToPort(Port &port, sai_attr_id_t attr_id, sai_object_id_t sai_dscp_to_tc_map);
bool applySchedulerToQueueSchedulerGroup(Port &port, size_t queue_ind, sai_object_id_t scheduler_profile_id);
bool applyWredProfileToQueue(Port &port, size_t queue_ind, sai_object_id_t sai_wred_profile);
Expand All @@ -140,5 +144,13 @@ class QosOrch : public Orch

private:
qos_table_handler_map m_qos_handler_map;

struct SchedulerGroupPortInfo_t
{
std::vector<sai_object_id_t> groups;
std::vector<std::vector<sai_object_id_t>> child_groups;
};

std::unordered_map<sai_object_id_t, SchedulerGroupPortInfo_t> m_scheduler_group_port_info;
};
#endif /* SWSS_QOSORCH_H */

0 comments on commit f939b95

Please sign in to comment.