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; }
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; }
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; }
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; }
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; }
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; }
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; }
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)); }