xdpsock_ctrl_proc.c (3873B)
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 18/* libbpf APIs for AF_XDP are deprecated starting from v0.7 */ 19#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 20 21static 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_xdp_detach(ifindex, 0, NULL); 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}