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); }
void update_notifications_pointers( _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list) { SWSS_LOG_ENTER(); /* * Sairedis is updating notifications pointers based on attribute, so when * we will do replay it will have invalid pointers from orchagent, so we * need to override them after create, and after set. * * NOTE: This needs to be updated every time new pointer will be added. */ for (uint32_t index = 0; index < attr_count; ++index) { sai_attribute_t &attr = attr_list[index]; auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); if (meta->attrvaluetype != SAI_ATTR_VALUE_TYPE_POINTER) { continue; } switch (attr.id) { case SAI_SWITCH_ATTR_SWITCH_STATE_CHANGE_NOTIFY: attr.value.ptr = (void*)&on_switch_state_change; break; case SAI_SWITCH_ATTR_SHUTDOWN_REQUEST_NOTIFY: attr.value.ptr = (void*)&on_switch_shutdown_request_notification; break; case SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY: attr.value.ptr = (void*)&on_fdb_event; break; case SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY: attr.value.ptr = (void*)&on_port_state_change; break; case SAI_SWITCH_ATTR_PACKET_EVENT_NOTIFY: attr.value.ptr = (void*)&on_packet_event; break; default: SWSS_LOG_ERROR("pointer for %s is not handled, FIXME!", meta->attridname); break; } } }
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; } } }
void check_attr_conditions( _In_ const sai_attr_metadata_t* md) { META_LOG_ENTER(); switch (md->conditiontype) { case SAI_ATTR_CONDITION_TYPE_NONE: case SAI_ATTR_CONDITION_TYPE_OR: break; default: META_ASSERT_FAIL(md, "invalid condition type specified: %d", md->conditiontype); } bool conditional = md->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE; if (!conditional && md->conditions != NULL) { META_ASSERT_FAIL(md, "not conditional but conditions specified"); } if (!conditional) { return; } if (md->conditions == NULL) { META_ASSERT_FAIL(md, "marked as conditional but no conditions specified"); } switch ((int)md->flags) { case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET: if (md->objecttype != SAI_OBJECT_TYPE_MIRROR_SESSION) { META_ASSERT_FAIL(md, "marked as conditional on non mirror session, but invalid creation flags: 0x%u", md->flags); } break; case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY: case SAI_ATTR_FLAGS_CREATE_ONLY: /* will require default value, on some cases may be dynamic */ break; default: META_ASSERT_FAIL(md, "marked as conditional, but invalid creation flags: 0x%u", md->flags); } /* condition must be the same object type as attribue we check */ size_t index = 0; for (; index < md->conditionslength; ++index) { const sai_attr_condition_t* c = md->conditions[index]; if (c->attrid == md->attrid) { META_ASSERT_FAIL(md, "conditional attr id %d is the same as condition attribute", c->attrid); } const sai_attr_metadata_t* cmd = sai_metadata_get_attr_metadata(md->objecttype, c->attrid); if (cmd == NULL) { META_ASSERT_FAIL(md, "conditional attribute id %d was not defined yet in metadata", c->attrid); } switch (cmd->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_BOOL: META_LOG_INFO("attr id: %d cond.bool: %d", c->attrid, c->condition.booldata); break; case SAI_ATTR_VALUE_TYPE_INT32: if (!cmd->isenum) { META_ASSERT_FAIL(md, "conditional attribute %d is not enum type", cmd->attrid); } META_LOG_INFO("attr id: %d cond.s32: %d ", c->attrid, c->condition.s32); /* check if condition enum is in condition attribute range */ if (sai_metadata_get_enum_value_name(cmd->enummetadata, c->condition.s32) == NULL) { META_ASSERT_FAIL(md, "condition enum %d not found on condition attribute enum range", c->condition.s32); } break; default: META_ASSERT_FAIL(md, "attr value type %d of conditional attribute is not supported yet", cmd->attrvaluetype); } if (cmd->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE) { if (cmd->flags == SAI_ATTR_FLAGS_CREATE_ONLY && cmd->attrvaluetype == SAI_ATTR_VALUE_TYPE_BOOL) { /* ok, that means there is default value (it may be depending on switch intenal) */ } else { META_ASSERT_FAIL(md, "conditional attibute is also conditional, not allowed"); } } switch ((int)cmd->flags) { case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY | SAI_ATTR_FLAGS_KEY: case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY: case SAI_ATTR_FLAGS_CREATE_ONLY: /* * condition attribute must be create only since * if it could change then other object may be required to pass * on creation time that was not passed */ break; default: META_ASSERT_FAIL(md, "conditional attribute must be create only"); } } }
void check_attr_default_value_type( _In_ const sai_attr_metadata_t* md) { META_LOG_ENTER(); switch (md->defaultvaluetype) { case SAI_DEFAULT_VALUE_TYPE_NONE: case SAI_DEFAULT_VALUE_TYPE_CONST: /* check conditions/cretion flags? */ break; case SAI_DEFAULT_VALUE_TYPE_INHERIT: if (md->objecttype == SAI_OBJECT_TYPE_BUFFER_PROFILE && md->attrid == SAI_BUFFER_PROFILE_ATTR_TH_MODE) { break; } META_ASSERT_FAIL(md, "inherit default value type not allowed"); case SAI_DEFAULT_VALUE_TYPE_ATTR_VALUE: { const sai_attr_metadata_t* def = sai_metadata_get_attr_metadata(md->defaultvalueobjecttype, md->defaultvalueattrid); if (def == NULL) { META_ASSERT_FAIL(md, "attr value can't be found"); } if (md->attrvaluetype != def->attrvaluetype) { META_ASSERT_FAIL(md, "attr value attribute value value type is different"); } break; } case SAI_DEFAULT_VALUE_TYPE_ATTR_RANGE: { const sai_attr_metadata_t* def = sai_metadata_get_attr_metadata(md->defaultvalueobjecttype, md->defaultvalueattrid); if (def == NULL) { META_ASSERT_FAIL(md, "attr range can't be found"); } META_ASSERT_FAIL(md, "attr value attribute value range not supported yet"); break; } case SAI_DEFAULT_VALUE_TYPE_EMPTY_LIST: switch (md->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_UINT32_LIST: case SAI_ATTR_VALUE_TYPE_INT32_LIST: case SAI_ATTR_VALUE_TYPE_UINT8_LIST: case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: break; default: META_ASSERT_FAIL(md, "default empty list specified, but attribute is not list"); } break; case SAI_DEFAULT_VALUE_TYPE_VENDOR_SPECIFIC: switch (md->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_MAC: case SAI_ATTR_VALUE_TYPE_UINT64: break; default: META_ASSERT_FAIL(md, "vendor specific not allowed on this type"); } break; default: META_ASSERT_FAIL(md, "invalid default value type specified: %d", md->defaultvaluetype); } }
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; }
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); }