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