1 /* Copyright (C) 2017 Cavium, Inc. 2 * 3 * This program is free software; you can redistribute it and/or modify it 4 * under the terms of version 2 of the GNU General Public License 5 * as published by the Free Software Foundation. 6 */ 7 #include <linux/bpf.h> 8 #include <linux/netlink.h> 9 #include <linux/rtnetlink.h> 10 #include <assert.h> 11 #include <errno.h> 12 #include <signal.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <sys/socket.h> 17 #include <unistd.h> 18 #include <bpf/bpf.h> 19 #include <arpa/inet.h> 20 #include <fcntl.h> 21 #include <poll.h> 22 #include <net/if.h> 23 #include <netdb.h> 24 #include <sys/ioctl.h> 25 #include <sys/syscall.h> 26 #include "bpf_util.h" 27 #include "bpf/libbpf.h" 28 #include <sys/resource.h> 29 #include <libgen.h> 30 31 int sock, sock_arp, flags = XDP_FLAGS_UPDATE_IF_NOEXIST; 32 static int total_ifindex; 33 static int *ifindex_list; 34 static __u32 *prog_id_list; 35 char buf[8192]; 36 static int lpm_map_fd; 37 static int rxcnt_map_fd; 38 static int arp_table_map_fd; 39 static int exact_match_map_fd; 40 static int tx_port_map_fd; 41 42 static int get_route_table(int rtm_family); 43 static void int_exit(int sig) 44 { 45 __u32 prog_id = 0; 46 int i = 0; 47 48 for (i = 0; i < total_ifindex; i++) { 49 if (bpf_get_link_xdp_id(ifindex_list[i], &prog_id, flags)) { 50 printf("bpf_get_link_xdp_id on iface %d failed\n", 51 ifindex_list[i]); 52 exit(1); 53 } 54 if (prog_id_list[i] == prog_id) 55 bpf_set_link_xdp_fd(ifindex_list[i], -1, flags); 56 else if (!prog_id) 57 printf("couldn't find a prog id on iface %d\n", 58 ifindex_list[i]); 59 else 60 printf("program on iface %d changed, not removing\n", 61 ifindex_list[i]); 62 prog_id = 0; 63 } 64 exit(0); 65 } 66 67 static void close_and_exit(int sig) 68 { 69 close(sock); 70 close(sock_arp); 71 72 int_exit(0); 73 } 74 75 /* Get the mac address of the interface given interface name */ 76 static __be64 getmac(char *iface) 77 { 78 struct ifreq ifr; 79 __be64 mac = 0; 80 int fd, i; 81 82 fd = socket(AF_INET, SOCK_DGRAM, 0); 83 ifr.ifr_addr.sa_family = AF_INET; 84 strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1); 85 if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { 86 printf("ioctl failed leaving....\n"); 87 return -1; 88 } 89 for (i = 0; i < 6 ; i++) 90 *((__u8 *)&mac + i) = (__u8)ifr.ifr_hwaddr.sa_data[i]; 91 close(fd); 92 return mac; 93 } 94 95 static int recv_msg(struct sockaddr_nl sock_addr, int sock) 96 { 97 struct nlmsghdr *nh; 98 int len, nll = 0; 99 char *buf_ptr; 100 101 buf_ptr = buf; 102 while (1) { 103 len = recv(sock, buf_ptr, sizeof(buf) - nll, 0); 104 if (len < 0) 105 return len; 106 107 nh = (struct nlmsghdr *)buf_ptr; 108 109 if (nh->nlmsg_type == NLMSG_DONE) 110 break; 111 buf_ptr += len; 112 nll += len; 113 if ((sock_addr.nl_groups & RTMGRP_NEIGH) == RTMGRP_NEIGH) 114 break; 115 116 if ((sock_addr.nl_groups & RTMGRP_IPV4_ROUTE) == RTMGRP_IPV4_ROUTE) 117 break; 118 } 119 return nll; 120 } 121 122 /* Function to parse the route entry returned by netlink 123 * Updates the route entry related map entries 124 */ 125 static void read_route(struct nlmsghdr *nh, int nll) 126 { 127 char dsts[24], gws[24], ifs[16], dsts_len[24], metrics[24]; 128 struct bpf_lpm_trie_key *prefix_key; 129 struct rtattr *rt_attr; 130 struct rtmsg *rt_msg; 131 int rtm_family; 132 int rtl; 133 int i; 134 struct route_table { 135 int dst_len, iface, metric; 136 char *iface_name; 137 __be32 dst, gw; 138 __be64 mac; 139 } route; 140 struct arp_table { 141 __be64 mac; 142 __be32 dst; 143 }; 144 145 struct direct_map { 146 struct arp_table arp; 147 int ifindex; 148 __be64 mac; 149 } direct_entry; 150 151 if (nh->nlmsg_type == RTM_DELROUTE) 152 printf("DELETING Route entry\n"); 153 else if (nh->nlmsg_type == RTM_GETROUTE) 154 printf("READING Route entry\n"); 155 else if (nh->nlmsg_type == RTM_NEWROUTE) 156 printf("NEW Route entry\n"); 157 else 158 printf("%d\n", nh->nlmsg_type); 159 160 memset(&route, 0, sizeof(route)); 161 printf("Destination\t\tGateway\t\tGenmask\t\tMetric\t\tIface\n"); 162 for (; NLMSG_OK(nh, nll); nh = NLMSG_NEXT(nh, nll)) { 163 rt_msg = (struct rtmsg *)NLMSG_DATA(nh); 164 rtm_family = rt_msg->rtm_family; 165 if (rtm_family == AF_INET) 166 if (rt_msg->rtm_table != RT_TABLE_MAIN) 167 continue; 168 rt_attr = (struct rtattr *)RTM_RTA(rt_msg); 169 rtl = RTM_PAYLOAD(nh); 170 171 for (; RTA_OK(rt_attr, rtl); rt_attr = RTA_NEXT(rt_attr, rtl)) { 172 switch (rt_attr->rta_type) { 173 case NDA_DST: 174 sprintf(dsts, "%u", 175 (*((__be32 *)RTA_DATA(rt_attr)))); 176 break; 177 case RTA_GATEWAY: 178 sprintf(gws, "%u", 179 *((__be32 *)RTA_DATA(rt_attr))); 180 break; 181 case RTA_OIF: 182 sprintf(ifs, "%u", 183 *((int *)RTA_DATA(rt_attr))); 184 break; 185 case RTA_METRICS: 186 sprintf(metrics, "%u", 187 *((int *)RTA_DATA(rt_attr))); 188 default: 189 break; 190 } 191 } 192 sprintf(dsts_len, "%d", rt_msg->rtm_dst_len); 193 route.dst = atoi(dsts); 194 route.dst_len = atoi(dsts_len); 195 route.gw = atoi(gws); 196 route.iface = atoi(ifs); 197 route.metric = atoi(metrics); 198 route.iface_name = alloca(sizeof(char *) * IFNAMSIZ); 199 route.iface_name = if_indextoname(route.iface, route.iface_name); 200 route.mac = getmac(route.iface_name); 201 if (route.mac == -1) 202 int_exit(0); 203 assert(bpf_map_update_elem(tx_port_map_fd, 204 &route.iface, &route.iface, 0) == 0); 205 if (rtm_family == AF_INET) { 206 struct trie_value { 207 __u8 prefix[4]; 208 __be64 value; 209 int ifindex; 210 int metric; 211 __be32 gw; 212 } *prefix_value; 213 214 prefix_key = alloca(sizeof(*prefix_key) + 3); 215 prefix_value = alloca(sizeof(*prefix_value)); 216 217 prefix_key->prefixlen = 32; 218 prefix_key->prefixlen = route.dst_len; 219 direct_entry.mac = route.mac & 0xffffffffffff; 220 direct_entry.ifindex = route.iface; 221 direct_entry.arp.mac = 0; 222 direct_entry.arp.dst = 0; 223 if (route.dst_len == 32) { 224 if (nh->nlmsg_type == RTM_DELROUTE) { 225 assert(bpf_map_delete_elem(exact_match_map_fd, 226 &route.dst) == 0); 227 } else { 228 if (bpf_map_lookup_elem(arp_table_map_fd, 229 &route.dst, 230 &direct_entry.arp.mac) == 0) 231 direct_entry.arp.dst = route.dst; 232 assert(bpf_map_update_elem(exact_match_map_fd, 233 &route.dst, 234 &direct_entry, 0) == 0); 235 } 236 } 237 for (i = 0; i < 4; i++) 238 prefix_key->data[i] = (route.dst >> i * 8) & 0xff; 239 240 printf("%3d.%d.%d.%d\t\t%3x\t\t%d\t\t%d\t\t%s\n", 241 (int)prefix_key->data[0], 242 (int)prefix_key->data[1], 243 (int)prefix_key->data[2], 244 (int)prefix_key->data[3], 245 route.gw, route.dst_len, 246 route.metric, 247 route.iface_name); 248 if (bpf_map_lookup_elem(lpm_map_fd, prefix_key, 249 prefix_value) < 0) { 250 for (i = 0; i < 4; i++) 251 prefix_value->prefix[i] = prefix_key->data[i]; 252 prefix_value->value = route.mac & 0xffffffffffff; 253 prefix_value->ifindex = route.iface; 254 prefix_value->gw = route.gw; 255 prefix_value->metric = route.metric; 256 257 assert(bpf_map_update_elem(lpm_map_fd, 258 prefix_key, 259 prefix_value, 0 260 ) == 0); 261 } else { 262 if (nh->nlmsg_type == RTM_DELROUTE) { 263 printf("deleting entry\n"); 264 printf("prefix key=%d.%d.%d.%d/%d", 265 prefix_key->data[0], 266 prefix_key->data[1], 267 prefix_key->data[2], 268 prefix_key->data[3], 269 prefix_key->prefixlen); 270 assert(bpf_map_delete_elem(lpm_map_fd, 271 prefix_key 272 ) == 0); 273 /* Rereading the route table to check if 274 * there is an entry with the same 275 * prefix but a different metric as the 276 * deleted enty. 277 */ 278 get_route_table(AF_INET); 279 } else if (prefix_key->data[0] == 280 prefix_value->prefix[0] && 281 prefix_key->data[1] == 282 prefix_value->prefix[1] && 283 prefix_key->data[2] == 284 prefix_value->prefix[2] && 285 prefix_key->data[3] == 286 prefix_value->prefix[3] && 287 route.metric >= prefix_value->metric) { 288 continue; 289 } else { 290 for (i = 0; i < 4; i++) 291 prefix_value->prefix[i] = 292 prefix_key->data[i]; 293 prefix_value->value = 294 route.mac & 0xffffffffffff; 295 prefix_value->ifindex = route.iface; 296 prefix_value->gw = route.gw; 297 prefix_value->metric = route.metric; 298 assert(bpf_map_update_elem(lpm_map_fd, 299 prefix_key, 300 prefix_value, 301 0) == 0); 302 } 303 } 304 } 305 memset(&route, 0, sizeof(route)); 306 memset(dsts, 0, sizeof(dsts)); 307 memset(dsts_len, 0, sizeof(dsts_len)); 308 memset(gws, 0, sizeof(gws)); 309 memset(ifs, 0, sizeof(ifs)); 310 memset(&route, 0, sizeof(route)); 311 } 312 } 313 314 /* Function to read the existing route table when the process is launched*/ 315 static int get_route_table(int rtm_family) 316 { 317 struct sockaddr_nl sa; 318 struct nlmsghdr *nh; 319 int sock, seq = 0; 320 struct msghdr msg; 321 struct iovec iov; 322 int ret = 0; 323 int nll; 324 325 struct { 326 struct nlmsghdr nl; 327 struct rtmsg rt; 328 char buf[8192]; 329 } req; 330 331 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 332 if (sock < 0) { 333 printf("open netlink socket: %s\n", strerror(errno)); 334 return -1; 335 } 336 memset(&sa, 0, sizeof(sa)); 337 sa.nl_family = AF_NETLINK; 338 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 339 printf("bind to netlink: %s\n", strerror(errno)); 340 ret = -1; 341 goto cleanup; 342 } 343 memset(&req, 0, sizeof(req)); 344 req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 345 req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; 346 req.nl.nlmsg_type = RTM_GETROUTE; 347 348 req.rt.rtm_family = rtm_family; 349 req.rt.rtm_table = RT_TABLE_MAIN; 350 req.nl.nlmsg_pid = 0; 351 req.nl.nlmsg_seq = ++seq; 352 memset(&msg, 0, sizeof(msg)); 353 iov.iov_base = (void *)&req.nl; 354 iov.iov_len = req.nl.nlmsg_len; 355 msg.msg_iov = &iov; 356 msg.msg_iovlen = 1; 357 ret = sendmsg(sock, &msg, 0); 358 if (ret < 0) { 359 printf("send to netlink: %s\n", strerror(errno)); 360 ret = -1; 361 goto cleanup; 362 } 363 memset(buf, 0, sizeof(buf)); 364 nll = recv_msg(sa, sock); 365 if (nll < 0) { 366 printf("recv from netlink: %s\n", strerror(nll)); 367 ret = -1; 368 goto cleanup; 369 } 370 nh = (struct nlmsghdr *)buf; 371 read_route(nh, nll); 372 cleanup: 373 close(sock); 374 return ret; 375 } 376 377 /* Function to parse the arp entry returned by netlink 378 * Updates the arp entry related map entries 379 */ 380 static void read_arp(struct nlmsghdr *nh, int nll) 381 { 382 struct rtattr *rt_attr; 383 char dsts[24], mac[24]; 384 struct ndmsg *rt_msg; 385 int rtl, ndm_family; 386 387 struct arp_table { 388 __be64 mac; 389 __be32 dst; 390 } arp_entry; 391 struct direct_map { 392 struct arp_table arp; 393 int ifindex; 394 __be64 mac; 395 } direct_entry; 396 397 if (nh->nlmsg_type == RTM_GETNEIGH) 398 printf("READING arp entry\n"); 399 printf("Address\tHwAddress\n"); 400 for (; NLMSG_OK(nh, nll); nh = NLMSG_NEXT(nh, nll)) { 401 rt_msg = (struct ndmsg *)NLMSG_DATA(nh); 402 rt_attr = (struct rtattr *)RTM_RTA(rt_msg); 403 ndm_family = rt_msg->ndm_family; 404 rtl = RTM_PAYLOAD(nh); 405 for (; RTA_OK(rt_attr, rtl); rt_attr = RTA_NEXT(rt_attr, rtl)) { 406 switch (rt_attr->rta_type) { 407 case NDA_DST: 408 sprintf(dsts, "%u", 409 *((__be32 *)RTA_DATA(rt_attr))); 410 break; 411 case NDA_LLADDR: 412 sprintf(mac, "%lld", 413 *((__be64 *)RTA_DATA(rt_attr))); 414 break; 415 default: 416 break; 417 } 418 } 419 arp_entry.dst = atoi(dsts); 420 arp_entry.mac = atol(mac); 421 printf("%x\t\t%llx\n", arp_entry.dst, arp_entry.mac); 422 if (ndm_family == AF_INET) { 423 if (bpf_map_lookup_elem(exact_match_map_fd, 424 &arp_entry.dst, 425 &direct_entry) == 0) { 426 if (nh->nlmsg_type == RTM_DELNEIGH) { 427 direct_entry.arp.dst = 0; 428 direct_entry.arp.mac = 0; 429 } else if (nh->nlmsg_type == RTM_NEWNEIGH) { 430 direct_entry.arp.dst = arp_entry.dst; 431 direct_entry.arp.mac = arp_entry.mac; 432 } 433 assert(bpf_map_update_elem(exact_match_map_fd, 434 &arp_entry.dst, 435 &direct_entry, 0 436 ) == 0); 437 memset(&direct_entry, 0, sizeof(direct_entry)); 438 } 439 if (nh->nlmsg_type == RTM_DELNEIGH) { 440 assert(bpf_map_delete_elem(arp_table_map_fd, 441 &arp_entry.dst) == 0); 442 } else if (nh->nlmsg_type == RTM_NEWNEIGH) { 443 assert(bpf_map_update_elem(arp_table_map_fd, 444 &arp_entry.dst, 445 &arp_entry.mac, 0 446 ) == 0); 447 } 448 } 449 memset(&arp_entry, 0, sizeof(arp_entry)); 450 memset(dsts, 0, sizeof(dsts)); 451 } 452 } 453 454 /* Function to read the existing arp table when the process is launched*/ 455 static int get_arp_table(int rtm_family) 456 { 457 struct sockaddr_nl sa; 458 struct nlmsghdr *nh; 459 int sock, seq = 0; 460 struct msghdr msg; 461 struct iovec iov; 462 int ret = 0; 463 int nll; 464 struct { 465 struct nlmsghdr nl; 466 struct ndmsg rt; 467 char buf[8192]; 468 } req; 469 470 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 471 if (sock < 0) { 472 printf("open netlink socket: %s\n", strerror(errno)); 473 return -1; 474 } 475 memset(&sa, 0, sizeof(sa)); 476 sa.nl_family = AF_NETLINK; 477 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 478 printf("bind to netlink: %s\n", strerror(errno)); 479 ret = -1; 480 goto cleanup; 481 } 482 memset(&req, 0, sizeof(req)); 483 req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); 484 req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; 485 req.nl.nlmsg_type = RTM_GETNEIGH; 486 req.rt.ndm_state = NUD_REACHABLE; 487 req.rt.ndm_family = rtm_family; 488 req.nl.nlmsg_pid = 0; 489 req.nl.nlmsg_seq = ++seq; 490 memset(&msg, 0, sizeof(msg)); 491 iov.iov_base = (void *)&req.nl; 492 iov.iov_len = req.nl.nlmsg_len; 493 msg.msg_iov = &iov; 494 msg.msg_iovlen = 1; 495 ret = sendmsg(sock, &msg, 0); 496 if (ret < 0) { 497 printf("send to netlink: %s\n", strerror(errno)); 498 ret = -1; 499 goto cleanup; 500 } 501 memset(buf, 0, sizeof(buf)); 502 nll = recv_msg(sa, sock); 503 if (nll < 0) { 504 printf("recv from netlink: %s\n", strerror(nll)); 505 ret = -1; 506 goto cleanup; 507 } 508 nh = (struct nlmsghdr *)buf; 509 read_arp(nh, nll); 510 cleanup: 511 close(sock); 512 return ret; 513 } 514 515 /* Function to keep track and update changes in route and arp table 516 * Give regular statistics of packets forwarded 517 */ 518 static int monitor_route(void) 519 { 520 unsigned int nr_cpus = bpf_num_possible_cpus(); 521 const unsigned int nr_keys = 256; 522 struct pollfd fds_route, fds_arp; 523 __u64 prev[nr_keys][nr_cpus]; 524 struct sockaddr_nl la, lr; 525 __u64 values[nr_cpus]; 526 struct nlmsghdr *nh; 527 int nll, ret = 0; 528 int interval = 5; 529 __u32 key; 530 int i; 531 532 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 533 if (sock < 0) { 534 printf("open netlink socket: %s\n", strerror(errno)); 535 return -1; 536 } 537 538 fcntl(sock, F_SETFL, O_NONBLOCK); 539 memset(&lr, 0, sizeof(lr)); 540 lr.nl_family = AF_NETLINK; 541 lr.nl_groups = RTMGRP_IPV6_ROUTE | RTMGRP_IPV4_ROUTE | RTMGRP_NOTIFY; 542 if (bind(sock, (struct sockaddr *)&lr, sizeof(lr)) < 0) { 543 printf("bind to netlink: %s\n", strerror(errno)); 544 ret = -1; 545 goto cleanup; 546 } 547 fds_route.fd = sock; 548 fds_route.events = POLL_IN; 549 550 sock_arp = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 551 if (sock_arp < 0) { 552 printf("open netlink socket: %s\n", strerror(errno)); 553 return -1; 554 } 555 556 fcntl(sock_arp, F_SETFL, O_NONBLOCK); 557 memset(&la, 0, sizeof(la)); 558 la.nl_family = AF_NETLINK; 559 la.nl_groups = RTMGRP_NEIGH | RTMGRP_NOTIFY; 560 if (bind(sock_arp, (struct sockaddr *)&la, sizeof(la)) < 0) { 561 printf("bind to netlink: %s\n", strerror(errno)); 562 ret = -1; 563 goto cleanup; 564 } 565 fds_arp.fd = sock_arp; 566 fds_arp.events = POLL_IN; 567 568 memset(prev, 0, sizeof(prev)); 569 do { 570 signal(SIGINT, close_and_exit); 571 signal(SIGTERM, close_and_exit); 572 573 sleep(interval); 574 for (key = 0; key < nr_keys; key++) { 575 __u64 sum = 0; 576 577 assert(bpf_map_lookup_elem(rxcnt_map_fd, 578 &key, values) == 0); 579 for (i = 0; i < nr_cpus; i++) 580 sum += (values[i] - prev[key][i]); 581 if (sum) 582 printf("proto %u: %10llu pkt/s\n", 583 key, sum / interval); 584 memcpy(prev[key], values, sizeof(values)); 585 } 586 587 memset(buf, 0, sizeof(buf)); 588 if (poll(&fds_route, 1, 3) == POLL_IN) { 589 nll = recv_msg(lr, sock); 590 if (nll < 0) { 591 printf("recv from netlink: %s\n", strerror(nll)); 592 ret = -1; 593 goto cleanup; 594 } 595 596 nh = (struct nlmsghdr *)buf; 597 printf("Routing table updated.\n"); 598 read_route(nh, nll); 599 } 600 memset(buf, 0, sizeof(buf)); 601 if (poll(&fds_arp, 1, 3) == POLL_IN) { 602 nll = recv_msg(la, sock_arp); 603 if (nll < 0) { 604 printf("recv from netlink: %s\n", strerror(nll)); 605 ret = -1; 606 goto cleanup; 607 } 608 609 nh = (struct nlmsghdr *)buf; 610 read_arp(nh, nll); 611 } 612 613 } while (1); 614 cleanup: 615 close(sock); 616 return ret; 617 } 618 619 static void usage(const char *prog) 620 { 621 fprintf(stderr, 622 "%s: %s [OPTS] interface name list\n\n" 623 "OPTS:\n" 624 " -S use skb-mode\n" 625 " -F force loading prog\n", 626 __func__, prog); 627 } 628 629 int main(int ac, char **argv) 630 { 631 struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 632 struct bpf_prog_load_attr prog_load_attr = { 633 .prog_type = BPF_PROG_TYPE_XDP, 634 }; 635 struct bpf_prog_info info = {}; 636 __u32 info_len = sizeof(info); 637 const char *optstr = "SF"; 638 struct bpf_object *obj; 639 char filename[256]; 640 char **ifname_list; 641 int prog_fd, opt; 642 int err, i = 1; 643 644 snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); 645 prog_load_attr.file = filename; 646 647 total_ifindex = ac - 1; 648 ifname_list = (argv + 1); 649 650 while ((opt = getopt(ac, argv, optstr)) != -1) { 651 switch (opt) { 652 case 'S': 653 flags |= XDP_FLAGS_SKB_MODE; 654 total_ifindex--; 655 ifname_list++; 656 break; 657 case 'F': 658 flags &= ~XDP_FLAGS_UPDATE_IF_NOEXIST; 659 total_ifindex--; 660 ifname_list++; 661 break; 662 default: 663 usage(basename(argv[0])); 664 return 1; 665 } 666 } 667 668 if (optind == ac) { 669 usage(basename(argv[0])); 670 return 1; 671 } 672 673 if (setrlimit(RLIMIT_MEMLOCK, &r)) { 674 perror("setrlimit(RLIMIT_MEMLOCK)"); 675 return 1; 676 } 677 678 if (bpf_prog_load_xattr(&prog_load_attr, &obj, &prog_fd)) 679 return 1; 680 681 printf("\n**************loading bpf file*********************\n\n\n"); 682 if (!prog_fd) { 683 printf("bpf_prog_load_xattr: %s\n", strerror(errno)); 684 return 1; 685 } 686 687 lpm_map_fd = bpf_object__find_map_fd_by_name(obj, "lpm_map"); 688 rxcnt_map_fd = bpf_object__find_map_fd_by_name(obj, "rxcnt"); 689 arp_table_map_fd = bpf_object__find_map_fd_by_name(obj, "arp_table"); 690 exact_match_map_fd = bpf_object__find_map_fd_by_name(obj, 691 "exact_match"); 692 tx_port_map_fd = bpf_object__find_map_fd_by_name(obj, "tx_port"); 693 if (lpm_map_fd < 0 || rxcnt_map_fd < 0 || arp_table_map_fd < 0 || 694 exact_match_map_fd < 0 || tx_port_map_fd < 0) { 695 printf("bpf_object__find_map_fd_by_name failed\n"); 696 return 1; 697 } 698 699 ifindex_list = (int *)calloc(total_ifindex, sizeof(int *)); 700 for (i = 0; i < total_ifindex; i++) { 701 ifindex_list[i] = if_nametoindex(ifname_list[i]); 702 if (!ifindex_list[i]) { 703 printf("Couldn't translate interface name: %s", 704 strerror(errno)); 705 return 1; 706 } 707 } 708 prog_id_list = (__u32 *)calloc(total_ifindex, sizeof(__u32 *)); 709 for (i = 0; i < total_ifindex; i++) { 710 if (bpf_set_link_xdp_fd(ifindex_list[i], prog_fd, flags) < 0) { 711 printf("link set xdp fd failed\n"); 712 int recovery_index = i; 713 714 for (i = 0; i < recovery_index; i++) 715 bpf_set_link_xdp_fd(ifindex_list[i], -1, flags); 716 717 return 1; 718 } 719 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); 720 if (err) { 721 printf("can't get prog info - %s\n", strerror(errno)); 722 return err; 723 } 724 prog_id_list[i] = info.id; 725 memset(&info, 0, sizeof(info)); 726 printf("Attached to %d\n", ifindex_list[i]); 727 } 728 signal(SIGINT, int_exit); 729 signal(SIGTERM, int_exit); 730 731 printf("*******************ROUTE TABLE*************************\n\n\n"); 732 get_route_table(AF_INET); 733 printf("*******************ARP TABLE***************************\n\n\n"); 734 get_arp_table(AF_INET); 735 if (monitor_route() < 0) { 736 printf("Error in receiving route update"); 737 return 1; 738 } 739 740 return 0; 741 } 742