/* 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;
}
Ejemplo n.º 5
0
/**
  * 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;
}