sai_status_t redis_generic_remove( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id) { SWSS_LOG_ENTER(); std::string str_object_id = sai_serialize_object_id(object_id); sai_status_t status = internal_redis_generic_remove( object_type, str_object_id); if (object_type == SAI_OBJECT_TYPE_SWITCH && status == SAI_STATUS_SUCCESS) { SWSS_LOG_NOTICE("removing switch id %s", sai_serialize_object_id(object_id).c_str()); redis_free_virtual_object_id(object_id); // TODO do we need some more actions here ? to clean all // objects that are in the same switch that were snooped // inside metadata ? should that be metadata job? } return status; }
static sai_status_t create_vlan_members() { SWSS_LOG_ENTER(); sai_object_id_t switch_id = ss->getSwitchId(); /* * Crete vlan members for bridge ports. */ for (auto bridge_port_id: bridge_port_list_port_based) { SWSS_LOG_DEBUG("create vlan member for bridge port %s", sai_serialize_object_id(bridge_port_id).c_str()); sai_attribute_t attrs[3]; attrs[0].id = SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID; attrs[0].value.oid = bridge_port_id; attrs[1].id = SAI_VLAN_MEMBER_ATTR_VLAN_ID; attrs[1].value.oid = default_vlan_id; attrs[2].id = SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE; attrs[2].value.s32 = SAI_VLAN_TAGGING_MODE_UNTAGGED; sai_object_id_t vlan_member_id; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_VLAN_MEMBER, &vlan_member_id, switch_id, 3, attrs)); } return SAI_STATUS_SUCCESS; }
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(); }
static sai_status_t create_bridge_ports() { SWSS_LOG_ENTER(); sai_object_id_t switch_id = ss->getSwitchId(); /* * Create bridge port for 1q router. */ sai_attribute_t attr; attr.id = SAI_BRIDGE_PORT_ATTR_TYPE; attr.value.s32 = SAI_BRIDGE_PORT_TYPE_1Q_ROUTER; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_BRIDGE_PORT, &default_bridge_port_1q_router, ss->getSwitchId(), 1, &attr)); attr.id = SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID; CHECK_STATUS(vs_generic_get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, &attr)); /* * Create bridge ports for regular ports. */ sai_object_id_t default_1q_bridge_id = attr.value.oid; bridge_port_list_port_based.clear(); for (const auto &port_id: port_list) { SWSS_LOG_DEBUG("create bridge port for port %s", sai_serialize_object_id(port_id).c_str()); sai_attribute_t attrs[4]; attrs[0].id = SAI_BRIDGE_PORT_ATTR_BRIDGE_ID; attrs[0].value.oid = default_1q_bridge_id; attrs[1].id = SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE; attrs[1].value.s32 = SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW; attrs[2].id = SAI_BRIDGE_PORT_ATTR_PORT_ID; attrs[2].value.oid = port_id; attrs[3].id = SAI_BRIDGE_PORT_ATTR_TYPE; attrs[3].value.s32 = SAI_BRIDGE_PORT_TYPE_PORT; sai_object_id_t bridge_port_id; CHECK_STATUS(vs_generic_create(SAI_OBJECT_TYPE_BRIDGE_PORT, &bridge_port_id, switch_id, 4, attrs)); bridge_port_list_port_based.push_back(bridge_port_id); } return SAI_STATUS_SUCCESS; }
void WatermarkOrch::clearSingleWm(Table *table, string wm_name, vector<sai_object_id_t> &obj_ids) { /* Zero-out some WM in some table for some vector of object ids*/ SWSS_LOG_ENTER(); SWSS_LOG_DEBUG("clear WM %s, for %ld obj ids", wm_name.c_str(), obj_ids.size()); vector<FieldValueTuple> vfvt = {{wm_name, "0"}}; for (sai_object_id_t id: obj_ids) { table->set(sai_serialize_object_id(id), vfvt); } }
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; }
sai_status_t vs_generic_get( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, _In_ uint32_t attr_count, _Out_ sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); std::string str_object_id = sai_serialize_object_id(object_id); sai_object_id_t switch_id = sai_switch_id_query(object_id); return internal_vs_generic_get( object_type, str_object_id, switch_id, attr_count, attr_list); }
sai_status_t redis_generic_get_stats( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, _In_ const sai_enum_metadata_t *stats_enum, _In_ uint32_t number_of_counters, _In_ const int32_t *counter_ids, _Out_ uint64_t *counters) { SWSS_LOG_ENTER(); std::string str_object_id = sai_serialize_object_id(object_id); return internal_redis_generic_get_stats( object_type, str_object_id, stats_enum, number_of_counters, counter_ids, counters); }
sai_status_t redis_bulk_generic_remove( _In_ sai_object_type_t object_type, _In_ uint32_t object_count, _In_ const sai_object_id_t *object_id, /* array */ _Out_ sai_status_t *object_statuses) /* array */ { SWSS_LOG_ENTER(); std::vector<std::string> serialized_object_ids; // on create vid is put in db by syncd for (uint32_t idx = 0; idx < object_count; idx++) { std::string str_object_id = sai_serialize_object_id(object_id[idx]); serialized_object_ids.push_back(str_object_id); } return internal_redis_bulk_generic_remove( object_type, serialized_object_ids, object_statuses); }
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 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); }
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 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 {
static sai_status_t refresh_vlan_member_list( _In_ const sai_attr_metadata_t *meta, _In_ sai_object_id_t vlan_id, _In_ sai_object_id_t switch_id) { SWSS_LOG_ENTER(); auto &all_vlan_members = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_VLAN_MEMBER); auto m_member_list = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_VLAN, SAI_VLAN_ATTR_MEMBER_LIST); auto md_vlan_id = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_VLAN_MEMBER, SAI_VLAN_MEMBER_ATTR_VLAN_ID); //auto md_brportid = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_VLAN_MEMBER, SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID); std::vector<sai_object_id_t> vlan_member_list; /* * We want order as bridge port order (so port order) */ sai_attribute_t attr; auto me = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_VLAN).at(sai_serialize_object_id(vlan_id)); for (auto vm: all_vlan_members) { if (vm.second.at(md_vlan_id->attridname)->getAttr()->value.oid != vlan_id) { /* * Only interested in our vlan */ continue; } // TODO we need order as bridge ports, but we need bridge id! { sai_object_id_t vlan_member_id; sai_deserialize_object_id(vm.first, vlan_member_id); vlan_member_list.push_back(vlan_member_id); } } uint32_t vlan_member_list_count = (uint32_t)vlan_member_list.size(); SWSS_LOG_NOTICE("recalculated %s: %u", m_member_list->attridname, vlan_member_list_count); attr.id = SAI_VLAN_ATTR_MEMBER_LIST; attr.value.objlist.count = vlan_member_list_count; attr.value.objlist.list = vlan_member_list.data(); return vs_generic_set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); }