void helperCheckCpuId() { SWSS_LOG_ENTER(); sai_object_id_t cpuId = saiGetCpuId(); sai_object_id_t redisCpuId = redisGetCpuId(); if (redisCpuId == SAI_NULL_OBJECT_ID) { redisSetDummyAsicStateForRealObjectId(cpuId); SWSS_LOG_INFO("redis cpu id is not defined yet"); redisSetCpuId(cpuId); redisCpuId = cpuId; } if (cpuId != redisCpuId) { // if this happens, we need to remap VIDTORID and RIDTOVID SWSS_LOG_ERROR("FIXME: cpu id differs: %llx vs %llx, ids must be remapped", cpuId, redisCpuId); exit(EXIT_FAILURE); } }
void helperCheckVirtualRouterId() { SWSS_LOG_ENTER(); sai_object_id_t vrId = saiGetDefaultVirtualRouter(); sai_object_id_t redisVrId = redisGetDefaultVirtualRouterId(); if (redisVrId == SAI_NULL_OBJECT_ID) { redisSetDummyAsicStateForRealObjectId(vrId); SWSS_LOG_INFO("redis default virtual router id is not defined yet"); redisSetDefaultVirtualRouterId(vrId); redisVrId = vrId; } if (vrId != redisVrId) { // if this happens, we need to remap VIDTORID and RIDTOVID SWSS_LOG_ERROR("FIXME: default virtual router id differs: %llx vs %llx, ids must be remapped", vrId, redisVrId); exit(EXIT_FAILURE); } }
static sai_status_t create_port_list() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create port list"); // TODO this is static, when we start to "create/remove" ports // we need to update this list since it's dynamic sai_attribute_t attr; sai_object_id_t switch_object_id = ss->getSwitchId(); uint32_t port_count = (uint32_t)port_list.size(); attr.id = SAI_SWITCH_ATTR_PORT_LIST; attr.value.objlist.count = port_count; attr.value.objlist.list = port_list.data(); CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr)); attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; attr.value.u32 = port_count; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr); }
void WatermarkOrch::doTask(SelectableTimer &timer) { SWSS_LOG_ENTER(); if (m_pg_ids.empty()) { init_pg_ids(); } if (m_multicast_queue_ids.empty() and m_unicast_queue_ids.empty()) { init_queue_ids(); } if (&timer == m_telemetryTimer) { /* If the interval was changed */ auto intervT = timespec { .tv_sec = m_telemetryInterval , .tv_nsec = 0 }; m_telemetryTimer->setInterval(intervT); m_telemetryTimer->reset(); clearSingleWm(m_periodicWatermarkTable.get(), "SAI_INGRESS_PRIORITY_GROUP_STAT_XOFF_ROOM_WATERMARK_BYTES", m_pg_ids); clearSingleWm(m_periodicWatermarkTable.get(), "SAI_INGRESS_PRIORITY_GROUP_STAT_SHARED_WATERMARK_BYTES", m_pg_ids); clearSingleWm(m_periodicWatermarkTable.get(), "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES", m_unicast_queue_ids); clearSingleWm(m_periodicWatermarkTable.get(), "SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES", m_multicast_queue_ids); SWSS_LOG_INFO("Periodic watermark cleared by timer!"); } }
void processFdbEntriesForAging() { SWSS_LOG_ENTER(); if (!g_recursive_mutex.try_lock()) { return; } SWSS_LOG_INFO("fdb infos to process: %zu", g_fdb_info_set.size()); uint32_t current = (uint32_t)time(NULL); // find aged fdb entries for (auto it = g_fdb_info_set.begin(); it != g_fdb_info_set.end();) { sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_FDB_AGING_TIME; sai_status_t status = vs_generic_get(SAI_OBJECT_TYPE_SWITCH, it->fdb_entry.switch_id, 1, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_WARN("failed to get FDB aging time for switch %s", sai_serialize_object_id(it->fdb_entry.switch_id).c_str()); ++it; continue; } uint32_t aging_time = attr.value.u32; if (aging_time == 0) { // aging is disabled ++it; continue; } if ((current - it->timestamp) >= aging_time) { fdb_info_t fi = *it; processFdbInfo(fi, SAI_FDB_EVENT_AGED); it = g_fdb_info_set.erase(it); } else { ++it; } } g_recursive_mutex.unlock(); }
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; }
static sai_status_t set_maximum_number_of_childs_per_scheduler_group() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create switch src mac address"); sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_CHILDS_PER_SCHEDULER_GROUP; attr.value.u32 = 16; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr); }
static sai_status_t set_default_notifications() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create defaultr notifications"); sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY; attr.value.ptr = NULL; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr); }
static sai_status_t set_number_of_ecmp_groups() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("set number of ecmp groups"); sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS; attr.value.u32 = 512; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr); }
static sai_status_t create_scheduler_groups() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create scheduler groups"); uint32_t port_sgs_count = 13; // brcm default // NOTE: this is only static data, to keep track of this // we would need to create actual objects and keep them // in respected objects, we need to move in to that // solution when we will start using different "profiles" // currently this is good enough for (const auto &port_id : port_list) { sai_attribute_t attr; attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_SCHEDULER_GROUPS; attr.value.u32 = port_sgs_count; CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); // scheduler groups per port std::vector<sai_object_id_t> sgs; for (uint32_t i = 0; i < port_sgs_count; ++i) { sai_object_id_t sg_id; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_SCHEDULER_GROUP, &sg_id, ss->getSwitchId(), 0, NULL)); sgs.push_back(sg_id); } attr.id = SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST; attr.value.objlist.count = port_sgs_count; attr.value.objlist.list = sgs.data(); CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); CHECK_STATUS(create_scheduler_group_tree(sgs, port_id)); } // SAI_SCHEDULER_GROUP_ATTR_CHILD_COUNT // sched_groups + count // scheduler group are organized in tree and on the bottom there are queues // order matters in returning api return SAI_STATUS_SUCCESS; }
static int profile_get_next_value( _In_ sai_switch_profile_id_t profile_id, _Out_ const char** variable, _Out_ const char** value) { SWSS_LOG_ENTER(); if (value == NULL) { SWSS_LOG_INFO("resetting profile map iterator"); return 0; } if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return -1; } SWSS_LOG_INFO("iterator reached end"); return -1; }
const char* profile_get_value( _In_ sai_switch_profile_id_t profile_id, _In_ const char* variable) { SWSS_LOG_ENTER(); if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return NULL; } auto it = gProfileMap.find(variable); if (it == gProfileMap.end()) { SWSS_LOG_INFO("%s: NULL", variable); return NULL; } SWSS_LOG_INFO("%s: %s", variable, it->second.c_str()); return it->second.c_str(); }
int profile_get_next_value( _In_ sai_switch_profile_id_t profile_id, _Out_ const char** variable, _Out_ const char** value) { SWSS_LOG_ENTER(); if (value == NULL) { SWSS_LOG_INFO("resetting profile map iterator"); gProfileIter = gProfileMap.begin(); return 0; } if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return -1; } if (gProfileIter == gProfileMap.end()) { SWSS_LOG_INFO("iterator reached end"); return -1; } *variable = gProfileIter->first.c_str(); *value = gProfileIter->second.c_str(); SWSS_LOG_INFO("key: %s:%s", *variable, *value); gProfileIter++; return 0; }
void helperCheckLaneMap() { SWSS_LOG_ENTER(); auto redisLaneMap = redisGetLaneMap(); auto laneMap = saiGetHardwareLaneMap(); if (redisLaneMap.size() == 0) { SWSS_LOG_INFO("no lanes defined in redis, seems like it is first syncd start"); // TODO put ports to db ? redisSaveLaneMap(laneMap); redisLaneMap = laneMap; // copy } if (laneMap.size() != redisLaneMap.size()) { SWSS_LOG_ERROR("lanes map size differ: %lu vs %lu", laneMap.size(), redisLaneMap.size()); exit(EXIT_FAILURE); } for (auto kv: laneMap) { sai_uint32_t lane = kv.first; sai_object_id_t portId = kv.second; if (redisLaneMap.find(lane) == redisLaneMap.end()) { SWSS_LOG_ERROR("lane %u not found in redis", lane); exit(EXIT_FAILURE); } if (redisLaneMap[lane] != portId) { // if this happens, we need to remap VIDTORID and RIDTOVID SWSS_LOG_ERROR("FIXME: lane port id differs: %llx vs %llx, port ids must be remapped", portId, redisLaneMap[lane]); exit(EXIT_FAILURE); } } }
static sai_status_t create_acl_entry_min_prio() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create acl entry min prio"); sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY; attr.value.u32 = 1; CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr)); attr.id = SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY; attr.value.u32 = 16000; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr); }
static sai_status_t create_default_virtual_router() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create default virtual router"); sai_object_id_t switch_object_id = ss->getSwitchId(); sai_object_id_t virtual_router_id; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, &virtual_router_id, switch_object_id, 0, NULL)); sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID; attr.value.oid = virtual_router_id; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr); }
static sai_status_t create_default_stp_instance() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create default stp instance"); sai_object_id_t stp_instance_id; sai_object_id_t switch_object_id = ss->getSwitchId(); CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_STP, &stp_instance_id, switch_object_id, 0, NULL)); sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID; attr.value.oid = stp_instance_id; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr); }
static sai_status_t set_switch_mac_address() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create switch src mac address"); sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS; attr.value.mac[0] = 0x11; attr.value.mac[1] = 0x22; attr.value.mac[2] = 0x33; attr.value.mac[3] = 0x44; attr.value.mac[4] = 0x55; attr.value.mac[5] = 0x66; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr); }
static sai_status_t create_qos_queues() { SWSS_LOG_ENTER(); // TODO queues size may change when we will modify queue or ports SWSS_LOG_INFO("create qos queues"); sai_object_id_t switch_object_id = ss->getSwitchId(); // 10 in and 10 out queues per port const uint32_t port_qos_queues_count = 20; for (auto &port_id : port_list) { std::vector<sai_object_id_t> queues; for (uint32_t i = 0; i < port_qos_queues_count; ++i) { sai_object_id_t queue_id; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_QUEUE, &queue_id, switch_object_id, 0, NULL)); queues.push_back(queue_id); } sai_attribute_t attr; attr.id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES; attr.value.u32 = port_qos_queues_count; CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); attr.id = SAI_PORT_ATTR_QOS_QUEUE_LIST; attr.value.objlist.count = port_qos_queues_count; attr.value.objlist.list = queues.data(); CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); } return SAI_STATUS_SUCCESS; }
static sai_status_t create_ingress_priority_groups() { SWSS_LOG_ENTER(); // TODO prioirity groups size may change when we will modify pg or ports SWSS_LOG_INFO("create priority groups"); sai_object_id_t switch_object_id = ss->getSwitchId(); // const uint32_t port_pgs_count = 8; for (auto &port_id : port_list) { std::vector<sai_object_id_t> pgs; for (uint32_t i = 0; i < port_pgs_count; ++i) { sai_object_id_t pg_id; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, &pg_id, switch_object_id, 0, NULL)); pgs.push_back(pg_id); } sai_attribute_t attr; attr.id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS; attr.value.u32 = port_pgs_count; CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); attr.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST; attr.value.objlist.count = port_pgs_count; attr.value.objlist.list = pgs.data(); CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_PORT, port_id, &attr)); } return SAI_STATUS_SUCCESS; }
static sai_status_t create_default_trap_group() { SWSS_LOG_ENTER(); sai_object_id_t switch_object_id = ss->getSwitchId(); SWSS_LOG_INFO("create default trap group"); sai_object_id_t trap_group_id; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP, &trap_group_id, switch_object_id, 0, NULL)); sai_attribute_t attr; // populate trap group on switch attr.id = SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP; attr.value.oid = trap_group_id; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_object_id, &attr); }
static sai_status_t create_default_vlan() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create default vlan"); sai_attribute_t attr; attr.id = SAI_VLAN_ATTR_VLAN_ID; attr.value.u16 = DEFAULT_VLAN_NUMBER; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_VLAN, &default_vlan_id, ss->getSwitchId(), 1, &attr)); /* set default vlan on switch */ attr.id = SAI_SWITCH_ATTR_DEFAULT_VLAN_ID; attr.value.oid = default_vlan_id; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, ss->getSwitchId(), &attr); }
void swss::NotificationConsumer::subscribe() { SWSS_LOG_ENTER(); /* Create new new context to DB */ if (m_db->getContext()->connection_type == REDIS_CONN_TCP) m_subscribe = new DBConnector(m_db->getDB(), m_db->getContext()->tcp.host, m_db->getContext()->tcp.port, NOTIFICATION_SUBSCRIBE_TIMEOUT); else m_subscribe = new DBConnector(m_db->getDB(), m_db->getContext()->unix_sock.path, NOTIFICATION_SUBSCRIBE_TIMEOUT); std::string s = "SUBSCRIBE " + m_channel; RedisReply r(m_subscribe, s, REDIS_REPLY_ARRAY); SWSS_LOG_INFO("subscribed to %s", m_channel.c_str()); }
static sai_status_t create_default_1q_bridge() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create default 1q bridge"); sai_attribute_t attr; attr.id = SAI_BRIDGE_ATTR_TYPE; attr.value.s32 = SAI_BRIDGE_TYPE_1Q; sai_object_id_t switch_id = ss->getSwitchId(); sai_object_id_t default_1q_bridge; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_BRIDGE, &default_1q_bridge, switch_id, 1, &attr)); attr.id = SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID; attr.value.oid = default_1q_bridge; return vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); }
void handleProfileMap(const std::string& profileMapFile) { SWSS_LOG_ENTER(); if (profileMapFile.size() == 0) return; std::ifstream profile(profileMapFile); if (!profile.is_open()) { SWSS_LOG_ERROR("failed to open profile map file: %s : %s", profileMapFile.c_str(), strerror(errno)); exit(EXIT_FAILURE); } std::string line; while(getline(profile, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) continue; size_t pos = line.find("="); if (pos == std::string::npos) { SWSS_LOG_WARN("not found '=' in line %s", line.c_str()); continue; } std::string key = line.substr(0, pos); std::string value = line.substr(pos + 1); gProfileMap[key] = value; SWSS_LOG_INFO("insert: %s:%s", key.c_str(), value.c_str()); } }
static sai_status_t create_cpu_port() { SWSS_LOG_ENTER(); SWSS_LOG_INFO("create cpu port"); sai_attribute_t attr; sai_object_id_t switch_id = ss->getSwitchId(); CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_PORT, &cpu_port_id, switch_id, 0, &attr)); // populate cpu port object on switch attr.id = SAI_SWITCH_ATTR_CPU_PORT; attr.value.oid = cpu_port_id; CHECK_STATUS(vs_generic_set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr)); // set type on cpu attr.id = SAI_PORT_ATTR_TYPE; attr.value.s32 = SAI_PORT_TYPE_CPU; return vs_generic_set(SAI_OBJECT_TYPE_PORT, cpu_port_id, &attr); }
sai_status_t handle_generic( _In_ sai_object_type_t object_type, _In_ const 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(); sai_object_id_t local_id; sai_deserialize_object_id(str_object_id, local_id); SWSS_LOG_DEBUG("generic %s for %s:%s", sai_serialize_common_api(api).c_str(), sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); auto info = sai_metadata_get_object_type_info(object_type); sai_object_meta_key_t meta_key; meta_key.objecttype = object_type; switch (api) { case SAI_COMMON_API_CREATE: { sai_object_id_t switch_id = sai_switch_id_query(local_id); if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_THROW("invalid switch_id translated from VID %s", sai_serialize_object_id(local_id).c_str()); } if (object_type == SAI_OBJECT_TYPE_SWITCH) { update_notifications_pointers(attr_count, attr_list); /* * We are creating switch, in both cases local and redis * switch id is deterministic and should be the same. */ } else { /* * When we creating switch, then switch_id parameter is * ignored, but we can't convert it using vid to rid map, * since rid don't exist yet, so skip translate for switch, * but use translate for all other objects. */ switch_id = translate_local_to_redis(switch_id); } sai_status_t status = info->create(&meta_key, switch_id, attr_count, attr_list); if (status == SAI_STATUS_SUCCESS) { sai_object_id_t rid = meta_key.objectkey.key.object_id; match_redis_with_rec(rid, local_id); SWSS_LOG_INFO("saved VID %s to RID %s", sai_serialize_object_id(local_id).c_str(), sai_serialize_object_id(rid).c_str()); } else { SWSS_LOG_ERROR("failed to create %s", sai_serialize_status(status).c_str()); } return status; } case SAI_COMMON_API_REMOVE: { meta_key.objectkey.key.object_id = translate_local_to_redis(local_id); return info->remove(&meta_key); } case SAI_COMMON_API_SET: { if (object_type == SAI_OBJECT_TYPE_SWITCH) { update_notifications_pointers(1, attr_list); } meta_key.objectkey.key.object_id = translate_local_to_redis(local_id); return info->set(&meta_key, attr_list); } case SAI_COMMON_API_GET: { meta_key.objectkey.key.object_id = translate_local_to_redis(local_id); return info->get(&meta_key, attr_count, attr_list); } default: SWSS_LOG_THROW("generic other apis not implemented"); } }
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); } }
void channelOpSetStats( _In_ const std::string &key, _In_ const std::vector<swss::FieldValueTuple> &values) { SWSS_LOG_ENTER(); // NOTE: we need to find stats for specific object, later SAI already have // this feature and this search could be optimized here: // https://github.com/opencomputeproject/SAI/commit/acc83933ff21c68e8ef10c9826de45807fdc0438 sai_object_id_t oid; sai_deserialize_object_id(key, oid); sai_object_type_t ot = sai_object_type_query(oid); if (ot == SAI_OBJECT_TYPE_NULL) { SWSS_LOG_ERROR("invalid object id: %s", key.c_str()); return; } sai_object_id_t switch_id = sai_switch_id_query(oid); if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_ERROR("unable to get switch_id from oid: %s", key.c_str()); return; } /* * Check if object for statistics was created and exists on switch. */ auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(ot); auto it = objectHash.find(key.c_str()); if (it == objectHash.end()) { SWSS_LOG_ERROR("object not found: %s", key.c_str()); return; } /* * Check if object for statistics have statistic map created, if not * create empty map. */ auto &countersMap = g_switch_state_map.at(switch_id)->countersMap; auto mapit = countersMap.find(key); if (mapit == countersMap.end()) countersMap[key] = std::map<int,uint64_t>(); /* * Find stats enum based on object type. In new metadata we have enum on * object type, but here we need to find it manually enum is in format * "sai_" + object_type + "_stat_t" */ std::string lower_ot = sai_serialize_object_type(ot).substr(16); // 16 = skip "SAI_OBJECT_TYPE_" std::transform(lower_ot.begin(), lower_ot.end(), lower_ot.begin(), ::tolower); std::string stat_enum_name = "sai_" + lower_ot + "_stat_t"; const sai_enum_metadata_t* statenum = NULL; for (size_t i = 0; i < sai_metadata_all_enums_count; ++i) { if (sai_metadata_all_enums[i]->name == stat_enum_name) { SWSS_LOG_INFO("found enum %s", stat_enum_name.c_str()); // found statenum = sai_metadata_all_enums[i]; break; } } if (statenum == NULL) { SWSS_LOG_ERROR("failed to find stat enum: %s", stat_enum_name.c_str()); return; } for (auto v: values) { // value format: stat_enum_name:uint64 auto name = fvField(v); uint64_t value; if (sscanf(fvValue(v).c_str(), "%lu", &value) != 1) { SWSS_LOG_ERROR("failed to deserialize %s as couner value uint64_t", fvValue(v).c_str()); } // linear search int enumvalue = -1; for (size_t i = 0; i < statenum->valuescount; ++i) { if (statenum->valuesnames[i] == name) { enumvalue = statenum->values[i]; break; } } if (enumvalue == -1) { SWSS_LOG_ERROR("failed to find enum value: %s", name.c_str()); continue; } SWSS_LOG_DEBUG("writting %s = %lu on %s", name.c_str(), value, key.c_str()); countersMap.at(key)[enumvalue] = value; } }