vale-ctl.c revision 260368
1100203Sgad/*
2100203Sgad * Copyright (C) 2013-2014 Michio Honda. All rights reserved.
3220586Sgad *
4100203Sgad * Redistribution and use in source and binary forms, with or without
5100203Sgad * modification, are permitted provided that the following conditions
6100203Sgad * are met:
7100203Sgad *   1. Redistributions of source code must retain the above copyright
8100203Sgad *      notice, this list of conditions and the following disclaimer.
9100203Sgad *   2. Redistributions in binary form must reproduce the above copyright
10100203Sgad *      notice, this list of conditions and the following disclaimer in the
11100203Sgad *    documentation and/or other materials provided with the distribution.
12100203Sgad *
13100203Sgad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14100203Sgad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15100203Sgad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16100203Sgad * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17100203Sgad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18100203Sgad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19100203Sgad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20100203Sgad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21100203Sgad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22100203Sgad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23100203Sgad * SUCH DAMAGE.
24100203Sgad */
25100203Sgad
26100203Sgad/* $FreeBSD: head/tools/tools/netmap/vale-ctl.c 260368 2014-01-06 12:53:15Z luigi $ */
27100203Sgad
28100203Sgad#include <errno.h>
29100203Sgad#include <stdio.h>
30100203Sgad#include <inttypes.h>	/* PRI* macros */
31100203Sgad#include <string.h>	/* strcmp */
32100203Sgad#include <fcntl.h>	/* open */
33100203Sgad#include <unistd.h>	/* close */
34100203Sgad#include <sys/ioctl.h>	/* ioctl */
35117541Sgad#include <sys/param.h>
36117541Sgad#include <net/if.h>	/* ifreq */
37100203Sgad#include <net/netmap.h>
38100203Sgad#include <net/netmap_user.h>
39100203Sgad#include <libgen.h>	/* basename */
40100203Sgad
41100203Sgad/* debug support */
42100203Sgad#define ND(format, ...)	do {} while(0)
43100203Sgad#define D(format, ...)					\
44100203Sgad	fprintf(stderr, "%s [%d] " format "\n",		\
45100203Sgad	__FUNCTION__, __LINE__, ##__VA_ARGS__)
46100203Sgad
47100203Sgadstatic int
48100203Sgadbdg_ctl(const char *name, int nr_cmd, int nr_arg)
49100203Sgad{
50100203Sgad	struct nmreq nmr;
51100203Sgad	int error = 0;
52100203Sgad	int fd = open("/dev/netmap", O_RDWR);
53100203Sgad
54100203Sgad	if (fd == -1) {
55100203Sgad		D("Unable to open /dev/netmap");
56100203Sgad		return -1;
57100203Sgad	}
58100203Sgad
59100203Sgad	bzero(&nmr, sizeof(nmr));
60100203Sgad	nmr.nr_version = NETMAP_API;
61100203Sgad	if (name != NULL) /* might be NULL */
62100203Sgad		strncpy(nmr.nr_name, name, sizeof(nmr.nr_name));
63100203Sgad	nmr.nr_cmd = nr_cmd;
64100203Sgad
65100203Sgad	switch (nr_cmd) {
66100203Sgad	case NETMAP_BDG_ATTACH:
67100203Sgad	case NETMAP_BDG_DETACH:
68100203Sgad		if (nr_arg && nr_arg != NETMAP_BDG_HOST)
69100203Sgad			nr_arg = 0;
70100203Sgad		nmr.nr_arg1 = nr_arg;
71100203Sgad		error = ioctl(fd, NIOCREGIF, &nmr);
72100203Sgad		if (error == -1)
73100203Sgad			D("Unable to %s %s to the bridge", nr_cmd ==
74100203Sgad			    NETMAP_BDG_DETACH?"detach":"attach", name);
75100203Sgad		else
76100203Sgad			D("Success to %s %s to the bridge\n", nr_cmd ==
77100203Sgad			    NETMAP_BDG_DETACH?"detach":"attach", name);
78100203Sgad		break;
79100203Sgad
80100203Sgad	case NETMAP_BDG_LIST:
81100203Sgad		if (strlen(nmr.nr_name)) { /* name to bridge/port info */
82100203Sgad			error = ioctl(fd, NIOCGINFO, &nmr);
83100203Sgad			if (error)
84100203Sgad				D("Unable to obtain info for %s", name);
85100203Sgad			else
86100203Sgad				D("%s at bridge:%d port:%d", name, nmr.nr_arg1,
87100203Sgad				    nmr.nr_arg2);
88100203Sgad			break;
89100203Sgad		}
90100203Sgad
91100203Sgad		/* scan all the bridges and ports */
92100203Sgad		nmr.nr_arg1 = nmr.nr_arg2 = 0;
93100203Sgad		for (; !ioctl(fd, NIOCGINFO, &nmr); nmr.nr_arg2++) {
94100203Sgad			D("bridge:%d port:%d %s", nmr.nr_arg1, nmr.nr_arg2,
95100203Sgad			    nmr.nr_name);
96100203Sgad			nmr.nr_name[0] = '\0';
97100203Sgad		}
98100203Sgad
99100203Sgad		break;
100100203Sgad
101100203Sgad	default: /* GINFO */
102100203Sgad		nmr.nr_cmd = nmr.nr_arg1 = nmr.nr_arg2 = 0;
103100203Sgad		error = ioctl(fd, NIOCGINFO, &nmr);
104100203Sgad		if (error)
105100203Sgad			D("Unable to get if info for %s", name);
106100203Sgad		else
107100203Sgad			D("%s: %d queues.", name, nmr.nr_rx_rings);
108100203Sgad		break;
109100203Sgad	}
110100203Sgad	close(fd);
111100203Sgad	return error;
112100203Sgad}
113100203Sgad
114100203Sgadint
115100203Sgadmain(int argc, char *argv[])
116100203Sgad{
117100203Sgad	int ch, nr_cmd = 0, nr_arg = 0;
118100203Sgad	const char *command = basename(argv[0]);
119100203Sgad	char *name = NULL;
120100203Sgad
121100203Sgad	if (argc > 3) {
122100203Sgadusage:
123100203Sgad		fprintf(stderr,
124100203Sgad			"Usage:\n"
125100203Sgad			"%s arguments\n"
126100203Sgad			"\t-g interface	interface name to get info\n"
127100203Sgad			"\t-d interface	interface name to be detached\n"
128100203Sgad			"\t-a interface	interface name to be attached\n"
129100203Sgad			"\t-h interface	interface name to be attached with the host stack\n"
130100203Sgad			"\t-l list all or specified bridge's interfaces (default)\n"
131100203Sgad			"", command);
132100203Sgad		return 0;
133100203Sgad	}
134100203Sgad
135100203Sgad	while ((ch = getopt(argc, argv, "d:a:h:g:l")) != -1) {
136100203Sgad		name = optarg; /* default */
137100203Sgad		switch (ch) {
138100203Sgad		default:
139100203Sgad			fprintf(stderr, "bad option %c %s", ch, optarg);
140100203Sgad			goto usage;
141100203Sgad		case 'd':
142100203Sgad			nr_cmd = NETMAP_BDG_DETACH;
143100203Sgad			break;
144100203Sgad		case 'a':
145100203Sgad			nr_cmd = NETMAP_BDG_ATTACH;
146100203Sgad			break;
147100203Sgad		case 'h':
148100203Sgad			nr_cmd = NETMAP_BDG_ATTACH;
149100203Sgad			nr_arg = NETMAP_BDG_HOST;
150100203Sgad			break;
151100203Sgad		case 'g':
152100203Sgad			nr_cmd = 0;
153100203Sgad			break;
154100203Sgad		case 'l':
155100203Sgad			nr_cmd = NETMAP_BDG_LIST;
156100203Sgad			if (optind < argc && argv[optind][0] == '-')
157100203Sgad				name = NULL;
158100203Sgad			break;
159100203Sgad		}
160100203Sgad		if (optind != argc) {
161100203Sgad			// fprintf(stderr, "optind %d argc %d\n", optind, argc);
162100203Sgad			goto usage;
163100203Sgad		}
164100203Sgad	}
165100203Sgad	if (argc == 1)
166100203Sgad		nr_cmd = NETMAP_BDG_LIST;
167100203Sgad	bdg_ctl(name, nr_cmd, nr_arg);
168100203Sgad	return 0;
169100203Sgad}
170100203Sgad