Skip to content

Commit e2d4a6b

Browse files
committed
Merge branch 'vrrp_orch' of https://github.com/vvbrcm/sonic-swss-vrrporchd into vrrp_orch
2 parents c165830 + cdb0e68 commit e2d4a6b

File tree

11 files changed

+153
-21
lines changed

11 files changed

+153
-21
lines changed

cfgmgr/buffer_check_headroom_mellanox.lua

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
-- KEYS - port name
22
-- ARGV[1] - profile name
33
-- ARGV[2] - new size
4-
-- ARGV[3] - pg to add
4+
-- ARGV[3] - new xon
5+
-- ARGV[4] - new xoff
6+
-- ARGV[5] - pg to add
57

68
local port = KEYS[1]
79
local input_profile_name = ARGV[1]
810
local input_profile_size = tonumber(ARGV[2])
9-
local new_pg = ARGV[3]
11+
local input_profile_xon = tonumber(ARGV[3])
12+
local input_profile_xoff = tonumber(ARGV[4])
13+
local new_pg = ARGV[5]
1014

1115
local function is_port_with_8lanes(lanes)
1216
-- On Spectrum 3, ports with 8 lanes have doubled pipeline latency
@@ -55,17 +59,31 @@ end
5559

5660
local asic_keys = redis.call('KEYS', 'ASIC_TABLE*')
5761
local pipeline_latency = tonumber(redis.call('HGET', asic_keys[1], 'pipeline_latency'))
62+
local cell_size = tonumber(redis.call('HGET', asic_keys[1], 'cell_size'))
63+
local port_reserved_shp = tonumber(redis.call('HGET', asic_keys[1], 'port_reserved_shp'))
64+
local port_max_shp = tonumber(redis.call('HGET', asic_keys[1], 'port_max_shp'))
5865
if is_port_with_8lanes(lanes) then
5966
-- The pipeline latency should be adjusted accordingly for ports with 2 buffer units
6067
pipeline_latency = pipeline_latency * 2 - 1
6168
egress_mirror_size = egress_mirror_size * 2
69+
port_reserved_shp = port_reserved_shp * 2
6270
end
71+
6372
local lossy_pg_size = pipeline_latency * 1024
6473
accumulative_size = accumulative_size + lossy_pg_size + egress_mirror_size
6574

6675
-- Fetch all keys in BUFFER_PG according to the port
6776
redis.call('SELECT', appl_db)
6877

78+
local is_shp_enabled
79+
local shp_size = tonumber(redis.call('HGET', 'BUFFER_POOL_TABLE:ingress_lossless_pool', 'xoff'))
80+
if shp_size == nil or shp_size == 0 then
81+
is_shp_enabled = false
82+
else
83+
is_shp_enabled = true
84+
end
85+
local accumulative_shared_headroom = 0
86+
6987
local debuginfo = {}
7088

