/* Parse the attributes */ static cps_api_return_code_t nas_qos_cps_parse_attr(cps_api_object_t obj, nas_qos_priority_group &priority_group) { uint64_t val; cps_api_object_it_t it; cps_api_object_it_begin(obj,&it); for ( ; cps_api_object_it_valid(&it) ; cps_api_object_it_next(&it) ) { cps_api_attr_id_t id = cps_api_object_attr_id(it.attr); switch (id) { case BASE_QOS_PRIORITY_GROUP_PORT_ID: case BASE_QOS_PRIORITY_GROUP_LOCAL_ID: case BASE_QOS_PRIORITY_GROUP_ID: break; // These are not settable from cps case BASE_QOS_PRIORITY_GROUP_BUFFER_PROFILE_ID: val = cps_api_object_attr_data_u64(it.attr); priority_group.mark_attr_dirty(id); priority_group.set_buffer_profile(val); break; case CPS_API_ATTR_RESERVE_RANGE_END: // skip keys break; default: EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MAJOR, "QOS", "Unrecognized option: %d", id); return NAS_QOS_E_UNSUPPORTED; } } return cps_api_ret_code_OK; }
bool cps_api_filter_get_count(cps_api_object_t obj, size_t *obj_count) { cps_api_attr_id_t ids[] = { CPS_API_ATTR_INFO, cps_api_ATTR_Q_COUNT}; cps_api_object_attr_t attr = cps_api_object_e_get(obj,ids,sizeof(ids)/sizeof(*ids)); if (attr==NULL) return false; *obj_count = (size_t)cps_api_object_attr_data_u64(attr); return true; }
/* Parse the attributes */ static cps_api_return_code_t nas_qos_cps_parse_attr(cps_api_object_t obj, nas_qos_scheduler_group &scheduler_group) { uint_t val; uint64_t val64; cps_api_object_it_t it; cps_api_object_it_begin(obj,&it); for ( ; cps_api_object_it_valid(&it) ; cps_api_object_it_next(&it) ) { cps_api_attr_id_t id = cps_api_object_attr_id(it.attr); switch (id) { case BASE_QOS_SCHEDULER_GROUP_SWITCH_ID: case BASE_QOS_SCHEDULER_GROUP_ID: break; // These are for part of the keys case BASE_QOS_SCHEDULER_GROUP_CHILD_COUNT: case BASE_QOS_SCHEDULER_GROUP_CHILD_LIST: // non-configurable. break; case BASE_QOS_SCHEDULER_GROUP_PORT_ID: val = cps_api_object_attr_data_u32(it.attr); if (scheduler_group.set_port_id(val) != STD_ERR_OK) return NAS_QOS_E_FAIL; break; case BASE_QOS_SCHEDULER_GROUP_LEVEL: val = cps_api_object_attr_data_u32(it.attr); scheduler_group.set_level(val); break; case BASE_QOS_SCHEDULER_GROUP_SCHEDULER_PROFILE_ID: val64 = cps_api_object_attr_data_u64(it.attr); scheduler_group.set_scheduler_profile_id(val64); break; case CPS_API_ATTR_RESERVE_RANGE_END: // skip keys break; default: EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MAJOR, "QOS", "Unrecognized option: %d", id); return NAS_QOS_E_UNSUPPORTED; } } return cps_api_ret_code_OK; }
bool nas::ndi_obj_id_table_cps_unserialize (ndi_obj_id_table_t& table, cps_api_object_t cps_obj, cps_api_attr_id_t *attr_id_list, size_t attr_id_size) { cps_api_object_it_t it_list; if (!cps_api_object_it(cps_obj, attr_id_list, attr_id_size, &it_list)) { // Opaque data not found NAS_COM_ERR ("Could not find opaque attribute \n"); return false; } int inst = 0; nas::ndi_obj_id_table_t temp_table; for (cps_api_object_it_inside (&it_list); cps_api_object_it_valid(&it_list); cps_api_object_it_next (&it_list), inst++) { npu_id_t npu_id = 0; ndi_obj_id_t ndi_obj_id = 0; NAS_COM_TRACE (3, "Unserializing entry %d\n", inst+1); cps_api_object_it_t it_map_entry = it_list; for (cps_api_object_it_inside (&it_map_entry); cps_api_object_it_valid (&it_map_entry); cps_api_object_it_next (&it_map_entry)) { switch (cps_api_object_attr_id (it_map_entry.attr)) { case OPAQUE_NPU_ATTR_ID: npu_id = cps_api_object_attr_data_u32 (it_map_entry.attr); NAS_COM_TRACE (3, "NPU ID %d\n", npu_id); break; case OPAQUE_NDI_OBJ_ATTR_ID: ndi_obj_id = cps_api_object_attr_data_u64 (it_map_entry.attr); NAS_COM_TRACE (3, "NDI Obj ID 0x%lx\n", ndi_obj_id); break; } } temp_table[npu_id] = ndi_obj_id; } table = std::move (temp_table); return true; }
/** * This function provides NAS-QoS Map CPS API read function * @Param Standard CPS API params * @Return Standard Error Code */ cps_api_return_code_t nas_qos_cps_api_map_read_type (void * context, cps_api_get_params_t * param, size_t ix, nas_qos_map_type_t map_type) { cps_api_object_t obj = cps_api_object_list_get(param->filters, ix); nas_attr_id_t obj_id; uint_t switch_id = 0; obj_id = qos_map_map_id_obj_id(map_type); cps_api_object_attr_t map_attr = cps_api_get_key_data(obj, obj_id); nas_obj_id_t map_id = (map_attr? cps_api_object_attr_data_u64(map_attr): 0); // check the request is on Map level or Entry level bool is_map_entry; cps_api_return_code_t rc = cps_api_ret_code_OK; if ((rc = qos_map_key_check(obj, map_type, &is_map_entry)) != cps_api_ret_code_OK) { EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Key error"); return rc; } obj_id = qos_map_entry_key_1_obj_id(map_type); cps_api_object_attr_t entry_attr = cps_api_get_key_data(obj, obj_id); if (entry_attr == NULL && is_map_entry) { // Inner list does not support wildcard get. EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Key value must be specified for inner list\n"); return NAS_QOS_E_MISSING_KEY; } nas_qos_map_entry_key_t search_key; if (entry_attr) { search_key.any = *(uint8_t *)cps_api_object_attr_data_bin(entry_attr); } if (map_type == NDI_QOS_MAP_TC_TO_QUEUE || map_type == NDI_QOS_MAP_TC_COLOR_TO_DOT1P || map_type == NDI_QOS_MAP_TC_COLOR_TO_DSCP || map_type == NDI_QOS_MAP_PG_TO_PFC || map_type == NDI_QOS_MAP_PFC_TO_QUEUE) { obj_id = qos_map_entry_key_2_obj_id(map_type); cps_api_object_attr_t entry_key2_attr = cps_api_get_key_data(obj, obj_id); if (entry_key2_attr == NULL && is_map_entry) { // Inner list does not support wildcard get. EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Secondary Key value missing for inner list\n"); return NAS_QOS_E_MISSING_KEY; } if (entry_key2_attr) { uint32_t key2; if (map_type == NDI_QOS_MAP_PG_TO_PFC) key2 = *(uint8_t *)cps_api_object_attr_data_bin(entry_key2_attr); else key2 = cps_api_object_attr_data_u32(entry_key2_attr); // form a complex key uint_t comp_key = MAKE_KEY(search_key.any, key2); if (map_type == NDI_QOS_MAP_TC_TO_QUEUE) search_key.tc_queue_type = comp_key; else if (map_type == NDI_QOS_MAP_TC_COLOR_TO_DOT1P || map_type == NDI_QOS_MAP_TC_COLOR_TO_DSCP) search_key.tc_color = comp_key; else if (map_type == NDI_QOS_MAP_PG_TO_PFC) search_key.pg_prio = comp_key; else if (map_type == NDI_QOS_MAP_PFC_TO_QUEUE) search_key.prio_queue_type = comp_key; } } EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Read switch id %u, map id %u\n", switch_id, map_id); nas_qos_switch * p_switch = nas_qos_get_switch(switch_id); if (p_switch == NULL) return NAS_QOS_E_FAIL; nas_qos_map * map; if (map_id) { map = p_switch->get_map(map_id); if (map == NULL) return NAS_QOS_E_FAIL; rc = _append_one_map(param, switch_id, map, map_type, search_key, is_map_entry); } else { // map id is not specified for (map_iter_t it = p_switch->get_map_it_begin(); it != p_switch->get_map_it_end(); it++) { map = &it->second; rc = _append_one_map(param, switch_id, map, map_type, search_key, false); if (rc != cps_api_ret_code_OK) return rc; } } return rc; }
static cps_api_return_code_t nas_qos_cps_api_scheduler_group_delete( cps_api_object_t obj, cps_api_object_list_t sav_obj) { cps_api_object_attr_t sg_attr = cps_api_get_key_data(obj, BASE_QOS_SCHEDULER_GROUP_ID); if (sg_attr == NULL) { EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", " scheduler group id not specified in the message\n"); return NAS_QOS_E_MISSING_KEY; } uint_t switch_id = 0; nas_obj_id_t scheduler_group_id = cps_api_object_attr_data_u64(sg_attr); nas_qos_switch *p_switch = nas_qos_get_switch(switch_id); if (p_switch == NULL) { EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", " switch: %u not found\n", switch_id); return NAS_QOS_E_FAIL; } nas_qos_scheduler_group *scheduler_group_p = p_switch->get_scheduler_group(scheduler_group_id); if (scheduler_group_p == NULL) { EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", " scheduler_group id: %u not found\n", scheduler_group_id); return NAS_QOS_E_FAIL; } EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Deleting scheduler_group %u on switch: %u\n", scheduler_group_p->get_scheduler_group_id(), p_switch->id()); // delete try { scheduler_group_p->commit_delete(sav_obj? false: true); EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Saving deleted scheduler_group %u\n", scheduler_group_p->get_scheduler_group_id()); // save current scheduler_group config for rollback if caller requests it. // use existing set_mask, existing config if (sav_obj) { cps_api_object_t tmp_obj = cps_api_object_list_create_obj_and_append(sav_obj); if (!tmp_obj) { return cps_api_ret_code_ERR; } nas_qos_store_prev_attr(tmp_obj, scheduler_group_p->set_attr_list(), *scheduler_group_p); } p_switch->remove_scheduler_group(scheduler_group_p->get_scheduler_group_id()); } catch (nas::base_exception e) { EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MAJOR, "QOS", "NAS SCHEDULER_GROUP Delete error code: %d ", e.err_code); return NAS_QOS_E_FAIL; } catch (...) { EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MAJOR, "QOS", "NAS SCHEDULER_GROUP Delete: Unexpected error"); return NAS_QOS_E_FAIL; } return cps_api_ret_code_OK; }
static cps_api_return_code_t nas_qos_cps_api_scheduler_group_set( cps_api_object_t obj, cps_api_object_list_t sav_obj) { cps_api_object_attr_t sg_attr = cps_api_get_key_data(obj, BASE_QOS_SCHEDULER_GROUP_ID); if (sg_attr == NULL) { EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "switch id and scheduler group id not specified in the message\n"); return NAS_QOS_E_MISSING_KEY; } uint_t switch_id = 0; nas_obj_id_t scheduler_group_id = cps_api_object_attr_data_u64(sg_attr); EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Modify switch id %u, scheduler_group id %u\n", switch_id, scheduler_group_id); nas_qos_scheduler_group * scheduler_group_p = nas_qos_cps_get_scheduler_group(switch_id, scheduler_group_id); if (scheduler_group_p == NULL) { return NAS_QOS_E_FAIL; } /* make a local copy of the existing scheduler_group */ nas_qos_scheduler_group scheduler_group(*scheduler_group_p); EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Modify switch id %u, scheduler_group id %u . After copy\n", switch_id, scheduler_group_id); cps_api_return_code_t rc = cps_api_ret_code_OK; if ((rc = nas_qos_cps_parse_attr(obj, scheduler_group)) != cps_api_ret_code_OK) return rc; if (scheduler_group.get_level() == 0 && scheduler_group.dirty_attr_list().contains(BASE_QOS_SCHEDULER_GROUP_SCHEDULER_PROFILE_ID)) { EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", " Scheduler Group Level 0 node does not accept Scheduler Profile ID; " " Use Port Egress Object to configure Scheduler Profile!\n"); return NAS_QOS_E_UNSUPPORTED; } try { EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Modifying scheduler_group %u attr on port %u \n", scheduler_group.get_scheduler_group_id(), scheduler_group.get_port_id()); nas::attr_set_t modified_attr_list = scheduler_group.commit_modify(*scheduler_group_p, (sav_obj? false: true)); EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "done with commit_modify \n"); // set attribute with full copy // save rollback info if caller requests it. // use modified attr list, current scheduler_group value if (sav_obj) { cps_api_object_t tmp_obj; tmp_obj = cps_api_object_list_create_obj_and_append(sav_obj); if (!tmp_obj) { return cps_api_ret_code_ERR; } nas_qos_store_prev_attr(tmp_obj, modified_attr_list, *scheduler_group_p); } // update the local cache with newly set values *scheduler_group_p = scheduler_group; } catch (nas::base_exception e) { EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MAJOR, "QOS", "NAS SCHEDULER_GROUP Attr Modify error code: %d ", e.err_code); return NAS_QOS_E_FAIL; } catch (...) { EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MAJOR, "QOS", "NAS SCHEDULER_GROUP Modify Unexpected error code"); return NAS_QOS_E_FAIL; } return cps_api_ret_code_OK; }
/** * This function provides NAS-QoS SCHEDULER_GROUP CPS API read function * @Param Standard CPS API params * @Return Standard Error Code */ cps_api_return_code_t nas_qos_cps_api_scheduler_group_read (void * context, cps_api_get_params_t * param, size_t ix) { cps_api_object_t obj = cps_api_object_list_get(param->filters, ix); cps_api_object_attr_t sg_attr = cps_api_get_key_data(obj, BASE_QOS_SCHEDULER_GROUP_ID); uint32_t port_id = 0, level; bool have_port = false, have_level = false; if (!sg_attr) { cps_api_object_it_t it; cps_api_object_it_begin(obj, &it); for ( ; cps_api_object_it_valid(&it); cps_api_object_it_next(&it)) { cps_api_attr_id_t id = cps_api_object_attr_id(it.attr); if (id == BASE_QOS_SCHEDULER_GROUP_PORT_ID) { port_id = cps_api_object_attr_data_u32(it.attr); have_port = true; } else if (id == BASE_QOS_SCHEDULER_GROUP_LEVEL) { level = cps_api_object_attr_data_u32(it.attr); have_level = true; } } } if (!sg_attr && !have_port) { EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MINOR, "NAS-QOS", "Invalid input attributes for reading"); return NAS_QOS_E_MISSING_KEY; } uint_t switch_id = 0; nas_obj_id_t scheduler_group_id = (sg_attr? cps_api_object_attr_data_u64(sg_attr): 0); EV_LOG_TRACE(ev_log_t_QOS, 3, "NAS-QOS", "Read switch id %u, scheduler_group id 0x%016lX\n", switch_id, scheduler_group_id); std_mutex_simple_lock_guard p_m(&scheduler_group_mutex); if (have_port) { nas_qos_port_scheduler_group_init(port_id); } nas_qos_switch * p_switch = nas_qos_get_switch(switch_id); if (p_switch == NULL) return NAS_QOS_E_FAIL; std::vector<nas_qos_scheduler_group *> sg_list; if (sg_attr) { nas_qos_scheduler_group *scheduler_group = p_switch->get_scheduler_group(scheduler_group_id); if (scheduler_group == NULL) { EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MINOR, "NAS-QOS", "Could not find scheduler group with ID %llu", scheduler_group_id); return NAS_QOS_E_FAIL; } sg_list.push_back(scheduler_group); } else { int match_level = have_level ? (int)level : -1; p_switch->get_port_scheduler_groups(port_id, match_level, sg_list); } /* fill in data */ cps_api_object_t ret_obj; for (auto scheduler_group: sg_list) { ret_obj = cps_api_object_list_create_obj_and_append (param->list); if (ret_obj == NULL) { EV_LOG_TRACE(ev_log_t_QOS, ev_log_s_MINOR, "NAS-QOS", "Failed to create cps object"); return cps_api_ret_code_ERR; } cps_api_key_from_attr_with_qual(cps_api_object_key(ret_obj),BASE_QOS_SCHEDULER_GROUP_OBJ, cps_api_qualifier_TARGET); cps_api_set_key_data(ret_obj, BASE_QOS_SCHEDULER_GROUP_SWITCH_ID, cps_api_object_ATTR_T_U32, &switch_id, sizeof(uint32_t)); scheduler_group_id = scheduler_group->get_scheduler_group_id(); cps_api_set_key_data(ret_obj, BASE_QOS_SCHEDULER_GROUP_ID, cps_api_object_ATTR_T_U64, &scheduler_group_id, sizeof(uint64_t)); cps_api_object_attr_add_u32(ret_obj, BASE_QOS_SCHEDULER_GROUP_CHILD_COUNT, scheduler_group->get_child_count()); for (uint32_t idx = 0; idx < scheduler_group->get_child_count(); idx++) { cps_api_object_attr_add_u64(ret_obj, BASE_QOS_SCHEDULER_GROUP_CHILD_LIST, scheduler_group->get_child_id(idx)); } cps_api_object_attr_add_u32(ret_obj, BASE_QOS_SCHEDULER_GROUP_PORT_ID, scheduler_group->get_port_id()); cps_api_object_attr_add_u32(ret_obj, BASE_QOS_SCHEDULER_GROUP_LEVEL, scheduler_group->get_level()); cps_api_object_attr_add_u64(ret_obj, BASE_QOS_SCHEDULER_GROUP_SCHEDULER_PROFILE_ID, scheduler_group->get_scheduler_profile_id()); } return cps_api_ret_code_OK; }