Skip to content

Commit 4d5a7bb

Browse files
kcudniklguohan
authored andcommitted
Rebuild VS local metadata on warm boot (#380)
1 parent b011f3d commit 4d5a7bb

File tree

3 files changed

+239
-4
lines changed

3 files changed

+239
-4
lines changed

meta/sai_meta.cpp

+43-4
Original file line numberDiff line numberDiff line change
@@ -2485,6 +2485,17 @@ sai_status_t meta_generic_validation_get(
24852485
return SAI_STATUS_SUCCESS;
24862486
}
24872487

2488+
bool warmBoot = false;
2489+
2490+
void meta_warm_boot_notify()
2491+
{
2492+
SWSS_LOG_ENTER();
2493+
2494+
warmBoot = true;
2495+
2496+
SWSS_LOG_NOTICE("warmBoot = true");
2497+
}
2498+
24882499
void meta_generic_validation_post_create(
24892500
_In_ const sai_object_meta_key_t& meta_key,
24902501
_In_ sai_object_id_t switch_id,
@@ -2497,12 +2508,26 @@ void meta_generic_validation_post_create(
24972508

24982509
if (object_exists(key))
24992510
{
2500-
SWSS_LOG_ERROR("object key %s already exists (vendor bug?)", key.c_str());
2511+
if (warmBoot && meta_key.objecttype == SAI_OBJECT_TYPE_SWITCH)
2512+
{
2513+
SWSS_LOG_NOTICE("post switch create after WARM BOOT");
2514+
}
2515+
else
2516+
{
2517+
SWSS_LOG_ERROR("object key %s already exists (vendor bug?)", key.c_str());
25012518

2502-
// this may produce inconsistency
2519+
// this may produce inconsistency
2520+
}
25032521
}
25042522

2505-
create_object(meta_key);
2523+
if (warmBoot && meta_key.objecttype == SAI_OBJECT_TYPE_SWITCH)
2524+
{
2525+
SWSS_LOG_NOTICE("skipping create switch on WARM BOOT since it was already created");
2526+
}
2527+
else
2528+
{
2529+
create_object(meta_key);
2530+
}
25062531

25072532
auto info = sai_metadata_get_object_type_info(meta_key.objecttype);
25082533

@@ -2581,11 +2606,25 @@ void meta_generic_validation_post_create(
25812606
}
25822607
}
25832608

2584-
object_reference_insert(oid);
2609+
if (warmBoot && meta_key.objecttype == SAI_OBJECT_TYPE_SWITCH)
2610+
{
2611+
SWSS_LOG_NOTICE("skip insert switch reference insert in WARM_BOOT");
2612+
}
2613+
else
2614+
{
2615+
object_reference_insert(oid);
2616+
}
25852617

25862618
} while (false);
25872619
}
25882620

2621+
if (warmBoot)
2622+
{
2623+
SWSS_LOG_NOTICE("warmBoot = false");
2624+
2625+
warmBoot = false;
2626+
}
2627+
25892628
bool haskeys;
25902629

25912630
for (uint32_t idx = 0; idx < attr_count; ++idx)

meta/sai_meta.h

+19
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,23 @@ sai_status_t meta_unittests_allow_readonly_set_once(
199199
_In_ sai_object_type_t object_type,
200200
_In_ int32_t attr_id);
201201

202+
// POST VALIDATE
203+
204+
/*
205+
* Those functions will be used to recreate virtual switch local metadata state
206+
* after WARM BOOT.
207+
*/
208+
209+
void meta_warm_boot_notify();
210+
211+
void meta_generic_validation_post_create(
212+
_In_ const sai_object_meta_key_t& meta_key,
213+
_In_ sai_object_id_t switch_id,
214+
_In_ const uint32_t attr_count,
215+
_In_ const sai_attribute_t *attr_list);
216+
217+
void meta_generic_validation_post_set(
218+
_In_ const sai_object_meta_key_t& meta_key,
219+
_In_ const sai_attribute_t *attr);
220+
202221
#endif // __SAI_META_H__

vslib/src/sai_vs_generic_create.cpp

+177
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,179 @@ std::shared_ptr<SwitchState> vs_read_switch_database_for_warm_restart(
367367
return ss;
368368
}
369369

