diff --git a/lib/inc/Context.h b/lib/inc/Context.h index bc651993fea9..8db8ad4cad77 100644 --- a/lib/inc/Context.h +++ b/lib/inc/Context.h @@ -19,6 +19,11 @@ namespace sairedis virtual ~Context(); + public: + + void populateMetadata( + _In_ sai_object_id_t switchId); + private: sai_switch_notifications_t handle_notification( diff --git a/lib/inc/RedisRemoteSaiInterface.h b/lib/inc/RedisRemoteSaiInterface.h index 811b4f8caf40..8ed001b7552d 100644 --- a/lib/inc/RedisRemoteSaiInterface.h +++ b/lib/inc/RedisRemoteSaiInterface.h @@ -17,6 +17,7 @@ #include #include +#include #define SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_REMOVE_ENTRY(ot) \ virtual sai_status_t remove( \ @@ -282,6 +283,8 @@ namespace sairedis sai_switch_notifications_t syncProcessNotification( _In_ std::shared_ptr notification); + const std::map& getTableDump() const; + private: // QUAD API helpers sai_status_t create( @@ -422,6 +425,8 @@ namespace sairedis _In_ uint32_t attrCount, _In_ const sai_attribute_t *attrList) const; + void refreshTableDump(); + private: uint32_t m_globalContext; @@ -453,5 +458,7 @@ namespace sairedis std::function)> m_notificationCallback; std::string m_dbAsic; + + std::map m_tableDump; }; } diff --git a/lib/src/Context.cpp b/lib/src/Context.cpp index 59ac4487b350..3e6715671dd0 100644 --- a/lib/src/Context.cpp +++ b/lib/src/Context.cpp @@ -46,3 +46,13 @@ sai_switch_notifications_t Context::handle_notification( return m_notificationCallback(notification, this); } + +void Context::populateMetadata( + _In_ sai_object_id_t switchId) +{ + SWSS_LOG_ENTER(); + + auto& dump = m_redisSai->getTableDump(); + + m_meta->populate(dump.at(switchId)); +} diff --git a/lib/src/RedisRemoteSaiInterface.cpp b/lib/src/RedisRemoteSaiInterface.cpp index 56bc91157891..86de5e3a5688 100644 --- a/lib/src/RedisRemoteSaiInterface.cpp +++ b/lib/src/RedisRemoteSaiInterface.cpp @@ -187,6 +187,35 @@ sai_status_t RedisRemoteSaiInterface::create( return SAI_STATUS_FAILURE; } + + auto *attr = sai_metadata_get_attr_by_id( + SAI_SWITCH_ATTR_INIT_SWITCH, + attr_count, + attr_list); + + if (attr && attr->value.booldata == false) + { + refreshTableDump(); + + if (m_tableDump.find(switchId) == m_tableDump.end()) + { + SWSS_LOG_ERROR("failed to find switch %s to connect (init=false)", + sai_serialize_object_id(switchId).c_str()); + + m_virtualObjectIdManager->releaseObjectId(switchId); + + return SAI_STATUS_FAILURE; + } + + // when init is false, don't send query to syncd, just return success + // that we found switch and we connected to it + + auto sw = std::make_shared(*objectId, attr_count, attr_list); + + m_switchContainer->insert(sw); + + return SAI_STATUS_SUCCESS; + } } else { @@ -1746,3 +1775,48 @@ sai_switch_notifications_t RedisRemoteSaiInterface::syncProcessNotification( return { }; } + +const std::map& RedisRemoteSaiInterface::getTableDump() const +{ + SWSS_LOG_ENTER(); + + return m_tableDump; +} + +void RedisRemoteSaiInterface::refreshTableDump() +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_TIMER("get asic view from %s", ASIC_STATE_TABLE); + + auto db = m_redisChannel->getDbConnector(); + + swss::Table table(db.get(), ASIC_STATE_TABLE); + + swss::TableDump dump; + + table.dump(dump); + + auto& map = m_tableDump; + + map.clear(); + + for (auto& key: dump) + { + sai_object_meta_key_t mk; + sai_deserialize_object_meta_key(key.first, mk); + + auto switchVID = switchIdQuery(mk.objectkey.key.object_id); + + map[switchVID][key.first] = key.second; + } + + SWSS_LOG_NOTICE("%s switch count: %zu:", ASIC_STATE_TABLE, map.size()); + + for (auto& kvp: map) + { + SWSS_LOG_NOTICE("%s: objects count: %zu", + sai_serialize_object_id(kvp.first).c_str(), + kvp.second.size()); + } +} diff --git a/lib/src/Sai.cpp b/lib/src/Sai.cpp index 61304676eba4..483eccd4141a 100644 --- a/lib/src/Sai.cpp +++ b/lib/src/Sai.cpp @@ -148,12 +148,29 @@ sai_status_t Sai::create( } } - return context->m_meta->create( + auto status = context->m_meta->create( objectType, objectId, switchId, attr_count, attr_list); + + if (objectType == SAI_OBJECT_TYPE_SWITCH && status == SAI_STATUS_SUCCESS) + { + auto *attr = sai_metadata_get_attr_by_id( + SAI_SWITCH_ATTR_INIT_SWITCH, + attr_count, + attr_list); + + if (attr && attr->value.booldata == false) + { + // request to connect to existing switch + + context->populateMetadata(*objectId); + } + } + + return status; } sai_status_t Sai::remove( diff --git a/meta/Meta.cpp b/meta/Meta.cpp index 6e1637cdce2e..34e5b1b808e5 100644 --- a/meta/Meta.cpp +++ b/meta/Meta.cpp @@ -4,6 +4,7 @@ #include "sai_serialize.h" #include "Globals.h" +#include "SaiAttributeList.h" #include @@ -7458,3 +7459,162 @@ bool Meta::objectExists( return m_saiObjectCollection.objectExists(mk); } +void Meta::populate( + _In_ const swss::TableDump& dump) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_TIMER("table dump populate"); + + // table dump contains only 1 switch the one that user wanted to connect + // using init=false + + for (const auto &key: dump) + { + sai_object_meta_key_t mk; + sai_deserialize_object_meta_key(key.first, mk); + + std::unordered_map hash; + + for (const auto &field: key.second) + { + hash[field.first] = field.second; + } + + SaiAttributeList alist(mk.objecttype, hash, false); + + auto attr_count = alist.get_attr_count(); + auto attr_list = alist.get_attr_list(); + + // make references and objects from object id + + if (!m_saiObjectCollection.objectExists(key.first)) + m_saiObjectCollection.createObject(mk); + + auto info = sai_metadata_get_object_type_info(mk.objecttype); + + if (info->isnonobjectid) + { + /* + * Increase object reference count for all object ids in non object id + * members. + */ + + for (size_t j = 0; j < info->structmemberscount; ++j) + { + const sai_struct_member_info_t *m = info->structmembers[j]; + + if (m->membervaluetype != SAI_ATTR_VALUE_TYPE_OBJECT_ID) + { + continue; + } + + if (!m_oids.objectReferenceExists(m->getoid(&mk))) + m_oids.objectReferenceInsert(m->getoid(&mk)); + + m_oids.objectReferenceIncrement(m->getoid(&mk)); + } + } + else + { + if (!m_oids.objectReferenceExists(mk.objectkey.key.object_id)) + m_oids.objectReferenceInsert(mk.objectkey.key.object_id); + } + + bool haskeys; + + for (uint32_t idx = 0; idx < attr_count; ++idx) + { + const sai_attribute_t* attr = &attr_list[idx]; + + auto mdp = sai_metadata_get_attr_metadata(mk.objecttype, attr->id); + + const sai_attribute_value_t& value = attr->value; + + const sai_attr_metadata_t& md = *mdp; + + if (SAI_HAS_FLAG_KEY(md.flags)) + { + haskeys = true; + META_LOG_DEBUG(md, "attr is key"); + } + + // increase reference on object id types + + uint32_t count = 0; + const sai_object_id_t *list; + + switch (md.attrvaluetype) + { + case SAI_ATTR_VALUE_TYPE_OBJECT_ID: + count = 1; + list = &value.oid; + break; + + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: + count = value.objlist.count; + list = value.objlist.list; + break; + + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: + if (value.aclfield.enable) + { + count = 1; + list = &value.aclfield.data.oid; + } + break; + + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: + if (value.aclfield.enable) + { + count = value.aclfield.data.objlist.count; + list = value.aclfield.data.objlist.list; + } + break; + + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: + if (value.aclaction.enable) + { + count = 1; + list = &value.aclaction.parameter.oid; + } + break; + + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: + if (value.aclaction.enable) + { + count = value.aclaction.parameter.objlist.count; + list = value.aclaction.parameter.objlist.list; + } + break; + + default: + + if (md.isoidattribute) + { + META_LOG_THROW(md, "missing process of oid attribute, FIXME"); + } + break; + } + + for (uint32_t index = 0; index < count; index++) + { + if (!m_oids.objectReferenceExists(list[index])) + m_oids.objectReferenceInsert(list[index]); + + m_oids.objectReferenceIncrement(list[index]); + } + + m_saiObjectCollection.setObjectAttr(mk, md, attr); + } + + if (haskeys) + { + auto mKey = sai_serialize_object_meta_key(mk); + + auto attrKey = AttrKeyMap::constructKey(mk, attr_count, attr_list); + + m_attrKeys.insert(mKey, attrKey); + } + } +} diff --git a/meta/Meta.h b/meta/Meta.h index 3b8c640ae6f7..7860fcc8b4d6 100644 --- a/meta/Meta.h +++ b/meta/Meta.h @@ -8,6 +8,8 @@ #include "AttrKeyMap.h" #include "OidRefCounter.h" +#include "swss/table.h" + #include #include #include @@ -530,6 +532,9 @@ namespace saimeta void meta_warm_boot_notify(); + void populate( + _In_ const swss::TableDump& dump); + private: void clean_after_switch_remove(