void init_switch_BCM56850( _In_ sai_object_id_t switch_id) { SWSS_LOG_ENTER(); if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_THROW("init switch with NULL switch id is not allowed"); } if (g_switch_state_map.find(switch_id) != g_switch_state_map.end()) { SWSS_LOG_THROW("switch already exists 0x%lx", switch_id); } ss = g_switch_state_map[switch_id] = std::make_shared<SwitchState>(switch_id); sai_status_t status = initialize_default_objects(); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("unable to init switch %s", sai_serialize_status(status).c_str()); } SWSS_LOG_NOTICE("initialized switch 0x%lx", switch_id); }
sai_status_t handle_route( _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_route_entry_t route_entry; sai_deserialize_route_entry(str_object_id, route_entry); route_entry.switch_id = translate_local_to_redis(route_entry.switch_id); route_entry.vr_id = translate_local_to_redis(route_entry.vr_id); switch(api) { case SAI_COMMON_API_CREATE: return sai_metadata_sai_route_api->create_route_entry(&route_entry, attr_count, attr_list); case SAI_COMMON_API_REMOVE: return sai_metadata_sai_route_api->remove_route_entry(&route_entry); case SAI_COMMON_API_SET: return sai_metadata_sai_route_api->set_route_entry_attribute(&route_entry, attr_list); case SAI_COMMON_API_GET: return sai_metadata_sai_route_api->get_route_entry_attribute(&route_entry, attr_count, attr_list); default: SWSS_LOG_THROW("route other apis not implemented"); } }
void uninit_switch_BCM56850( _In_ sai_object_id_t switch_id) { SWSS_LOG_ENTER(); if (g_switch_state_map.find(switch_id) == g_switch_state_map.end()) { SWSS_LOG_THROW("switch don't exists 0x%lx", switch_id); } SWSS_LOG_NOTICE("remove switch 0x%lx", switch_id); g_switch_state_map.erase(switch_id); }
void performSleep(const std::string& line) { SWSS_LOG_ENTER(); // timestamp|action|sleeptime auto v = swss::tokenize(line, '|'); if (v.size() < 3) { SWSS_LOG_THROW("invalid line %s", line.c_str()); } uint32_t useconds; sai_deserialize_number(v[2], useconds); if (useconds > 0) { useconds *= 1000; // 1ms resolution is enough for sleep SWSS_LOG_NOTICE("usleep(%u)", useconds); usleep(useconds); } }
sai_object_id_t translate_local_to_redis( _In_ sai_object_id_t rid) { SWSS_LOG_ENTER(); SWSS_LOG_DEBUG("translating local RID %s", sai_serialize_object_id(rid).c_str()); if (rid == SAI_NULL_OBJECT_ID) { return SAI_NULL_OBJECT_ID; } auto it = local_to_redis.find(rid); if (it == local_to_redis.end()) { SWSS_LOG_THROW("failed to translate local RID %s", sai_serialize_object_id(rid).c_str()); } return it->second; }
std::vector<swss::FieldValueTuple> serialize_counter_id_list( _In_ const sai_enum_metadata_t *stats_enum, _In_ uint32_t count, _In_ const int32_t *counter_id_list) { SWSS_LOG_ENTER(); std::vector<swss::FieldValueTuple> values; for (uint32_t i = 0; i < count; i++) { const char *name = sai_metadata_get_enum_value_name(stats_enum, counter_id_list[i]); if (name == NULL) { SWSS_LOG_THROW("failed to find enum %d in %s", counter_id_list[i], stats_enum->name); } values.emplace_back(name, ""); } return std::move(values); }
void match_redis_with_rec( sai_object_id_t get_oid, sai_object_id_t oid) { SWSS_LOG_ENTER(); auto it = redis_to_local.find(get_oid); if (it == redis_to_local.end()) { redis_to_local[get_oid] = oid; local_to_redis[oid] = get_oid; } if (oid != redis_to_local[get_oid]) { SWSS_LOG_THROW("match failed, oid order is mismatch :( oid 0x%lx get_oid 0x%lx second 0x%lx", oid, get_oid, redis_to_local[get_oid]); } SWSS_LOG_DEBUG("map size: %zu", local_to_redis.size()); }
void performNotifySyncd(const std::string& request, const std::string response) { SWSS_LOG_ENTER(); // timestamp|action|data auto r = swss::tokenize(request, '|'); auto R = swss::tokenize(response, '|'); if (r[1] != "a" || R[1] != "A") { SWSS_LOG_THROW("invalid syncd notify request/response %s/%s", request.c_str(), response.c_str()); } if (g_notifySyncd == false) { SWSS_LOG_NOTICE("skipping notify syncd, selected by user"); return; } // tell syncd that we are compiling new view sai_attribute_t attr; attr.id = SAI_REDIS_SWITCH_ATTR_NOTIFY_SYNCD; const std::string requestAction = r[2]; if (requestAction == SYNCD_INIT_VIEW) { attr.value.s32 = SAI_REDIS_NOTIFY_SYNCD_INIT_VIEW; } else if (requestAction == SYNCD_APPLY_VIEW) { attr.value.s32 = SAI_REDIS_NOTIFY_SYNCD_APPLY_VIEW; } else { SWSS_LOG_THROW("invalid syncd notify request: %s", request.c_str()); } /* * NOTE: We don't need actual switch to set those attributes. */ sai_object_id_t switch_id = SAI_NULL_OBJECT_ID; sai_status_t status = sai_metadata_sai_switch_api->set_switch_attribute(switch_id, &attr); const std::string& responseStatus = R[2]; sai_status_t response_status; sai_deserialize_status(responseStatus, response_status); if (status != response_status) { SWSS_LOG_THROW("response status %s is different than syncd status %s", responseStatus.c_str(), sai_serialize_status(status).c_str()); } if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to notify syncd %s", sai_serialize_status(status).c_str()); } // OK }
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"); } }
void match_redis_with_rec( sai_object_type_t object_type, uint32_t get_attr_count, sai_attribute_t* get_attr_list, uint32_t attr_count, sai_attribute_t* attr_list) { SWSS_LOG_ENTER(); if (get_attr_count != attr_count) { SWSS_LOG_THROW("list number don't match %u != %u", get_attr_count, attr_count); } for (uint32_t i = 0; i < attr_count; ++i) { sai_attribute_t &get_attr = get_attr_list[i]; sai_attribute_t &attr = attr_list[i]; auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %s, attribute %d", sai_serialize_object_type(object_type).c_str(), attr.id); } switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: match_redis_with_rec(get_attr.value.oid, attr.value.oid); break; case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: match_redis_with_rec(get_attr.value.objlist, attr.value.objlist); break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) match_redis_with_rec(get_attr.value.aclfield.data.oid, attr.value.aclfield.data.oid); break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) match_redis_with_rec(get_attr.value.aclfield.data.objlist, attr.value.aclfield.data.objlist); break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) match_redis_with_rec(get_attr.value.aclaction.parameter.oid, attr.value.aclaction.parameter.oid); break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) match_redis_with_rec(get_attr.value.aclaction.parameter.objlist, attr.value.aclaction.parameter.objlist); break; default: // XXX if (meta->isoidattribute) if (meta->allowedobjecttypeslength > 0) { SWSS_LOG_THROW("attribute %s is oid attribute but not handled, FIXME", meta->attridname); } break; } } }
void translate_local_to_redis( _In_ sai_object_type_t object_type, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); for (uint32_t i = 0; i < attr_count; i++) { sai_attribute_t &attr = attr_list[i]; auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %s, attribute %d", sai_serialize_object_type(object_type).c_str(), attr.id); } switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: attr.value.oid = translate_local_to_redis(attr.value.oid); break; case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: translate_local_to_redis(attr.value.objlist); break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) attr.value.aclfield.data.oid = translate_local_to_redis(attr.value.aclfield.data.oid); break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) translate_local_to_redis(attr.value.aclfield.data.objlist); break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) attr.value.aclaction.parameter.oid = translate_local_to_redis(attr.value.aclaction.parameter.oid); break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) translate_local_to_redis(attr.value.aclaction.parameter.objlist); break; default: // XXX if (meta->isoidattribute) if (meta->allowedobjecttypeslength > 0) { SWSS_LOG_THROW("attribute %s is oid attribute but not handled, FIXME", meta->attridname); } break; } } }
int replay(int argc, char **argv) { //swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG); SWSS_LOG_ENTER(); if (argc < 2) { fprintf(stderr, "ERR: need to specify filename\n"); return -1; } char* filename = argv[argc - 1]; SWSS_LOG_NOTICE("using file: %s", filename); std::ifstream infile(filename); if (!infile.is_open()) { SWSS_LOG_ERROR("failed to open file %s", filename); return -1; } std::string line; while (std::getline(infile, line)) { // std::cout << "processing " << line << std::endl; sai_common_api_t api = SAI_COMMON_API_CREATE; auto p = line.find_first_of("|"); char op = line[p+1]; switch (op) { case 'a': { std::string response; do { // this line may be notification, we need to skip if (!std::getline(infile, response)) { SWSS_LOG_THROW("failed to read next file from file, previous: %s", line.c_str()); } } while (response[response.find_first_of("|") + 1] == 'n'); performNotifySyncd(line, response); } continue; case '@': performSleep(line); continue; case 'c': api = SAI_COMMON_API_CREATE; break; case 'r': api = SAI_COMMON_API_REMOVE; break; case 's': api = SAI_COMMON_API_SET; break; case 'S': processBulk((sai_common_api_t)SAI_COMMON_API_BULK_SET, line); continue; case 'g': api = SAI_COMMON_API_GET; break; case '#': case 'n': continue; // skip comment and notification default: SWSS_LOG_THROW("unknown op %c on line %s", op, line.c_str()); } // timestamp|action|objecttype:objectid|attrid=value,... auto fields = swss::tokenize(line, '|'); // objecttype:objectid (object id may contain ':') auto start = fields[2].find_first_of(":"); auto str_object_type = fields[2].substr(0, start); auto str_object_id = fields[2].substr(start + 1); sai_object_type_t object_type = deserialize_object_type(str_object_type); auto values = get_values(fields); SaiAttributeList list(object_type, values, false); sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); SWSS_LOG_DEBUG("attr count: %u", list.get_attr_count()); if (api != SAI_COMMON_API_GET) { translate_local_to_redis(object_type, attr_count, attr_list); } sai_status_t status; auto info = sai_metadata_get_object_type_info(object_type); switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: status = handle_fdb(str_object_id, api, attr_count, attr_list); break; case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: status = handle_neighbor(str_object_id, api, attr_count, attr_list); break; case SAI_OBJECT_TYPE_ROUTE_ENTRY: status = handle_route(str_object_id, api, attr_count, attr_list); break; default: if (info->isnonobjectid) { SWSS_LOG_THROW("object %s:%s is non object id, but not handled, FIXME", sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); } status = handle_generic(object_type, str_object_id, api, attr_count, attr_list); break; } if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to execute api: %c: %s", op, sai_serialize_status(status).c_str()); } if (api == SAI_COMMON_API_GET) { std::string response; do { // this line may be notification, we need to skip std::getline(infile, response); } while (response[response.find_first_of("|") + 1] == 'n'); try { handle_get_response(object_type, attr_count, attr_list, response); } catch (const std::exception &e) { SWSS_LOG_NOTICE("line: %s", line.c_str()); SWSS_LOG_NOTICE("resp: %s", response.c_str()); exit(EXIT_FAILURE); } } } infile.close(); SWSS_LOG_NOTICE("finished replaying %s with SUCCESS", filename); return 0; }
void getPortLaneMap( _Inout_ std::vector<std::vector<uint32_t>> &laneMap) { SWSS_LOG_ENTER(); laneMap.clear(); for (auto v: g_laneMap) { size_t s = v.size(); if (s != 1 && s != 2 && s != 4) { SWSS_LOG_THROW("invald number of lanes for interface: %zu", s); } laneMap.push_back(v); } if (g_laneMap.size()) { SWSS_LOG_NOTICE("got port lane map with %zu interfaces", laneMap.size()); return; } const uint32_t default_port_count = 32; sai_uint32_t default_lanes[] = { 29,30,31,32, 25,26,27,28, 37,38,39,40, 33,34,35,36, 41,42,43,44, 45,46,47,48, 5,6,7,8, 1,2,3,4, 9,10,11,12, 13,14,15,16, 21,22,23,24, 17,18,19,20, 49,50,51,52, 53,54,55,56, 61,62,63,64, 57,58,59,60, 65,66,67,68, 69,70,71,72, 77,78,79,80, 73,74,75,76, 105,106,107,108, 109,110,111,112, 117,118,119,120, 113,114,115,116, 121,122,123,124, 125,126,127,128, 85,86,87,88, 81,82,83,84, 89,90,91,92, 93,94,95,96, 97,98,99,100, 101,102,103,104 }; // populate default lane map for (size_t i = 0; i < default_port_count; i++) { std::vector<uint32_t> portLanes; for(int j = 0; j < 4; j++) portLanes.push_back(default_lanes[4*i + j]); laneMap.push_back(portLanes); } SWSS_LOG_NOTICE("populated default port lane map with %zu interfaces", laneMap.size()); }
static sai_status_t refresh_bridge_port_list( _In_ const sai_attr_metadata_t *meta, _In_ sai_object_id_t bridge_id, _In_ sai_object_id_t switch_id) { SWSS_LOG_ENTER(); /* * TODO possible issues with vxlan and lag. */ auto &all_bridge_ports = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT); sai_attribute_t attr; auto m_port_list = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE, SAI_BRIDGE_ATTR_PORT_LIST); auto m_port_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID); auto m_bridge_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_BRIDGE_ID); /* * First get all port's that belong to this bridge id. */ std::map<sai_object_id_t, AttrHash> bridge_port_list_on_bridge_id; for (const auto &bp: all_bridge_ports) { auto it = bp.second.find(m_bridge_id->attridname); if (it == bp.second.end()) { continue; } if (bridge_id == it->second->getAttr()->value.oid) { /* * This bridge port belongs to currently processing bridge ID. */ sai_object_id_t bridge_port; sai_deserialize_object_id(bp.first, bridge_port); bridge_port_list_on_bridge_id[bridge_port] = bp.second; } } /* * Now sort those bridge port id's by port id to be consistent. */ std::vector<sai_object_id_t> bridge_port_list; for (const auto &p: port_list) { for (const auto &bp: bridge_port_list_on_bridge_id) { auto it = bp.second.find(m_port_id->attridname); if (it == bp.second.end()) { SWSS_LOG_THROW("bridge port is missing %s, not supported yet, FIXME", m_port_id->attridname); } if (p == it->second->getAttr()->value.oid) { bridge_port_list.push_back(bp.first); } } } if (bridge_port_list_on_bridge_id.size() != bridge_port_list.size()) { SWSS_LOG_THROW("filter by port id failed size on lists is different: %zu vs %zu", bridge_port_list_on_bridge_id.size(), bridge_port_list.size()); } uint32_t bridge_port_list_count = (uint32_t)bridge_port_list.size(); SWSS_LOG_NOTICE("recalculated %s: %u", m_port_list->attridname, bridge_port_list_count); attr.id = SAI_BRIDGE_ATTR_PORT_LIST; attr.value.objlist.count = bridge_port_list_count; attr.value.objlist.list = bridge_port_list.data(); return vs_generic_set(SAI_OBJECT_TYPE_BRIDGE, bridge_id, &attr); }
sai_status_t handle_bulk_route( _In_ const std::vector<std::string> &object_ids, _In_ sai_common_api_t api, _In_ const std::vector<std::shared_ptr<SaiAttributeList>> &attributes, _In_ const std::vector<sai_status_t> &recorded_statuses) { SWSS_LOG_ENTER(); std::vector<sai_route_entry_t> routes; for (size_t i = 0; i < object_ids.size(); ++i) { sai_route_entry_t route_entry; sai_deserialize_route_entry(object_ids[i], route_entry); route_entry.vr_id = translate_local_to_redis(route_entry.vr_id); routes.push_back(route_entry); SWSS_LOG_DEBUG("route: %s", object_ids[i].c_str()); } std::vector<sai_status_t> statuses; statuses.resize(recorded_statuses.size()); if (api == (sai_common_api_t)SAI_COMMON_API_BULK_SET) { /* * TODO: since SDK don't support bulk route api yet, we just use our * implementation, and later on we can switch to SDK api. * * TODO: we need to get operation type from recording, currently is not * serialized and it is hard coded here. */ std::vector<sai_attribute_t> attrs; for (const auto &a: attributes) { /* * Set has only 1 attribute, so we can just join them nicely here. */ attrs.push_back(a->get_attr_list()[0]); } sai_status_t status = sai_bulk_set_route_entry_attribute( (uint32_t)routes.size(), routes.data(), attrs.data(), SAI_BULK_OP_TYPE_INGORE_ERROR, // TODO we need to get that from recording statuses.data()); if (status != SAI_STATUS_SUCCESS) { /* * Entire API failes, so no need to compare statuses. */ return status; } for (size_t i = 0; i < statuses.size(); ++i) { if (statuses[i] != recorded_statuses[i]) { /* * If recorded statuses are different than received, throw * excetion since data don't match. */ SWSS_LOG_THROW("recorded status is %s but returned is %s on %s", sai_serialize_status(recorded_statuses[i]).c_str(), sai_serialize_status(statuses[i]).c_str(), object_ids[i].c_str()); } } return status; } else { SWSS_LOG_THROW("api %d is not supported in bulk route", api); } }
void processBulk( _In_ sai_common_api_t api, _In_ const std::string &line) { SWSS_LOG_ENTER(); if (!line.size()) { return; } if (api != (sai_common_api_t)SAI_COMMON_API_BULK_SET) { SWSS_LOG_THROW("bulk common api %d is not supported yet, FIXME", api); } /* * Here we know we have bulk SET api */ // timestamp|action|objecttype||objectid|attrid=value|...|status||objectid||objectid|attrid=value|...|status||... auto fields = tokenize(line, "||"); auto first = fields.at(0); // timestamp|acion|objecttype std::string str_object_type = swss::tokenize(first, '|').at(2); sai_object_type_t object_type = deserialize_object_type(str_object_type); std::vector<std::string> object_ids; std::vector<std::shared_ptr<SaiAttributeList>> attributes; std::vector<sai_status_t> statuses; for (size_t idx = 1; idx < fields.size(); ++idx) { // object_id|attr=value|...|status const std::string &joined = fields[idx]; auto split = swss::tokenize(joined, '|'); std::string str_object_id = split.front(); object_ids.push_back(str_object_id); std::string str_status = split.back(); sai_status_t status; sai_deserialize_status(str_status, status); statuses.push_back(status); std::vector<swss::FieldValueTuple> entries; // attributes per object id // skip front object_id and back status SWSS_LOG_DEBUG("processing: %s", joined.c_str()); for (size_t i = 1; i < split.size() - 1; ++i) { const auto &item = split[i]; auto start = item.find_first_of("="); auto field = item.substr(0, start); auto value = item.substr(start + 1); swss::FieldValueTuple entry(field, value); entries.push_back(entry); } // since now we converted this to proper list, we can extract attributes std::shared_ptr<SaiAttributeList> list = std::make_shared<SaiAttributeList>(object_type, entries, false); sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); if (api != (sai_common_api_t)SAI_COMMON_API_BULK_GET) { translate_local_to_redis(object_type, attr_count, attr_list); } attributes.push_back(list); } sai_status_t status; switch (object_type) { case SAI_OBJECT_TYPE_ROUTE_ENTRY: status = handle_bulk_route(object_ids, api, attributes, statuses); break; default: SWSS_LOG_THROW("bulk op for %s is not supported yet, FIXME", sai_serialize_object_type(object_type).c_str()); } if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to execute bulk api, FIXME"); } }
void match_list_lengths( sai_object_type_t object_type, uint32_t get_attr_count, sai_attribute_t* get_attr_list, uint32_t attr_count, sai_attribute_t* attr_list) { SWSS_LOG_ENTER(); if (get_attr_count != attr_count) { SWSS_LOG_THROW("list number don't match %u != %u", get_attr_count, attr_count); } for (uint32_t i = 0; i < attr_count; ++i) { sai_attribute_t &get_attr = get_attr_list[i]; sai_attribute_t &attr = attr_list[i]; auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %s, attribute %d", sai_serialize_object_type(object_type).c_str(), attr.id); } switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: CHECK_LIST(value.objlist); break; case SAI_ATTR_VALUE_TYPE_UINT8_LIST: CHECK_LIST(value.u8list); break; case SAI_ATTR_VALUE_TYPE_INT8_LIST: CHECK_LIST(value.s8list); break; case SAI_ATTR_VALUE_TYPE_UINT16_LIST: CHECK_LIST(value.u16list); break; case SAI_ATTR_VALUE_TYPE_INT16_LIST: CHECK_LIST(value.s16list); break; case SAI_ATTR_VALUE_TYPE_UINT32_LIST: CHECK_LIST(value.u32list); break; case SAI_ATTR_VALUE_TYPE_INT32_LIST: CHECK_LIST(value.s32list); break; case SAI_ATTR_VALUE_TYPE_VLAN_LIST: CHECK_LIST(value.vlanlist); break; case SAI_ATTR_VALUE_TYPE_QOS_MAP_LIST: CHECK_LIST(value.qosmap); break; case SAI_ATTR_VALUE_TYPE_TUNNEL_MAP_LIST: CHECK_LIST(value.tunnelmap); break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: CHECK_LIST(value.aclfield.data.objlist); break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT8_LIST: CHECK_LIST(value.aclfield.data.u8list); CHECK_LIST(value.aclfield.mask.u8list); break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: CHECK_LIST(value.aclaction.parameter.objlist); break; default: break; } } }