Skip to content

Commit 72d8cc3

Browse files
authored
Add warm boot support for virtual switch (sonic-net#374)
* Add warm boot support for virtual switch * Update default boot type to cold
1 parent 333c5ff commit 72d8cc3

12 files changed

+480
-21
lines changed

meta/sai_meta.cpp

+26-1
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,21 @@ sai_status_t meta_generic_validation_remove(
17451745

17461746
if (count != 0)
17471747
{
1748+
if (object_type == SAI_OBJECT_TYPE_SWITCH)
1749+
{
1750+
/*
1751+
* We allow to remove switch object even if there are ROUTE_ENTRY
1752+
* created and refrencing this switch, since remove could be used
1753+
* in WARM boot scenario.
1754+
*/
1755+
1756+
SWSS_LOG_WARN("removing switch object 0x%lx reference count is %d, removing all objects from meta DB", oid, count);
1757+
1758+
meta_init_db();
1759+
1760+
return SAI_STATUS_SUCCESS;
1761+
}
1762+
17481763
SWSS_LOG_ERROR("object 0x%lx reference count is %d, can't remove", oid, count);
17491764

17501765
return SAI_STATUS_INVALID_PARAMETER;
@@ -2719,6 +2734,16 @@ void meta_generic_validation_post_remove(
27192734
{
27202735
SWSS_LOG_ENTER();
27212736

2737+
if (meta_key.objecttype == SAI_OBJECT_TYPE_SWITCH)
2738+
{
2739+
/*
2740+
* If switch object was removed then meta db was cleared and there are
2741+
* no other attributes, no need for reference counting.
2742+
*/
2743+
2744+
return;
2745+
}
2746+
27222747
// get all attributes that was set
27232748

27242749
for (auto&it: get_object_attributes(meta_key))
@@ -5456,7 +5481,7 @@ sai_status_t meta_sai_validate_oid(
54565481

54575482
if (oid == SAI_NULL_OBJECT_ID)
54585483
{
5459-
SWSS_LOG_ERROR("oid is set to null object id");
5484+
SWSS_LOG_ERROR("oid is set to null object id on %s", otname);
54605485

54615486
return SAI_STATUS_INVALID_PARAMETER;
54625487
}

saiplayer/saiplayer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ void handle_get_response(
726726
if (status != SAI_STATUS_SUCCESS)
727727
{
728728
// TODO check if status is correct for get
729+
SWSS_LOG_WARN("status is not success: %s", sai_serialize_status(status).c_str());
729730
return;
730731
}
731732

syncd/syncd_applyview.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -6218,9 +6218,13 @@ void populateExistingObjects(
62186218
continue;
62196219
}
62206220

6221+
// TODO this object in current view may have some attributes, we need to copy them
6222+
// to temp view, so they match on compare, or in case of those objects matched
6223+
// just ignore operations ? what about attributes with oids?
6224+
62216225
temporaryView.createDummyExistingObject(rid, vid);
62226226

6223-
SWSS_LOG_DEBUG("populate existing %s RID %s VID %s",
6227+
SWSS_LOG_INFO("populate existing %s RID %s VID %s",
62246228
sai_serialize_object_type(sai_object_type_query(rid)).c_str(),
62256229
sai_serialize_object_id(rid).c_str(),
62266230
sai_serialize_object_id(vid).c_str());

syncd/syncd_hard_reinit.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,10 @@ static sai_object_id_t g_switch_vid = SAI_NULL_OBJECT_ID;
4747

4848
static std::shared_ptr<SaiSwitch> g_sw;
4949

50-
#ifdef SAITHRIFT
5150
/*
5251
* SAI switch global needed for RPC server
5352
*/
5453
extern sai_object_id_t gSwitchId;
55-
#endif
5654

5755
void processAttributesForOids(
5856
_In_ sai_object_type_t objectType,
@@ -425,10 +423,8 @@ void processSwitches()
425423

426424
sai_status_t status = sai_metadata_sai_switch_api->create_switch(&switch_rid, attr_count, attr_list);
427425

428-
#ifdef SAITHRIFT
429426
gSwitchId = switch_rid;
430427
SWSS_LOG_NOTICE("Initialize gSwitchId with ID = 0x%lx", gSwitchId);
431-
#endif
432428

433429
if (status != SAI_STATUS_SUCCESS)
434430
{
@@ -1298,5 +1294,12 @@ void performWarmRestart()
12981294

12991295
g_sw = sw;
13001296

1297+
/*
1298+
* Populate gSwitchId since it's needed if we want to make multiple warm
1299+
* starts in a row.
1300+
*/
1301+
1302+
gSwitchId = g_switch_rid;
1303+
13011304
startDiagShell();
13021305
}

vslib/inc/sai_vs.h

+12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ extern "C" {
2727
#define SAI_VALUE_VS_SWITCH_TYPE_BCM56850 "SAI_VS_SWITCH_TYPE_BCM56850"
2828
#define SAI_VALUE_VS_SWITCH_TYPE_MLNX2700 "SAI_VS_SWITCH_TYPE_MLNX2700"
2929

30+
#define SAI_VS_COLD_BOOT 0
31+
#define SAI_VS_WARM_BOOT 1
32+
#define SAI_VS_FAST_BOOT 2
33+
34+
#define SAI_VS_MAX_PORTS 1024
35+
3036
/**
3137
* @def SAI_VS_UNITTEST_CHANNEL
3238
*
@@ -71,6 +77,12 @@ extern bool g_vs_hostif_use_tap_device;
7177
extern sai_vs_switch_type_t g_vs_switch_type;
7278
extern std::recursive_mutex g_recursive_mutex;
7379

80+
extern int g_vs_boot_type;
81+
82+
extern const char *g_boot_type;
83+
extern const char *g_warm_boot_read_file;
84+
extern const char *g_warm_boot_write_file;
85+
7486
extern const sai_acl_api_t vs_acl_api;
7587
extern const sai_bfd_api_t vs_bfd_api;
7688
extern const sai_bridge_api_t vs_bridge_api;

vslib/inc/sai_vs_switch_BCM56850.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
#include "meta/saiattributelist.h"
77

88
void init_switch_BCM56850(
9-
_In_ sai_object_id_t switch_id);
9+
_In_ sai_object_id_t switch_id,
10+
_In_ std::shared_ptr<SwitchState> warmBootState);
1011

1112
void uninit_switch_BCM56850(
1213
_In_ sai_object_id_t switch_id);

vslib/inc/sai_vs_switch_MLNX2700.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
#include "meta/saiattributelist.h"
77

88
void init_switch_MLNX2700(
9-
_In_ sai_object_id_t switch_id);
9+
_In_ sai_object_id_t switch_id,
10+
_In_ std::shared_ptr<SwitchState> warmBootState);
1011

1112
void uninit_switch_MLNX2700(
1213
_In_ sai_object_id_t switch_id);

vslib/src/sai_vs_generic_create.cpp

+163-2
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,53 @@ sai_object_id_t vs_create_real_object_id(
207207
return object_id;
208208
}
209209

210+
void vs_update_real_object_ids(
211+
_In_ const std::shared_ptr<SwitchState> warmBootState)
212+
{
213+
SWSS_LOG_ENTER();
214+
215+
/*
216+
* Since we loaded state from warm boot, we need to update real object id's
217+
* in case a new object will be created. We need this so new objects will
218+
* not have the same ID as existing ones.
219+
*/
220+
221+
for (auto oh: warmBootState->objectHash)
222+
{
223+
sai_object_type_t ot = oh.first;
224+
225+
if (ot == SAI_OBJECT_TYPE_NULL)
226+
continue;
227+
228+
auto oi = sai_metadata_get_object_type_info(ot);
229+
230+
if (oi == NULL)
231+
{
232+
SWSS_LOG_THROW("failed to find object type info for object type: %d", ot);
233+
}
234+
235+
if (oi->isnonobjectid)
236+
continue;
237+
238+
for (auto o: oh.second)
239+
{
240+
sai_object_id_t oid;
241+
242+
sai_deserialize_object_id(o.first, oid);
243+
244+
// lower 32 bits on VS is real id on specific object type
245+
uint64_t real_id = oid & ((uint64_t)-1) >> (64 - OT_POSITION);
246+
247+
if (real_ids[ot] <= real_id)
248+
{
249+
real_ids[ot] = real_id + 1; // +1 since this will be next object number
250+
}
251+
252+
SWSS_LOG_INFO("update %s:%s real id to from %lu to %lu", oi->objecttypename, o.first.c_str(), real_id, real_ids[ot]);
253+
}
254+
}
255+
}
256+
210257
void vs_free_real_object_id(
211258
_In_ sai_object_id_t object_id)
212259
{
@@ -218,6 +265,108 @@ void vs_free_real_object_id(
218265
}
219266
}
220267

268+
std::shared_ptr<SwitchState> vs_read_switch_database_for_warm_restart(
269+
_In_ sai_object_id_t switch_id)
270+
{
271+
SWSS_LOG_ENTER();
272+
273+
if (g_warm_boot_read_file == NULL)
274+
{
275+
SWSS_LOG_ERROR("warm boot read file is NULL");
276+
return nullptr;
277+
}
278+
279+
std::ifstream dumpFile;
280+
281+
dumpFile.open(g_warm_boot_read_file);
282+
283+
if (!dumpFile.is_open())
284+
{
285+
SWSS_LOG_ERROR("failed to open: %s, switching to cold boot", g_warm_boot_read_file);
286+
287+
g_vs_boot_type = SAI_VS_COLD_BOOT;
288+
289+
return nullptr;
290+
}
291+
292+
std::shared_ptr<SwitchState> ss = std::make_shared<SwitchState>(switch_id);
293+
294+
size_t count = 1; // count is 1 since switch_id was inserted to objectHash in SwitchState constructor
295+
296+
std::string line;
297+
while (std::getline(dumpFile, line))
298+
{
299+
// line format: OBJECT_TYPE OBJECT_ID ATTR_ID ATTR_VALUE
300+
std::istringstream iss(line);
301+
302+
std::string str_object_type;
303+
std::string str_object_id;
304+
std::string str_attr_id;
305+
std::string str_attr_value;
306+
307+
iss >> str_object_type >> str_object_id >> str_attr_id >> str_attr_value;
308+
309+
sai_object_meta_key_t meta_key;
310+
311+
sai_deserialize_object_meta_key(str_object_type + ":" + str_object_id, meta_key);
312+
313+
auto &objectHash = ss->objectHash.at(meta_key.objecttype);
314+
315+
if (objectHash.find(str_object_id) == objectHash.end())
316+
{
317+
count++;
318+
319+
objectHash[str_object_id] = {};
320+
}
321+
322+
if (str_attr_id == "NULL")
323+
{
324+
// skip empty attributes
325+
continue;
326+
}
327+
328+
if (meta_key.objecttype == SAI_OBJECT_TYPE_SWITCH)
329+
{
330+
if (meta_key.objectkey.key.object_id != switch_id)
331+
{
332+
SWSS_LOG_THROW("created switch id is %s but warm boot serialized is %s",
333+
sai_serialize_object_id(switch_id).c_str(),
334+
str_object_id.c_str());
335+
}
336+
}
337+
338+
auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str());
339+
340+
if (meta == NULL)
341+
{
342+
SWSS_LOG_THROW("failed to find metadata for %s", str_attr_id.c_str());
343+
}
344+
345+
// populate attributes
346+
347+
sai_attribute_t attr;
348+
349+
attr.id = meta->attrid;
350+
351+
sai_deserialize_attr_value(str_attr_value.c_str(), *meta, attr, false);
352+
353+
auto a = std::make_shared<SaiAttrWrap>(meta_key.objecttype, &attr);
354+
355+
objectHash[str_object_id][a->getAttrMetadata()->attridname] = a;
356+
357+
// free possible list attributes
358+
sai_deserialize_free_attribute_value(meta->attrvaluetype, attr);
359+
}
360+
361+
// NOTE notification pointers should be restored by attr_list when creating switch
362+
363+
dumpFile.close();
364+
365+
SWSS_LOG_NOTICE("loaded %zu objects from: %s", count, g_warm_boot_read_file);
366+
367+
return ss;
368+
}
369+
221370
sai_status_t internal_vs_generic_create(
222371
_In_ sai_object_type_t object_type,
223372
_In_ const std::string &serialized_object_id,
@@ -229,20 +378,32 @@ sai_status_t internal_vs_generic_create(
229378

230379
if (object_type == SAI_OBJECT_TYPE_SWITCH)
231380
{
381+
std::shared_ptr<SwitchState> warmBootState = nullptr;
382+
383+
if (g_vs_boot_type == SAI_VS_WARM_BOOT)
384+
{
385+
warmBootState = vs_read_switch_database_for_warm_restart(switch_id);
386+
}
387+
232388
switch (g_vs_switch_type)
233389
{
234390
case SAI_VS_SWITCH_TYPE_BCM56850:
235-
init_switch_BCM56850(switch_id);
391+
init_switch_BCM56850(switch_id, warmBootState);
236392
break;
237393

238394
case SAI_VS_SWITCH_TYPE_MLNX2700:
239-
init_switch_MLNX2700(switch_id);
395+
init_switch_MLNX2700(switch_id, warmBootState);
240396
break;
241397

242398
default:
243399
SWSS_LOG_WARN("unknown switch type: %d", g_vs_switch_type);
244400
return SAI_STATUS_FAILURE;
245401
}
402+
403+
if (warmBootState != nullptr)
404+
{
405+
vs_update_real_object_ids(warmBootState);
406+
}
246407
}
247408

248409
auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(object_type);

0 commit comments

Comments
 (0)