mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
3.8 KiB
190 lines
3.8 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
/* Copyright(c) 2017 - 2018 Intel Corporation. */ |
|
|
|
#include <errno.h> |
|
#include <getopt.h> |
|
#include <libgen.h> |
|
#include <net/if.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <sys/socket.h> |
|
#include <sys/un.h> |
|
#include <unistd.h> |
|
|
|
#include <bpf/bpf.h> |
|
#include <bpf/xsk.h> |
|
#include "xdpsock.h" |
|
|
|
/* libbpf APIs for AF_XDP are deprecated starting from v0.7 */ |
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
|
|
|
static const char *opt_if = ""; |
|
|
|
static struct option long_options[] = { |
|
{"interface", required_argument, 0, 'i'}, |
|
{0, 0, 0, 0} |
|
}; |
|
|
|
static void usage(const char *prog) |
|
{ |
|
const char *str = |
|
" Usage: %s [OPTIONS]\n" |
|
" Options:\n" |
|
" -i, --interface=n Run on interface n\n" |
|
"\n"; |
|
fprintf(stderr, "%s\n", str); |
|
|
|
exit(0); |
|
} |
|
|
|
static void parse_command_line(int argc, char **argv) |
|
{ |
|
int option_index, c; |
|
|
|
opterr = 0; |
|
|
|
for (;;) { |
|
c = getopt_long(argc, argv, "i:", |
|
long_options, &option_index); |
|
if (c == -1) |
|
break; |
|
|
|
switch (c) { |
|
case 'i': |
|
opt_if = optarg; |
|
break; |
|
default: |
|
usage(basename(argv[0])); |
|
} |
|
} |
|
} |
|
|
|
static int send_xsks_map_fd(int sock, int fd) |
|
{ |
|
char cmsgbuf[CMSG_SPACE(sizeof(int))]; |
|
struct msghdr msg; |
|
struct iovec iov; |
|
int value = 0; |
|
|
|
if (fd == -1) { |
|
fprintf(stderr, "Incorrect fd = %d\n", fd); |
|
return -1; |
|
} |
|
iov.iov_base = &value; |
|
iov.iov_len = sizeof(int); |
|
|
|
msg.msg_name = NULL; |
|
msg.msg_namelen = 0; |
|
msg.msg_iov = &iov; |
|
msg.msg_iovlen = 1; |
|
msg.msg_flags = 0; |
|
msg.msg_control = cmsgbuf; |
|
msg.msg_controllen = CMSG_LEN(sizeof(int)); |
|
|
|
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); |
|
|
|
cmsg->cmsg_level = SOL_SOCKET; |
|
cmsg->cmsg_type = SCM_RIGHTS; |
|
cmsg->cmsg_len = CMSG_LEN(sizeof(int)); |
|
|
|
*(int *)CMSG_DATA(cmsg) = fd; |
|
int ret = sendmsg(sock, &msg, 0); |
|
|
|
if (ret == -1) { |
|
fprintf(stderr, "Sendmsg failed with %s", strerror(errno)); |
|
return -errno; |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
int |
|
main(int argc, char **argv) |
|
{ |
|
struct sockaddr_un server; |
|
int listening = 1; |
|
int rval, msgsock; |
|
int ifindex = 0; |
|
int flag = 1; |
|
int cmd = 0; |
|
int sock; |
|
int err; |
|
int xsks_map_fd; |
|
|
|
parse_command_line(argc, argv); |
|
|
|
ifindex = if_nametoindex(opt_if); |
|
if (ifindex == 0) { |
|
fprintf(stderr, "Unable to get ifindex for Interface %s. Reason:%s", |
|
opt_if, strerror(errno)); |
|
return -errno; |
|
} |
|
|
|
sock = socket(AF_UNIX, SOCK_STREAM, 0); |
|
if (sock < 0) { |
|
fprintf(stderr, "Opening socket stream failed: %s", strerror(errno)); |
|
return -errno; |
|
} |
|
|
|
server.sun_family = AF_UNIX; |
|
strcpy(server.sun_path, SOCKET_NAME); |
|
|
|
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int)); |
|
|
|
if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_un))) { |
|
fprintf(stderr, "Binding to socket stream failed: %s", strerror(errno)); |
|
return -errno; |
|
} |
|
|
|
listen(sock, MAX_NUM_OF_CLIENTS); |
|
|
|
err = xsk_setup_xdp_prog(ifindex, &xsks_map_fd); |
|
if (err) { |
|
fprintf(stderr, "Setup of xdp program failed\n"); |
|
goto close_sock; |
|
} |
|
|
|
while (listening) { |
|
msgsock = accept(sock, 0, 0); |
|
if (msgsock == -1) { |
|
fprintf(stderr, "Error accepting connection: %s", strerror(errno)); |
|
err = -errno; |
|
goto close_sock; |
|
} |
|
err = send_xsks_map_fd(msgsock, xsks_map_fd); |
|
if (err <= 0) { |
|
fprintf(stderr, "Error %d sending xsks_map_fd\n", err); |
|
goto cleanup; |
|
} |
|
do { |
|
rval = read(msgsock, &cmd, sizeof(int)); |
|
if (rval < 0) { |
|
fprintf(stderr, "Error reading stream message"); |
|
} else { |
|
if (cmd != CLOSE_CONN) |
|
fprintf(stderr, "Recv unknown cmd = %d\n", cmd); |
|
listening = 0; |
|
break; |
|
} |
|
} while (rval > 0); |
|
} |
|
close(msgsock); |
|
close(sock); |
|
unlink(SOCKET_NAME); |
|
|
|
/* Unset fd for given ifindex */ |
|
err = bpf_set_link_xdp_fd(ifindex, -1, 0); |
|
if (err) { |
|
fprintf(stderr, "Error when unsetting bpf prog_fd for ifindex(%d)\n", ifindex); |
|
return err; |
|
} |
|
|
|
return 0; |
|
|
|
cleanup: |
|
close(msgsock); |
|
close_sock: |
|
close(sock); |
|
unlink(SOCKET_NAME); |
|
return err; |
|
}
|
|
|