Ejemplo n.º 1
0
static bool get_src_intf_attr(cps_api_object_t obj, nas_mirror_src_intf_map_t & intf_map,
                              const cps_api_object_it_t & it){

    cps_api_object_it_t it_lvl_1 = it;
    cps_api_attr_id_t ids[3] = {BASE_MIRROR_ENTRY_INTF,0, BASE_MIRROR_ENTRY_INTF_SRC };
    const int ids_len = sizeof(ids)/sizeof(ids[0]);

    for (cps_api_object_it_inside (&it_lvl_1); cps_api_object_it_valid (&it_lvl_1);
         cps_api_object_it_next (&it_lvl_1)) {

        ids[1] = cps_api_object_attr_id (it_lvl_1.attr);
        ids[2]=BASE_MIRROR_ENTRY_INTF_SRC;
        cps_api_object_attr_t src_intf = cps_api_object_e_get(obj,ids,ids_len);
        ids[2]=BASE_MIRROR_ENTRY_INTF_DIRECTION;
        cps_api_object_attr_t direction = cps_api_object_e_get(obj,ids,ids_len);

        if(src_intf == NULL){
            NAS_MIRROR_LOG(ERR,0,"Source Interface Index not passed for creating/updating a session");
            return false;
        }

        if(direction == NULL){
           NAS_MIRROR_LOG(ERR,0,"Mirroring Direction not passed for creating/updating a session");
           return false;
        }
        hal_ifindex_t ifindex = cps_api_object_attr_data_u32(src_intf);
        BASE_CMN_TRAFFIC_PATH_t dir = (BASE_CMN_TRAFFIC_PATH_t)cps_api_object_attr_data_u32(direction);
        if(intf_map.find(ifindex) == intf_map.end()){
            intf_map[ifindex] = dir;
        }
    }

    return true;
}
Ejemplo n.º 2
0
void nas_route_dump_route_object_content(cps_api_object_t obj) {

    char str[INET6_ADDRSTRLEN];
    char if_name[IFNAMSIZ];
    uint32_t addr_len = 0, af_data = 0;
    uint32_t nhc = 0, nh_itr = 0;

    cps_api_object_it_t it;
    cps_api_object_it_begin(obj,&it);

    cps_api_object_attr_t af       = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_AF);
    af_data = cps_api_object_attr_data_u32(af) ;

    addr_len = ((af_data == AF_INET) ? HAL_INET4_LEN : HAL_INET6_LEN);

    cps_api_object_attr_t prefix   = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_ROUTE_PREFIX);
    cps_api_object_attr_t pref_len = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN);
    cps_api_object_attr_t nh_count = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_NH_COUNT);
    std::cout<<"AF "<<((af_data == AF_INET) ? "IPv4" : "IPv6")<<","<<
        inet_ntop(af_data, cps_api_object_attr_data_bin(prefix), str,addr_len)<<"/"<<
        cps_api_object_attr_data_u32(pref_len)<<std::endl;
    if (nh_count != CPS_API_ATTR_NULL) {
        nhc = cps_api_object_attr_data_u32(nh_count);
        std::cout<<"NHC "<<nhc<<std::endl;
    }

    for (nh_itr = 0; nh_itr < nhc; nh_itr++)
    {
        cps_api_attr_id_t ids[3] = { BASE_ROUTE_OBJ_ENTRY_NH_LIST,
            0, BASE_ROUTE_OBJ_ENTRY_NH_LIST_NH_ADDR};
        const int ids_len = sizeof(ids)/sizeof(*ids);
        ids[1] = nh_itr;

        cps_api_object_attr_t attr = cps_api_object_e_get(obj,ids,ids_len);
        if (attr != CPS_API_ATTR_NULL)
            std::cout<<"NextHop "<<inet_ntop(af_data,cps_api_object_attr_data_bin(attr),str,addr_len)<<std::endl;

        ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_IFINDEX;
        attr = cps_api_object_e_get(obj,ids,ids_len);
        if (attr != CPS_API_ATTR_NULL)
            if_indextoname((int)cps_api_object_attr_data_u32(attr), if_name);
        std::cout<<"IfIndex "<<if_name<<"("<<cps_api_object_attr_data_u32(attr)<<")"<<std::endl;

        ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_WEIGHT;
        attr = cps_api_object_e_get(obj,ids,ids_len);
        if (attr != CPS_API_ATTR_NULL)
            std::cout<<"Weight "<<cps_api_object_attr_data_u32(attr)<<std::endl;

        ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_RESOLVED;
        attr = cps_api_object_e_get(obj,ids,ids_len);
        if (attr != CPS_API_ATTR_NULL)
            std::cout<<"Is Next Hop Resolved "<<cps_api_object_attr_data_u32(attr)<<std::endl;
    }
}
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;
}
Ejemplo n.º 4
0
t_std_error nas_sflow_create_session(cps_api_object_t obj){

    cps_api_object_attr_t ifindex_attr;
    cps_api_attr_id_t ifindex_attr_id = BASE_SFLOW_ENTRY_IFINDEX;

    ifindex_attr = cps_api_object_e_get (obj, &ifindex_attr_id, 1);

    if (ifindex_attr == NULL) {
        NAS_SFLOW_LOG(ERR,ev_log_s_MINOR,"No Interface Index passed for creating sFlow session");
        return STD_ERR(SFLOW,CFG,0);
    }

    nas_sflow_entry_t nas_sflow_entry;

    if(!nas_sflow_fill_session_info(obj,&nas_sflow_entry)){
        return STD_ERR(SFLOW,CFG,0);
    }

    interface_ctrl_t intf_ctrl;
    memset(&intf_ctrl, 0, sizeof(interface_ctrl_t));

    intf_ctrl.q_type = HAL_INTF_INFO_FROM_IF;
    intf_ctrl.if_index = nas_sflow_entry.ifindex;

    if (dn_hal_get_interface_info(&intf_ctrl) != STD_ERR_OK) {
        NAS_SFLOW_LOG(ERR,0,"Interface %d has NO slot %d, port %d",
                intf_ctrl.if_index, intf_ctrl.npu_id, intf_ctrl.port_id);
        return STD_ERR(SFLOW,FAIL,0);
    }

    nas_sflow_entry.ndi_sflow_entry.port_id = intf_ctrl.port_id;
    nas_sflow_entry.ndi_sflow_entry.npu_id = intf_ctrl.npu_id;
    nas_sflow_entry.ndi_sflow_entry.enabled = true;

    std_mutex_simple_lock_guard lock(&nas_sflow_mutex);

    if(ndi_sflow_create_session(&(nas_sflow_entry.ndi_sflow_entry)) != STD_ERR_OK){
        return STD_ERR(SFLOW,FAIL,0);
    }

    if(!nas_sflow_update_direction(&nas_sflow_entry.ndi_sflow_entry,true)){
        NAS_SFLOW_LOG(ERR,0,"Failed to add source ports to session %llu ",
                      nas_sflow_entry.ndi_sflow_entry.ndi_sflow_id);
        ndi_sflow_delete_session(&nas_sflow_entry.ndi_sflow_entry);
        return STD_ERR(SFLOW,FAIL,0);
    }

    nas_sflow_entry.nas_sflow_id= nas_sflow_get_next_index();
    cps_api_set_key_data(obj,BASE_SFLOW_ENTRY_ID,cps_api_object_ATTR_T_U32,
                         &nas_sflow_entry.nas_sflow_id,sizeof(nas_sflow_entry.nas_sflow_id));
    NAS_SFLOW_LOG(INFO,0,"Created new nas sflow entry with id %d",nas_sflow_entry.nas_sflow_id);
    nas_sflow_table.insert(nas_sflow_pair(nas_sflow_entry.nas_sflow_id,std::move(nas_sflow_entry)));

    return STD_ERR_OK;
}
Ejemplo n.º 5
0
static cps_api_return_code_t cps_nas_switch_log_set_function(void * context,
                             cps_api_transaction_params_t * param, size_t ix){

    cps_api_object_t obj = cps_api_object_list_get(param->change_list,ix);
    cps_api_operation_types_t op = cps_api_object_type_operation(cps_api_object_key(obj));

    if (op != cps_api_oper_ACTION) {
        EV_LOG(ERR,SYSTEM,0,"NAS-DIAG","Invalid operation %d for setting switch log",op);
        return cps_api_ret_code_ERR;
    }

    BASE_SWITCH_SUBSYSTEM_t switch_system_id;
    cps_api_object_attr_t switch_system_id_attr;

    if ((switch_system_id_attr = cps_api_get_key_data(obj,BASE_SWITCH_SET_LOG_INPUT_SUBSYSTEM_ID)) == NULL) {
        EV_LOG(ERR,SYSTEM,0,"NAS-DIAG","No Module id passed for Updating sai log level");
        return cps_api_ret_code_ERR;
    }

    switch_system_id = (BASE_SWITCH_SUBSYSTEM_t) cps_api_object_attr_data_u32(switch_system_id_attr);
    cps_api_attr_id_t log_level_attr_id = BASE_SWITCH_SET_LOG_INPUT_LEVEL;
    cps_api_object_attr_t log_level_attr = cps_api_object_e_get (obj, &log_level_attr_id, 1);

    if(log_level_attr == NULL){
        EV_LOG(ERR,SYSTEM,0,"NAS-DIAG","No log level passed for Updating sai log level"
                            "for module %d",switch_system_id);
        return cps_api_ret_code_ERR;
    }

    BASE_SWITCH_LOG_LEVEL_t log_level = (BASE_SWITCH_LOG_LEVEL_t)
                                        cps_api_object_attr_data_u32(log_level_attr);
    t_std_error rc;
    if( (rc =ndi_switch_set_sai_log_level(switch_system_id,log_level)) != STD_ERR_OK ){
        EV_LOG(ERR,SYSTEM,0,"NAS-DIAG","Failed to set log_level to %d for sai module %d "
                "got the return code %d ",log_level,switch_system_id,rc);
        return cps_api_ret_code_ERR;
    }

    return cps_api_ret_code_OK;
}
Ejemplo n.º 6
0
static bool nas_mirror_fill_rspan_attr(cps_api_object_t obj, nas_mirror_entry * entry, bool update){

    nas::attr_set_t attrs;

    cps_api_object_attr_t vlan_attr;
    cps_api_attr_id_t vlan_attr_id = BASE_MIRROR_ENTRY_VLAN;

    vlan_attr = cps_api_object_e_get (obj, &vlan_attr_id, 1);
    if(!update && vlan_attr == NULL){
        NAS_MIRROR_LOG(ERR,0,"No VLAN Id Passed for creating rspan mirror session");
        return false;
    }

    if(vlan_attr != NULL){
        attrs.add(BASE_MIRROR_ENTRY_VLAN);
        entry->set_vlan(cps_api_object_attr_data_u32(vlan_attr));

        if(update){
           return nas_mirror_update_attrs(entry,attrs);
        }
    }

    return true;
}
Ejemplo n.º 7
0
static t_std_error nas_os_publish_route(int rt_msg_type, cps_api_object_t obj)
{
    static char buff[MAX_CPS_MSG_SIZE];

    cps_api_object_t new_obj = cps_api_object_init(buff,sizeof(buff));
    cps_api_key_init(cps_api_object_key(new_obj),cps_api_qualifier_TARGET,
            cps_api_obj_cat_ROUTE,cps_api_route_obj_ROUTE,0 );

    cps_api_object_attr_t prefix   = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_ROUTE_PREFIX);
    cps_api_object_attr_t af       = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_AF);
    cps_api_object_attr_t pref_len = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN);
    cps_api_object_attr_t nh_count = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_NH_COUNT);

    if(rt_msg_type == RTM_NEWROUTE) {
        cps_api_object_attr_add_u32(new_obj, cps_api_if_ROUTE_A_MSG_TYPE,ROUTE_ADD);
    } else if(rt_msg_type == RTM_DELROUTE) {
        cps_api_object_attr_add_u32(new_obj, cps_api_if_ROUTE_A_MSG_TYPE,ROUTE_DEL);
    } else {
        return false;
    }

    cps_api_object_attr_add_u32(new_obj,cps_api_if_ROUTE_A_FAMILY,
            cps_api_object_attr_data_u32(af));

    uint32_t addr_len;
    hal_ip_addr_t ip;
    if(cps_api_object_attr_data_u32(af) == AF_INET) {
        struct in_addr *inp = (struct in_addr *) cps_api_object_attr_data_bin(prefix);
        std_ip_from_inet(&ip,inp);
        addr_len = HAL_INET4_LEN;
    } else {
        struct in6_addr *inp6 = (struct in6_addr *) cps_api_object_attr_data_bin(prefix);
        std_ip_from_inet6(&ip,inp6);
        addr_len = HAL_INET6_LEN;
    }

    cps_api_attr_id_t attr = cps_api_if_ROUTE_A_PREFIX;
    cps_api_object_e_add(new_obj, &attr, 1, cps_api_object_ATTR_T_BIN, &ip, sizeof(ip));

    cps_api_object_attr_add_u32(new_obj,cps_api_if_ROUTE_A_PREFIX_LEN,
            cps_api_object_attr_data_u32(pref_len));

    uint32_t nhc = 0;
    if (nh_count != CPS_API_ATTR_NULL) nhc = cps_api_object_attr_data_u32(nh_count);

    if (nhc == 1) {
        cps_api_object_attr_add_u32(new_obj,cps_api_if_ROUTE_A_HOP_COUNT,nhc);

        cps_api_attr_id_t ids[3] = { BASE_ROUTE_OBJ_ENTRY_NH_LIST,
                                 0, BASE_ROUTE_OBJ_ENTRY_NH_LIST_NH_ADDR};
        const int ids_len = sizeof(ids)/sizeof(*ids);

        cps_api_object_attr_t gw = cps_api_object_e_get(obj,ids,ids_len);

        ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_IFINDEX;
        cps_api_object_attr_t gwix = cps_api_object_e_get(obj,ids,ids_len);

        cps_api_attr_id_t new_ids[3];
        new_ids[0] = cps_api_if_ROUTE_A_NH;
        new_ids[1] = 0;

        if (gw != CPS_API_ATTR_NULL) {
            new_ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_ADDR;

            hal_ip_addr_t ip;
            if(addr_len == HAL_INET4_LEN) {
                ip.af_index = AF_INET;
                memcpy(&(ip.u.v4_addr), cps_api_object_attr_data_bin(gw),addr_len);
            } else {
                ip.af_index = AF_INET6;
                memcpy(&(ip.u.v6_addr), cps_api_object_attr_data_bin(gw),addr_len);
            }
            cps_api_object_e_add(new_obj, new_ids, ids_len, cps_api_object_ATTR_T_BIN,
                    &ip,sizeof(ip));
        }

        if (gwix != CPS_API_ATTR_NULL) {
            new_ids[2] = cps_api_if_ROUTE_A_NH_IFINDEX;
            uint32_t gw_idx = cps_api_object_attr_data_u32(gwix);
            cps_api_object_e_add(new_obj,new_ids,ids_len,cps_api_object_ATTR_T_U32,
                     (void *)&gw_idx, sizeof(uint32_t));
        }
    }

    EV_LOG(INFO, NAS_OS, 2,"ROUTE-UPD","Publishing object");

    net_publish_event(new_obj);

    return STD_ERR_OK;
}
Ejemplo n.º 8
0
cps_api_return_code_t nas_os_update_route (cps_api_object_t obj, msg_type m_type)
{
    static char buff[NL_RT_MSG_BUFFER_LEN]; // Allocate from DS
    char            addr_str[INET6_ADDRSTRLEN];
    memset(buff,0,sizeof(buff));

    cps_api_object_attr_t prefix   = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_ROUTE_PREFIX);
    cps_api_object_attr_t af       = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_AF);
    cps_api_object_attr_t nh_count = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_NH_COUNT);
    cps_api_object_attr_t pref_len = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN);

    if (prefix == CPS_API_ATTR_NULL || af == CPS_API_ATTR_NULL ||  pref_len == CPS_API_ATTR_NULL
        || (m_type != NAS_RT_DEL && nh_count == CPS_API_ATTR_NULL)) {
        EV_LOG(ERR, NAS_OS, ev_log_s_CRITICAL, "ROUTE-UPD", "Missing route params");
        return cps_api_ret_code_ERR;
    }

    struct nlmsghdr *nlh = (struct nlmsghdr *)
                         nlmsg_reserve((struct nlmsghdr *)buff,sizeof(buff),sizeof(struct nlmsghdr));
    struct rtmsg * rm = (struct rtmsg *) nlmsg_reserve(nlh,sizeof(buff),sizeof(struct rtmsg));

    uint16_t flags = nas_os_get_nl_flags(m_type);
    uint16_t type = (m_type == NAS_RT_DEL)?RTM_DELROUTE:RTM_NEWROUTE;

    nas_os_pack_nl_hdr(nlh, type, flags);

    rm->rtm_table = RT_TABLE_MAIN;
    rm->rtm_protocol = RTPROT_UNSPEC; // This could be assigned to correct owner in future

    /* For route delete, initialize scope to no-where and
     * this will get updated to link when Nh addr/ifx is provided.
     */
    if (type != RTM_DELROUTE)
        rm->rtm_scope = RT_SCOPE_UNIVERSE;
    else
        rm->rtm_scope = RT_SCOPE_NOWHERE;

    rm->rtm_type = RTN_UNICAST;

    rm->rtm_dst_len = cps_api_object_attr_data_u32(pref_len);
    rm->rtm_family = (unsigned char) cps_api_object_attr_data_u32(af);

    uint32_t addr_len = (rm->rtm_family == AF_INET)?HAL_INET4_LEN:HAL_INET6_LEN;
    nlmsg_add_attr(nlh,sizeof(buff),RTA_DST,cps_api_object_attr_data_bin(prefix),addr_len);

    uint32_t nhc = 0;
    if (nh_count != CPS_API_ATTR_NULL) nhc = cps_api_object_attr_data_u32(nh_count);

    EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","NH count:%d family:%s msg:%s for prefix:%s len:%d scope:%d", nhc,
           ((rm->rtm_family == AF_INET) ? "IPv4" : "IPv6"), ((m_type == NAS_RT_ADD) ? "Route-Add" : ((m_type == NAS_RT_DEL) ? "Route-Del" : "Route-Set")),
           ((rm->rtm_family == AF_INET) ?
            (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(prefix), addr_str, INET_ADDRSTRLEN)) :
            (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(prefix), addr_str, INET6_ADDRSTRLEN))),
           rm->rtm_dst_len, rm->rtm_scope);

    if (nhc == 1) {
        cps_api_attr_id_t ids[3] = { BASE_ROUTE_OBJ_ENTRY_NH_LIST,
                                     0, BASE_ROUTE_OBJ_ENTRY_NH_LIST_NH_ADDR};
        const int ids_len = sizeof(ids)/sizeof(*ids);
        cps_api_object_attr_t gw = cps_api_object_e_get(obj,ids,ids_len);
        if (gw != CPS_API_ATTR_NULL) {
            nlmsg_add_attr(nlh,sizeof(buff),RTA_GATEWAY,cps_api_object_attr_data_bin(gw),addr_len);
            rm->rtm_scope = RT_SCOPE_UNIVERSE; // set scope to universe when gateway is specified
            EV_LOG(INFO, NAS_OS, 2,"ROUTE-UPD","NH:%s scope:%d",
                   ((rm->rtm_family == AF_INET) ?
                    (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(gw), addr_str, INET_ADDRSTRLEN)) :
                    (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(gw), addr_str, INET6_ADDRSTRLEN))),
                   rm->rtm_scope);
        } else {
            EV_LOG(INFO, NAS_OS, ev_log_s_MINOR, "ROUTE-UPD", "Missing Gateway, could be intf route");
            /*
             * This could be an interface route, do not return from here!
             */
        }

        ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_IFINDEX;
        cps_api_object_attr_t gwix = cps_api_object_e_get(obj,ids,ids_len);
        if (gwix != CPS_API_ATTR_NULL) {
            if (gw == CPS_API_ATTR_NULL) {
                rm->rtm_scope = RT_SCOPE_LINK;
            }

            EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","out-intf: %d scope:%d",
                   (int)cps_api_object_attr_data_u32(gwix), rm->rtm_scope);
            nas_nl_add_attr_int(nlh,sizeof(buff),RTA_OIF,gwix);
        }

        ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_WEIGHT;
        cps_api_object_attr_t weight = cps_api_object_e_get(obj,ids,ids_len);
        if (weight != CPS_API_ATTR_NULL) nas_nl_add_attr_int(nlh,sizeof(buff),RTA_PRIORITY,weight);

    } else if (nhc > 1){
        struct nlattr * attr_nh = nlmsg_nested_start(nlh, sizeof(buff));

        attr_nh->nla_len = 0;
        attr_nh->nla_type = RTA_MULTIPATH;
        size_t ix = 0;
        for (ix = 0; ix < nhc ; ++ix) {
            struct rtnexthop * rtnh =
                (struct rtnexthop * )nlmsg_reserve(nlh,sizeof(buff), sizeof(struct rtnexthop));
            memset(rtnh,0,sizeof(*rtnh));

            cps_api_attr_id_t ids[3] = { BASE_ROUTE_OBJ_ENTRY_NH_LIST,
                                         ix, BASE_ROUTE_OBJ_ENTRY_NH_LIST_NH_ADDR};
            const int ids_len = sizeof(ids)/sizeof(*ids);
            cps_api_object_attr_t attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr != CPS_API_ATTR_NULL) {
                nlmsg_add_attr(nlh,sizeof(buff),RTA_GATEWAY,
                               cps_api_object_attr_data_bin(attr),addr_len);
                rm->rtm_scope = RT_SCOPE_UNIVERSE; // set scope to universe when gateway is specified
                EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","MP-NH:%d %s scope:%d",ix,
                       ((rm->rtm_family == AF_INET) ?
                        (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(attr), addr_str, INET_ADDRSTRLEN)) :
                        (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(attr), addr_str, INET6_ADDRSTRLEN))),
                       rm->rtm_scope);
            } else {
                EV_LOG(ERR, NAS_OS, ev_log_s_CRITICAL, "ROUTE-UPD", "Error - Missing Gateway");
                return cps_api_ret_code_ERR;
            }

            ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_IFINDEX;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr != CPS_API_ATTR_NULL)
                rtnh->rtnh_ifindex = (int)cps_api_object_attr_data_u32(attr);

            ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_WEIGHT;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr != CPS_API_ATTR_NULL) rtnh->rtnh_hops = (char)cps_api_object_attr_data_u32(attr);

            rtnh->rtnh_len = (char*)nlmsg_tail(nlh) - (char*)rtnh;
        }
        nlmsg_nested_end(nlh,attr_nh);
    }

    t_std_error rc = nl_do_set_request(nas_nl_sock_T_ROUTE,nlh,buff,sizeof(buff));
    int err_code = STD_ERR_EXT_PRIV (rc);
    EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","Netlink error_code %d", err_code);

    /*
     * Return success if the error is exist, in case of addition, or
     * no-exist, in case of deletion. This is because, kernel might have
     * deleted the route entries (when interface goes down) but has not sent netlink
     * events for those routes and RTM is trying to delete after that.
     * Similarly, during ip address configuration, kernel may add the routes
     * before RTM tries to configure kernel.
     *
     */
    if(err_code == ESRCH || err_code == EEXIST ) {
        EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","No such process or Entry already exists");
        /*
         * Kernel may or may not have the routes but NAS routing needs to be informed
         * as is from kernel netlink to program NPU for the route addition/deletion to
         * ensure stale routes are cleaned
         */
        if(err_code == ESRCH)
            nas_os_publish_route(RTM_DELROUTE, obj);
        else
            nas_os_publish_route(RTM_NEWROUTE, obj);
        rc = STD_ERR_OK;
    }

    return rc;

}
Ejemplo n.º 9
0
static cps_api_return_code_t _op(cps_api_operation_types_t op,void * context, cps_api_object_t obj, cps_api_object_t prev) {

    char buff[1024];
    memset(buff,0,sizeof(buff));
    cps_api_object_attr_t list[cps_api_if_ROUTE_A_MAX];
    cps_api_object_attr_fill_list(obj,0,list,sizeof(list)/sizeof(*list));

    if (list[cps_api_if_ROUTE_A_PREFIX]==NULL) return cps_api_ret_code_ERR;
    if (list[cps_api_if_ROUTE_A_PREFIX_LEN]==NULL) return cps_api_ret_code_ERR;
    if (list[cps_api_if_ROUTE_A_FAMILY]==NULL) return cps_api_ret_code_ERR;

    uint32_t prefix_len =  cps_api_object_attr_data_u32(list[cps_api_if_ROUTE_A_PREFIX_LEN]);

    struct nlmsghdr *nlh = (struct nlmsghdr *) nlmsg_reserve((struct nlmsghdr *)buff,sizeof(buff),sizeof(struct nlmsghdr));
    struct rtmsg * rm = (struct rtmsg *) nlmsg_reserve(nlh,sizeof(buff),sizeof(struct rtmsg));

    //sizeof structure + attrs nlh->nlmsg_len
    nlh->nlmsg_pid = 0;
    nlh->nlmsg_seq = 0;
    nlh->nlmsg_type =RTM_NEWROUTE;
    nlh->nlmsg_flags =  NLM_F_REQUEST | NLM_F_ACK ;

    if (op==cps_api_oper_CREATE) {
        nlh->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
    }
    if (op==cps_api_oper_SET) {
        nlh->nlmsg_flags |=NLM_F_REPLACE;
    }
    if (op==cps_api_oper_DELETE) {
        nlh->nlmsg_type =RTM_DELROUTE;
    }

    rm->rtm_table = RT_TABLE_MAIN;
    rm->rtm_protocol = RTPROT_BOOT;
    rm->rtm_dst_len = prefix_len;
    rm->rtm_scope = RT_SCOPE_UNIVERSE;
    rm->rtm_type = RTN_UNICAST;

    rm->rtm_family = (unsigned char) cps_api_object_attr_data_u32(list[cps_api_if_ROUTE_A_FAMILY]);

    EV_LOG(INFO,NETLINK,3,"ROUTEADD","Family is %d",rm->rtm_family);

    if (list[cps_api_if_ROUTE_A_PREFIX]!=NULL) nas_nl_add_attr_ip(nlh,sizeof(buff),RTA_DST,list[cps_api_if_ROUTE_A_PREFIX]);

    if (list[cps_api_if_ROUTE_A_HOP_COUNT]==NULL) return cps_api_ret_code_ERR;
    uint32_t hc =  cps_api_object_attr_data_u32(list[cps_api_if_ROUTE_A_HOP_COUNT]);
    EV_LOG(INFO,NETLINK,3,"ROUTEADD","hopcount is %d",hc);

    if (hc==1) {
        cps_api_attr_id_t ids[3] = { cps_api_if_ROUTE_A_NH, 0, cps_api_if_ROUTE_A_NEXT_HOP_ADDR};
        const int ids_len = sizeof(ids)/sizeof(*ids);
        cps_api_object_attr_t gw = cps_api_object_e_get(obj,ids,ids_len);

        EV_LOG(INFO,NETLINK,3,"ROUTEADD","nh addr is %d",(int)(size_t)gw);
        if (gw!=NULL) nas_nl_add_attr_ip(nlh,sizeof(buff),RTA_GATEWAY,gw);

        ids[2] = cps_api_if_ROUTE_A_NH_IFINDEX;
        cps_api_object_attr_t gwix = cps_api_object_e_get(obj,ids,ids_len);
        EV_LOG(INFO,NETLINK,3,"ROUTEADD","nh index is %d",(int)(size_t)gwix);
        if (gwix!=NULL) nas_nl_add_attr_int(nlh,sizeof(buff),RTA_OIF,gwix);

        ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_WEIGHT;
        cps_api_object_attr_t weight = cps_api_object_e_get(obj,ids,ids_len);
        if (weight!=NULL) nas_nl_add_attr_int(nlh,sizeof(buff),RTA_PRIORITY,weight);

    } else {
        struct nlattr * attr_nh = nlmsg_nested_start(nlh, sizeof(buff));

        attr_nh->nla_len = 0;
        attr_nh->nla_type = RTA_MULTIPATH;
        size_t ix = 0;
        for (ix = 0; ix < hc ; ++ix) {
            struct rtnexthop * rtnh = (struct rtnexthop * )nlmsg_reserve(nlh,sizeof(buff), sizeof(struct rtnexthop));
            memset(rtnh,0,sizeof(*rtnh));

            cps_api_attr_id_t ids[3] = { cps_api_if_ROUTE_A_NH, ix, cps_api_if_ROUTE_A_NEXT_HOP_ADDR};
            const int ids_len = sizeof(ids)/sizeof(*ids);
            cps_api_object_attr_t attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr!=NULL) nas_nl_add_attr_ip(nlh,sizeof(buff),RTA_GATEWAY,attr);

            ids[2] = cps_api_if_ROUTE_A_NH_IFINDEX;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr!=NULL) rtnh->rtnh_ifindex = (int)cps_api_object_attr_data_u32(attr);

            ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_WEIGHT;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr!=NULL) rtnh->rtnh_hops = (char)cps_api_object_attr_data_u32(attr);

            ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_FLAGS;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr!=NULL) rtnh->rtnh_flags = (char)cps_api_object_attr_data_u32(attr);


            rtnh->rtnh_len = (char*)nlmsg_tail(nlh) - (char*)rtnh;
        }
        nlmsg_nested_end(nlh,attr_nh);
    }
    return (cps_api_return_code_t) nl_do_set_request(nas_nl_sock_T_ROUTE,nlh,buff,sizeof(buff));
}