in bpf/xdp_router_ipv4_user.c [381:464]
static void read_arp(struct nlmsghdr *nh, int nll)
{
struct rtattr *rt_attr;
char dsts[24], mac[24];
struct ndmsg *rt_msg;
int rtl, ndm_family;
struct arp_table {
__be64 mac;
__be32 dst;
} arp_entry;
struct direct_map {
struct arp_table arp;
int ifindex;
__be64 mac;
} direct_entry;
if (nh->nlmsg_type == RTM_GETNEIGH)
printf("READING arp entry\n");
printf("Address HwAddress\n");
for (; NLMSG_OK(nh, nll); nh = NLMSG_NEXT(nh, nll)) {
struct in_addr dst_addr;
char mac_str[18];
int len = 0, i;
rt_msg = (struct ndmsg *)NLMSG_DATA(nh);
rt_attr = (struct rtattr *)RTM_RTA(rt_msg);
ndm_family = rt_msg->ndm_family;
rtl = RTM_PAYLOAD(nh);
for (; RTA_OK(rt_attr, rtl); rt_attr = RTA_NEXT(rt_attr, rtl)) {
switch (rt_attr->rta_type) {
case NDA_DST:
sprintf(dsts, "%u",
*((__be32 *)RTA_DATA(rt_attr)));
break;
case NDA_LLADDR:
sprintf(mac, "%lld",
*((__be64 *)RTA_DATA(rt_attr)));
break;
default:
break;
}
}
arp_entry.dst = atoi(dsts);
arp_entry.mac = atol(mac);
dst_addr.s_addr = arp_entry.dst;
for (i = 0; i < 6; i++)
len += snprintf(mac_str + len, 18 - len, "%02llx%s",
((arp_entry.mac >> i * 8) & 0xff),
i < 5 ? ":" : "");
printf("%-16s%s\n", inet_ntoa(dst_addr), mac_str);
if (ndm_family == AF_INET) {
if (bpf_map_lookup_elem(exact_match_map_fd,
&arp_entry.dst,
&direct_entry) == 0) {
if (nh->nlmsg_type == RTM_DELNEIGH) {
direct_entry.arp.dst = 0;
direct_entry.arp.mac = 0;
} else if (nh->nlmsg_type == RTM_NEWNEIGH) {
direct_entry.arp.dst = arp_entry.dst;
direct_entry.arp.mac = arp_entry.mac;
}
assert(bpf_map_update_elem(exact_match_map_fd,
&arp_entry.dst,
&direct_entry, 0
) == 0);
memset(&direct_entry, 0, sizeof(direct_entry));
}
if (nh->nlmsg_type == RTM_DELNEIGH) {
assert(bpf_map_delete_elem(arp_table_map_fd,
&arp_entry.dst) == 0);
} else if (nh->nlmsg_type == RTM_NEWNEIGH) {
assert(bpf_map_update_elem(arp_table_map_fd,
&arp_entry.dst,
&arp_entry.mac, 0
) == 0);
}
}
memset(&arp_entry, 0, sizeof(arp_entry));
memset(dsts, 0, sizeof(dsts));
}
}