vale-ctl.c revision 261909
1251139Sluigi/*
2260368Sluigi * Copyright (C) 2013-2014 Michio Honda. All rights reserved.
3251139Sluigi *
4251139Sluigi * Redistribution and use in source and binary forms, with or without
5251139Sluigi * modification, are permitted provided that the following conditions
6251139Sluigi * are met:
7251139Sluigi *   1. Redistributions of source code must retain the above copyright
8251139Sluigi *      notice, this list of conditions and the following disclaimer.
9251139Sluigi *   2. Redistributions in binary form must reproduce the above copyright
10251139Sluigi *      notice, this list of conditions and the following disclaimer in the
11251139Sluigi *    documentation and/or other materials provided with the distribution.
12251139Sluigi *
13251139Sluigi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14251139Sluigi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15251139Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16251139Sluigi * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17251139Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18251139Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19251139Sluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20251139Sluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21251139Sluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22251139Sluigi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23251139Sluigi * SUCH DAMAGE.
24251139Sluigi */
25251139Sluigi
26251139Sluigi/* $FreeBSD: head/tools/tools/netmap/vale-ctl.c 261909 2014-02-15 04:53:04Z luigi $ */
27251139Sluigi
28251139Sluigi#include <errno.h>
29251139Sluigi#include <stdio.h>
30251139Sluigi#include <inttypes.h>	/* PRI* macros */
31251139Sluigi#include <string.h>	/* strcmp */
32251139Sluigi#include <fcntl.h>	/* open */
33251139Sluigi#include <unistd.h>	/* close */
34251139Sluigi#include <sys/ioctl.h>	/* ioctl */
35251139Sluigi#include <sys/param.h>
36261909Sluigi#include <sys/socket.h>	/* apple needs sockaddr */
37251139Sluigi#include <net/if.h>	/* ifreq */
38251139Sluigi#include <net/netmap.h>
39251139Sluigi#include <net/netmap_user.h>
40251139Sluigi#include <libgen.h>	/* basename */
41251139Sluigi
42251139Sluigi/* debug support */
43251139Sluigi#define ND(format, ...)	do {} while(0)
44251139Sluigi#define D(format, ...)					\
45251139Sluigi	fprintf(stderr, "%s [%d] " format "\n",		\
46251139Sluigi	__FUNCTION__, __LINE__, ##__VA_ARGS__)
47251139Sluigi
48251139Sluigistatic int
49251139Sluigibdg_ctl(const char *name, int nr_cmd, int nr_arg)
50251139Sluigi{
51251139Sluigi	struct nmreq nmr;
52251139Sluigi	int error = 0;
53251139Sluigi	int fd = open("/dev/netmap", O_RDWR);
54251139Sluigi
55251139Sluigi	if (fd == -1) {
56251139Sluigi		D("Unable to open /dev/netmap");
57251139Sluigi		return -1;
58251139Sluigi	}
59251139Sluigi
60251139Sluigi	bzero(&nmr, sizeof(nmr));
61251139Sluigi	nmr.nr_version = NETMAP_API;
62251139Sluigi	if (name != NULL) /* might be NULL */
63251139Sluigi		strncpy(nmr.nr_name, name, sizeof(nmr.nr_name));
64251139Sluigi	nmr.nr_cmd = nr_cmd;
65251139Sluigi
66251139Sluigi	switch (nr_cmd) {
67251139Sluigi	case NETMAP_BDG_ATTACH:
68251139Sluigi	case NETMAP_BDG_DETACH:
69251139Sluigi		if (nr_arg && nr_arg != NETMAP_BDG_HOST)
70251139Sluigi			nr_arg = 0;
71251139Sluigi		nmr.nr_arg1 = nr_arg;
72251139Sluigi		error = ioctl(fd, NIOCREGIF, &nmr);
73260700Sluigi		if (error == -1) {
74260700Sluigi			ND("Unable to %s %s to the bridge", nr_cmd ==
75251139Sluigi			    NETMAP_BDG_DETACH?"detach":"attach", name);
76260700Sluigi			perror(name);
77260700Sluigi		} else
78260700Sluigi			ND("Success to %s %s to the bridge", nr_cmd ==
79251139Sluigi			    NETMAP_BDG_DETACH?"detach":"attach", name);
80251139Sluigi		break;
81251139Sluigi
82251139Sluigi	case NETMAP_BDG_LIST:
83251139Sluigi		if (strlen(nmr.nr_name)) { /* name to bridge/port info */
84251139Sluigi			error = ioctl(fd, NIOCGINFO, &nmr);
85260700Sluigi			if (error) {
86260700Sluigi				ND("Unable to obtain info for %s", name);
87260700Sluigi				perror(name);
88260700Sluigi			} else
89251139Sluigi				D("%s at bridge:%d port:%d", name, nmr.nr_arg1,
90251139Sluigi				    nmr.nr_arg2);
91251139Sluigi			break;
92251139Sluigi		}
93251139Sluigi
94251139Sluigi		/* scan all the bridges and ports */
95251139Sluigi		nmr.nr_arg1 = nmr.nr_arg2 = 0;
96251139Sluigi		for (; !ioctl(fd, NIOCGINFO, &nmr); nmr.nr_arg2++) {
97251139Sluigi			D("bridge:%d port:%d %s", nmr.nr_arg1, nmr.nr_arg2,
98251139Sluigi			    nmr.nr_name);
99251139Sluigi			nmr.nr_name[0] = '\0';
100251139Sluigi		}
101251139Sluigi
102251139Sluigi		break;
103251139Sluigi
104251139Sluigi	default: /* GINFO */
105251139Sluigi		nmr.nr_cmd = nmr.nr_arg1 = nmr.nr_arg2 = 0;
106251139Sluigi		error = ioctl(fd, NIOCGINFO, &nmr);
107260700Sluigi		if (error) {
108260700Sluigi			ND("Unable to get if info for %s", name);
109260700Sluigi			perror(name);
110260700Sluigi		} else
111251139Sluigi			D("%s: %d queues.", name, nmr.nr_rx_rings);
112251139Sluigi		break;
113251139Sluigi	}
114251139Sluigi	close(fd);
115251139Sluigi	return error;
116251139Sluigi}
117251139Sluigi
118251139Sluigiint
119251139Sluigimain(int argc, char *argv[])
120251139Sluigi{
121251139Sluigi	int ch, nr_cmd = 0, nr_arg = 0;
122251139Sluigi	const char *command = basename(argv[0]);
123251139Sluigi	char *name = NULL;
124251139Sluigi
125260368Sluigi	if (argc > 3) {
126251139Sluigiusage:
127251139Sluigi		fprintf(stderr,
128251139Sluigi			"Usage:\n"
129251139Sluigi			"%s arguments\n"
130251139Sluigi			"\t-g interface	interface name to get info\n"
131251139Sluigi			"\t-d interface	interface name to be detached\n"
132251139Sluigi			"\t-a interface	interface name to be attached\n"
133251139Sluigi			"\t-h interface	interface name to be attached with the host stack\n"
134260368Sluigi			"\t-l list all or specified bridge's interfaces (default)\n"
135251139Sluigi			"", command);
136251139Sluigi		return 0;
137251139Sluigi	}
138251139Sluigi
139260368Sluigi	while ((ch = getopt(argc, argv, "d:a:h:g:l")) != -1) {
140260368Sluigi		name = optarg; /* default */
141251139Sluigi		switch (ch) {
142251139Sluigi		default:
143251139Sluigi			fprintf(stderr, "bad option %c %s", ch, optarg);
144251139Sluigi			goto usage;
145251139Sluigi		case 'd':
146251139Sluigi			nr_cmd = NETMAP_BDG_DETACH;
147251139Sluigi			break;
148251139Sluigi		case 'a':
149251139Sluigi			nr_cmd = NETMAP_BDG_ATTACH;
150251139Sluigi			break;
151251139Sluigi		case 'h':
152251139Sluigi			nr_cmd = NETMAP_BDG_ATTACH;
153251139Sluigi			nr_arg = NETMAP_BDG_HOST;
154251139Sluigi			break;
155251139Sluigi		case 'g':
156251139Sluigi			nr_cmd = 0;
157251139Sluigi			break;
158251139Sluigi		case 'l':
159251139Sluigi			nr_cmd = NETMAP_BDG_LIST;
160260368Sluigi			if (optind < argc && argv[optind][0] == '-')
161260368Sluigi				name = NULL;
162251139Sluigi			break;
163251139Sluigi		}
164260368Sluigi		if (optind != argc) {
165260368Sluigi			// fprintf(stderr, "optind %d argc %d\n", optind, argc);
166260368Sluigi			goto usage;
167260368Sluigi		}
168251139Sluigi	}
169251139Sluigi	if (argc == 1)
170251139Sluigi		nr_cmd = NETMAP_BDG_LIST;
171260700Sluigi	return bdg_ctl(name, nr_cmd, nr_arg) ? 1 : 0;
172251139Sluigi}
173