vale-ctl.c revision 262151
1/*
2 * Copyright (C) 2013-2014 Michio Honda. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *   1. Redistributions of source code must retain the above copyright
8 *      notice, this list of conditions and the following disclaimer.
9 *   2. Redistributions in binary form must reproduce the above copyright
10 *      notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26/* $FreeBSD: stable/10/tools/tools/netmap/vale-ctl.c 262151 2014-02-18 05:01:04Z luigi $ */
27
28#include <errno.h>
29#include <stdio.h>
30#include <inttypes.h>	/* PRI* macros */
31#include <string.h>	/* strcmp */
32#include <fcntl.h>	/* open */
33#include <unistd.h>	/* close */
34#include <sys/ioctl.h>	/* ioctl */
35#include <sys/param.h>
36#include <sys/socket.h>	/* apple needs sockaddr */
37#include <net/if.h>	/* ifreq */
38#include <net/netmap.h>
39#include <net/netmap_user.h>
40#include <libgen.h>	/* basename */
41
42/* debug support */
43#define ND(format, ...)	do {} while(0)
44#define D(format, ...)					\
45	fprintf(stderr, "%s [%d] " format "\n",		\
46	__FUNCTION__, __LINE__, ##__VA_ARGS__)
47
48static int
49bdg_ctl(const char *name, int nr_cmd, int nr_arg)
50{
51	struct nmreq nmr;
52	int error = 0;
53	int fd = open("/dev/netmap", O_RDWR);
54
55	if (fd == -1) {
56		D("Unable to open /dev/netmap");
57		return -1;
58	}
59
60	bzero(&nmr, sizeof(nmr));
61	nmr.nr_version = NETMAP_API;
62	if (name != NULL) /* might be NULL */
63		strncpy(nmr.nr_name, name, sizeof(nmr.nr_name));
64	nmr.nr_cmd = nr_cmd;
65
66	switch (nr_cmd) {
67	case NETMAP_BDG_ATTACH:
68	case NETMAP_BDG_DETACH:
69		if (nr_arg && nr_arg != NETMAP_BDG_HOST)
70			nr_arg = 0;
71		nmr.nr_arg1 = nr_arg;
72		error = ioctl(fd, NIOCREGIF, &nmr);
73		if (error == -1) {
74			ND("Unable to %s %s to the bridge", nr_cmd ==
75			    NETMAP_BDG_DETACH?"detach":"attach", name);
76			perror(name);
77		} else
78			ND("Success to %s %s to the bridge", nr_cmd ==
79			    NETMAP_BDG_DETACH?"detach":"attach", name);
80		break;
81
82	case NETMAP_BDG_LIST:
83		if (strlen(nmr.nr_name)) { /* name to bridge/port info */
84			error = ioctl(fd, NIOCGINFO, &nmr);
85			if (error) {
86				ND("Unable to obtain info for %s", name);
87				perror(name);
88			} else
89				D("%s at bridge:%d port:%d", name, nmr.nr_arg1,
90				    nmr.nr_arg2);
91			break;
92		}
93
94		/* scan all the bridges and ports */
95		nmr.nr_arg1 = nmr.nr_arg2 = 0;
96		for (; !ioctl(fd, NIOCGINFO, &nmr); nmr.nr_arg2++) {
97			D("bridge:%d port:%d %s", nmr.nr_arg1, nmr.nr_arg2,
98			    nmr.nr_name);
99			nmr.nr_name[0] = '\0';
100		}
101
102		break;
103
104	default: /* GINFO */
105		nmr.nr_cmd = nmr.nr_arg1 = nmr.nr_arg2 = 0;
106		error = ioctl(fd, NIOCGINFO, &nmr);
107		if (error) {
108			ND("Unable to get if info for %s", name);
109			perror(name);
110		} else
111			D("%s: %d queues.", name, nmr.nr_rx_rings);
112		break;
113	}
114	close(fd);
115	return error;
116}
117
118int
119main(int argc, char *argv[])
120{
121	int ch, nr_cmd = 0, nr_arg = 0;
122	const char *command = basename(argv[0]);
123	char *name = NULL;
124
125	if (argc > 3) {
126usage:
127		fprintf(stderr,
128			"Usage:\n"
129			"%s arguments\n"
130			"\t-g interface	interface name to get info\n"
131			"\t-d interface	interface name to be detached\n"
132			"\t-a interface	interface name to be attached\n"
133			"\t-h interface	interface name to be attached with the host stack\n"
134			"\t-l list all or specified bridge's interfaces (default)\n"
135			"", command);
136		return 0;
137	}
138
139	while ((ch = getopt(argc, argv, "d:a:h:g:l")) != -1) {
140		name = optarg; /* default */
141		switch (ch) {
142		default:
143			fprintf(stderr, "bad option %c %s", ch, optarg);
144			goto usage;
145		case 'd':
146			nr_cmd = NETMAP_BDG_DETACH;
147			break;
148		case 'a':
149			nr_cmd = NETMAP_BDG_ATTACH;
150			break;
151		case 'h':
152			nr_cmd = NETMAP_BDG_ATTACH;
153			nr_arg = NETMAP_BDG_HOST;
154			break;
155		case 'g':
156			nr_cmd = 0;
157			break;
158		case 'l':
159			nr_cmd = NETMAP_BDG_LIST;
160			if (optind < argc && argv[optind][0] == '-')
161				name = NULL;
162			break;
163		}
164		if (optind != argc) {
165			// fprintf(stderr, "optind %d argc %d\n", optind, argc);
166			goto usage;
167		}
168	}
169	if (argc == 1)
170		nr_cmd = NETMAP_BDG_LIST;
171	return bdg_ctl(name, nr_cmd, nr_arg) ? 1 : 0;
172}
173