370+
void vs_validate_switch_warm_boot_atributes(
371+
_In_ uint32_t attr_count,
372+
_In_ const sai_attribute_t *attr_list)
373+
{
374+
SWSS_LOG_ENTER();
375+
376+
/*
377+
* When in warm boot, as init attributes on switch we only allow
378+
* notifications and init attribute. Actually we should check if
379+
* notifications we pass are the same as the one that we have in dumped db,
380+
* if not we should set missing one to NULL ptr.
381+
*/
382+
383+
for (uint32_t i = 0; i < attr_count; ++i)
384+
{
385+
auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr_list[i].id);
386+
387+
if (meta == NULL)
388+
{
389+
SWSS_LOG_THROW("failed to find metadata for switch attribute %d", attr_list[i].id);
390+
}
391+
392+
if (meta->attrid == SAI_SWITCH_ATTR_INIT_SWITCH)
393+
continue;
394+
395+
if (meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_POINTER)
396+
continue;
397+
398+
SWSS_LOG_THROW("attribute %s ist not INIT and not notification, not supported in warm boot", meta->attridname);
399+
}
400+
}
401+
402+
void vs_update_local_metadata(
403+
_In_ sai_object_id_t switch_id)
404+
{
405+
SWSS_LOG_ENTER();
406+
407+
/*
408+
* After warm boot we recreated all ASIC state, but since we are using
409+
* meta_* to check all needed data, we need to use post_create/post_set
410+
* methods to recreate state in local metadata so when next APIs will be
411+
* called, we could check the actual state.
412+
*/
413+
414+
auto &objectHash = g_switch_state_map.at(switch_id)->objectHash;//.at(object_type);
415+
416+
// first create switch
417+
// first we need to create all "oid" objects to have reference base
418+
// then set all object attributes on those oids
419+
// then create all non oid like route etc.
420+
421+
/*
422+
* First update switch, since all non switch objects will be using
423+
* sai_switch_id_query to check if oid is valid.
424+
*/
425+
426+
sai_object_meta_key_t mk;
427+
428+
mk.objecttype = SAI_OBJECT_TYPE_SWITCH;
429+
mk.objectkey.key.object_id = switch_id;
430+
431+
meta_generic_validation_post_create(mk, switch_id, 0, NULL);
432+
433+
/*
434+
* Create every non object id except switch. Switch object was already
435+
* created above, and non object ids like route may contain other obejct
436+
* id's inside *_entry struct, and since metadata is checking reference of
437+
* those objects, they must exists first.
438+
*/
439+
440+
for (auto kvp: objectHash)
441+
{
442+
sai_object_type_t ot = kvp.first;
443+
444+
if (ot == SAI_OBJECT_TYPE_NULL)
445+
continue;
446+
447+
if (ot == SAI_OBJECT_TYPE_SWITCH)
448+
continue;
449+
450+
auto info = sai_metadata_get_object_type_info(ot);
451+
452+
if (info == NULL)
453+
SWSS_LOG_THROW("failed to get object type info for object type %d", ot);
454+
455+
if (info->isnonobjectid)
456+
continue;
457+
458+
mk.objecttype = ot;
459+
460+
for (auto obj: kvp.second)
461+
{
462+
sai_deserialize_object_id(obj.first, mk.objectkey.key.object_id);
463+
464+
meta_generic_validation_post_create(mk, switch_id, 0, NULL);
465+
}
466+
}
467+
468+
/*
469+
* Create all non object id's. All oids are created, so objects inside
470+
* *_entry structs can be referenced correctly.
471+
*/
472+
473+
for (auto kvp: objectHash)
474+
{
475+
sai_object_type_t ot = kvp.first;
476+
477+
if (ot == SAI_OBJECT_TYPE_NULL)
478+
continue;
479+
480+
auto info = sai_metadata_get_object_type_info(ot);
481+
482+
if (info == NULL)
483+
SWSS_LOG_THROW("failed to get object type info for object type %d", ot);
484+
485+
if (info->isobjectid)
486+
continue;
487+
488+
for (auto obj: kvp.second)
489+
{
490+
std::string key = std::string(info->objecttypename) + ":" + obj.first;
491+
492+
sai_deserialize_object_meta_key(key, mk);
493+
494+
meta_generic_validation_post_create(mk, switch_id, 0, NULL);
495+
}
496+
}
497+
498+
/*
499+
* Set all attributes on all objects. Since attributes maybe OID attributes
500+
* we need to set them too for correct reference count.
501+
*/
502+
503+
for (auto kvp: objectHash)
504+
{
505+
sai_object_type_t ot = kvp.first;
506+
507+
if (ot == SAI_OBJECT_TYPE_NULL)
508+
continue;
509+
510+
auto info = sai_metadata_get_object_type_info(ot);
511+
512+
if (info == NULL)
513+
SWSS_LOG_THROW("failed to get object type info for object type %d", ot);
514+
515+
for (auto obj: kvp.second)
516+
{
517+
std::string key = std::string(info->objecttypename) + ":" + obj.first;
518+
519+
sai_deserialize_object_meta_key(key, mk);
520+
521+
for (auto a: obj.second)
522+
{
523+
auto meta = a.second->getAttrMetadata();
524+
525+
if (meta->isreadonly)
526+
continue;
527+
528+
meta_generic_validation_post_set(mk, a.second->getAttr());
529+
}
530+
}
531+
}
532+
533+
/*
534+
* Since this method is called inside internal_vs_generic_create next
535+
* meta_generic_validation_post_create will be called after success return
536+
* of meta_sai_create_oid and it would fail since we already created switch
537+
* so we need to notify metadata that this is warm boot.
538+
*/
539+
540+
meta_warm_boot_notify();
541+
}
542+
370543
sai_status_t internal_vs_generic_create(
371544
_In_ sai_object_type_t object_type,
372545
_In_ const std::string &serialized_object_id,
@@ -383,6 +556,8 @@ sai_status_t internal_vs_generic_create(
383556
if (g_vs_boot_type == SAI_VS_WARM_BOOT)
384557
{
385558
warmBootState = vs_read_switch_database_for_warm_restart(switch_id);
559+
560+
vs_validate_switch_warm_boot_atributes(attr_count, attr_list);
386561
}
387562

388563
switch (g_vs_switch_type)
@@ -403,6 +578,8 @@ sai_status_t internal_vs_generic_create(
403578
if (warmBootState != nullptr)
404579
{
405580
vs_update_real_object_ids(warmBootState);
581+
582+
vs_update_local_metadata(switch_id);
406583
}
407584
}
408585

0 commit comments

Comments
 (0)