From 189a9641cf47e81c7c90d2501e70b73b74b082e1 Mon Sep 17 00:00:00 2001 From: Stephen Sun <5379172+stephenxs@users.noreply.github.com> Date: Mon, 8 Feb 2021 05:22:09 +0800 Subject: [PATCH] [buffermgr] Support maximum port headroom checking (#1607) * Support maximum port headroom checking - Fetch the maximum port headroom via fetching the port attribute SAI_PORT_ATTR_QOS_MAXIMUM_HEADROOM_SIZE when the orchagent starts and push the data into STATE_DB - Check the accumulative port headroom against the maximum headroom in buffer_check_headroom_.lua On Mellanox platform, this PR depends on PR #6566 to be merged. In that PR the required SAI attribute is supported. On other platforms, there is no dependency. Signed-off-by: Stephen Sun stephens@nvidia.com Why I did it On some platforms, the SAI will notify orchagent shut down if a headroom size that causes the accumulative port headroom to exceed its limit is programmed to SAI. To avoid that, we need to check this before programming it to SAI. How I verified it Run the regression test. --- cfgmgr/buffer_check_headroom_mellanox.lua | 28 ++--------------------- orchagent/port.h | 1 + orchagent/portsorch.cpp | 23 +++++++++++++++++++ orchagent/portsorch.h | 3 +++ 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/cfgmgr/buffer_check_headroom_mellanox.lua b/cfgmgr/buffer_check_headroom_mellanox.lua index da4a443b1b40..510a967b7303 100644 --- a/cfgmgr/buffer_check_headroom_mellanox.lua +++ b/cfgmgr/buffer_check_headroom_mellanox.lua @@ -10,36 +10,15 @@ local new_pg = ARGV[3] local accumulative_size = 0 local appl_db = "0" -local config_db = "4" local state_db = "6" local ret_true = {} -local ret_false = {} local ret = {} local default_ret = {} table.insert(ret_true, "result:true") -table.insert(ret_false, "result:false") --- Fetch the cable length from CONFIG_DB -redis.call('SELECT', config_db) -local cable_length_keys = redis.call('KEYS', 'CABLE_LENGTH*') -if #cable_length_keys == 0 then - return ret_true -end - --- Check whether cable length exceeds 300m (maximum value in the non-dynamic-buffer solution) -local cable_length_str = redis.call('HGET', cable_length_keys[1], port) -if cable_length_str == nil then - return ret_true -end -local cable_length = tonumber(string.sub(cable_length_str, 1, -2)) -if cable_length > 300 then - default_ret = ret_false -else - default_ret = ret_true -end -table.insert(default_ret, 'debug:no max_headroom_size configured, check cable length instead') +default_ret = ret_true local speed = redis.call('HGET', 'PORT|' .. port, 'speed') @@ -67,7 +46,6 @@ local function get_number_of_pgs(keyname) local range = string.match(keyname, "Ethernet%d+:([^%s]+)$") local size if range == nil then - table.insert(debuginfo, "debug:invalid pg:" .. keyname) return 0 end if string.len(range) == 1 then @@ -119,11 +97,9 @@ if max_headroom_size > accumulative_size then table.insert(ret, "result:true") else table.insert(ret, "result:false") + table.insert(ret, "debug:Accumulative headroom on port " .. accumulative_size .. " exceeds the maximum available headroom which is " .. max_headroom_size) end -table.insert(ret, "debug:max headroom:" .. max_headroom_size) -table.insert(ret, "debug:accumulative headroom:" .. accumulative_size) - for i = 1, #debuginfo do table.insert(ret, debuginfo[i]) end diff --git a/orchagent/port.h b/orchagent/port.h index baf8e3046ec4..35085c16c11a 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -124,6 +124,7 @@ class Port uint32_t m_vnid = VNID_NONE; uint32_t m_fdb_count = 0; uint32_t m_up_member_count = 0; + uint32_t m_maximum_headroom = 0; /* * Following two bit vectors are used to lock diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 334cd68f1807..8f2902c77edd 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -257,6 +257,9 @@ PortsOrch::PortsOrch(DBConnector *db, vector &tableNames) m_flexCounterTable = unique_ptr(new ProducerTable(m_flex_db.get(), FLEX_COUNTER_TABLE)); m_flexCounterGroupTable = unique_ptr(new ProducerTable(m_flex_db.get(), FLEX_COUNTER_GROUP_TABLE)); + m_state_db = shared_ptr(new DBConnector("STATE_DB", 0)); + m_stateBufferMaximumValueTable = unique_ptr(new Table(m_state_db.get(), STATE_BUFFER_MAXIMUM_VALUE_TABLE)); + initGearbox(); string queueWmSha, pgWmSha; @@ -3291,6 +3294,25 @@ void PortsOrch::initializePriorityGroups(Port &port) SWSS_LOG_INFO("Get priority groups for port %s", port.m_alias.c_str()); } +void PortsOrch::initializePortMaximumHeadroom(Port &port) +{ + sai_attribute_t attr; + + attr.id = SAI_PORT_ATTR_QOS_MAXIMUM_HEADROOM_SIZE; + + sai_status_t status = sai_port_api->get_port_attribute(port.m_port_id, 1, &attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_NOTICE("Unable to get the maximum headroom for port %s rv:%d, ignored", port.m_alias.c_str(), status); + return; + } + + vector fvVector; + port.m_maximum_headroom = attr.value.u32; + fvVector.emplace_back("max_headroom_size", to_string(port.m_maximum_headroom)); + m_stateBufferMaximumValueTable->set(port.m_alias, fvVector); +} + bool PortsOrch::initializePort(Port &port) { SWSS_LOG_ENTER(); @@ -3299,6 +3321,7 @@ bool PortsOrch::initializePort(Port &port) initializePriorityGroups(port); initializeQueues(port); + initializePortMaximumHeadroom(port); /* Create host interface */ if (!addHostIntfs(port, port.m_alias, port.m_hif_id)) diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index ecf65c4f8e90..e24ecb94507c 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -155,6 +155,7 @@ class PortsOrch : public Orch, public Subject unique_ptr
m_pgTable; unique_ptr
m_pgPortTable; unique_ptr
m_pgIndexTable; + unique_ptr
m_stateBufferMaximumValueTable; unique_ptr m_flexCounterTable; unique_ptr m_flexCounterGroupTable; @@ -164,6 +165,7 @@ class PortsOrch : public Orch, public Subject shared_ptr m_counter_db; shared_ptr m_flex_db; + shared_ptr m_state_db; FlexCounterManager port_stat_manager; FlexCounterManager port_buffer_drop_stat_manager; @@ -226,6 +228,7 @@ class PortsOrch : public Orch, public Subject bool initializePort(Port &port); void initializePriorityGroups(Port &port); + void initializePortMaximumHeadroom(Port &port); void initializeQueues(Port &port); bool addHostIntfs(Port &port, string alias, sai_object_id_t &host_intfs_id);