Skip to content

Commit 037d2f8

Browse files
authored
Implement bulk API for NEXT_HOP_GROUP_MEMBER in syncd (sonic-net#243)
* Fix configure parameter name Signed-off-by: Qi Luo <qiluo-msft@users.noreply.github.com> * Move tests to syncd directory, add consumer in tests Signed-off-by: Qi Luo <qiluo-msft@users.noreply.github.com> * Test for bulk create nhgm Signed-off-by: Qi Luo <qiluo-msft@users.noreply.github.com> * Refactor namespace prefix Signed-off-by: Qi Luo <qiluo-msft@users.noreply.github.com> * Fix reference Signed-off-by: Qi Luo <qiluo-msft@users.noreply.github.com> * Fix function paramter reference Signed-off-by: Qi Luo <qiluo-msft@users.noreply.github.com>
1 parent bfe594d commit 037d2f8

File tree

8 files changed

+150
-32
lines changed

8 files changed

+150
-32
lines changed

configure.ac

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ AM_COND_IF([SAITHRIFT], [
4040
AC_CHECK_LIB([thrift], [main], [AC_MSG_NOTICE(libthrift found)], [AC_MSG_ERROR(libthrift is required for rpcserver)])
4141
])
4242

43-
AC_ARG_ENABLE(rtest,
43+
AC_ARG_ENABLE(redis-test,
4444
[ --enable-redis-test test with redis service],
4545
[case "${enableval}" in
4646
yes) rtest=true ;;

lib/src/Makefile.am

-10
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,3 @@ libsairedis_la_SOURCES = \
4646

4747
libsairedis_la_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
4848
libsairedis_la_LIBADD = -lhiredis -lswsscommon
49-
50-
bin_PROGRAMS = tests
51-
52-
tests_SOURCES = tests.cpp
53-
tests_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
54-
tests_LDADD = -lhiredis -lswsscommon -lpthread -L$(top_srcdir)/lib/src/.libs -lsairedis -L$(top_srcdir)/meta/.libs -lsaimetadata -lsaimeta
55-
56-
if RTEST
57-
TESTS = tests
58-
endif

syncd/Makefile.am

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
AM_CPPFLAGS = -I$(top_srcdir)/vslib/inc -I$(top_srcdir)/lib/inc -I$(top_srcdir)/SAI/inc -I$(top_srcdir)/SAI/meta
22

3-
bin_PROGRAMS = syncd syncd_request_shutdown
3+
bin_PROGRAMS = syncd syncd_request_shutdown tests
44

55
if DEBUG
66
DBGFLAGS = -ggdb -DDEBUG
@@ -15,6 +15,7 @@ SAILIB=-lsai
1515
endif
1616

1717
syncd_SOURCES = \
18+
main.cpp \
1819
syncd.cpp \
1920
syncd_saiswitch.cpp \
2021
syncd_hard_reinit.cpp \
@@ -34,3 +35,20 @@ endif
3435
syncd_request_shutdown_SOURCES = syncd_request_shutdown.cpp
3536
syncd_request_shutdown_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
3637
syncd_request_shutdown_LDADD = -lhiredis -lswsscommon -lpthread
38+
39+
tests_SOURCES = \
40+
tests.cpp \
41+
syncd.cpp \
42+
syncd_saiswitch.cpp \
43+
syncd_hard_reinit.cpp \
44+
syncd_notifications.cpp \
45+
syncd_counters.cpp \
46+
syncd_applyview.cpp \
47+
syncd_pfc_watchdog.cpp
48+
49+
tests_CPPFLAGS = $(DBGFLAGS) $(AM_CPPFLAGS) $(CFLAGS_COMMON)
50+
tests_LDADD = -lhiredis -lswsscommon -lpthread -L$(top_srcdir)/lib/src/.libs -lsairedis -L$(top_srcdir)/meta/.libs -lsaimetadata -lsaimeta
51+
52+
if RTEST
53+
TESTS = tests
54+
endif

syncd/main.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
int syncd_main(int argc, char **argv);
3+
4+
int main(int argc, char **argv)
5+
{
6+
return syncd_main(argc, argv);
7+
}

syncd/syncd.cpp

+22-15
Original file line numberDiff line numberDiff line change
@@ -1958,7 +1958,8 @@ sai_object_id_t extractSwitchVid(
19581958
}
19591959
}
19601960

1961-
sai_status_t handle_bulk_route(
1961+
sai_status_t handle_bulk_generic(
1962+
_In_ sai_object_type_t object_type,
19621963
_In_ const std::vector<std::string> &object_ids,
19631964
_In_ sai_common_api_t api,
19641965
_In_ const std::vector<std::shared_ptr<SaiAttributeList>> &attributes)
@@ -1979,24 +1980,29 @@ sai_status_t handle_bulk_route(
19791980
sai_attribute_t *attr_list = list->get_attr_list();
19801981
uint32_t attr_count = list->get_attr_count();
19811982

1982-
if (api == (sai_common_api_t)SAI_COMMON_API_BULK_SET)
1983-
{
1984-
sai_object_meta_key_t meta_key;
1983+
sai_object_meta_key_t meta_key;
19851984

1985+
if (object_type == SAI_OBJECT_TYPE_ROUTE_ENTRY)
1986+
{
19861987
meta_key.objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY;
1987-
19881988
sai_deserialize_route_entry(object_ids[idx], meta_key.objectkey.key.route_entry);
1989+
}
1990+
else if (object_type == SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER)
1991+
{
1992+
meta_key.objecttype = SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER;
1993+
sai_deserialize_object_id(object_ids[idx], meta_key.objectkey.key.object_id);
1994+
}
1995+
else
1996+
{
1997+
throw std::invalid_argument("object_type");
1998+
}
19891999

2000+
if (api == (sai_common_api_t)SAI_COMMON_API_BULK_SET)
2001+
{
19902002
status = handle_non_object_id(meta_key, SAI_COMMON_API_SET, attr_count, attr_list);
19912003
}
19922004
else if (api == (sai_common_api_t)SAI_COMMON_API_BULK_CREATE)
19932005
{
1994-
sai_object_meta_key_t meta_key;
1995-
1996-
meta_key.objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY;
1997-
1998-
sai_deserialize_route_entry(object_ids[idx], meta_key.objectkey.key.route_entry);
1999-
20002006
status = handle_non_object_id(meta_key, SAI_COMMON_API_CREATE, attr_count, attr_list);
20012007
}
20022008
else
@@ -2100,7 +2106,8 @@ sai_status_t processBulkEvent(
21002106
switch (object_type)
21012107
{
21022108
case SAI_OBJECT_TYPE_ROUTE_ENTRY:
2103-
status = handle_bulk_route(object_ids, api, attributes);
2109+
case SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER:
2110+
status = handle_bulk_generic(object_type, object_ids, api, attributes);
21042111
break;
21052112

21062113
default:
@@ -3004,7 +3011,7 @@ void sai_meta_log_syncd(
30043011
swss::Logger::getInstance().write(p, ":- %s: %s", func, buffer);
30053012
}
30063013

3007-
int main(int argc, char **argv)
3014+
int syncd_main(int argc, char **argv)
30083015
{
30093016
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);
30103017

@@ -3091,7 +3098,7 @@ int main(int argc, char **argv)
30913098
if (status != SAI_STATUS_SUCCESS)
30923099
{
30933100
SWSS_LOG_ERROR("fail to sai_api_initialize: %d", status);
3094-
exit(EXIT_FAILURE);
3101+
return EXIT_FAILURE;
30953102
}
30963103

30973104
int failed = sai_metadata_apis_query(sai_api_query);
@@ -3215,5 +3222,5 @@ int main(int argc, char **argv)
32153222

32163223
SWSS_LOG_NOTICE("uninitialize finished");
32173224

3218-
exit(EXIT_SUCCESS);
3225+
return EXIT_SUCCESS;
32193226
}

syncd/syncd.h

+4
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,8 @@ bool is_set_attribute_workaround(
113113
void startNotificationsProcessingThread();
114114
void stopNotificationsProcessingThread();
115115

116+
sai_status_t processBulkEvent(
117+
_In_ sai_common_api_t api,
118+
_In_ const swss::KeyOpFieldsValuesTuple &kco);
119+
116120
#endif // __SYNCD_H__

lib/src/tests.cpp syncd/tests.cpp

+96-5
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,50 @@ extern "C" {
55
}
66

77
#include "swss/logger.h"
8+
#include "swss/dbconnector.h"
9+
#include "swss/schema.h"
10+
#include "swss/redisreply.h"
811
#include "sairedis.h"
912
#include "sai_redis.h"
1013
#include "meta/saiserialize.h"
14+
#include "syncd.h"
1115

1216
#include <map>
1317
#include <unordered_map>
1418
#include <vector>
19+
#include <thread>
20+
#include <tuple>
1521

1622
#define ASSERT_SUCCESS(format,...) \
1723
if ((status)!=SAI_STATUS_SUCCESS) \
1824
SWSS_LOG_THROW(format ": %s", ##__VA_ARGS__, sai_serialize_status(status).c_str());
1925

20-
const char* profile_get_value(
26+
static sai_next_hop_group_api_t test_next_hop_group_api;
27+
static std::vector<std::tuple<sai_object_id_t, sai_object_id_t, std::vector<sai_attribute_t>>> created_next_hop_group_member;
28+
29+
sai_status_t test_create_next_hop_group_member(
30+
_Out_ sai_object_id_t *next_hop_group_member_id,
31+
_In_ sai_object_id_t switch_id,
32+
_In_ uint32_t attr_count,
33+
_In_ const sai_attribute_t *attr_list)
34+
{
35+
created_next_hop_group_member.emplace_back();
36+
auto& back = created_next_hop_group_member.back();
37+
std::get<0>(back) = *next_hop_group_member_id;
38+
std::get<1>(back) = switch_id;
39+
auto& attrs = std::get<2>(back);
40+
attrs.insert(attrs.end(), attr_list, attr_list + attr_count);
41+
return 0;
42+
}
43+
44+
void clearDB()
45+
{
46+
swss::DBConnector db(ASIC_DB, "localhost", 6379, 0);
47+
swss::RedisReply r(&db, "FLUSHALL", REDIS_REPLY_STATUS);
48+
r.checkStatusOK();
49+
}
50+
51+
static const char* profile_get_value(
2152
_In_ sai_switch_profile_id_t profile_id,
2253
_In_ const char* variable)
2354
{
@@ -26,7 +57,7 @@ const char* profile_get_value(
2657
return NULL;
2758
}
2859

29-
int profile_get_next_value(
60+
static int profile_get_next_value(
3061
_In_ sai_switch_profile_id_t profile_id,
3162
_Out_ const char** variable,
3263
_Out_ const char** value)
@@ -50,7 +81,7 @@ int profile_get_next_value(
5081
return -1;
5182
}
5283

53-
service_method_table_t test_services = {
84+
static service_method_table_t test_services = {
5485
profile_get_value,
5586
profile_get_next_value
5687
};
@@ -64,6 +95,11 @@ void test_sai_initialize()
6495
// with enabled unix socket
6596
sai_status_t status = sai_api_initialize(0, (service_method_table_t*)&test_services);
6697

98+
// Mock the SAI api
99+
test_next_hop_group_api.create_next_hop_group_member = test_create_next_hop_group_member;
100+
sai_metadata_sai_next_hop_group_api = &test_next_hop_group_api;
101+
created_next_hop_group_member.clear();
102+
67103
ASSERT_SUCCESS("Failed to initialize api");
68104
}
69105

@@ -100,15 +136,55 @@ sai_object_id_t create_dummy_object_id(
100136
return (((sai_object_id_t)objecttype) << 48) | ++index;
101137
}
102138

139+
bool starts_with(const std::string& str, const std::string& substr)
140+
{
141+
return strncmp(str.c_str(), substr.c_str(), substr.size()) == 0;
142+
}
143+
144+
void bulk_nhgm_consumer_worker()
145+
{
146+
std::string tableName = ASIC_STATE_TABLE;
147+
swss::DBConnector db(ASIC_DB, "localhost", 6379, 0);
148+
swss::ConsumerTable c(&db, tableName);
149+
swss::Select cs;
150+
swss::Selectable *selectcs;
151+
int tmpfd;
152+
int ret = 0;
153+
154+
cs.addSelectable(&c);
155+
while ((ret = cs.select(&selectcs, &tmpfd)) == swss::Select::OBJECT)
156+
{
157+
swss::KeyOpFieldsValuesTuple kco;
158+
c.pop(kco);
159+
160+
auto& key = kfvKey(kco);
161+
auto& op = kfvOp(kco);
162+
auto& values = kfvFieldsValues(kco);
163+
164+
if (starts_with(key, "SAI_OBJECT_TYPE_SWITCH")) continue;
165+
166+
if (op == "bulkcreate")
167+
{
168+
sai_status_t status = processBulkEvent((sai_common_api_t)SAI_COMMON_API_BULK_CREATE, kco);
169+
ASSERT_SUCCESS("Failed to processBulkEvent");
170+
break;
171+
}
172+
173+
}
174+
}
175+
103176
void test_bulk_next_hop_group_member_create()
104177
{
105178
SWSS_LOG_ENTER();
106179

107180
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE);
108181

182+
clearDB();
109183
meta_init_db();
110184
redis_clear_switch_ids();
111185

186+
auto consumerThreads = new std::thread(bulk_nhgm_consumer_worker);
187+
112188
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);
113189

114190
sai_status_t status;
@@ -144,6 +220,7 @@ void test_bulk_next_hop_group_member_create()
144220
sai_object_meta_key_t meta_key_hopgruop = { .objecttype = SAI_OBJECT_TYPE_NEXT_HOP_GROUP, .objectkey = { .key = { .object_id = hopgroup } } };
145221
std::string hopgroup_key = sai_serialize_object_meta_key(meta_key_hopgruop);
146222
ObjectAttrHash[hopgroup_key] = { };
223+
sai_object_id_t hopgroup_vid = translate_rid_to_vid(hopgroup, switch_id);
147224

148225
for (uint32_t i = 0; i < count; ++i)
149226
{
@@ -153,15 +230,16 @@ void test_bulk_next_hop_group_member_create()
153230
sai_object_meta_key_t meta_key_hop = { .objecttype = SAI_OBJECT_TYPE_NEXT_HOP, .objectkey = { .key = { .object_id = hop } } };
154231
std::string hop_key = sai_serialize_object_meta_key(meta_key_hop);
155232
ObjectAttrHash[hop_key] = { };
233+
sai_object_id_t hop_vid = translate_rid_to_vid(hop, switch_id);
156234

157235
std::vector<sai_attribute_t> list(2);
158236
sai_attribute_t &attr1 = list[0];
159237
sai_attribute_t &attr2 = list[1];
160238

161239
attr1.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID;
162-
attr1.value.oid = hopgroup;
240+
attr1.value.oid = hopgroup_vid;
163241
attr2.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID;
164-
attr2.value.oid = hop;
242+
attr2.value.oid = hop_vid;
165243
nhgm_attrs.push_back(list);
166244
nhgm_attrs_count.push_back(2);
167245
}
@@ -181,6 +259,18 @@ void test_bulk_next_hop_group_member_create()
181259
status = statuses[j];
182260
ASSERT_SUCCESS("Failed to create nhgm # %zu", j);
183261
}
262+
263+
consumerThreads->join();
264+
delete consumerThreads;
265+
266+
// check the SAI api calling
267+
for (size_t i = 0; i < created_next_hop_group_member.size(); i++)
268+
{
269+
auto& created = created_next_hop_group_member[i];
270+
auto& created_attrs = std::get<2>(created);
271+
assert(created_attrs.size() == 2);
272+
assert(created_attrs[1].value.oid == nhgm_attrs[i][1].value.oid);
273+
}
184274
}
185275

186276
void test_bulk_route_set()
@@ -189,6 +279,7 @@ void test_bulk_route_set()
189279

190280
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE);
191281

282+
clearDB();
192283
meta_init_db();
193284
redis_clear_switch_ids();
194285

tests/Makefile.am

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ endif
1111
SAILIB=-L$(top_srcdir)/vslib/src/.libs -lsaivs
1212

1313
vssyncd_SOURCES = \
14+
../syncd/main.cpp \
1415
../syncd/syncd.cpp \
1516
../syncd/syncd_saiswitch.cpp \
1617
../syncd/syncd_hard_reinit.cpp \

0 commit comments

Comments
 (0)