1313local counters_db = ARGV [1 ]
1414local counters_table_name = ARGV [2 ]
1515local rates_table_name = " RATES"
16+ local appl_db_port = " PORT_TABLE"
17+ -- refer back to common/schema.h
18+ local appl_db = " 0"
1619
1720-- Get configuration
1821redis .call (' SELECT' , counters_db )
@@ -29,11 +32,117 @@ logit(alpha)
2932logit (one_minus_alpha )
3033logit (delta )
3134
35+ local port_interface_oid_map = redis .call (' HGETALL' , " COUNTERS_PORT_NAME_MAP" )
36+ local port_interface_oid_key_count = redis .call (' HLEN' , " COUNTERS_PORT_NAME_MAP" )
37+
38+ -- lookup interface name from port oid
39+
40+ local function find_interface_name_from_oid (port )
41+
42+ for i = 1 , port_interface_oid_key_count do
43+ local index = i * 2 - 1
44+ if port_interface_oid_map [index + 1 ] == port then
45+ return port_interface_oid_map [index ]
46+ end
47+ end
48+
49+ return 0
50+ end
51+
52+ -- calculate lanes and serdes speed from interface lane count & speed
53+ -- return lane speed and serdes speed
54+
55+ local function calculate_lane_and_serdes_speed (count , speed )
56+
57+ local serdes = 0
58+ local lane_speed = 0
59+
60+ if count == 0 or speed == 0 then
61+ logit (" Invalid number of lanes or speed" )
62+ return 0 , 0
63+ end
64+
65+ -- check serdes_cnt if it is a multiple of speed
66+ local serdes_cnt = math.fmod (speed , count )
67+
68+ if serdes_cnt ~= 0 then
69+ logit (" Invalid speed and number of lanes combination" )
70+ return 0 , 0
71+ end
72+
73+ lane_speed = math.floor (speed / count )
74+
75+ -- return value in bits
76+ if lane_speed == 1000 then
77+ serdes = 1.25e + 9
78+ elseif lane_speed == 10000 then
79+ serdes = 10.3125e + 9
80+ elseif lane_speed == 25000 then
81+ serdes = 25.78125e + 9
82+ elseif lane_speed == 50000 then
83+ serdes = 53.125e + 9
84+ elseif lane_speed == 100000 then
85+ serdes = 106.25e + 9
86+ else
87+ logit (" Invalid serdes speed" )
88+ end
89+
90+ return lane_speed , serdes
91+ end
92+
93+ -- look up interface lanes count, lanes speed & serdes speed
94+ -- return lane count, lane speed, serdes speed
95+
96+ local function find_lanes_and_serdes (interface_name )
97+ -- get the port config from config db
98+ local _
99+ local serdes , lane_speed , count = 0 , 0 , 0
100+
101+ -- Get the port configure
102+ redis .call (' SELECT' , appl_db )
103+ local lanes = redis .call (' HGET' , appl_db_port .. ' :' .. interface_name , ' lanes' )
104+
105+ if lanes then
106+ local speed = redis .call (' HGET' , appl_db_port .. ' :' .. interface_name , ' speed' )
107+
108+ -- we were spliting it on ','
109+ _ , count = string.gsub (lanes , " ," , " ," )
110+ count = count + 1
111+
112+ lane_speed , serdes = calculate_lane_and_serdes_speed (count , speed )
113+
114+ end
115+ -- switch back to counter db
116+ redis .call (' SELECT' , counters_db )
117+
118+ return count , lane_speed , serdes
119+ end
120+
32121local function compute_rate (port )
122+
33123 local state_table = rates_table_name .. ' :' .. port .. ' :' .. ' PORT'
34124 local initialized = redis .call (' HGET' , state_table , ' INIT_DONE' )
35125 logit (initialized )
36126
127+ -- FEC BER
128+ local fec_corr_bits , fec_uncorr_frames
129+ local fec_corr_bits_ber_new , fec_uncorr_bits_ber_new = - 1 , - 1
130+ -- HLD review suggest to use the statistical average when calculate the post fec ber
131+ local rs_average_frame_ber = 1e-8
132+ local lanes_speed , serdes_speed , lanes_count = 0 , 0 , 0
133+
134+ -- lookup interface name from oid
135+ local interface_name = find_interface_name_from_oid (port )
136+ if interface_name then
137+ lanes_count , lanes_speed , serdes_speed = find_lanes_and_serdes (interface_name )
138+
139+ if lanes_count and serdes_speed then
140+ fec_corr_bits = redis .call (' HGET' , counters_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_IN_FEC_CORRECTED_BITS' )
141+ fec_uncorr_frames = redis .call (' HGET' , counters_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_IN_FEC_NOT_CORRECTABLE_FRAMES' )
142+ end
143+ end
144+
145+
37146 -- Get new COUNTERS values
38147 local in_ucast_pkts = redis .call (' HGET' , counters_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_IN_UCAST_PKTS' )
39148 local in_non_ucast_pkts = redis .call (' HGET' , counters_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS' )
@@ -58,10 +167,11 @@ local function compute_rate(port)
58167 local out_octets_last = redis .call (' HGET' , rates_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_OUT_OCTETS_last' )
59168
60169 -- Calculate new rates values
61- local rx_bps_new = (in_octets - in_octets_last ) / delta * 1000
62- local tx_bps_new = (out_octets - out_octets_last ) / delta * 1000
63- local rx_pps_new = ((in_ucast_pkts + in_non_ucast_pkts ) - (in_ucast_pkts_last + in_non_ucast_pkts_last )) / delta * 1000
64- local tx_pps_new = ((out_ucast_pkts + out_non_ucast_pkts ) - (out_ucast_pkts_last + out_non_ucast_pkts_last )) / delta * 1000
170+ local scale_factor = 1000 / delta
171+ local rx_bps_new = (in_octets - in_octets_last ) * scale_factor
172+ local tx_bps_new = (out_octets - out_octets_last ) * scale_factor
173+ local rx_pps_new = ((in_ucast_pkts + in_non_ucast_pkts ) - (in_ucast_pkts_last + in_non_ucast_pkts_last )) * scale_factor
174+ local tx_pps_new = ((out_ucast_pkts + out_non_ucast_pkts ) - (out_ucast_pkts_last + out_non_ucast_pkts_last )) * scale_factor
65175
66176 if initialized == " DONE" then
67177 -- Get old rates values
@@ -83,6 +193,21 @@ local function compute_rate(port)
83193 redis .call (' HSET' , rates_table_name .. ' :' .. port , ' TX_PPS' , tx_pps_new )
84194 redis .call (' HSET' , state_table , ' INIT_DONE' , ' DONE' )
85195 end
196+
197+ -- only do the calculation when all info present
198+
199+ if fec_corr_bits and fec_uncorr_frames and lanes_count and serdes_speed then
200+ local fec_corr_bits_last = redis .call (' HGET' , rates_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_FEC_CORRECTED_BITS_last' )
201+ local fec_uncorr_frames_last = redis .call (' HGET' , rates_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_FEC_NOT_CORRECTABLE_FARMES_last' )
202+
203+ local serdes_rate_total = lanes_count * serdes_speed * delta / 1000
204+
205+ fec_corr_bits_ber_new = (fec_corr_bits - fec_corr_bits_last ) / serdes_rate_total
206+ fec_uncorr_bits_ber_new = (fec_uncorr_frames - fec_uncorr_frames_last ) * rs_average_frame_ber / serdes_rate_total
207+ else
208+ logit (" FEC counters or lane info not found on " .. port )
209+ end
210+
86211 else
87212 redis .call (' HSET' , state_table , ' INIT_DONE' , ' COUNTERS_LAST' )
88213 end
@@ -94,6 +219,19 @@ local function compute_rate(port)
94219 redis .call (' HSET' , rates_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS_last' , out_non_ucast_pkts )
95220 redis .call (' HSET' , rates_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_IN_OCTETS_last' , in_octets )
96221 redis .call (' HSET' , rates_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_OUT_OCTETS_last' , out_octets )
222+
223+ -- do not update FEC related stat if we dont have it
224+
225+ if not fec_corr_bits or not fec_uncorr_frames or not fec_corr_bits_ber_new or
226+ not fec_uncorr_bits_ber_new then
227+ logit (" FEC counters not found on " .. port )
228+ return
229+ end
230+ -- Set BER values
231+ redis .call (' HSET' , rates_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_FEC_CORRECTED_BITS_last' , fec_corr_bits )
232+ redis .call (' HSET' , rates_table_name .. ' :' .. port , ' SAI_PORT_STAT_IF_FEC_NOT_CORRECTABLE_FARMES_last' , fec_uncorr_frames )
233+ redis .call (' HSET' , rates_table_name .. ' :' .. port , ' FEC_PRE_BER' , fec_corr_bits_ber_new )
234+ redis .call (' HSET' , rates_table_name .. ' :' .. port , ' FEC_POST_BER' , fec_uncorr_bits_ber_new )
97235end
98236
99237local n = table .getn (KEYS )
0 commit comments