static void mac_create(switchlink_mac_addr_t mac_addr, switchlink_handle_t bridge_h, switchlink_handle_t intf_h) { switchlink_handle_t old_intf_h; switchlink_db_status_t status; status = switchlink_db_mac_get_intf(mac_addr, bridge_h, &old_intf_h); if (status == SWITCHLINK_DB_STATUS_SUCCESS) { if (old_intf_h == intf_h) { // no change return; } else { // update handled as delete followed by add mac_delete(mac_addr, bridge_h); } } switchlink_mac_create(mac_addr, bridge_h, intf_h); switchlink_db_mac_add(mac_addr, bridge_h, intf_h); }
void process_neigh_msg(struct nlmsghdr *nlmsg, int type) { int hdrlen, attrlen; struct nlattr *attr; struct ndmsg *nbh; switchlink_mac_addr_t mac_addr; bool mac_addr_valid = false; bool ipaddr_valid = false; switchlink_ip_addr_t ipaddr; assert((type == RTM_NEWNEIGH) || (type == RTM_DELNEIGH)); nbh = nlmsg_data(nlmsg); hdrlen = sizeof(struct ndmsg); NL_LOG_DEBUG(("%sneigh: family = %d, ifindex = %d, state = 0x%x, " "flags = 0x%x, type = %d\n", ((type == RTM_NEWNEIGH) ? "new" : "del"), nbh->ndm_family, nbh->ndm_ifindex, nbh->ndm_state, nbh->ndm_flags, nbh->ndm_type)); switchlink_db_interface_info_t ifinfo; if (switchlink_db_interface_get_info(nbh->ndm_ifindex, &ifinfo) != SWITCHLINK_DB_STATUS_SUCCESS) { NL_LOG_DEBUG(("neigh: switchlink_db_interface_get_info failed\n")); return; } if (strncmp(ifinfo.ifname, SWITCHLINK_CPU_INTERFACE_NAME, SWITCHLINK_INTERFACE_NAME_LEN_MAX) == 0) { NL_LOG_DEBUG(("neigh: skipping neighbor on CPU interface\n")); return; } memset(&ipaddr, 0, sizeof(switchlink_ip_addr_t)); attrlen = nlmsg_attrlen(nlmsg, hdrlen); attr = nlmsg_attrdata(nlmsg, hdrlen); while (nla_ok(attr, attrlen)) { int attr_type = nla_type(attr); switch (attr_type) { case NDA_DST: ipaddr_valid = true; ipaddr.family = nbh->ndm_family; if (nbh->ndm_family == AF_INET) { ipaddr.ip.v4addr.s_addr = ntohl(nla_get_u32(attr)); ipaddr.prefix_len = 32; } else { memcpy(&(ipaddr.ip.v6addr), nla_data(attr), nla_len(attr)); ipaddr.prefix_len = 128; } break; case NDA_LLADDR: { uint64_t lladdr; mac_addr_valid = true; lladdr = nla_get_u64(attr); memcpy(mac_addr, &lladdr, 6); break; } default: NL_LOG_DEBUG(("neigh: skipping attr(%d)\n", attr_type)); break; } attr = nla_next(attr, &attrlen); } switchlink_handle_t intf_h = ifinfo.intf_h; switchlink_handle_t bridge_h = 0; if (ifinfo.intf_type == SWITCHLINK_INTF_TYPE_L2_ACCESS) { bridge_h = ifinfo.bridge_h; assert(bridge_h); } if (type == RTM_NEWNEIGH) { if (bridge_h && mac_addr_valid) { mac_create(mac_addr, bridge_h, intf_h); } if (ipaddr_valid) { if (mac_addr_valid) { neigh_create(g_default_vrf_h, &ipaddr, mac_addr, intf_h); } else { // mac address is not valid, remove the neighbor entry neigh_delete(g_default_vrf_h, &ipaddr, intf_h); } } } else { if (bridge_h && mac_addr_valid) { mac_delete(mac_addr, bridge_h); } if (ipaddr_valid) { neigh_delete(g_default_vrf_h, &ipaddr, intf_h); } } }