Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
anilkpan committed Nov 23, 2024
2 parents d67bb1a + 1847195 commit e12d545
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 26 deletions.
7 changes: 7 additions & 0 deletions orchagent/flexcounterorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,13 @@ map<string, FlexCounterQueueStates> FlexCounterOrch::getQueueConfigurations()
{
queuesStateVector.at(configPortName).enableQueueCounter(startIndex);
}

Port port;
gPortsOrch->getPort(configPortName, port);
if (port.m_host_tx_queue_configured && port.m_host_tx_queue <= maxQueueIndex)
{
queuesStateVector.at(configPortName).enableQueueCounter(port.m_host_tx_queue);
}
} catch (std::invalid_argument const& e) {
SWSS_LOG_ERROR("Invalid queue index [%s] for port [%s]", configPortQueues.c_str(), configPortName.c_str());
continue;
Expand Down
4 changes: 2 additions & 2 deletions orchagent/p4orch/tests/fake_portorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,11 @@ void PortsOrch::generateQueueMapPerPort(const Port &port, FlexCounterQueueStates
{
}

void PortsOrch::createPortBufferQueueCounters(const Port &port, string queues)
void PortsOrch::createPortBufferQueueCounters(const Port &port, string queues, bool skip_host_tx_queue)
{
}

void PortsOrch::removePortBufferQueueCounters(const Port &port, string queues)
void PortsOrch::removePortBufferQueueCounters(const Port &port, string queues, bool skip_host_tx_queue)
{
}

Expand Down
2 changes: 2 additions & 0 deletions orchagent/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ class Port
sai_port_priority_flow_control_mode_t m_pfc_asym = SAI_PORT_PRIORITY_FLOW_CONTROL_MODE_COMBINED;
uint8_t m_pfc_bitmask = 0; // PFC enable bit mask
uint8_t m_pfcwd_sw_bitmask = 0; // PFC software watchdog enable
uint8_t m_host_tx_queue = 0;
bool m_host_tx_queue_configured = false;
uint16_t m_tpid = DEFAULT_TPID;
uint32_t m_nat_zone_id = 0;
uint32_t m_vnid = VNID_NONE;
Expand Down
146 changes: 142 additions & 4 deletions orchagent/port_rates.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ end
local counters_db = ARGV[1]
local counters_table_name = ARGV[2]
local rates_table_name = "RATES"
local appl_db_port = "PORT_TABLE"
-- refer back to common/schema.h
local appl_db = "0"

-- Get configuration
redis.call('SELECT', counters_db)
Expand All @@ -29,11 +32,117 @@ logit(alpha)
logit(one_minus_alpha)
logit(delta)

local port_interface_oid_map = redis.call('HGETALL', "COUNTERS_PORT_NAME_MAP")
local port_interface_oid_key_count = redis.call('HLEN', "COUNTERS_PORT_NAME_MAP")

-- lookup interface name from port oid

local function find_interface_name_from_oid(port)

for i = 1, port_interface_oid_key_count do
local index = i * 2 - 1
if port_interface_oid_map[index + 1] == port then
return port_interface_oid_map[index]
end
end

return 0
end

-- calculate lanes and serdes speed from interface lane count & speed
-- return lane speed and serdes speed

local function calculate_lane_and_serdes_speed(count, speed)

local serdes = 0
local lane_speed = 0

if count == 0 or speed == 0 then
logit("Invalid number of lanes or speed")
return 0, 0
end

-- check serdes_cnt if it is a multiple of speed
local serdes_cnt = math.fmod(speed, count)

if serdes_cnt ~= 0 then
logit("Invalid speed and number of lanes combination")
return 0, 0
end

lane_speed = math.floor(speed / count)

-- return value in bits
if lane_speed == 1000 then
serdes = 1.25e+9
elseif lane_speed == 10000 then
serdes = 10.3125e+9
elseif lane_speed == 25000 then
serdes = 25.78125e+9
elseif lane_speed == 50000 then
serdes = 53.125e+9
elseif lane_speed == 100000 then
serdes = 106.25e+9
else
logit("Invalid serdes speed")
end

return lane_speed, serdes
end

-- look up interface lanes count, lanes speed & serdes speed
-- return lane count, lane speed, serdes speed

local function find_lanes_and_serdes(interface_name)
-- get the port config from config db
local _
local serdes, lane_speed, count = 0, 0, 0

-- Get the port configure
redis.call('SELECT', appl_db)
local lanes = redis.call('HGET', appl_db_port ..':'..interface_name, 'lanes')

if lanes then
local speed = redis.call('HGET', appl_db_port ..':'..interface_name, 'speed')

-- we were spliting it on ','
_, count = string.gsub(lanes, ",", ",")
count = count + 1

lane_speed, serdes = calculate_lane_and_serdes_speed(count, speed)

end
-- switch back to counter db
redis.call('SELECT', counters_db)

return count, lane_speed, serdes
end

local function compute_rate(port)

local state_table = rates_table_name .. ':' .. port .. ':' .. 'PORT'
local initialized = redis.call('HGET', state_table, 'INIT_DONE')
logit(initialized)

-- FEC BER
local fec_corr_bits, fec_uncorr_frames
local fec_corr_bits_ber_new, fec_uncorr_bits_ber_new = -1, -1
-- HLD review suggest to use the statistical average when calculate the post fec ber
local rs_average_frame_ber = 1e-8
local lanes_speed, serdes_speed, lanes_count = 0, 0, 0

-- lookup interface name from oid
local interface_name = find_interface_name_from_oid(port)
if interface_name then
lanes_count, lanes_speed, serdes_speed = find_lanes_and_serdes(interface_name)

if lanes_count and serdes_speed then
fec_corr_bits = redis.call('HGET', counters_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_IN_FEC_CORRECTED_BITS')
fec_uncorr_frames = redis.call('HGET', counters_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES')
end
end


-- Get new COUNTERS values
local in_ucast_pkts = redis.call('HGET', counters_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_IN_UCAST_PKTS')
local in_non_ucast_pkts = redis.call('HGET', counters_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS')
Expand All @@ -58,10 +167,11 @@ local function compute_rate(port)
local out_octets_last = redis.call('HGET', rates_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_OUT_OCTETS_last')

-- Calculate new rates values
local rx_bps_new = (in_octets - in_octets_last) / delta * 1000
local tx_bps_new = (out_octets - out_octets_last) / delta * 1000
local rx_pps_new = ((in_ucast_pkts + in_non_ucast_pkts) - (in_ucast_pkts_last + in_non_ucast_pkts_last)) / delta * 1000
local tx_pps_new = ((out_ucast_pkts + out_non_ucast_pkts) - (out_ucast_pkts_last + out_non_ucast_pkts_last)) / delta * 1000
local scale_factor = 1000 / delta
local rx_bps_new = (in_octets - in_octets_last) * scale_factor
local tx_bps_new = (out_octets - out_octets_last) * scale_factor
local rx_pps_new = ((in_ucast_pkts + in_non_ucast_pkts) - (in_ucast_pkts_last + in_non_ucast_pkts_last)) * scale_factor
local tx_pps_new = ((out_ucast_pkts + out_non_ucast_pkts) - (out_ucast_pkts_last + out_non_ucast_pkts_last)) * scale_factor

if initialized == "DONE" then
-- Get old rates values
Expand All @@ -83,6 +193,21 @@ local function compute_rate(port)
redis.call('HSET', rates_table_name .. ':' .. port, 'TX_PPS', tx_pps_new)
redis.call('HSET', state_table, 'INIT_DONE', 'DONE')
end

-- only do the calculation when all info present

if fec_corr_bits and fec_uncorr_frames and lanes_count and serdes_speed then
local fec_corr_bits_last = redis.call('HGET', rates_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_FEC_CORRECTED_BITS_last')
local fec_uncorr_frames_last = redis.call('HGET', rates_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_FEC_NOT_CORRECTABLE_FARMES_last')

local serdes_rate_total = lanes_count * serdes_speed * delta / 1000

fec_corr_bits_ber_new = (fec_corr_bits - fec_corr_bits_last) / serdes_rate_total
fec_uncorr_bits_ber_new = (fec_uncorr_frames - fec_uncorr_frames_last) * rs_average_frame_ber / serdes_rate_total
else
logit("FEC counters or lane info not found on " .. port)
end

else
redis.call('HSET', state_table, 'INIT_DONE', 'COUNTERS_LAST')
end
Expand All @@ -94,6 +219,19 @@ local function compute_rate(port)
redis.call('HSET', rates_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS_last', out_non_ucast_pkts)
redis.call('HSET', rates_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_IN_OCTETS_last', in_octets)
redis.call('HSET', rates_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_OUT_OCTETS_last', out_octets)

-- do not update FEC related stat if we dont have it

if not fec_corr_bits or not fec_uncorr_frames or not fec_corr_bits_ber_new or
not fec_uncorr_bits_ber_new then
logit("FEC counters not found on " .. port)
return
end
-- Set BER values
redis.call('HSET', rates_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_FEC_CORRECTED_BITS_last', fec_corr_bits)
redis.call('HSET', rates_table_name .. ':' .. port, 'SAI_PORT_STAT_IF_FEC_NOT_CORRECTABLE_FARMES_last', fec_uncorr_frames)
redis.call('HSET', rates_table_name .. ':' .. port, 'FEC_PRE_BER', fec_corr_bits_ber_new)
redis.call('HSET', rates_table_name .. ':' .. port, 'FEC_POST_BER', fec_uncorr_bits_ber_new)
end

local n = table.getn(KEYS)
Expand Down
40 changes: 38 additions & 2 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3570,6 +3570,12 @@ bool PortsOrch::initPort(const PortConfig &port)
m_recircPortRole[alias] = role;
}

// We have to test the size of m_queue_ids here since it isn't initialized on some platforms (like DPU)
if (p.m_host_tx_queue_configured && p.m_queue_ids.size() > p.m_host_tx_queue)
{
createPortBufferQueueCounters(p, to_string(p.m_host_tx_queue), false);
}

SWSS_LOG_NOTICE("Initialized port %s", alias.c_str());
}
else
Expand Down Expand Up @@ -3600,6 +3606,11 @@ void PortsOrch::deInitPort(string alias, sai_object_id_t port_id)
return;
}

if (p.m_host_tx_queue_configured && p.m_queue_ids.size() > p.m_host_tx_queue)
{
removePortBufferQueueCounters(p, to_string(p.m_host_tx_queue), false);
}

/* remove port from flex_counter_table for updating counters */
auto flex_counters_orch = gDirectory.get<FlexCounterOrch*>();
if ((flex_counters_orch->getPortCountersState()))
Expand Down Expand Up @@ -6013,6 +6024,9 @@ bool PortsOrch::addHostIntfs(Port &port, string alias, sai_object_id_t &host_int
attr.id = SAI_HOSTIF_ATTR_QUEUE;
attr.value.u32 = DEFAULT_HOSTIF_TX_QUEUE;
attrs.push_back(attr);

port.m_host_tx_queue = DEFAULT_HOSTIF_TX_QUEUE;
port.m_host_tx_queue_configured = true;
}

sai_status_t status = sai_hostif_api->create_hostif(&host_intfs_id, gSwitchId, (uint32_t)attrs.size(), attrs.data());
Expand Down Expand Up @@ -7320,6 +7334,10 @@ void PortsOrch::generateQueueMap(map<string, FlexCounterQueueStates> queuesState
{
flexCounterQueueState.enableQueueCounters(0, maxQueueNumber - 1);
}
else if (it.second.m_host_tx_queue_configured && it.second.m_host_tx_queue <= maxQueueNumber)
{
flexCounterQueueState.enableQueueCounters(it.second.m_host_tx_queue, it.second.m_host_tx_queue);
}
queuesStateVector.insert(make_pair(it.second.m_alias, flexCounterQueueState));
}
generateQueueMapPerPort(it.second, queuesStateVector.at(it.second.m_alias), false);
Expand Down Expand Up @@ -7458,6 +7476,10 @@ void PortsOrch::addQueueFlexCounters(map<string, FlexCounterQueueStates> queuesS
{
flexCounterQueueState.enableQueueCounters(0, maxQueueNumber - 1);
}
else if (it.second.m_host_tx_queue_configured && it.second.m_host_tx_queue <= maxQueueNumber)
{
flexCounterQueueState.enableQueueCounters(it.second.m_host_tx_queue, it.second.m_host_tx_queue);
}
queuesStateVector.insert(make_pair(it.second.m_alias, flexCounterQueueState));
}
addQueueFlexCountersPerPort(it.second, queuesStateVector.at(it.second.m_alias));
Expand Down Expand Up @@ -7539,6 +7561,10 @@ void PortsOrch::addQueueWatermarkFlexCounters(map<string, FlexCounterQueueStates
{
flexCounterQueueState.enableQueueCounters(0, maxQueueNumber - 1);
}
else if (it.second.m_host_tx_queue_configured && it.second.m_host_tx_queue <= maxQueueNumber)
{
flexCounterQueueState.enableQueueCounters(it.second.m_host_tx_queue, it.second.m_host_tx_queue);
}
queuesStateVector.insert(make_pair(it.second.m_alias, flexCounterQueueState));
}
addQueueWatermarkFlexCountersPerPort(it.second, queuesStateVector.at(it.second.m_alias));
Expand Down Expand Up @@ -7586,7 +7612,7 @@ void PortsOrch::addQueueWatermarkFlexCountersPerPortPerQueueIndex(const Port& po
startFlexCounterPolling(gSwitchId, key, counters_str, QUEUE_COUNTER_ID_LIST);
}

void PortsOrch::createPortBufferQueueCounters(const Port &port, string queues)
void PortsOrch::createPortBufferQueueCounters(const Port &port, string queues, bool skip_host_tx_queue)
{
SWSS_LOG_ENTER();

Expand All @@ -7606,6 +7632,11 @@ void PortsOrch::createPortBufferQueueCounters(const Port &port, string queues)

for (auto queueIndex = startIndex; queueIndex <= endIndex; queueIndex++)
{
if (queueIndex == (uint32_t)port.m_host_tx_queue && skip_host_tx_queue)
{
continue;
}

std::ostringstream name;
name << port.m_alias << ":" << queueIndex;

Expand Down Expand Up @@ -7643,7 +7674,7 @@ void PortsOrch::createPortBufferQueueCounters(const Port &port, string queues)
CounterCheckOrch::getInstance().addPort(port);
}

void PortsOrch::removePortBufferQueueCounters(const Port &port, string queues)
void PortsOrch::removePortBufferQueueCounters(const Port &port, string queues, bool skip_host_tx_queue)
{
SWSS_LOG_ENTER();

Expand All @@ -7659,6 +7690,11 @@ void PortsOrch::removePortBufferQueueCounters(const Port &port, string queues)

for (auto queueIndex = startIndex; queueIndex <= endIndex; queueIndex++)
{
if (queueIndex == (uint32_t)port.m_host_tx_queue && skip_host_tx_queue)
{
continue;
}

std::ostringstream name;
name << port.m_alias << ":" << queueIndex;
const auto id = sai_serialize_object_id(port.m_queue_ids[queueIndex]);
Expand Down
4 changes: 2 additions & 2 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ class PortsOrch : public Orch, public Subject

void generateQueueMap(map<string, FlexCounterQueueStates> queuesStateVector);
uint32_t getNumberOfPortSupportedQueueCounters(string port);
void createPortBufferQueueCounters(const Port &port, string queues);
void removePortBufferQueueCounters(const Port &port, string queues);
void createPortBufferQueueCounters(const Port &port, string queues, bool skip_host_tx_queue=true);
void removePortBufferQueueCounters(const Port &port, string queues, bool skip_host_tx_queue=true);
void addQueueFlexCounters(map<string, FlexCounterQueueStates> queuesStateVector);
void addQueueWatermarkFlexCounters(map<string, FlexCounterQueueStates> queuesStateVector);

Expand Down
Loading

0 comments on commit e12d545

Please sign in to comment.