std::unordered_map<sai_object_id_t, sai_object_id_t> redisGetObjectMap(std::string key) { SWSS_LOG_ENTER(); auto hash = g_redisClient->hgetall(key); std::unordered_map<sai_object_id_t, sai_object_id_t> map; for (auto &kv: hash) { const std::string &str_key = kv.first; const std::string &str_value = kv.second; sai_object_id_t objectIdKey; sai_object_id_t objectIdValue; int index = 0; sai_deserialize_primitive(str_key, index, objectIdKey); index = 0; sai_deserialize_primitive(str_value, index, objectIdValue); map[objectIdKey] = objectIdValue; } return map; }
std::unordered_map<sai_uint32_t, sai_object_id_t> redisGetLaneMap() { SWSS_LOG_ENTER(); auto hash = g_redisClient->hgetall(LANES); SWSS_LOG_DEBUG("previous lanes: %lu", hash.size()); std::unordered_map<sai_uint32_t, sai_object_id_t> map; for (auto &kv: hash) { const std::string &str_key = kv.first; const std::string &str_value = kv.second; sai_uint32_t lane; sai_object_id_t portId; int index = 0; sai_deserialize_primitive(str_key, index, lane); index = 0; sai_deserialize_primitive(str_value, index, portId); map[lane] = portId; } return map; }
sai_status_t handle_trap( _In_ std::string &str_object_id, _In_ sai_common_api_t api, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); int index = 0; sai_object_id_t dummy_id; sai_deserialize_primitive(str_object_id, index, dummy_id); sai_hostif_trap_id_t trap_id = (sai_hostif_trap_id_t)dummy_id; switch(api) { case SAI_COMMON_API_SET: return sai_hostif_api->set_trap_attribute(trap_id, attr_list); case SAI_COMMON_API_GET: return sai_hostif_api->get_trap_attribute(trap_id, attr_count, attr_list); default: SWSS_LOG_ERROR("trap other apis not implemented"); exit(EXIT_FAILURE); } }
sai_status_t handle_vlan( _In_ std::string &str_object_id, _In_ sai_common_api_t api, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); int index = 0; sai_vlan_id_t vlan_id; sai_deserialize_primitive(str_object_id, index, vlan_id); switch(api) { case SAI_COMMON_API_CREATE: return sai_vlan_api->create_vlan(vlan_id); case SAI_COMMON_API_REMOVE: return sai_vlan_api->remove_vlan(vlan_id); case SAI_COMMON_API_SET: return sai_vlan_api->set_vlan_attribute(vlan_id, attr_list); case SAI_COMMON_API_GET: return sai_vlan_api->get_vlan_attribute(vlan_id, attr_count, attr_list); default: SWSS_LOG_ERROR("vlan other apis not implemented"); exit(EXIT_FAILURE); } }
sai_object_id_t translate_rid_to_vid( _In_ sai_object_id_t rid) { SWSS_LOG_ENTER(); if (rid == SAI_NULL_OBJECT_ID) { SWSS_LOG_DEBUG("translated RID null to VID null"); return SAI_NULL_OBJECT_ID; } sai_object_id_t vid; std::string str_rid; std::string str_vid; sai_serialize_primitive(rid, str_rid); auto pvid = g_redisClient->hget(RIDTOVID, str_rid); if (pvid != NULL) { // object exists str_vid = *pvid; int index = 0; sai_deserialize_primitive(str_vid, index, vid); SWSS_LOG_DEBUG("translated RID %llx to VID %llx", rid, vid); return vid; } SWSS_LOG_INFO("spotted new RID %llx", rid); sai_object_type_t object_type = sai_object_type_query(rid); if (object_type == SAI_OBJECT_TYPE_NULL) { SWSS_LOG_ERROR("sai_object_type_query returned NULL type for RID %llx", rid); exit(EXIT_FAILURE); } vid = redis_create_virtual_object_id(object_type); SWSS_LOG_DEBUG("translated RID %llx to VID %llx", rid, vid); sai_serialize_primitive(vid, str_vid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); g_redisClient->hset(VIDTORID, str_vid, str_rid); return vid; }
sai_object_id_t redisGetCpuId() { SWSS_LOG_ENTER(); auto redisCpuId = g_redisClient->hget(HIDDEN, CPU_PORT_ID); if (redisCpuId == NULL) return SAI_NULL_OBJECT_ID; sai_object_id_t cpuId; int index = 0; sai_deserialize_primitive(*redisCpuId, index, cpuId); return cpuId; }
sai_object_id_t redisGetDefaultVirtualRouterId() { SWSS_LOG_ENTER(); auto redisVrId = g_redisClient->hget(HIDDEN, DEFAULT_VIRTUAL_ROUTER_ID); if (redisVrId == NULL) return SAI_NULL_OBJECT_ID; sai_object_id_t vr_id; int index = 0; sai_deserialize_primitive(*redisVrId, index, vr_id); return vr_id; }
sai_object_id_t translate_vid_to_rid( _In_ sai_object_id_t vid) { SWSS_LOG_ENTER(); if (vid == SAI_NULL_OBJECT_ID) { SWSS_LOG_DEBUG("translated RID null to VID null"); return SAI_NULL_OBJECT_ID; } std::string str_vid; sai_serialize_primitive(vid, str_vid); std::string str_rid; auto prid = g_redisClient->hget(VIDTORID, str_vid); if (prid == NULL) { SWSS_LOG_ERROR("unable to get RID for VID: %s", str_vid.c_str()); exit(EXIT_FAILURE); } str_rid = *prid; sai_object_id_t rid; int index = 0; sai_deserialize_primitive(str_rid, index, rid); SWSS_LOG_DEBUG("translated VID %llx to RID %llx", vid, rid); return rid; }
sai_status_t processEvent(swss::ConsumerTable &consumer) { std::lock_guard<std::mutex> lock(g_mutex); SWSS_LOG_ENTER(); swss::KeyOpFieldsValuesTuple kco; consumer.pop(kco); const std::string &key = kfvKey(kco); const std::string &op = kfvOp(kco); std::string str_object_type = key.substr(0, key.find(":")); std::string str_object_id = key.substr(key.find(":")+1); SWSS_LOG_INFO("key: %s op: %s", key.c_str(), op.c_str()); sai_common_api_t api = SAI_COMMON_API_MAX; if (op == "create") api = SAI_COMMON_API_CREATE; else if (op == "remove") api = SAI_COMMON_API_REMOVE; else if (op == "set") api = SAI_COMMON_API_SET; else if (op == "get") api = SAI_COMMON_API_GET; else { if (op != "delget") SWSS_LOG_ERROR("api %s is not implemented", op.c_str()); return SAI_STATUS_NOT_SUPPORTED; } std::stringstream ss; int index = 0; sai_object_type_t object_type; sai_deserialize_primitive(str_object_type, index, object_type); if (object_type >= SAI_OBJECT_TYPE_MAX) { SWSS_LOG_ERROR("undefined object type %d", object_type); return SAI_STATUS_NOT_SUPPORTED; } const std::vector<swss::FieldValueTuple> &values = kfvFieldsValues(kco); SaiAttributeList list(object_type, values, false); if (api != SAI_COMMON_API_GET) translate_vid_to_rid_list(object_type, list.get_attr_count(), list.get_attr_list()); sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); sai_status_t status; switch (object_type) { case SAI_OBJECT_TYPE_FDB: status = handle_fdb(str_object_id, api, attr_count, attr_list); break; case SAI_OBJECT_TYPE_SWITCH: status = handle_switch(str_object_id, api, attr_count, attr_list); break; case SAI_OBJECT_TYPE_NEIGHBOR: status = handle_neighbor(str_object_id, api, attr_count, attr_list); break; case SAI_OBJECT_TYPE_ROUTE: status = handle_route(str_object_id, api, attr_count, attr_list); break; case SAI_OBJECT_TYPE_VLAN: status = handle_vlan(str_object_id, api, attr_count, attr_list); break; case SAI_OBJECT_TYPE_TRAP: status = handle_trap(str_object_id, api, attr_count, attr_list); break; default: status = handle_generic(object_type, str_object_id, api, attr_count, attr_list); break; } if (api == SAI_COMMON_API_GET) { internal_syncd_get_send(object_type, status, attr_count, attr_list); } else if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to execute api: %s: %d", op.c_str(), status); exit(EXIT_FAILURE); } return status; }
sai_status_t handle_generic( _In_ sai_object_type_t object_type, _In_ std::string &str_object_id, _In_ sai_common_api_t api, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); int index = 0; sai_object_id_t object_id; sai_deserialize_primitive(str_object_id, index, object_id); SWSS_LOG_DEBUG("common generic api: %d", api); switch(api) { case SAI_COMMON_API_CREATE: { SWSS_LOG_DEBUG("generic create for object type %x", object_type); create_fn create = common_create[object_type]; if (create == NULL) { SWSS_LOG_ERROR("create function is not defined for object type %x", object_type); exit(EXIT_FAILURE); } sai_object_id_t real_object_id; sai_status_t status = create(&real_object_id, attr_count, attr_list); if (status == SAI_STATUS_SUCCESS) { // object was created so new object id was generated // we need to save virtual id's to redis db std::string str_vid; std::string str_rid; sai_serialize_primitive(object_id, str_vid); sai_serialize_primitive(real_object_id, str_rid); g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); SWSS_LOG_INFO("saved VID %s to RID %s", str_vid.c_str(), str_rid.c_str()); } else { SWSS_LOG_ERROR("failed to create %d", status); } return status; } case SAI_COMMON_API_REMOVE: { SWSS_LOG_DEBUG("generic remove for object type %x", object_type); remove_fn remove = common_remove[object_type]; if (remove == NULL) { SWSS_LOG_ERROR("remove function is not defined for object type %x", object_type); exit(EXIT_FAILURE); } sai_object_id_t rid = translate_vid_to_rid(object_id); std::string str_vid; sai_serialize_primitive(object_id, str_vid); std::string str_rid; sai_serialize_primitive(rid, str_rid); g_redisClient->hdel(VIDTORID, str_vid); g_redisClient->hdel(RIDTOVID, str_rid); return remove(rid); } case SAI_COMMON_API_SET: { SWSS_LOG_DEBUG("generic set for object type %x", object_type); set_attribute_fn set = common_set_attribute[object_type]; if (set == NULL) { SWSS_LOG_ERROR("set function is not defined for object type %x", object_type); exit(EXIT_FAILURE); } sai_object_id_t rid = translate_vid_to_rid(object_id); return set(rid, attr_list); } case SAI_COMMON_API_GET: { SWSS_LOG_DEBUG("generic get for object type %x", object_type); get_attribute_fn get = common_get_attribute[object_type]; if (get == NULL) { SWSS_LOG_ERROR("get function is not defined for object type %x", object_type); exit(EXIT_FAILURE); } sai_object_id_t rid = translate_vid_to_rid(object_id); return get(rid, attr_count, attr_list); } default: SWSS_LOG_ERROR("generic other apis not implemented"); exit(EXIT_FAILURE); } }