Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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}