linux/samples/bpf/xdpsock_ctrl_proc.c
<<
>>
Prefs
   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}
 188