sai_status_t internal_redis_generic_remove( _In_ sai_object_type_t object_type, _In_ const std::string &serialized_object_id) { SWSS_LOG_ENTER(); std::string str_object_type = sai_serialize_object_type(object_type); std::string key = str_object_type + ":" + serialized_object_id; SWSS_LOG_DEBUG("generic remove key: %s", key.c_str()); if (g_record) { recordLine("r|" + key); } g_asicState->del(key, "remove"); return SAI_STATUS_SUCCESS; }
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"); } }
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 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; } } }
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; }
sai_status_t internal_redis_bulk_generic_remove( _In_ sai_object_type_t object_type, _In_ const std::vector<std::string> &serialized_object_ids, _Out_ sai_status_t *object_statuses) /* array */ { SWSS_LOG_ENTER(); std::string str_object_type = sai_serialize_object_type(object_type); std::vector<swss::FieldValueTuple> entries; /* * We are recording all entries and their statuses, but we send to sairedis * only those that succeeded metadata check, since only those will be * executed on syncd, so there is no need with bothering decoding statuses * on syncd side. */ for (size_t idx = 0; idx < serialized_object_ids.size(); ++idx) { std::string str_attr = ""; swss::FieldValueTuple fvtNoStatus(serialized_object_ids[idx], str_attr); entries.push_back(fvtNoStatus); } /* * We are adding number of entries to actually add ':' to be compatible * with previous */ if (g_record) { std::string joined; for (const auto &e: entries) { // ||obj_id|attr=val|attr=val||obj_id|attr=val|attr=val joined += "||" + fvField(e) + "|" + fvValue(e); } /* * Capital 'C' stands for bulk CREATE operation. */ recordLine("C|" + str_object_type + joined); } // key: object_type:count // field: object_id // value: object_attrs std::string key = str_object_type + ":" + std::to_string(entries.size()); if (entries.size()) { g_asicState->set(key, entries, "bulkremove"); } return SAI_STATUS_SUCCESS; }
sai_status_t redis_generic_stats_function( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, _In_ const sai_enum_metadata_t *enum_metadata, _In_ uint32_t number_of_counters, _In_ const int32_t *counter_ids, _In_ sai_stats_mode_t mode, _Out_ uint64_t *counters) { SWSS_LOG_ENTER(); /* * Do all parameter validation. */ if (object_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_ERROR("object id is NULL"); return SAI_STATUS_INVALID_PARAMETER; } sai_object_type_t ot = sai_object_type_query(object_id); if (ot != object_type) { SWSS_LOG_ERROR("object %s is %s but expected %s", sai_serialize_object_id(object_id).c_str(), sai_serialize_object_type(ot).c_str(), sai_serialize_object_type(object_type).c_str()); return SAI_STATUS_INVALID_PARAMETER; } sai_object_id_t switch_id = sai_switch_id_query(object_id); if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_ERROR("object %s does not correspond to any switch object", sai_serialize_object_id(object_id).c_str()); return SAI_STATUS_INVALID_PARAMETER; } uint32_t count = number_of_counters & ~REDIS_COUNTERS_COUNT_MSB; if (count > REDIS_MAX_COUNTERS) { SWSS_LOG_ERROR("max supported counters to get/clear is %u, but %u given", REDIS_MAX_COUNTERS, count); return SAI_STATUS_INVALID_PARAMETER; } if (counter_ids == NULL) { SWSS_LOG_ERROR("counter ids pointer is NULL"); return SAI_STATUS_INVALID_PARAMETER; } if (counters == NULL) { SWSS_LOG_ERROR("counters output pointer is NULL"); return SAI_STATUS_INVALID_PARAMETER; } if (enum_metadata == NULL) { SWSS_LOG_ERROR("enum metadata pointer is NULL, bug?"); return SAI_STATUS_FAILURE; } for (uint32_t i = 0; i < count; i++) { if (sai_metadata_get_enum_value_name(enum_metadata, counter_ids[i]) == NULL) { SWSS_LOG_ERROR("counter id %u is not allowed on %s", counter_ids[i], enum_metadata->name); return SAI_STATUS_INVALID_PARAMETER; } } switch (mode) { case SAI_STATS_MODE_READ: case SAI_STATS_MODE_READ_AND_CLEAR: break; default: SWSS_LOG_ERROR("counters mode is invalid %d", mode); return SAI_STATUS_INVALID_PARAMETER; } return internal_redis_generic_stats_function( object_type, object_id, switch_id, enum_metadata, number_of_counters, counter_ids, mode, counters); }
sai_status_t internal_redis_generic_get_stats( _In_ sai_object_type_t object_type, _In_ const std::string &serialized_object_id, _In_ const sai_enum_metadata_t *stats_enum, _In_ uint32_t count, _In_ const int32_t *counter_id_list, _Out_ uint64_t *counter_list) { SWSS_LOG_ENTER(); std::vector<swss::FieldValueTuple> entry = serialize_counter_id_list( stats_enum, count, counter_id_list); std::string str_object_type = sai_serialize_object_type(object_type); std::string key = str_object_type + ":" + serialized_object_id; SWSS_LOG_DEBUG("generic get stats key: %s, fields: %lu", key.c_str(), entry.size()); if (g_record) { recordLine("m|" + key + "|" + joinFieldValues(entry)); } // get is special, it will not put data // into asic view, only to message queue g_asicState->set(key, entry, "get_stats"); // wait for response swss::Select s; s.addSelectable(g_redisGetConsumer.get()); while (true) { SWSS_LOG_DEBUG("wait for get_stats response"); swss::Selectable *sel; int result = s.select(&sel, GET_RESPONSE_TIMEOUT); if (result == swss::Select::OBJECT) { swss::KeyOpFieldsValuesTuple kco; g_redisGetConsumer->pop(kco); const std::string &op = kfvOp(kco); const std::string &opkey = kfvKey(kco); SWSS_LOG_DEBUG("response: op = %s, key = %s", opkey.c_str(), op.c_str()); if (op != "getresponse") // ignore non response messages { continue; } sai_status_t status = internal_redis_get_stats_process( object_type, count, counter_list, kco); if (g_record) { const auto &str_status = kfvKey(kco); const auto &values = kfvFieldsValues(kco); // first serialized is status recordLine("M|" + str_status + "|" + joinFieldValues(values)); } SWSS_LOG_DEBUG("generic get status: %d", status); return status; } SWSS_LOG_ERROR("generic get failed due to SELECT operation result"); break; } if (g_record) { recordLine("M|SAI_STATUS_FAILURE"); } SWSS_LOG_ERROR("generic get stats failed to get response"); return SAI_STATUS_FAILURE; }
void channelOpSetReadOnlyAttribute( _In_ const std::string &key, _In_ const std::vector<swss::FieldValueTuple> &values) { SWSS_LOG_ENTER(); for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } if (values.size() != 1) { SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size()); return; } const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX) { SWSS_LOG_ERROR("invalid object type: %d", object_type); return; } auto info = sai_metadata_get_object_type_info(object_type); if (info->isnonobjectid) { SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str()); return; } sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_type_t ot = sai_object_type_query(object_id); if (ot != object_type) { SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s", str_object_type.c_str(), sai_serialize_object_type(ot).c_str()); return; } sai_object_id_t switch_id = sai_switch_id_query(object_id); if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str()); return; } // oid is validated and we got switch id const std::string &str_attr_id = fvField(values.at(0)); const std::string &str_attr_value = fvValue(values.at(0)); auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str()); if (meta == NULL) { SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str()); return; } if (meta->objecttype != ot) { SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s", str_attr_id.c_str(), sai_serialize_object_type(ot).c_str()); return; } // we got attr metadata sai_attribute_t attr; attr.id = meta->attrid; sai_deserialize_attr_value(str_attr_value, *meta, attr); SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str()); sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str()); return; } sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } }; status = info->set(&meta_key, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to set %s to %s on %s", str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str()); } else { SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s", str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str()); } sai_deserialize_free_attribute_value(meta->attrvaluetype, attr); }
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; } }
void handleUnittestChannelOp( _In_ const std::string &op, _In_ const std::string &key, _In_ const std::vector<swss::FieldValueTuple> &values) { /* * Since we will access and modify DB we need to be under mutex. * * NOTE: since this unittest channel is handled in thread, then that means * there is a DELAY from producer and consumer thread in VS, so if user * will set value on the specific READ_ONLY value he should wait for some * time until that value will be propagated to virtual switch. */ MUTEX(); SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("read only SET: op = %s, key = %s", op.c_str(), key.c_str()); if (op == SAI_VS_UNITTEST_ENABLE_UNITTESTS) { bool enable = (key == "true"); meta_unittests_enable(enable); } else if (op == SAI_VS_UNITTEST_SET_RO_OP) { for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } if (values.size() != 1) { SWSS_LOG_ERROR("expected 1 value only, but given: %zu", values.size()); return; } const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_MAX) { SWSS_LOG_ERROR("invalid object type: %d", object_type); return; } auto info = sai_metadata_get_object_type_info(object_type); if (info->isnonobjectid) { SWSS_LOG_ERROR("non object id %s is not supported yet", str_object_type.c_str()); return; } sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_type_t ot = sai_object_type_query(object_id); if (ot != object_type) { SWSS_LOG_ERROR("object type is differnt than provided %s, but oid is %s", str_object_type.c_str(), sai_serialize_object_type(ot).c_str()); return; } sai_object_id_t switch_id = sai_switch_id_query(object_id); if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_ERROR("failed to find switch id for oid %s", str_object_id.c_str()); return; } // oid is validated and we got switch id const std::string &str_attr_id = fvField(values.at(0)); const std::string &str_attr_value = fvValue(values.at(0)); auto meta = sai_metadata_get_attr_metadata_by_attr_id_name(str_attr_id.c_str()); if (meta == NULL) { SWSS_LOG_ERROR("failed to find attr %s", str_attr_id.c_str()); return; } if (meta->objecttype != ot) { SWSS_LOG_ERROR("attr %s belongs to differnt object type than oid: %s", str_attr_id.c_str(), sai_serialize_object_type(ot).c_str()); return; } // we got attr metadata sai_attribute_t attr; attr.id = meta->attrid; sai_deserialize_attr_value(str_attr_value, *meta, attr); SWSS_LOG_NOTICE("switch id is %s", sai_serialize_object_id(switch_id).c_str()); sai_status_t status = meta_unittests_allow_readonly_set_once(meta->objecttype, meta->attrid); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to enable SET readonly attribute once: %s", sai_serialize_status(status).c_str()); return; } sai_object_meta_key_t meta_key = { .objecttype = ot, .objectkey = { .key = { .object_id = object_id } } }; status = info->set(&meta_key, &attr); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to set %s to %s on %s", str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str()); } else { SWSS_LOG_NOTICE("SUCCESS to set %s to %s on %s", str_attr_id.c_str(), str_attr_value.c_str(), str_object_id.c_str()); } sai_deserialize_free_attribute_value(meta->attrvaluetype, attr); } else {
sai_status_t internal_vs_generic_get( _In_ sai_object_type_t object_type, _In_ const std::string &serialized_object_id, _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, _Out_ sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(object_type); auto it = objectHash.find(serialized_object_id); if (it == objectHash.end()) { SWSS_LOG_ERROR("not found %s:%s", sai_serialize_object_type(object_type).c_str(), serialized_object_id.c_str()); return SAI_STATUS_ITEM_NOT_FOUND; } /* * We need reference here since we can potentially update attr hash for RO * object. */ AttrHash& attrHash = it->second; /* * Some of the list query maybe for length, so we can't do * normal serialize, maybe with count only. */ sai_status_t final_status = SAI_STATUS_SUCCESS; for (uint32_t idx = 0; idx < attr_count; ++idx) { sai_attr_id_t id = attr_list[idx].id; auto meta = sai_metadata_get_attr_metadata(object_type, id); if (meta == NULL) { SWSS_LOG_ERROR("failed to find attribute %d for %s:%s", id, sai_serialize_object_type(object_type).c_str(), serialized_object_id.c_str()); return SAI_STATUS_FAILURE; } sai_status_t status; if (HAS_FLAG_READ_ONLY(meta->flags)) { /* * Read only attributes may require recalculation. * Metadata makes sure that non object id's can't have * read only attributes. So here is defenetly OID. */ sai_object_id_t oid; sai_deserialize_object_id(serialized_object_id, oid); status = refresh_read_only(meta, oid, switch_id); if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("%s read only not implemented on %s", meta->attridname, serialized_object_id.c_str()); return status; } } auto ait = attrHash.find(meta->attridname); if (ait == attrHash.end()) { SWSS_LOG_ERROR("%s not implemented on %s", meta->attridname, serialized_object_id.c_str()); return SAI_STATUS_NOT_IMPLEMENTED; } auto attr = ait->second->getAttr(); status = transfer_attributes(object_type, 1, attr, &attr_list[idx], false); if (status == SAI_STATUS_BUFFER_OVERFLOW) { /* * This is considered partial success, since we get correct list * length. Note that other items ARE processes on the list. */ SWSS_LOG_NOTICE("BUFFER_OVERFLOW %s: %s", serialized_object_id.c_str(), meta->attridname); /* * We still continue processing other attributes for get as long as * we only will be getting buffer overflow error. */ final_status = status; continue; } if (status != SAI_STATUS_SUCCESS) { // all other errors SWSS_LOG_ERROR("get failed %s: %s: %s", serialized_object_id.c_str(), meta->attridname, sai_serialize_status(status).c_str()); return status; } } return final_status; }