Skip to content

Commit 8f82786

Browse files
venkatmahalingamraphaelt-nvidia
authored andcommitted
Fix sFlow sampling-rate and admin-state (sonic-net#1728)
* Fixed incorrect interface admin-status when 'all' interface is disabled but there are local sampling-rate configurations. Signed-off-by: Venkatesan Mahalingam <[email protected]>
1 parent 8f62c92 commit 8f82786

File tree

3 files changed

+108
-16
lines changed

3 files changed

+108
-16
lines changed

cfgmgr/sflowmgr.cpp

+34-15
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer)
8383
if (sflowPortConf == m_sflowPortConfMap.end())
8484
{
8585
new_port = true;
86-
port_info.local_conf = false;
86+
port_info.local_rate_cfg = false;
87+
port_info.local_admin_cfg = false;
8788
port_info.speed = SFLOW_ERROR_SPEED_STR;
8889
port_info.rate = "";
8990
port_info.admin = "";
@@ -107,8 +108,8 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer)
107108

108109
if (m_gEnable && m_intfAllConf)
109110
{
110-
// If the Local Conf is already present, dont't override it even though the speed is changed
111-
if (new_port || (speed_change && !m_sflowPortConfMap[key].local_conf))
111+
// If the Local rate Conf is already present, dont't override it even though the speed is changed
112+
if (new_port || (speed_change && !m_sflowPortConfMap[key].local_rate_cfg))
112113
{
113114
vector<FieldValueTuple> fvs;
114115
sflowGetGlobalInfo(fvs, m_sflowPortConfMap[key].speed);
@@ -121,7 +122,8 @@ void SflowMgr::sflowUpdatePortInfo(Consumer &consumer)
121122
auto sflowPortConf = m_sflowPortConfMap.find(key);
122123
if (sflowPortConf != m_sflowPortConfMap.end())
123124
{
124-
bool local_cfg = m_sflowPortConfMap[key].local_conf;
125+
bool local_cfg = m_sflowPortConfMap[key].local_rate_cfg ||
126+
m_sflowPortConfMap[key].local_admin_cfg;
125127

126128
m_sflowPortConfMap.erase(key);
127129
if ((m_intfAllConf && m_gEnable) || local_cfg)
@@ -138,18 +140,27 @@ void SflowMgr::sflowHandleSessionAll(bool enable)
138140
{
139141
for (auto it: m_sflowPortConfMap)
140142
{
141-
if (!it.second.local_conf)
143+
if (enable)
142144
{
143145
vector<FieldValueTuple> fvs;
144-
sflowGetGlobalInfo(fvs, it.second.speed);
145-
if (enable)
146+
if (it.second.local_rate_cfg || it.second.local_admin_cfg)
146147
{
147-
m_appSflowSessionTable.set(it.first, fvs);
148+
sflowGetPortInfo(fvs, it.second);
149+
/* Use global admin state if there is not a local one */
150+
if (!it.second.local_admin_cfg) {
151+
FieldValueTuple fv1("admin_state", "up");
152+
fvs.push_back(fv1);
153+
}
148154
}
149155
else
150156
{
151-
m_appSflowSessionTable.del(it.first);
157+
sflowGetGlobalInfo(fvs, it.second.speed);
152158
}
159+
m_appSflowSessionTable.set(it.first, fvs);
160+
}
161+
else if (!it.second.local_admin_cfg)
162+
{
163+
m_appSflowSessionTable.del(it.first);
153164
}
154165
}
155166
}
@@ -158,7 +169,7 @@ void SflowMgr::sflowHandleSessionLocal(bool enable)
158169
{
159170
for (auto it: m_sflowPortConfMap)
160171
{
161-
if (it.second.local_conf)
172+
if (it.second.local_admin_cfg || it.second.local_rate_cfg)
162173
{
163174
vector<FieldValueTuple> fvs;
164175
sflowGetPortInfo(fvs, it.second);
@@ -194,7 +205,7 @@ void SflowMgr::sflowGetGlobalInfo(vector<FieldValueTuple> &fvs, string speed)
194205

195206
void SflowMgr::sflowGetPortInfo(vector<FieldValueTuple> &fvs, SflowPortInfo &local_info)
196207
{
197-
if (local_info.admin.length() > 0)
208+
if (local_info.local_admin_cfg)
198209
{
199210
FieldValueTuple fv1("admin_state", local_info.admin);
200211
fvs.push_back(fv1);
@@ -217,13 +228,15 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va
217228
{
218229
rate_present = true;
219230
m_sflowPortConfMap[alias].rate = fvValue(i);
231+
m_sflowPortConfMap[alias].local_rate_cfg = true;
220232
FieldValueTuple fv(fvField(i), fvValue(i));
221233
fvs.push_back(fv);
222234
}
223235
if (fvField(i) == "admin_state")
224236
{
225237
admin_present = true;
226238
m_sflowPortConfMap[alias].admin = fvValue(i);
239+
m_sflowPortConfMap[alias].local_admin_cfg = true;
227240
FieldValueTuple fv(fvField(i), fvValue(i));
228241
fvs.push_back(fv);
229242
}
@@ -235,7 +248,11 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va
235248

236249
if (!rate_present)
237250
{
238-
if (m_sflowPortConfMap[alias].rate == "")
251+
/* Go back to default sample-rate if there is not existing rate OR
252+
* if a local config has been done but the rate has been removed
253+
*/
254+
if (m_sflowPortConfMap[alias].rate == "" ||
255+
m_sflowPortConfMap[alias].local_rate_cfg)
239256
{
240257
string speed = m_sflowPortConfMap[alias].speed;
241258

@@ -249,6 +266,7 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va
249266
}
250267
m_sflowPortConfMap[alias].rate = rate;
251268
}
269+
m_sflowPortConfMap[alias].local_rate_cfg = false;
252270
FieldValueTuple fv("sample_rate", m_sflowPortConfMap[alias].rate);
253271
fvs.push_back(fv);
254272
}
@@ -257,9 +275,10 @@ void SflowMgr::sflowCheckAndFillValues(string alias, vector<FieldValueTuple> &va
257275
{
258276
if (m_sflowPortConfMap[alias].admin == "")
259277
{
260-
/* By default admin state is enable if not set explicitly */
278+
/* By default admin state is enabled if not set explicitly */
261279
m_sflowPortConfMap[alias].admin = "up";
262280
}
281+
m_sflowPortConfMap[alias].local_admin_cfg = false;
263282
FieldValueTuple fv("admin_state", m_sflowPortConfMap[alias].admin);
264283
fvs.push_back(fv);
265284
}
@@ -347,7 +366,6 @@ void SflowMgr::doTask(Consumer &consumer)
347366
}
348367
vector<FieldValueTuple> fvs;
349368
sflowCheckAndFillValues(key, values, fvs);
350-
m_sflowPortConfMap[key].local_conf = true;
351369
if (m_gEnable)
352370
{
353371
m_appSflowSessionTable.set(key, fvs);
@@ -384,7 +402,8 @@ void SflowMgr::doTask(Consumer &consumer)
384402
else
385403
{
386404
m_appSflowSessionTable.del(key);
387-
m_sflowPortConfMap[key].local_conf = false;
405+
m_sflowPortConfMap[key].local_rate_cfg = false;
406+
m_sflowPortConfMap[key].local_admin_cfg = false;
388407
m_sflowPortConfMap[key].rate = "";
389408
m_sflowPortConfMap[key].admin = "";
390409

cfgmgr/sflowmgr.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ namespace swss {
3232

3333
struct SflowPortInfo
3434
{
35-
bool local_conf;
35+
bool local_rate_cfg;
36+
bool local_admin_cfg;
3637
std::string speed;
3738
std::string rate;
3839
std::string admin;

tests/test_sflow.py

+72
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import time
2+
from swsscommon import swsscommon
23

34
class TestSflow:
45
speed_rate_table = {
@@ -175,7 +176,78 @@ def test_SamplingRateManualUpdate(self, dvs, testlog):
175176
time.sleep(1)
176177
appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet4", {"sample_rate": "256"})
177178

179+
def test_InterfaceDisableAllUpdate(self, dvs, testlog):
180+
'''
181+
This test checks if the SflowMgr updates sflow session table in APPL_DB when user has not configured the admin_status.
182+
Steps to verify the issue:
183+
1) Enable sflow globally
184+
2) Configure sample rate for Ethernet0
185+
3) Configure sample rate for Ethernet4
186+
4) verify whether sample rates are reflected in the Ethernet0 & Ethernet4 interfaces
187+
5) Execute sflow disable all command to disable all interfaces
188+
6) Verify whether all interfaces are disabled (without the fix, interfaces were shown with admin up with configured rate,
189+
this is not expected).
190+
'''
191+
self.setup_sflow(dvs)
192+
193+
appldb = dvs.get_app_db()
194+
# create the interface session
195+
session_params = {"sample_rate": "256"}
196+
self.cdb.create_entry("SFLOW_SESSION", "Ethernet0", session_params)
197+
expected_fields = {"sample_rate": "256"}
198+
appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields)
199+
200+
session_params = {"sample_rate": "512"}
201+
self.cdb.create_entry("SFLOW_SESSION", "Ethernet4", session_params)
202+
expected_fields = {"sample_rate": "512"}
203+
appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet4", expected_fields)
178204

205+
session_params = {"admin_state": "down"}
206+
self.cdb.create_entry("SFLOW_SESSION", "all", session_params)
207+
# Wait for the APPL_DB from sflowmgrd
208+
expected_fields = {}
209+
appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields)
210+
appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet4", expected_fields)
211+
212+
self.cdb.delete_entry("SFLOW_SESSION", "all")
213+
self.cdb.delete_entry("SFLOW_SESSION", "Ethernet0")
214+
self.cdb.delete_entry("SFLOW_SESSION", "Ethernet4")
215+
216+
def test_InterfaceDefaultSampleRate(self, dvs, testlog):
217+
'''
218+
This test checks if the SflowMgr updates sflow session table in APPL_DB with default rate.
219+
Steps to verify the issue:
220+
1) Enable sflow globally
221+
2) Configure sample rate for Ethernet0
222+
3) Verify whether sample rate is reflected in the Ethernet0 interfaces
223+
4) Remove sample rate for Ethernet0
224+
5) Verify whether sample rate of Ethernet0 interface moved to default sample rate
225+
'''
226+
self.setup_sflow(dvs)
227+
228+
port_oid = self.adb.port_name_map["Ethernet0"]
229+
expected_fields = {"SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE": "oid:0x0"}
230+
fvs = self.adb.wait_for_field_negative_match("ASIC_STATE:SAI_OBJECT_TYPE_PORT", port_oid, expected_fields)
231+
speed = fvs["SAI_PORT_ATTR_SPEED"]
232+
rate = self.speed_rate_table.get(speed, None)
233+
assert rate
234+
235+
appldb = dvs.get_app_db()
236+
# create the interface session
237+
session_params = {"sample_rate": "256"}
238+
self.cdb.create_entry("SFLOW_SESSION", "Ethernet0", session_params)
239+
expected_fields = {"admin_state": "up", "sample_rate": "256"}
240+
appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields)
241+
242+
cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0)
243+
tbl = swsscommon.Table(cdb, "SFLOW_SESSION")
244+
tbl.hdel("Ethernet0","sample_rate")
245+
246+
expected_fields = {"admin_state": "up", "sample_rate": rate}
247+
appldb.wait_for_field_match("SFLOW_SESSION_TABLE", "Ethernet0", expected_fields)
248+
249+
self.cdb.delete_entry("SFLOW_SESSION", "Ethernet0")
250+
179251
def test_Teardown(self, dvs, testlog):
180252
self.setup_sflow(dvs)
181253

0 commit comments

Comments
 (0)