Skip to content

Commit

Permalink
[sairedis] [meta] Support connect to existing switch (sonic-net#602)
Browse files Browse the repository at this point in the history
* [sairedis] [meta] Support connect to existing switch

* Remove comment
  • Loading branch information
kcudnik authored Apr 16, 2020
1 parent 0b43cab commit a77fc0a
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 1 deletion.
5 changes: 5 additions & 0 deletions lib/inc/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ namespace sairedis

virtual ~Context();

public:

void populateMetadata(
_In_ sai_object_id_t switchId);

private:

sai_switch_notifications_t handle_notification(
Expand Down
7 changes: 7 additions & 0 deletions lib/inc/RedisRemoteSaiInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <memory>
#include <functional>
#include <map>

#define SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_REMOVE_ENTRY(ot) \
virtual sai_status_t remove( \
Expand Down Expand Up @@ -282,6 +283,8 @@ namespace sairedis
sai_switch_notifications_t syncProcessNotification(
_In_ std::shared_ptr<Notification> notification);

const std::map<sai_object_id_t, swss::TableDump>& getTableDump() const;

private: // QUAD API helpers

sai_status_t create(
Expand Down Expand Up @@ -422,6 +425,8 @@ namespace sairedis
_In_ uint32_t attrCount,
_In_ const sai_attribute_t *attrList) const;

void refreshTableDump();

private:

uint32_t m_globalContext;
Expand Down Expand Up @@ -453,5 +458,7 @@ namespace sairedis
std::function<sai_switch_notifications_t(std::shared_ptr<Notification>)> m_notificationCallback;

std::string m_dbAsic;

std::map<sai_object_id_t, swss::TableDump> m_tableDump;
};
}
10 changes: 10 additions & 0 deletions lib/src/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
74 changes: 74 additions & 0 deletions lib/src/RedisRemoteSaiInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Switch>(*objectId, attr_count, attr_list);

m_switchContainer->insert(sw);

return SAI_STATUS_SUCCESS;
}
}
else
{
Expand Down Expand Up @@ -1746,3 +1775,48 @@ sai_switch_notifications_t RedisRemoteSaiInterface::syncProcessNotification(

return { };
}

const std::map<sai_object_id_t, swss::TableDump>& 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());
}
}
19 changes: 18 additions & 1 deletion lib/src/Sai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
160 changes: 160 additions & 0 deletions meta/Meta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "sai_serialize.h"

#include "Globals.h"
#include "SaiAttributeList.h"

#include <inttypes.h>

Expand Down Expand Up @@ -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<std::string, std::string> 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);
}
}
}
5 changes: 5 additions & 0 deletions meta/Meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "AttrKeyMap.h"
#include "OidRefCounter.h"

#include "swss/table.h"

#include <vector>
#include <memory>
#include <set>
Expand Down Expand Up @@ -530,6 +532,9 @@ namespace saimeta

void meta_warm_boot_notify();

void populate(
_In_ const swss::TableDump& dump);

private:

void clean_after_switch_remove(
Expand Down

0 comments on commit a77fc0a

Please sign in to comment.