@@ -367,6 +367,179 @@ std::shared_ptr<SwitchState> vs_read_switch_database_for_warm_restart(
367
367
return ss;
368
368
}
369
369
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
+
370
543
sai_status_t internal_vs_generic_create (
371
544
_In_ sai_object_type_t object_type,
372
545
_In_ const std::string &serialized_object_id,
@@ -383,6 +556,8 @@ sai_status_t internal_vs_generic_create(
383
556
if (g_vs_boot_type == SAI_VS_WARM_BOOT)
384
557
{
385
558
warmBootState = vs_read_switch_database_for_warm_restart (switch_id);
559
+
560
+ vs_validate_switch_warm_boot_atributes (attr_count, attr_list);
386
561
}
387
562
388
563
switch (g_vs_switch_type)
@@ -403,6 +578,8 @@ sai_status_t internal_vs_generic_create(
403
578
if (warmBootState != nullptr )
404
579
{
405
580
vs_update_real_object_ids (warmBootState);
581
+
582
+ vs_update_local_metadata (switch_id);
406
583
}
407
584
}
408
585
0 commit comments