aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/bpf
diff options
context:
space:
mode:
authorYonghong Song <yhs@fb.com>2018-09-05 19:58:04 -0400
committerAlexei Starovoitov <ast@kernel.org>2018-09-07 01:34:08 -0400
commitf7010770fbac47b1fc9fb723b1d2019eb23c04f2 (patch)
tree4c58b2106198e64b4712fc3d27a6dcc5ba5b87a7 /tools/lib/bpf
parent52b7b7843d9523ebc3c60c51c7afc4a45cc10aad (diff)
tools/bpf: move bpf/lib netlink related functions into a new file
There are no functionality change for this patch. In the subsequent patches, more netlink related library functions will be added and a separate file is better than cluttering bpf.c. Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/lib/bpf')
-rw-r--r--tools/lib/bpf/Build2
-rw-r--r--tools/lib/bpf/bpf.c129
-rw-r--r--tools/lib/bpf/netlink.c165
3 files changed, 166 insertions, 130 deletions
diff --git a/tools/lib/bpf/Build b/tools/lib/bpf/Build
index 13a861135127..512b2c0ba0d2 100644
--- a/tools/lib/bpf/Build
+++ b/tools/lib/bpf/Build
@@ -1 +1 @@
libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o libbpf-y := libbpf.o bpf.o nlattr.o btf.o libbpf_errno.o netlink.o
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 60aa4ca8b2c5..3878a26a2071 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -28,16 +28,8 @@
28#include <linux/bpf.h> 28#include <linux/bpf.h>
29#include "bpf.h" 29#include "bpf.h"
30#include "libbpf.h" 30#include "libbpf.h"
31#include "nlattr.h"
32#include <linux/rtnetlink.h>
33#include <linux/if_link.h>
34#include <sys/socket.h>
35#include <errno.h> 31#include <errno.h>
36 32
37#ifndef SOL_NETLINK
38#define SOL_NETLINK 270
39#endif
40
41/* 33/*
42 * When building perf, unistd.h is overridden. __NR_bpf is 34 * When building perf, unistd.h is overridden. __NR_bpf is
43 * required to be defined explicitly. 35 * required to be defined explicitly.
@@ -499,127 +491,6 @@ int bpf_raw_tracepoint_open(const char *name, int prog_fd)
499 return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr)); 491 return sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
500} 492}
501 493
502int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
503{
504 struct sockaddr_nl sa;
505 int sock, seq = 0, len, ret = -1;
506 char buf[4096];
507 struct nlattr *nla, *nla_xdp;
508 struct {
509 struct nlmsghdr nh;
510 struct ifinfomsg ifinfo;
511 char attrbuf[64];
512 } req;
513 struct nlmsghdr *nh;
514 struct nlmsgerr *err;
515 socklen_t addrlen;
516 int one = 1;
517
518 memset(&sa, 0, sizeof(sa));
519 sa.nl_family = AF_NETLINK;
520
521 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
522 if (sock < 0) {
523 return -errno;
524 }
525
526 if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
527 &one, sizeof(one)) < 0) {
528 fprintf(stderr, "Netlink error reporting not supported\n");
529 }
530
531 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
532 ret = -errno;
533 goto cleanup;
534 }
535
536 addrlen = sizeof(sa);
537 if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
538 ret = -errno;
539 goto cleanup;
540 }
541
542 if (addrlen != sizeof(sa)) {
543 ret = -LIBBPF_ERRNO__INTERNAL;
544 goto cleanup;
545 }
546
547 memset(&req, 0, sizeof(req));
548 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
549 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
550 req.nh.nlmsg_type = RTM_SETLINK;
551 req.nh.nlmsg_pid = 0;
552 req.nh.nlmsg_seq = ++seq;
553 req.ifinfo.ifi_family = AF_UNSPEC;
554 req.ifinfo.ifi_index = ifindex;
555
556 /* started nested attribute for XDP */
557 nla = (struct nlattr *)(((char *)&req)
558 + NLMSG_ALIGN(req.nh.nlmsg_len));
559 nla->nla_type = NLA_F_NESTED | IFLA_XDP;
560 nla->nla_len = NLA_HDRLEN;
561
562 /* add XDP fd */
563 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
564 nla_xdp->nla_type = IFLA_XDP_FD;
565 nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
566 memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
567 nla->nla_len += nla_xdp->nla_len;
568
569 /* if user passed in any flags, add those too */
570 if (flags) {
571 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
572 nla_xdp->nla_type = IFLA_XDP_FLAGS;
573 nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
574 memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
575 nla->nla_len += nla_xdp->nla_len;
576 }
577
578 req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
579
580 if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
581 ret = -errno;
582 goto cleanup;
583 }
584
585 len = recv(sock, buf, sizeof(buf), 0);
586 if (len < 0) {
587 ret = -errno;
588 goto cleanup;
589 }
590
591 for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
592 nh = NLMSG_NEXT(nh, len)) {
593 if (nh->nlmsg_pid != sa.nl_pid) {
594 ret = -LIBBPF_ERRNO__WRNGPID;
595 goto cleanup;
596 }
597 if (nh->nlmsg_seq != seq) {
598 ret = -LIBBPF_ERRNO__INVSEQ;
599 goto cleanup;
600 }
601 switch (nh->nlmsg_type) {
602 case NLMSG_ERROR:
603 err = (struct nlmsgerr *)NLMSG_DATA(nh);
604 if (!err->error)
605 continue;
606 ret = err->error;
607 nla_dump_errormsg(nh);
608 goto cleanup;
609 case NLMSG_DONE:
610 break;
611 default:
612 break;
613 }
614 }
615
616 ret = 0;
617
618cleanup:
619 close(sock);
620 return ret;
621}
622
623int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, 494int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size,
624 bool do_log) 495 bool do_log)
625{ 496{
diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c
new file mode 100644
index 000000000000..ccaa991fe9d8
--- /dev/null
+++ b/tools/lib/bpf/netlink.c
@@ -0,0 +1,165 @@
1// SPDX-License-Identifier: LGPL-2.1
2/* Copyright (c) 2018 Facebook */
3
4#include <stdlib.h>
5#include <memory.h>
6#include <unistd.h>
7#include <linux/bpf.h>
8#include <linux/rtnetlink.h>
9#include <sys/socket.h>
10#include <errno.h>
11#include <time.h>
12
13#include "bpf.h"
14#include "libbpf.h"
15#include "nlattr.h"
16
17#ifndef SOL_NETLINK
18#define SOL_NETLINK 270
19#endif
20
21static int bpf_netlink_open(__u32 *nl_pid)
22{
23 struct sockaddr_nl sa;
24 socklen_t addrlen;
25 int one = 1, ret;
26 int sock;
27
28 memset(&sa, 0, sizeof(sa));
29 sa.nl_family = AF_NETLINK;
30
31 sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
32 if (sock < 0)
33 return -errno;
34
35 if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
36 &one, sizeof(one)) < 0) {
37 fprintf(stderr, "Netlink error reporting not supported\n");
38 }
39
40 if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
41 ret = -errno;
42 goto cleanup;
43 }
44
45 addrlen = sizeof(sa);
46 if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
47 ret = -errno;
48 goto cleanup;
49 }
50
51 if (addrlen != sizeof(sa)) {
52 ret = -LIBBPF_ERRNO__INTERNAL;
53 goto cleanup;
54 }
55
56 *nl_pid = sa.nl_pid;
57 return sock;
58
59cleanup:
60 close(sock);
61 return ret;
62}
63
64static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq)
65{
66 struct nlmsgerr *err;
67 struct nlmsghdr *nh;
68 char buf[4096];
69 int len, ret;
70
71 while (1) {
72 len = recv(sock, buf, sizeof(buf), 0);
73 if (len < 0) {
74 ret = -errno;
75 goto done;
76 }
77
78 for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
79 nh = NLMSG_NEXT(nh, len)) {
80 if (nh->nlmsg_pid != nl_pid) {
81 ret = -LIBBPF_ERRNO__WRNGPID;
82 goto done;
83 }
84 if (nh->nlmsg_seq != seq) {
85 ret = -LIBBPF_ERRNO__INVSEQ;
86 goto done;
87 }
88 switch (nh->nlmsg_type) {
89 case NLMSG_ERROR:
90 err = (struct nlmsgerr *)NLMSG_DATA(nh);
91 if (!err->error)
92 continue;
93 ret = err->error;
94 nla_dump_errormsg(nh);
95 goto done;
96 case NLMSG_DONE:
97 return 0;
98 default:
99 break;
100 }
101 }
102 }
103 ret = 0;
104done:
105 return ret;
106}
107
108int bpf_set_link_xdp_fd(int ifindex, int fd, __u32 flags)
109{
110 int sock, seq = 0, ret;
111 struct nlattr *nla, *nla_xdp;
112 struct {
113 struct nlmsghdr nh;
114 struct ifinfomsg ifinfo;
115 char attrbuf[64];
116 } req;
117 __u32 nl_pid;
118
119 sock = bpf_netlink_open(&nl_pid);
120 if (sock < 0)
121 return sock;
122
123 memset(&req, 0, sizeof(req));
124 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
125 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
126 req.nh.nlmsg_type = RTM_SETLINK;
127 req.nh.nlmsg_pid = 0;
128 req.nh.nlmsg_seq = ++seq;
129 req.ifinfo.ifi_family = AF_UNSPEC;
130 req.ifinfo.ifi_index = ifindex;
131
132 /* started nested attribute for XDP */
133 nla = (struct nlattr *)(((char *)&req)
134 + NLMSG_ALIGN(req.nh.nlmsg_len));
135 nla->nla_type = NLA_F_NESTED | IFLA_XDP;
136 nla->nla_len = NLA_HDRLEN;
137
138 /* add XDP fd */
139 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
140 nla_xdp->nla_type = IFLA_XDP_FD;
141 nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
142 memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd));
143 nla->nla_len += nla_xdp->nla_len;
144
145 /* if user passed in any flags, add those too */
146 if (flags) {
147 nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
148 nla_xdp->nla_type = IFLA_XDP_FLAGS;
149 nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
150 memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
151 nla->nla_len += nla_xdp->nla_len;
152 }
153
154 req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);
155
156 if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
157 ret = -errno;
158 goto cleanup;
159 }
160 ret = bpf_netlink_recv(sock, nl_pid, seq);
161
162cleanup:
163 close(sock);
164 return ret;
165}