blob: cc4408797ab702a22cf546e1d6dd1bcac8caabc1 [file] [log] [blame]
Mariusz Dudek3627d972020-12-03 10:05:46 +01001// SPDX-License-Identifier: GPL-2.0
2/* Copyright(c) 2017 - 2018 Intel Corporation. */
3
4#include <errno.h>
5#include <getopt.h>
6#include <libgen.h>
7#include <net/if.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <sys/socket.h>
11#include <sys/un.h>
12#include <unistd.h>
13
14#include <bpf/bpf.h>
15#include <bpf/xsk.h>
16#include "xdpsock.h"
17
Andrii Nakryikoc58f9812021-12-01 15:28:23 -080018/* libbpf APIs for AF_XDP are deprecated starting from v0.7 */
19#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
20
Mariusz Dudek3627d972020-12-03 10:05:46 +010021static const char *opt_if = "";
22
23static struct option long_options[] = {
24 {"interface", required_argument, 0, 'i'},
25 {0, 0, 0, 0}
26};
27
28static void usage(const char *prog)
29{
30 const char *str =
31 " Usage: %s [OPTIONS]\n"
32 " Options:\n"
33 " -i, --interface=n Run on interface n\n"
34 "\n";
35 fprintf(stderr, "%s\n", str);
36
37 exit(0);
38}
39
40static void parse_command_line(int argc, char **argv)
41{
42 int option_index, c;
43
44 opterr = 0;
45
46 for (;;) {
47 c = getopt_long(argc, argv, "i:",
48 long_options, &option_index);
49 if (c == -1)
50 break;
51
52 switch (c) {
53 case 'i':
54 opt_if = optarg;
55 break;
56 default:
57 usage(basename(argv[0]));
58 }
59 }
60}
61
62static int send_xsks_map_fd(int sock, int fd)
63{
64 char cmsgbuf[CMSG_SPACE(sizeof(int))];
65 struct msghdr msg;
66 struct iovec iov;
67 int value = 0;
68
69 if (fd == -1) {
70 fprintf(stderr, "Incorrect fd = %d\n", fd);
71 return -1;
72 }
73 iov.iov_base = &value;
74 iov.iov_len = sizeof(int);
75
76 msg.msg_name = NULL;
77 msg.msg_namelen = 0;
78 msg.msg_iov = &iov;
79 msg.msg_iovlen = 1;
80 msg.msg_flags = 0;
81 msg.msg_control = cmsgbuf;
82 msg.msg_controllen = CMSG_LEN(sizeof(int));
83
84 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
85
86 cmsg->cmsg_level = SOL_SOCKET;
87 cmsg->cmsg_type = SCM_RIGHTS;
88 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
89
90 *(int *)CMSG_DATA(cmsg) = fd;
91 int ret = sendmsg(sock, &msg, 0);
92
93 if (ret == -1) {
94 fprintf(stderr, "Sendmsg failed with %s", strerror(errno));
95 return -errno;
96 }
97
98 return ret;
99}
100
101int
102main(int argc, char **argv)
103{
104 struct sockaddr_un server;
105 int listening = 1;
106 int rval, msgsock;
107 int ifindex = 0;
108 int flag = 1;
109 int cmd = 0;
110 int sock;
111 int err;
112 int xsks_map_fd;
113
114 parse_command_line(argc, argv);
115
116 ifindex = if_nametoindex(opt_if);
117 if (ifindex == 0) {
118 fprintf(stderr, "Unable to get ifindex for Interface %s. Reason:%s",
119 opt_if, strerror(errno));
120 return -errno;
121 }
122
123 sock = socket(AF_UNIX, SOCK_STREAM, 0);
124 if (sock < 0) {
125 fprintf(stderr, "Opening socket stream failed: %s", strerror(errno));
126 return -errno;
127 }
128
129 server.sun_family = AF_UNIX;
130 strcpy(server.sun_path, SOCKET_NAME);
131
132 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));
133
134 if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un))) {
135 fprintf(stderr, "Binding to socket stream failed: %s", strerror(errno));
136 return -errno;
137 }
138
139 listen(sock, MAX_NUM_OF_CLIENTS);
140
141 err = xsk_setup_xdp_prog(ifindex, &xsks_map_fd);
142 if (err) {
143 fprintf(stderr, "Setup of xdp program failed\n");
144 goto close_sock;
145 }
146
147 while (listening) {
148 msgsock = accept(sock, 0, 0);
149 if (msgsock == -1) {
150 fprintf(stderr, "Error accepting connection: %s", strerror(errno));
151 err = -errno;
152 goto close_sock;
153 }
154 err = send_xsks_map_fd(msgsock, xsks_map_fd);
155 if (err <= 0) {
156 fprintf(stderr, "Error %d sending xsks_map_fd\n", err);
157 goto cleanup;
158 }
159 do {
160 rval = read(msgsock, &cmd, sizeof(int));
161 if (rval < 0) {
162 fprintf(stderr, "Error reading stream message");
163 } else {
164 if (cmd != CLOSE_CONN)
165 fprintf(stderr, "Recv unknown cmd = %d\n", cmd);
166 listening = 0;
167 break;
168 }
169 } while (rval > 0);
170 }
171 close(msgsock);
172 close(sock);
173 unlink(SOCKET_NAME);
174
175 /* Unset fd for given ifindex */
176 err = bpf_set_link_xdp_fd(ifindex, -1, 0);
177 if (err) {
178 fprintf(stderr, "Error when unsetting bpf prog_fd for ifindex(%d)\n", ifindex);
179 return err;
180 }
181
182 return 0;
183
184cleanup:
185 close(msgsock);
186close_sock:
187 close(sock);
188 unlink(SOCKET_NAME);
189 return err;
190}