saiasiccmp/View.cpp (308 lines of code) (raw):

#include "View.h" #include "syncd/ComparisonLogic.h" #include "syncd/VidManager.h" #include "meta/sai_serialize.h" #include "SaiSwitchAsic.h" using json = nlohmann::json; using namespace saiasiccmp; View::View( _In_ const std::string& filename): m_maxObjectIndex(0), m_otherMaxObjectIndex(0) { SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("loading view from: %s", filename.c_str()); std::ifstream file(filename); if (!file.good()) { SWSS_LOG_THROW("failed to open %s", filename.c_str()); } json j; file >> j; loadVidRidMaps(j); loadAsicView(j); loadColdVids(j); loadHidden(j); for (auto& it: m_objTypeStrMap) { SWSS_LOG_NOTICE("%s: %zu", sai_serialize_object_type(it.first).c_str(), it.second.size()); } } void View::loadVidRidMaps( _In_ const json& j) { SWSS_LOG_ENTER(); json v2r = j["VIDTORID"].at("value"); for (auto it = v2r.begin(); it != v2r.end(); it++) { std::string v = it.key(); std::string r = it.value(); sai_object_id_t vid; sai_object_id_t rid; sai_deserialize_object_id(v, vid); sai_deserialize_object_id(r, rid); m_vid2rid[vid] = rid; m_rid2vid[rid] = vid; auto ot = syncd::VidManager::objectTypeQuery(vid); m_oidTypeMap[ot].insert(vid); uint64_t index = syncd::VidManager::getObjectIndex(vid); m_maxObjectIndex = std::max(m_maxObjectIndex, index); } SWSS_LOG_NOTICE("oids: %zu\n", m_vid2rid.size()); if (m_oidTypeMap.at(SAI_OBJECT_TYPE_SWITCH).size() != 1) { SWSS_LOG_THROW("expected only 1 switch in view, FIXME"); } m_switchVid = *m_oidTypeMap.at(SAI_OBJECT_TYPE_SWITCH).begin(); m_switchRid = m_vid2rid.at(m_switchVid); } void View::loadAsicView( _In_ const json& j) { SWSS_LOG_ENTER(); for (auto it = j.begin(); it != j.end(); it++) { std::string key = it.key(); if (key.rfind("ASIC_STATE:") != 0) continue; json vals = it.value().at("value"); // skip ASIC_STATE key = key.substr(key.find_first_of(":") + 1); sai_object_meta_key_t mk; sai_deserialize_object_meta_key(key, mk); m_objTypeStrMap[mk.objecttype].insert(key); m_dump[key] = {}; // in case of NULL for (auto itt = vals.begin(); itt != vals.end(); itt++) { if (itt.key() != "NULL") { m_dump[key][itt.key()] = itt.value(); } } } m_asicView = std::make_shared<syncd::AsicView>(m_dump); SWSS_LOG_NOTICE("view objects: %zu", m_asicView->m_soAll.size()); } void View::loadColdVids( _In_ const json& j) { SWSS_LOG_ENTER(); json cold = j["COLDVIDS"].at("value"); // TODO depend on switch for (auto it = cold.begin(); it != cold.end(); it++) { std::string v = it.key(); std::string o = it.value(); sai_object_id_t vid; sai_object_type_t ot; sai_deserialize_object_id(v, vid); sai_deserialize_object_type(o, ot); m_coldVids[vid] = ot; } SWSS_LOG_NOTICE("cold vids: %zu", m_coldVids.size()); } void View::loadHidden( _In_ const json& j) { SWSS_LOG_ENTER(); json hidden = j["HIDDEN"].at("value"); // TODO depend on switch for (auto it = hidden.begin(); it != hidden.end(); it++) { std::string h = it.key(); std::string r = it.value(); sai_object_id_t rid; sai_deserialize_object_id(r, rid); m_hidden[h] = rid; } SWSS_LOG_NOTICE("hidden: %zu", m_hidden.size()); } void View::translateViewVids( _In_ uint64_t otherMaxObjectIndex) { SWSS_LOG_ENTER(); // TODO use other views ? m_otherMaxObjectIndex = otherMaxObjectIndex; SWSS_LOG_NOTICE("max index: %lu (0x%lx), other max index: %lu (0x%lx)", m_maxObjectIndex, m_maxObjectIndex, m_otherMaxObjectIndex, m_otherMaxObjectIndex); translateVidRidMaps(); translateAsicView(); translateColdVids(); // no need for hidden, since they are RIDs } void View::translateVidRidMaps() { SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("translating old VIDs to new VIDs"); // TODO consider saving oids when rid/vid match both views m_oldVid2NewVid.clear(); uint64_t index = std::max(m_maxObjectIndex, m_otherMaxObjectIndex) + 1; // translate except our starting point auto copy = m_vid2rid; m_vid2rid.clear(); m_rid2vid.clear(); m_oidTypeMap.clear(); for (auto it: copy) { auto oldVid = it.first; auto rid = it.second; auto newVid = syncd::VidManager::updateObjectIndex(oldVid, index); index++; auto ot = syncd::VidManager::objectTypeQuery(oldVid); switch (ot) { case SAI_OBJECT_TYPE_SWITCH: case SAI_OBJECT_TYPE_PORT: case SAI_OBJECT_TYPE_QUEUE: case SAI_OBJECT_TYPE_SCHEDULER_GROUP: case SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP: // don't translate starting point vids newVid = oldVid; break; default: SWSS_LOG_INFO("translating old VID %s to new VID %s", sai_serialize_object_id(oldVid).c_str(), sai_serialize_object_id(newVid).c_str()); break; } m_oldVid2NewVid[oldVid] = newVid; m_vid2rid[newVid] = rid; m_rid2vid[rid] = newVid; m_oidTypeMap[ot].insert(newVid); } } sai_object_id_t View::translateOldVidToNewVid( _In_ sai_object_id_t oldVid) const { SWSS_LOG_ENTER(); if (oldVid == SAI_NULL_OBJECT_ID) return SAI_NULL_OBJECT_ID; auto it = m_oldVid2NewVid.find(oldVid); if (it == m_oldVid2NewVid.end()) { SWSS_LOG_THROW("missing old vid %s", sai_serialize_object_id(oldVid).c_str()); } SWSS_LOG_INFO("translating old vid %s", sai_serialize_object_id(oldVid).c_str()); return m_oldVid2NewVid.at(oldVid); } void View::translateMetaKeyVids( _Inout_ sai_object_meta_key_t& mk) const { SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(mk.objecttype); if (info->isobjectid) { mk.objectkey.key.object_id = translateOldVidToNewVid(mk.objectkey.key.object_id); return; } // non object id, translate structure oids 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; } sai_object_id_t vid = m->getoid(&mk); vid = translateOldVidToNewVid(vid); m->setoid(&mk, vid); } } void View::translateAttrVids( _In_ const sai_attr_metadata_t* meta, _Inout_ sai_attribute_t& attr) { SWSS_LOG_ENTER(); uint32_t count = 0; sai_object_id_t *objectIdList = NULL; switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: count = 1; objectIdList = &attr.value.oid; break; case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: count = attr.value.objlist.count; objectIdList = attr.value.objlist.list; break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) { count = 1; objectIdList = &attr.value.aclfield.data.oid; } break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) { count = attr.value.aclfield.data.objlist.count; objectIdList = attr.value.aclfield.data.objlist.list; } break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) { count = 1; objectIdList = &attr.value.aclaction.parameter.oid; } break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) { count = attr.value.aclaction.parameter.objlist.count; objectIdList = attr.value.aclaction.parameter.objlist.list; } break; default: if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is oid attrubute but not handled", meta->attridname); } // Attribute not contain any object ids. break; } for (uint32_t i = 0; i < count; i++) { objectIdList[i] = translateOldVidToNewVid(objectIdList[i]); } } void View::translateAsicView() { SWSS_LOG_ENTER(); m_objTypeStrMap.clear(); swss::TableDump dump; for (auto it: m_dump) { std::string oldkey = it.first; sai_object_meta_key_t mk; sai_deserialize_object_meta_key(oldkey, mk); translateMetaKeyVids(mk); std::string key = sai_serialize_object_meta_key(mk); m_objTypeStrMap[mk.objecttype].insert(key); SWSS_LOG_INFO("translated %s to %s", oldkey.c_str(), key.c_str()); dump[key] = {}; // in case of NULL // TODO translate oid attributes for (auto at: it.second) { auto attrId = at.first; auto attrOldVal = at.second; syncd::SaiAttr attr(attrId, attrOldVal); translateAttrVids(attr.getAttrMetadata(), *attr.getRWSaiAttr()); auto attrVal = sai_serialize_attr_value(*attr.getAttrMetadata(), *attr.getRWSaiAttr()); SWSS_LOG_INFO("translate %s: %s to %s", attrId.c_str(), attrOldVal.c_str(), attrVal.c_str()); dump[key][attrId] = attrVal; } } m_asicView = std::make_shared<syncd::AsicView>(dump); SWSS_LOG_NOTICE("view objects: %zu", m_asicView->m_soAll.size()); } void View::translateColdVids() { SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("translating cold VIDs"); auto copy = m_coldVids; m_coldVids.clear(); for (auto it: copy) { auto oldVid = it.first; auto ot = it.second; if (m_oldVid2NewVid.find(oldVid) == m_oldVid2NewVid.end()) { // some cold vids may be missing from rid vid map // like vlan member or bridge port continue; } m_coldVids[ m_oldVid2NewVid.at(oldVid) ] = ot; } SWSS_LOG_NOTICE("cold vids: %zu", m_coldVids.size()); }