static bool qos_map_e_add_int_by_type (cps_api_object_t obj,
        cps_api_attr_id_t *id,  size_t id_size,
        uint val, cps_api_object_ATTR_TYPE_t type)
{
    switch (type) {
    case cps_api_object_ATTR_T_BIN:
    {
        uint8_t val8 = (uint8_t)val;
        return cps_api_object_e_add (obj,
                                   id, id_size,
                                   cps_api_object_ATTR_T_BIN,
                                   &val8,
                                   sizeof (uint8_t));
    }
    case cps_api_object_ATTR_T_U16:
    {
        uint16_t val16 = (uint16_t)val;
        return cps_api_object_e_add (obj,
                                   id, id_size,
                                   cps_api_object_ATTR_T_BIN,
                                   &val16,
                                   sizeof (uint16_t));

    }
    case cps_api_object_ATTR_T_U32:
    {
        uint32_t val32 = (uint32_t)val;
        return cps_api_object_e_add (obj,
                                   id, id_size,
                                   cps_api_object_ATTR_T_BIN,
                                   &val32,
                                   sizeof (uint32_t));

    }
    case cps_api_object_ATTR_T_U64:
    {
        uint64_t val64 = (uint64_t)val;
        return cps_api_object_e_add (obj,
                                   id, id_size,
                                   cps_api_object_ATTR_T_BIN,
                                   &val64,
                                   sizeof (uint64_t));

    }

    default:
        return false;
    }
}
cps_api_return_code_t cps_api_set_node_group(cps_api_node_group_t *group) {

    cps_api_object_guard og(cps_api_object_create());

    cps_api_key_from_attr_with_qual(cps_api_object_key(og.get()),CPS_NODE_GROUP, cps_api_qualifier_TARGET);

    cps_api_object_attr_add(og.get(),CPS_NODE_GROUP_NAME,group->id,strlen(group->id)+1);

    for ( size_t ix = 0; ix < group->addr_len; ++ix ) {
        cps_api_attr_id_t _ip[]= {CPS_NODE_GROUP_NODE,ix,CPS_NODE_GROUP_NODE_IP};
        cps_api_object_e_add(og.get(),_ip,sizeof(_ip)/sizeof(*_ip),cps_api_object_ATTR_T_BIN,
                             group->addrs[ix].addr,strlen(group->addrs[ix].addr)+1);
        cps_api_attr_id_t _alias[]= {CPS_NODE_GROUP_NODE,ix,CPS_NODE_GROUP_NODE_NAME};
        cps_api_object_e_add(og.get(),_alias,sizeof(_alias)/sizeof(*_alias),cps_api_object_ATTR_T_BIN,
                             group->addrs[ix].node_name,strlen(group->addrs[ix].node_name)+1);
    }

    cps_api_object_attr_add(og.get(),CPS_NODE_GROUP_TYPE,&group->data_type,sizeof(group->data_type));

    cps_db::connection_request b(cps_db::ProcessDBCache(),DEFAULT_REDIS_ADDR);
    if (!b.valid()) {
        return cps_api_ret_code_ERR;
    }
    cps_api_object_guard tmp(cps_api_object_create());

    if (!cps_api_object_clone(tmp.get(),og.get())) {
        return cps_api_ret_code_ERR;
    }

    bool changed = false;
    if (cps_db::get_object(b.get(),tmp.get())) {
        changed = true;
    }

    (void)changed;
    if (!cps_db::store_object(b.get(),og.get())) {
        return cps_api_ret_code_ERR;
    }

    if(group->data_type == cps_api_node_data_1_PLUS_1_REDUNDENCY) {
        return cps_api_create_global_instance(group);
    }
    ///TODO send out changed...

    return cps_api_ret_code_OK;
}
bool
nas_acl_fill_action_attr_list (cps_api_object_t obj, const nas_acl_entry& entry)
{
    nas::attr_list_t           parent_attr_id_list;
    cps_api_attr_id_t          list_index = 0;
    BASE_ACL_ACTION_TYPE_t     action_type_val;
    nas_acl_common_data_list_t common_data_list;

    // Parent attr list to build attr hierarchy
    //  - ACTION-List-Attr . Action-ListIndex . Action-Value-Attr . Action-Value-Child-Attr
    parent_attr_id_list.reserve(NAS_ACL_MAX_ATTR_DEPTH);

    //  Of this the following hierarchy is filled in this function
    //  - ACTION-List-Attr . Action-ListIndex

    for (const auto& action_kv: entry.get_action_list ()) {

        action_type_val = action_kv.second.action_type ();

        auto map_kv = nas_acl_get_action_map().find (action_type_val);

        if (map_kv == nas_acl_get_action_map().end ()) {
            return false;
        }

        const nas_acl_action_info_t& map_info = map_kv->second;

        parent_attr_id_list.clear ();

        parent_attr_id_list.push_back (BASE_ACL_ENTRY_ACTION);
        parent_attr_id_list.push_back (list_index);
        parent_attr_id_list.push_back (BASE_ACL_ENTRY_ACTION_TYPE);

        if (!cps_api_object_e_add (obj,
                                   parent_attr_id_list.data (),
                                   parent_attr_id_list.size (),
                                   cps_api_object_ATTR_T_U32,
                                   &action_type_val,
                                   sizeof (uint32_t))) {
            return false;
        }
        parent_attr_id_list.pop_back ();

        if (map_info.val.data_type != NAS_ACL_DATA_NONE) {
           if (!nas_acl_fill_action_attr (obj, action_kv.second,
                                             action_type_val, parent_attr_id_list))
           {
               NAS_ACL_LOG_ERR ("nas_acl_copy_data_to_obj() failed for Match type %d (%s)",
                                action_type_val, nas_acl_action_t::type_name (action_type_val));
               return false;
           }
        }

        list_index++;
    }

    return true;
}
static void nas_mirror_fill_object(cps_api_object_t obj, nas_mirror_table_it it){

    nas_mirror_entry & entry = it->second;
    cps_api_key_from_attr_with_qual(cps_api_object_key(obj),BASE_MIRROR_ENTRY_OBJ,
                                    cps_api_qualifier_TARGET);
    nas_mirror_id_t id = entry.get_id();
    cps_api_set_key_data(obj,BASE_MIRROR_ENTRY_ID,cps_api_object_ATTR_T_U32,
                         &id,sizeof(id));
    cps_api_object_attr_add_u32(obj,BASE_MIRROR_ENTRY_ID,id);

    nas::ndi_obj_id_table_t mirror_opaque_data_table;
    mirror_opaque_data_table[entry.get_npu_id()] = entry.get_ndi_id();
    cps_api_attr_id_t  attr_id_list[] = {BASE_MIRROR_ENTRY_OPAQUE_DATA};
    nas::ndi_obj_id_table_cps_serialize (mirror_opaque_data_table, obj, attr_id_list,
                                         sizeof(attr_id_list)/sizeof(attr_id_list[0]));


    cps_api_object_attr_add_u32(obj,BASE_MIRROR_ENTRY_DST_INTF,entry.get_dst_intf());
    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(auto src_it = entry.get_src_intf_map()->begin() ; src_it != entry.get_src_intf_map()->end() ; ++src_it){
        cps_api_object_e_add(obj,ids,ids_len,cps_api_object_ATTR_T_U32,&(src_it->first),sizeof(src_it->first));
        ids[2]=BASE_MIRROR_ENTRY_INTF_DIRECTION;
        cps_api_object_e_add(obj,ids,ids_len,cps_api_object_ATTR_T_U32,&(src_it->second),sizeof(src_it->second));
        ids[2]=BASE_MIRROR_ENTRY_INTF_SRC;
        ++ids[1];
    }

    cps_api_object_attr_add_u32(obj,BASE_MIRROR_ENTRY_FLOW_ENABLED,entry.get_flow());
    cps_api_object_attr_add_u32(obj,BASE_MIRROR_ENTRY_TYPE,entry.get_mode());

    if(entry.get_mode() == BASE_MIRROR_MODE_RSPAN){
        cps_api_object_attr_add_u32(obj,BASE_MIRROR_ENTRY_VLAN,entry.get_vlan_id());
    }

    if(entry.get_mode() == BASE_MIRROR_MODE_ERSPAN){
        cps_api_object_attr_add_u32(obj,BASE_MIRROR_ENTRY_SOURCE_IP,entry.get_dst_ip()->u.v4_addr);
        cps_api_object_attr_add_u32(obj,BASE_MIRROR_ENTRY_DESTINATION_IP,entry.get_src_ip()->u.v4_addr);
        cps_api_object_attr_add(obj,BASE_MIRROR_ENTRY_SOURCE_MAC,(void *)entry.get_src_mac(),sizeof(hal_mac_addr_t));
        cps_api_object_attr_add(obj,BASE_MIRROR_ENTRY_DEST_MAC,(void *)entry.get_dst_mac(),sizeof(hal_mac_addr_t));
        cps_api_object_attr_add_u32(obj,BASE_MIRROR_ENTRY_ERSPAN_VLAN_ID,entry.get_vlan_id());
    }
}
// C++ Serialize and  Unserialize APIs
bool nas::ndi_obj_id_table_cps_serialize (const 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)
{
    std::vector<cps_api_attr_id_t> internal_ids (attr_id_list,
                                                 attr_id_list+attr_id_size);

    cps_api_attr_id_t  inst_attr_id = OPAQUE_INST_ATTR_ID_START;

    for (auto map_elem: table) {
        // Insert the List index in the CPS object
        internal_ids.push_back (inst_attr_id);

        // Insert the NPU ID in the CPS object
        internal_ids.push_back (OPAQUE_NPU_ATTR_ID);
        auto npu_id = map_elem.first;
        if (!cps_api_object_e_add(cps_obj, internal_ids.data(), internal_ids.size(),
                             cps_api_object_ATTR_T_U32, &npu_id, sizeof (npu_id))) {
            return false;
        }
        internal_ids.pop_back ();

        // Insert the NDI Obj ID in the CPS object
        internal_ids.push_back (OPAQUE_NDI_OBJ_ATTR_ID);
        auto ndi_obj_id = map_elem.second;
        NAS_COM_TRACE (3, "Serialize [Inst %d] NPU-ID %d : NDI-ID 0x%lx\n",
                       inst_attr_id, npu_id, ndi_obj_id);

        if (!cps_api_object_e_add(cps_obj, internal_ids.data(), internal_ids.size(),
                                  cps_api_object_ATTR_T_U64, &ndi_obj_id,
                                  sizeof (ndi_obj_id))) {
            return false;
        }
        internal_ids.pop_back ();

        internal_ids.pop_back ();
        inst_attr_id++;
    }
    return true;
}
TEST(std_nas_route_test, nas_route_add) {

    cps_api_object_t obj = cps_api_object_create();

    cps_api_key_from_attr_with_qual(cps_api_object_key(obj),
           BASE_ROUTE_OBJ_OBJ,cps_api_qualifier_TARGET);

    //cps_api_key_init(cps_api_object_key(obj),cps_api_qualifier_TARGET,
       //     cps_api_obj_CAT_BASE_ROUTE, BASE_ROUTE_OBJ_OBJ,0 );

    /*
     * Check mandatory route attributes
     *  BASE_ROUTE_OBJ_ENTRY_AF,     BASE_ROUTE_OBJ_ENTRY_VRF_ID);
     * BASE_ROUTE_OBJ_ENTRY_ROUTE_PREFIX,   BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN;
     */

    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_AF,AF_INET);
    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_VRF_ID,0);
    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN,32);

    uint32_t ip;
    struct in_addr a;
    inet_aton("6.6.6.6",&a);
    ip=a.s_addr;

    cps_api_object_attr_add(obj,BASE_ROUTE_OBJ_ENTRY_ROUTE_PREFIX,&ip,sizeof(ip));
    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN,32);
    cps_api_attr_id_t ids[3];
    const int ids_len = sizeof(ids)/sizeof(*ids);
    ids[0] = BASE_ROUTE_OBJ_ENTRY_NH_LIST;
    ids[1] = 0;
    ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_NH_ADDR;

    /*
     * Set Loopback0 NH
     */
    inet_aton("127.0.0.1",&a);
    ip=a.s_addr;
    cps_api_object_e_add(obj,ids,ids_len,cps_api_object_ATTR_T_BIN,
                    &ip,sizeof(ip));
    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_NH_COUNT,1);

    /*
     * CPS transaction
     */
    cps_api_transaction_params_t tr;
    ASSERT_TRUE(cps_api_transaction_init(&tr)==cps_api_ret_code_OK);
    cps_api_create(&tr,obj);
    ASSERT_TRUE(cps_api_commit(&tr)==cps_api_ret_code_OK);
    cps_api_transaction_close(&tr);

}
Exemple #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;
}
//db_route_t
bool nl_to_route_info(int rt_msg_type, struct nlmsghdr *hdr, cps_api_object_t obj) {

    struct rtmsg    *rtmsg = (struct rtmsg *)NLMSG_DATA(hdr);
    char            addr_str[INET6_ADDRSTRLEN];

    if(hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*rtmsg)))
        return false;

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

    cps_api_object_attr_add_u32(obj,cps_api_if_ROUTE_A_PROTOCOL,rtmsg->rtm_protocol);

    cps_api_object_attr_add_u32(obj,cps_api_if_ROUTE_A_FAMILY,rtmsg->rtm_family);


    int attr_len = nlmsg_attrlen(hdr,sizeof(*rtmsg));
    struct nlattr *head = nlmsg_attrdata(hdr, sizeof(struct rtmsg));

    struct nlattr *attrs[__IFLA_MAX];
    memset(attrs,0,sizeof(attrs));

    if (nla_parse(attrs,__IFLA_MAX,head,attr_len)!=0) {
        EV_LOG(ERR,ROUTE,0,"NL-ROUTE-PARSE","Failed to parse attributes");
        return false;
    }

    cps_api_key_init(cps_api_object_key(obj),cps_api_qualifier_TARGET,
            cps_api_obj_cat_ROUTE,cps_api_route_obj_ROUTE,0 );

    if(attrs[RTA_DST]!=NULL) {
        rta_add_ip((struct nlattr*)attrs[RTA_DST],rtmsg->rtm_family,
                obj,cps_api_if_ROUTE_A_PREFIX);
    }

    if((rtmsg->rtm_flags & RTM_F_CLONED) && (rtmsg->rtm_family == AF_INET6)) {
        // Skip cloned route updates
        char addr_str[INET6_ADDRSTRLEN];
        EV_LOG(INFO, NETLINK,3,"ROUTE-EVENT","Cache entry %s",
                (attrs[RTA_DST]!=NULL)?(inet_ntop(rtmsg->rtm_family,
                ((struct in6_addr *) nla_data((struct nlattr*)attrs[RTA_DST])),
                addr_str, INET6_ADDRSTRLEN)):"");
        return false;
    }

    cps_api_object_attr_add_u32(obj,cps_api_if_ROUTE_A_PREFIX_LEN,rtmsg->rtm_dst_len);
    size_t hop_count = 0;

    cps_api_attr_id_t ids[3];

    const int ids_len = sizeof(ids)/sizeof(*ids);
    ids[0] = cps_api_if_ROUTE_A_NH;
    ids[1] = hop_count;

    if (attrs[RTA_GATEWAY]!=NULL) {
        ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_ADDR;
        rta_add_e_ip((struct nlattr*)attrs[RTA_GATEWAY],
                rtmsg->rtm_family,obj, ids,ids_len);

        rta_add_ip((struct nlattr*)attrs[RTA_GATEWAY],rtmsg->rtm_family,obj,
                cps_api_if_ROUTE_A_NEXT_HOP_ADDR);
    }

    if (attrs[RTA_OIF]!=NULL) {
        ids[2] = cps_api_if_ROUTE_A_NH_IFINDEX;
        unsigned int *x = (unsigned int *) nla_data(attrs[RTA_OIF]);

        cps_api_object_e_add(obj,ids,ids_len,cps_api_object_ATTR_T_U32,
                nla_data(attrs[RTA_OIF]),sizeof(uint32_t));

        cps_api_object_attr_add_u32(obj,cps_api_if_ROUTE_A_NH_IFINDEX,*x);
    }
    nas_os_log_route_info(rt_msg_type, rtmsg, attrs);
    if (attrs[RTA_MULTIPATH]) {
        //array of next hops
        struct rtnexthop * rtnh = (struct rtnexthop * )nla_data(attrs[RTA_MULTIPATH]);
        int remaining = nla_len(attrs[RTA_MULTIPATH]);
        while (RTNH_OK(rtnh, remaining)) {
            ids[1] = hop_count;
            ids[2] = cps_api_if_ROUTE_A_NH_IFINDEX;
            uint32_t _int = rtnh->rtnh_ifindex;
            cps_api_object_e_add(obj,ids,ids_len,cps_api_object_ATTR_T_U32,
                    &rtnh->rtnh_ifindex,sizeof(uint32_t));

            _int = rtnh->rtnh_flags;
            ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_FLAGS;
            cps_api_object_e_add(obj,ids,ids_len,cps_api_object_ATTR_T_U32,
                    &_int,sizeof(uint32_t));

            ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_WEIGHT;
            _int = rtnh->rtnh_hops;
            cps_api_object_e_add(obj,ids,ids_len,cps_api_object_ATTR_T_U32,
                    &_int,sizeof(uint32_t));

            struct nlattr *nhattr[__RTA_MAX];
            memset(nhattr,0,sizeof(nhattr));
            nhrt_parse(nhattr,__IFLA_MAX,rtnh);
            if (nhattr[RTA_GATEWAY]) {
                ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_ADDR;
                rta_add_e_ip((struct nlattr*)nhattr[RTA_GATEWAY],
                             rtmsg->rtm_family,obj, ids,ids_len);
                EV_LOG(INFO, NETLINK,3,"ROUTE-EVENT","MultiPath nh-cnt:%d gateway:%s ifIndex:%d nh-flags:0x%x weight:%d",
                       hop_count,
                       ((rtmsg->rtm_family == AF_INET) ?
                        (inet_ntop(rtmsg->rtm_family, ((struct in_addr *) nla_data((struct nlattr*)nhattr[RTA_GATEWAY])), addr_str,
                                   INET_ADDRSTRLEN)) :
                        (inet_ntop(rtmsg->rtm_family, ((struct in6_addr *) nla_data((struct nlattr*)nhattr[RTA_GATEWAY])),
                                   addr_str, INET6_ADDRSTRLEN))),
                        rtnh->rtnh_ifindex, rtnh->rtnh_flags, rtnh->rtnh_hops);
            } else {
                EV_LOG(INFO, NETLINK,3,"ROUTE-EVENT","MultiPath nh-cnt:%d ifIndex:%d nh-flags:0x%x weight:%d",
                       hop_count, rtnh->rtnh_ifindex, rtnh->rtnh_flags, rtnh->rtnh_hops);
            }
            rtnh = rtnh_next(rtnh,&remaining);
            ++hop_count;
        }

    } else {
        ++hop_count;
    }
    cps_api_object_attr_add_u32(obj,cps_api_if_ROUTE_A_HOP_COUNT,hop_count);

    return true;
}
//Scale tests for route add/delete
TEST(std_nas_route_test, nas_route_add_scale) {
    char ip_addr[256];
    int i=1, j=1 ,count=0;
    uint32_t ip;
    struct in_addr a;


   for(i=1; i<101; i++) {
       for (j=1; j<251; j++) {

    cps_api_object_t obj = cps_api_object_create();

    cps_api_key_from_attr_with_qual(cps_api_object_key(obj),
           BASE_ROUTE_OBJ_OBJ,cps_api_qualifier_TARGET);

    //cps_api_key_init(cps_api_object_key(obj),cps_api_qualifier_TARGET,
       //     cps_api_obj_CAT_BASE_ROUTE, BASE_ROUTE_OBJ_OBJ,0 );

    /*
     * Check mandatory route attributes
     *  BASE_ROUTE_OBJ_ENTRY_AF,     BASE_ROUTE_OBJ_ENTRY_VRF_ID);
     * BASE_ROUTE_OBJ_ENTRY_ROUTE_PREFIX,   BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN;
     */

    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_AF,AF_INET);
    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_VRF_ID,0);
    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN,32);


    snprintf(ip_addr,256, "11.10.%d.%d",i,j);
   // printf ("Add Route:%s, NH:1.1.1.4\n", ip_addr);

    inet_aton(ip_addr,&a);
    //inet_aton("6.6.6.6",&a);
    ip=a.s_addr;
    //printf ("Route:%d\n", ip);
    cps_api_object_attr_add(obj,BASE_ROUTE_OBJ_ENTRY_ROUTE_PREFIX,&ip,sizeof(ip));
    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN,32);
    cps_api_attr_id_t ids[3];
    const int ids_len = sizeof(ids)/sizeof(*ids);
    ids[0] = BASE_ROUTE_OBJ_ENTRY_NH_LIST;
    ids[1] = 0;
    ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_NH_ADDR;

    /*
     * Set  NH
     */
    inet_aton("1.1.1.4",&a);
    ip=a.s_addr;
    cps_api_object_e_add(obj,ids,ids_len,cps_api_object_ATTR_T_BIN,
                    &ip,sizeof(ip));
    cps_api_object_attr_add_u32(obj,BASE_ROUTE_OBJ_ENTRY_NH_COUNT,1);

    /*
     * CPS transaction
     */
    cps_api_transaction_params_t tr;
    ASSERT_TRUE(cps_api_transaction_init(&tr)==cps_api_ret_code_OK);
    cps_api_create(&tr,obj);
    ASSERT_TRUE(cps_api_commit(&tr)==cps_api_ret_code_OK);
    cps_api_transaction_close(&tr);
    count++;

       }
   }
printf("Sent %d Routes\n", count);
}