extern "C" bool nl_get_ip_info (int rt_msg_type, struct nlmsghdr *hdr, cps_api_object_t obj) { struct ifaddrmsg *ifmsg = (struct ifaddrmsg *)NLMSG_DATA(hdr); if(hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifmsg))) return false; typedef enum { IP_KEY, IFINDEX, PREFIX, ADDRESS, IFNAME } attr_t ; static const std::map<uint32_t, std::map<int,cps_api_attr_id_t>> _ipmap = { {AF_INET, { {IP_KEY, BASE_IP_IPV4_OBJ}, {IFINDEX, BASE_IP_IPV4_IFINDEX}, {PREFIX, BASE_IP_IPV4_ADDRESS_PREFIX_LENGTH}, {ADDRESS, BASE_IP_IPV4_ADDRESS_IP}, {IFNAME, BASE_IP_IPV4_NAME} }}, {AF_INET6, { {IP_KEY, BASE_IP_IPV6_OBJ}, {IFINDEX, BASE_IP_IPV6_IFINDEX}, {PREFIX, BASE_IP_IPV6_ADDRESS_PREFIX_LENGTH}, {ADDRESS, BASE_IP_IPV6_ADDRESS_IP}, {IFNAME, BASE_IP_IPV6_NAME} }} }; cps_api_key_from_attr_with_qual(cps_api_object_key(obj),_ipmap.at(ifmsg->ifa_family).at(IP_KEY), cps_api_qualifier_TARGET); cps_api_set_key_data(obj,_ipmap.at(ifmsg->ifa_family).at(IFINDEX), cps_api_object_ATTR_T_U32, &ifmsg->ifa_index,sizeof(ifmsg->ifa_index)); cps_api_object_attr_add_u32(obj, _ipmap.at(ifmsg->ifa_family).at(IFINDEX), ifmsg->ifa_index); cps_api_object_attr_add_u32(obj, _ipmap.at(ifmsg->ifa_family).at(PREFIX), ifmsg->ifa_prefixlen); int nla_len = nlmsg_attrlen(hdr,sizeof(*ifmsg)); struct nlattr *head = nlmsg_attrdata(hdr, sizeof(struct ifaddrmsg)); struct nlattr *attrs[__IFLA_MAX]; memset(attrs,0,sizeof(attrs)); if (nla_parse(attrs,__IFLA_MAX,head,nla_len)!=0) { EV_LOG_TRACE(ev_log_t_NAS_OS,ev_log_s_WARNING,"IP-NL-PARSE","Failed to parse attributes"); cps_api_object_delete(obj); return false; } if(attrs[IFA_ADDRESS]!=NULL) { rta_add_ip((struct nlattr*)ifmsg, ifmsg->ifa_family, obj, _ipmap.at(ifmsg->ifa_family).at(ADDRESS)); } if(attrs[IFA_LABEL]!=NULL) { rta_add_name(attrs[IFA_LABEL], obj, _ipmap.at(ifmsg->ifa_family).at(IFNAME)); } if (rt_msg_type == RTM_NEWADDR) { cps_api_object_set_type_operation(cps_api_object_key(obj),cps_api_oper_CREATE); } else if (rt_msg_type == RTM_DELADDR) { cps_api_object_set_type_operation(cps_api_object_key(obj),cps_api_oper_DELETE); } else { cps_api_object_set_type_operation(cps_api_object_key(obj),cps_api_oper_SET); } return true; }
//db_if_event_t bool nl_get_if_info (int rt_msg_type, struct nlmsghdr *hdr, cps_api_object_t obj) { struct ifinfomsg *ifmsg = (struct ifinfomsg *)NLMSG_DATA(hdr); if(hdr->nlmsg_len < NLMSG_LENGTH(sizeof(*ifmsg))) return false; db_if_type_t _type = DB_IF_TYPE_PHYS_INTER; uint_t ifindex = ifmsg->ifi_index; uint32_t op = 0; EV_LOG(INFO, NAS_OS, 3, "NET-MAIN", "nl_get_if_info msgType %d, ifindex %d change %x\n", rt_msg_type, ifindex, ifmsg->ifi_change); if (rt_msg_type ==RTM_NEWLINK) { op = DB_INTERFACE_OP_CREATE; } else if (rt_msg_type ==RTM_DELLINK) { op = DB_INTERFACE_OP_DELETE; } else { op = DB_INTERFACE_OP_SET; } cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_OPERATION,op); cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_FLAGS, ifmsg->ifi_flags); cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_IFINDEX,ifindex); if(ifmsg->ifi_flags & IFF_UP) { cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_ADMIN_STATE,DB_ADMIN_STATE_UP); } else { cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_ADMIN_STATE,DB_ADMIN_STATE_DN); } int nla_len = nlmsg_attrlen(hdr,sizeof(*ifmsg)); struct nlattr *head = nlmsg_attrdata(hdr, sizeof(struct ifinfomsg)); struct nlattr *attrs[__IFLA_MAX]; memset(attrs,0,sizeof(attrs)); if (nla_parse(attrs,__IFLA_MAX,head,nla_len)!=0) { EV_LOG(ERR,NAS_OS,0,"NL-PARSE","Failed to parse attributes"); cps_api_object_delete(obj); return false; } if (attrs[IFLA_ADDRESS]!=NULL) { rta_add_mac(attrs[IFLA_ADDRESS],obj,cps_api_if_STRUCT_A_IF_MACADDR); } if(attrs[IFLA_IFNAME]!=NULL) { rta_add_name(attrs[IFLA_IFNAME],obj,cps_api_if_STRUCT_A_NAME); } if(attrs[IFLA_MTU]!=NULL) { int *mtu = (int *) nla_data(attrs[IFLA_MTU]); cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_MTU,(*mtu + NAS_LINK_MTU_HDR_SIZE)); } if(attrs[IFLA_MASTER]!=NULL) { /* This gives us the bridge index, which should be sent to * NAS for correlation */ EV_LOG(INFO, NAS_OS, 3, "NET-MAIN", "Rcvd master index %d", *(int *)nla_data(attrs[IFLA_MASTER])); cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_MASTER, *(int *)nla_data(attrs[IFLA_MASTER])); if(op == DB_INTERFACE_OP_DELETE) { /* With Dell offering VLAN data structures use port index instead of * vlan interface */ int phy_ifindex = 0; nas_os_physical_to_vlan_ifindex(ifindex, 0, false, &phy_ifindex); cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_IFINDEX, phy_ifindex); cps_api_object_attr_add_u32(obj, cps_api_if_STRUCT_A_VLAN_PORT_INDEX, ifindex); _type = DB_IF_TYPE_VLAN_INTER; } } struct nlattr *linkinfo[IFLA_INFO_MAX]; struct nlattr *vlan[IFLA_VLAN_MAX]; char *info_kind; if (attrs[IFLA_LINKINFO]) { memset(linkinfo,0,sizeof(linkinfo)); nla_parse_nested(linkinfo,IFLA_INFO_MAX,attrs[IFLA_LINKINFO]); if(linkinfo[IFLA_INFO_KIND]) { info_kind = (char *)nla_data(linkinfo[IFLA_INFO_KIND]); EV_LOG(INFO, NAS_OS, 3, "NET-MAIN", "In IFLA_INFO_KIND for %s index %d", info_kind, ifindex); if(!strncmp(info_kind, "vlan", 4)) { if(attrs[IFLA_MASTER]!=NULL) { if (linkinfo[IFLA_INFO_DATA]) { memset(vlan,0,sizeof(vlan)); nla_parse_nested(vlan,IFLA_VLAN_MAX,linkinfo[IFLA_INFO_DATA]); if (vlan[IFLA_VLAN_ID]) { EV_LOG(INFO, NAS_OS, 3, "NET-MAIN", "Received VLAN %d", ifindex); cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_VLAN_ID, *(uint16_t*)nla_data(vlan[IFLA_VLAN_ID])); _type = DB_IF_TYPE_VLAN_INTER; if (attrs[IFLA_LINK]) { //port that is added to vlan uint32_t portIndex = *(uint32_t*)nla_data(attrs[IFLA_LINK]); if (op == DB_INTERFACE_OP_DELETE) { cps_api_object_attr_add_u32(obj, cps_api_if_STRUCT_A_VLAN_PORT_INDEX, ifindex); } else { cps_api_object_attr_add_u32(obj, cps_api_if_STRUCT_A_VLAN_PORT_INDEX, portIndex); } } //IFLA_LINK } //IFLA_VLAN_ID }//IFLA_INFO_DATA }// IFLA_MASTER } // vlan interface else if(!strncmp(info_kind, "tun", 3)) { /* TODO : Revisit this and introduce a logical interface type */ if(attrs[IFLA_MASTER]!=NULL) { EV_LOG(INFO, NAS_OS,3, "NET-MAIN", "Received tun %d", ifindex); _type = DB_IF_TYPE_VLAN_INTER; cps_api_object_attr_add_u32(obj, cps_api_if_STRUCT_A_VLAN_PORT_INDEX, ifindex); } if(ifmsg->ifi_flags & IFF_SLAVE) { EV_LOG(INFO, NAS_OS,3, "NET-MAIN", "Received tun %d and state IFF_UP", ifindex,ifmsg->ifi_flags); _type = DB_IF_TYPE_LAG_INTER; } } else if(!strncmp(info_kind, "bridge", 6)) { EV_LOG(INFO,NAS_OS,3, "NET-MAIN", "Bridge intf index is %d ", ifindex); _type = DB_IF_TYPE_BRIDGE_INTER; } /* bridge interface */ else if(!strncmp(info_kind, "bond", 4)) { EV_LOG(INFO, NAS_OS,3, "NET-MAIN", "Bond interface index is %d ", ifindex); _type = DB_IF_TYPE_LAG_INTER; if(attrs[IFLA_MASTER]!=NULL) { EV_LOG(INFO, NAS_OS,3, "NET-MAIN", "Received bond %d with master set %d", ifindex, *(int *)nla_data(attrs[IFLA_MASTER])); /* Bond with master set, means configured in a bridge * Pass the master index as the ifindex for vlan processing to continue */ _type = DB_IF_TYPE_VLAN_INTER; cps_api_object_attr_add_u32(obj, cps_api_if_STRUCT_A_VLAN_PORT_INDEX, ifindex); if (op == DB_INTERFACE_OP_DELETE ) { cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_IFINDEX, *(int *)nla_data(attrs[IFLA_MASTER])); } } } // bond interface } } if(attrs[IFLA_OPERSTATE]!=NULL) { int *link = (int *) nla_data(attrs[IFLA_OPERSTATE]); if (*link==IF_OPER_UP) { cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_OPER_STATE,DB_OPER_STATE_UP); } else if (*link==IF_OPER_DOWN) { cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_OPER_STATE,DB_OPER_STATE_DN); } } cps_api_object_attr_add_u32(obj,cps_api_if_STRUCT_A_IF_TYPE,_type); cps_api_int_if_key_create(cps_api_object_key(obj),true,0,ifindex); return true; }