7189
local function get_number_of_pgs(keyname)
@@ -122,26 +140,50 @@ end
122140
table.insert(debuginfo, 'debug:other overhead:' .. accumulative_size)
123141
for pg_key, profile in pairs(all_pgs) do
124142
local current_profile_size
143+
local current_profile_xon
144+
local current_profile_xoff
145+
local buffer_profile_table_name = 'BUFFER_PROFILE_TABLE:'
125146
if profile ~= input_profile_name then
126-
local referenced_profile_size = redis.call('HGET', 'BUFFER_PROFILE_TABLE:' .. profile, 'size')
147+
local referenced_profile_size = redis.call('HGET', buffer_profile_table_name .. profile, 'size')
127148
if not referenced_profile_size then
128-
referenced_profile_size = redis.call('HGET', '_BUFFER_PROFILE_TABLE:' .. profile, 'size')
149+
buffer_profile_table_name = '_BUFFER_PROFILE_TABLE:'
150+
referenced_profile_size = redis.call('HGET', buffer_profile_table_name .. profile, 'size')
129151
table.insert(debuginfo, 'debug:pending profile: ' .. profile)
130152
end
131153
current_profile_size = tonumber(referenced_profile_size)
154+
current_profile_xon = tonumber(redis.call('HGET', buffer_profile_table_name .. profile, 'xon'))
155+
current_profile_xoff = tonumber(redis.call('HGET', buffer_profile_table_name .. profile, 'xoff'))
132156
else
133157
current_profile_size = input_profile_size
158+
current_profile_xon = input_profile_xon
159+
current_profile_xoff = input_profile_xoff
134160
end
135161
if current_profile_size == 0 then
136162
current_profile_size = lossy_pg_size
137163
end
138164
accumulative_size = accumulative_size + current_profile_size * get_number_of_pgs(pg_key)
139-
table.insert(debuginfo, 'debug:' .. pg_key .. ':' .. profile .. ':' .. current_profile_size .. ':' .. get_number_of_pgs(pg_key) .. ':accu:' .. accumulative_size)
165+
166+
if is_shp_enabled and current_profile_xon and current_profile_xoff then
167+
if current_profile_size < current_profile_xon + current_profile_xoff then
168+
accumulative_shared_headroom = accumulative_shared_headroom + (current_profile_xon + current_profile_xoff - current_profile_size) * get_number_of_pgs(pg_key)
169+
end
170+
end
171+
table.insert(debuginfo, 'debug:' .. pg_key .. ':' .. profile .. ':' .. current_profile_size .. ':' .. get_number_of_pgs(pg_key) .. ':accu:' .. accumulative_size .. ':accu_shp:' .. accumulative_shared_headroom)
140172
end
141173

142174
if max_headroom_size > accumulative_size then
143-
table.insert(ret, "result:true")
144-
table.insert(ret, "debug:Accumulative headroom on port " .. accumulative_size .. ", the maximum available headroom " .. max_headroom_size)
175+
if is_shp_enabled then
176+
local max_shp = (port_max_shp + port_reserved_shp) * cell_size
177+
if accumulative_shared_headroom > max_shp then
178+
table.insert(ret, "result:false")
179+
else
180+
table.insert(ret, "result:true")
181+
end
182+
table.insert(ret, "debug:Accumulative headroom on port " .. accumulative_size .. ", the maximum available headroom " .. max_headroom_size .. ", the port SHP " .. accumulative_shared_headroom .. ", max SHP " .. max_shp)
183+
else
184+
table.insert(ret, "result:true")
185+
table.insert(ret, "debug:Accumulative headroom on port " .. accumulative_size .. ", the maximum available headroom " .. max_headroom_size)
186+
end
145187
else
146188
table.insert(ret, "result:false")
147189
table.insert(ret, "debug:Accumulative headroom on port " .. accumulative_size .. " exceeds the maximum available headroom which is " .. max_headroom_size)

cfgmgr/buffermgrdyn.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,14 +1056,16 @@ bool BufferMgrDynamic::isHeadroomResourceValid(const string &port, const buffer_
10561056

10571057
argv.emplace_back(profile.name);
10581058
argv.emplace_back(profile.size);
1059+
argv.emplace_back(profile.xon);
1060+
argv.emplace_back(profile.xoff);
10591061

10601062
if (!new_pg.empty())
10611063
{
10621064
argv.emplace_back(new_pg);
10631065
}
10641066

1065-
SWSS_LOG_INFO("Checking headroom for port %s with profile %s size %s pg %s",
1066-
port.c_str(), profile.name.c_str(), profile.size.c_str(), new_pg.c_str());
1067+
SWSS_LOG_INFO("Checking headroom for port %s with profile %s size %s xon %s xoff %s pg %s",
1068+
port.c_str(), profile.name.c_str(), profile.size.c_str(), profile.xon.c_str(), profile.xoff.c_str(), new_pg.c_str());
10671069

10681070
try
10691071
{

cfgmgr/portmgr.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,15 @@ void PortMgr::doTask(Consumer &consumer)
192192
}
193193
}
194194

195+
if (!portOk)
196+
{
197+
// Port configuration is handled by the orchagent. If the configuration is written to the APP DB using
198+
// multiple Redis write commands, the orchagent may receive a partial configuration and create a port
199+
// with incorrect settings.
200+
field_values.emplace_back("mtu", mtu);
201+
field_values.emplace_back("admin_status", admin_status);
202+
}
203+
195204
if (field_values.size())
196205
{
197206
writeConfigToAppDb(alias, field_values);
@@ -201,8 +210,6 @@ void PortMgr::doTask(Consumer &consumer)
201210
{
202211
SWSS_LOG_INFO("Port %s is not ready, pending...", alias.c_str());
203212

204-
writeConfigToAppDb(alias, "mtu", mtu);
205-
writeConfigToAppDb(alias, "admin_status", admin_status);
206213
/* Retry setting these params after the netdev is created */
207214
field_values.clear();
208215
field_values.emplace_back("mtu", mtu);

orchagent/orch.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,14 +242,12 @@ void Consumer::execute()
242242
// ConsumerBase::execute_impl<swss::ConsumerTableBase>();
243243
SWSS_LOG_ENTER();
244244

245-
size_t update_size = 0;
246245
auto table = static_cast<swss::ConsumerTableBase *>(getSelectable());
247-
do
248-
{
249-
std::deque<KeyOpFieldsValuesTuple> entries;
250-
table->pops(entries);
251-
update_size = addToSync(entries);
252-
} while (update_size != 0);
246+
std::deque<KeyOpFieldsValuesTuple> entries;
247+
table->pops(entries);
248+
249+
// add to sync
250+
addToSync(entries);
253251

254252
drain();
255253
}

tests/dash/dash_db.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from dvslib.dvs_common import wait_for_result
33
import typing
44
import pytest
5+
import time
56

67
from dash_api.appliance_pb2 import *
78
from dash_api.vnet_pb2 import *
@@ -58,9 +59,11 @@ def __setitem__(self, key: str, pairs: typing.Union[dict, list, tuple]):
5859
for k, v in pairs:
5960
pairs_str.append((to_string(k), to_string(v)))
6061
self.set(key, pairs_str)
62+
time.sleep(1)
6163

6264
def __delitem__(self, key: str):
6365
self.delete(str(key))
66+
time.sleep(1)
6467

6568

6669
class Table(swsscommon.Table):

tests/dash/test_dash_acl.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,12 @@ def __setitem__(self, key: str, pairs: Union[dict, list, tuple]):
8787
pairs_str.append((to_string(k), to_string(v)))
8888
self.table.set(key, pairs_str)
8989
self.keys.add(key)
90+
time.sleep(1)
9091

9192
def __delitem__(self, key: str):
9293
self.table.delete(str(key))
9394
self.keys.discard(key)
95+
time.sleep(1)
9496

9597
def get_keys(self):
9698
return self.keys

tests/dvslib/dvs_hash.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Utilities for interacting with HASH objects when writing VS tests."""
22
from typing import Dict, List
3+
import time
34

45

56
class DVSHash:
@@ -21,6 +22,7 @@ def update_switch_hash(
2122
) -> None:
2223
"""Update switch hash global in Config DB."""
2324
self.config_db.update_entry(self.CDB_SWITCH_HASH, self.KEY_SWITCH_HASH_GLOBAL, qualifiers)
25+
time.sleep(1)
2426

2527
def get_hash_ids(
2628
self,

tests/mock_tests/consumer_ut.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,25 @@ namespace consumer_test
1010
{
1111
using namespace std;
1212

13+
class TestOrch : public Orch
14+
{
15+
public:
16+
TestOrch(swss::DBConnector *db, string tableName)
17+
:Orch(db, tableName),
18+
m_notification_count(0)
19+
{
20+
}
21+
22+
void doTask(Consumer& consumer)
23+
{
24+
std::cout << "TestOrch::doTask " << consumer.m_toSync.size() << std::endl;
25+
m_notification_count += consumer.m_toSync.size();
26+
consumer.m_toSync.clear();
27+
}
28+
29+
long m_notification_count;
30+
};
31+
1332
struct ConsumerTest : public ::testing::Test
1433
{
1534
shared_ptr<swss::DBConnector> m_app_db;
@@ -322,4 +341,31 @@ namespace consumer_test
322341
validate_syncmap(consumer->m_toSync, 1, key, exp_kofv);
323342

324343
}
344+
345+
TEST_F(ConsumerTest, ConsumerPops_notification_count)
346+
{
347+
int consumer_pops_batch_size = 10;
348+
TestOrch test_orch(m_config_db.get(), "CFG_TEST_TABLE");
349+
Consumer test_consumer(
350+
new swss::ConsumerStateTable(m_config_db.get(), "CFG_TEST_TABLE", consumer_pops_batch_size, 1), &test_orch, "CFG_TEST_TABLE");
351+
swss::ProducerStateTable producer_table(m_config_db.get(), "CFG_TEST_TABLE");
352+
353+
m_config_db->flushdb();
354+
for (int notification_count = 0; notification_count< consumer_pops_batch_size*2; notification_count++)
355+
{
356+
std::vector<FieldValueTuple> fields;
357+
FieldValueTuple t("test_field", "test_value");
358+
fields.push_back(t);
359+
producer_table.set(std::to_string(notification_count), fields);
360+
361+
cout << "ConsumerPops_notification_count:: add key: " << notification_count << endl;
362+
}
363+
364+
// consumer should pops consumer_pops_batch_size notifications
365+
test_consumer.execute();
366+
ASSERT_EQ(test_orch.m_notification_count, consumer_pops_batch_size);
367+
368+
test_consumer.execute();
369+
ASSERT_EQ(test_orch.m_notification_count, consumer_pops_batch_size*2);
370+
}
325371
}

tests/mock_tests/mock_consumerstatetable.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,34 @@ namespace swss
77
TableName_KeySet(tableName)
88
{
99
}
10+
11+
void ConsumerStateTable::pops(std::deque<KeyOpFieldsValuesTuple> &vkco, const std::string& /*prefix*/)
12+
{
13+
int count = 0;
14+
swss::Table table(getDbConnector(), getTableName());
15+
std::vector<std::string> keys;
16+
table.getKeys(keys);
17+
for (const auto &key: keys)
18+
{
19+
// pop with batch size
20+
if (count < POP_BATCH_SIZE)
21+
{
22+
count++;
23+
}
24+
else
25+
{
26+
break;
27+
}
28+
29+
KeyOpFieldsValuesTuple kco;
30+
kfvKey(kco) = key;
31+
kfvOp(kco) = SET_COMMAND;
32+
if (!table.get(key, kfvFieldsValues(kco)))
33+
{
34+
continue;
35+
}
36+
table.del(key);
37+
vkco.push_back(kco);
38+
}
39+
}
1040
}

tests/test_ipv6_link_local.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ def test_NeighborAddRemoveIpv6LinkLocal(self, dvs, testlog):
5959
time.sleep(2)
6060

6161
# Neigh entries should contain Ipv6-link-local neighbors, should be 4
62-
neigh_entries = self.pdb.get_keys("NEIGH_TABLE")
63-
assert (len(neigh_entries) == 4)
62+
self.pdb.wait_for_n_keys("NEIGH_TABLE", 4)
6463

6564
found_entry = False
65+
neigh_entries = self.pdb.get_keys("NEIGH_TABLE")
6666
for key in neigh_entries:
6767
if (key.find("Ethernet4:2001::2") or key.find("Ethernet0:2000::2")):
6868
found_entry = True

0 commit comments

Comments
 (0)