xref: /freebsd/usr.sbin/valectl/valectl.c (revision 9fd3f663da44f5506fd4a13d6b7bf24efe525c78)
1c7c78055SVincenzo Maffione /*
2c7c78055SVincenzo Maffione  * Copyright (C) 2013-2014 Michio Honda. All rights reserved.
3c7c78055SVincenzo Maffione  *
4c7c78055SVincenzo Maffione  * Redistribution and use in source and binary forms, with or without
5c7c78055SVincenzo Maffione  * modification, are permitted provided that the following conditions
6c7c78055SVincenzo Maffione  * are met:
7c7c78055SVincenzo Maffione  *   1. Redistributions of source code must retain the above copyright
8c7c78055SVincenzo Maffione  *      notice, this list of conditions and the following disclaimer.
9c7c78055SVincenzo Maffione  *   2. Redistributions in binary form must reproduce the above copyright
10c7c78055SVincenzo Maffione  *      notice, this list of conditions and the following disclaimer in the
11c7c78055SVincenzo Maffione  *    documentation and/or other materials provided with the distribution.
12c7c78055SVincenzo Maffione  *
13c7c78055SVincenzo Maffione  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14c7c78055SVincenzo Maffione  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15c7c78055SVincenzo Maffione  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16c7c78055SVincenzo Maffione  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17c7c78055SVincenzo Maffione  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18c7c78055SVincenzo Maffione  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19c7c78055SVincenzo Maffione  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20c7c78055SVincenzo Maffione  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21c7c78055SVincenzo Maffione  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22c7c78055SVincenzo Maffione  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23c7c78055SVincenzo Maffione  * SUCH DAMAGE.
24c7c78055SVincenzo Maffione  */
25c7c78055SVincenzo Maffione 
26c7c78055SVincenzo Maffione /* $FreeBSD$ */
27c7c78055SVincenzo Maffione 
28*9fd3f663SVincenzo Maffione #define LIBNETMAP_NOTHREADSAFE
29*9fd3f663SVincenzo Maffione #include <libnetmap.h>
30c7c78055SVincenzo Maffione 
31c7c78055SVincenzo Maffione #include <errno.h>
32c7c78055SVincenzo Maffione #include <stdio.h>
33c7c78055SVincenzo Maffione #include <inttypes.h>	/* PRI* macros */
34c7c78055SVincenzo Maffione #include <string.h>	/* strcmp */
35c7c78055SVincenzo Maffione #include <fcntl.h>	/* open */
36c7c78055SVincenzo Maffione #include <unistd.h>	/* close */
37c7c78055SVincenzo Maffione #include <sys/ioctl.h>	/* ioctl */
38c7c78055SVincenzo Maffione #include <sys/param.h>
39c7c78055SVincenzo Maffione #include <sys/socket.h>	/* apple needs sockaddr */
40c7c78055SVincenzo Maffione #include <net/if.h>	/* ifreq */
41c7c78055SVincenzo Maffione #include <libgen.h>	/* basename */
42c7c78055SVincenzo Maffione #include <stdlib.h>	/* atoi, free */
43c7c78055SVincenzo Maffione 
44*9fd3f663SVincenzo Maffione int verbose;
45*9fd3f663SVincenzo Maffione 
46*9fd3f663SVincenzo Maffione struct args {
47*9fd3f663SVincenzo Maffione 	const char *name;
48*9fd3f663SVincenzo Maffione 	const char *config;
49*9fd3f663SVincenzo Maffione 	const char *mem_id;
50*9fd3f663SVincenzo Maffione 
51*9fd3f663SVincenzo Maffione 	uint16_t nr_reqtype;
52*9fd3f663SVincenzo Maffione 	uint32_t nr_mode;
53*9fd3f663SVincenzo Maffione };
54*9fd3f663SVincenzo Maffione 
55c7c78055SVincenzo Maffione static void
56*9fd3f663SVincenzo Maffione dump_port_info(struct nmreq_port_info_get *v)
57*9fd3f663SVincenzo Maffione {
58*9fd3f663SVincenzo Maffione 	printf("memsize:    %"PRIu64"\n", v->nr_memsize);
59*9fd3f663SVincenzo Maffione 	printf("tx_slots:   %"PRIu32"\n", v->nr_tx_slots);
60*9fd3f663SVincenzo Maffione 	printf("rx_slots:   %"PRIu32"\n", v->nr_rx_slots);
61*9fd3f663SVincenzo Maffione 	printf("tx_rings:   %"PRIu16"\n", v->nr_tx_rings);
62*9fd3f663SVincenzo Maffione 	printf("rx_rings    %"PRIu16"\n", v->nr_rx_rings);
63*9fd3f663SVincenzo Maffione 	printf("mem_id:     %"PRIu16"\n", v->nr_mem_id);
64*9fd3f663SVincenzo Maffione }
65*9fd3f663SVincenzo Maffione 
66*9fd3f663SVincenzo Maffione static void
67*9fd3f663SVincenzo Maffione dump_newif(struct nmreq_vale_newif *v)
68*9fd3f663SVincenzo Maffione {
69*9fd3f663SVincenzo Maffione 	printf("tx_slots:   %"PRIu32"\n", v->nr_tx_slots);
70*9fd3f663SVincenzo Maffione 	printf("rx_slots:   %"PRIu32"\n", v->nr_rx_slots);
71*9fd3f663SVincenzo Maffione 	printf("tx_rings:   %"PRIu16"\n", v->nr_tx_rings);
72*9fd3f663SVincenzo Maffione 	printf("rx_ring:    %"PRIu16"\n", v->nr_rx_rings);
73*9fd3f663SVincenzo Maffione 	printf("mem_id:     %"PRIu16"\n", v->nr_mem_id);
74*9fd3f663SVincenzo Maffione }
75*9fd3f663SVincenzo Maffione 
76*9fd3f663SVincenzo Maffione static void
77*9fd3f663SVincenzo Maffione dump_vale_list(struct nmreq_vale_list *v)
78*9fd3f663SVincenzo Maffione {
79*9fd3f663SVincenzo Maffione 	printf("bridge_idx: %"PRIu16"\n", v->nr_bridge_idx);
80*9fd3f663SVincenzo Maffione 	printf("port_idx:   %"PRIu16"\n", v->nr_port_idx);
81*9fd3f663SVincenzo Maffione }
82*9fd3f663SVincenzo Maffione 
83*9fd3f663SVincenzo Maffione 
84*9fd3f663SVincenzo Maffione static void
85*9fd3f663SVincenzo Maffione parse_ring_config(const char* conf,
86*9fd3f663SVincenzo Maffione 		uint32_t *nr_tx_slots,
87*9fd3f663SVincenzo Maffione 		uint32_t *nr_rx_slots,
88*9fd3f663SVincenzo Maffione 		uint16_t *nr_tx_rings,
89*9fd3f663SVincenzo Maffione 		uint16_t *nr_rx_rings)
90c7c78055SVincenzo Maffione {
91c7c78055SVincenzo Maffione 	char *w, *tok;
92c7c78055SVincenzo Maffione 	int i, v;
93c7c78055SVincenzo Maffione 
94*9fd3f663SVincenzo Maffione 	*nr_tx_rings = *nr_rx_rings = 0;
95*9fd3f663SVincenzo Maffione 	*nr_tx_slots = *nr_rx_slots = 0;
96c7c78055SVincenzo Maffione 	if (conf == NULL || ! *conf)
97c7c78055SVincenzo Maffione 		return;
98c7c78055SVincenzo Maffione 	w = strdup(conf);
99c7c78055SVincenzo Maffione 	for (i = 0, tok = strtok(w, ","); tok; i++, tok = strtok(NULL, ",")) {
100c7c78055SVincenzo Maffione 		v = atoi(tok);
101c7c78055SVincenzo Maffione 		switch (i) {
102c7c78055SVincenzo Maffione 		case 0:
103*9fd3f663SVincenzo Maffione 			*nr_tx_slots = *nr_rx_slots = v;
104c7c78055SVincenzo Maffione 			break;
105c7c78055SVincenzo Maffione 		case 1:
106*9fd3f663SVincenzo Maffione 			*nr_rx_slots = v;
107c7c78055SVincenzo Maffione 			break;
108c7c78055SVincenzo Maffione 		case 2:
109*9fd3f663SVincenzo Maffione 			*nr_tx_rings = *nr_rx_rings = v;
110c7c78055SVincenzo Maffione 			break;
111c7c78055SVincenzo Maffione 		case 3:
112*9fd3f663SVincenzo Maffione 			*nr_rx_rings = v;
113c7c78055SVincenzo Maffione 			break;
114c7c78055SVincenzo Maffione 		default:
115*9fd3f663SVincenzo Maffione 			fprintf(stderr, "ignored config: %s", tok);
116c7c78055SVincenzo Maffione 			break;
117c7c78055SVincenzo Maffione 		}
118c7c78055SVincenzo Maffione 	}
119*9fd3f663SVincenzo Maffione 	ND("txr %d txd %d rxr %d rxd %d",
120*9fd3f663SVincenzo Maffione 			*nr_tx_rings, *nr_tx_slots,
121*9fd3f663SVincenzo Maffione 			*nr_rx_rings, *nr_rx_slots);
122c7c78055SVincenzo Maffione 	free(w);
123c7c78055SVincenzo Maffione }
124c7c78055SVincenzo Maffione 
125c7c78055SVincenzo Maffione static int
126*9fd3f663SVincenzo Maffione parse_poll_config(const char *conf, struct nmreq_vale_polling *v)
127c7c78055SVincenzo Maffione {
128*9fd3f663SVincenzo Maffione 	char *w, *tok;
129*9fd3f663SVincenzo Maffione 	int i, p;
130c7c78055SVincenzo Maffione 
131*9fd3f663SVincenzo Maffione 	if (conf == NULL || ! *conf) {
132*9fd3f663SVincenzo Maffione 		fprintf(stderr, "invalid null/empty config\n");
133c7c78055SVincenzo Maffione 		return -1;
134c7c78055SVincenzo Maffione 	}
135*9fd3f663SVincenzo Maffione 	w = strdup(conf);
136*9fd3f663SVincenzo Maffione 	for (i = 0, tok = strtok(w, ","); tok; i++, tok = strtok(NULL, ",")) {
137*9fd3f663SVincenzo Maffione 		p = atoi(tok);
138*9fd3f663SVincenzo Maffione 		switch (i) {
139*9fd3f663SVincenzo Maffione 		case 0:
140*9fd3f663SVincenzo Maffione 			v->nr_mode = p ? NETMAP_POLLING_MODE_MULTI_CPU :
141*9fd3f663SVincenzo Maffione 				NETMAP_POLLING_MODE_SINGLE_CPU;
142*9fd3f663SVincenzo Maffione 			break;
143*9fd3f663SVincenzo Maffione 		case 1:
144*9fd3f663SVincenzo Maffione 			v->nr_first_cpu_id = p;
145*9fd3f663SVincenzo Maffione 			break;
146*9fd3f663SVincenzo Maffione 		case 2:
147*9fd3f663SVincenzo Maffione 			if (v->nr_mode != NETMAP_POLLING_MODE_MULTI_CPU) {
148*9fd3f663SVincenzo Maffione 				fprintf(stderr, "too many numbers in '%s'\n", conf);
149*9fd3f663SVincenzo Maffione 				return -1;
150c7c78055SVincenzo Maffione 			}
151*9fd3f663SVincenzo Maffione 			v->nr_num_polling_cpus = p;
152c7c78055SVincenzo Maffione 			break;
153*9fd3f663SVincenzo Maffione 		case 3:
154*9fd3f663SVincenzo Maffione 			fprintf(stderr, "too many numbers in '%s'\n", conf);
155*9fd3f663SVincenzo Maffione 			return -1;
156c7c78055SVincenzo Maffione 		}
157*9fd3f663SVincenzo Maffione 	}
158*9fd3f663SVincenzo Maffione 	free(w);
159*9fd3f663SVincenzo Maffione 	return 0;
160c7c78055SVincenzo Maffione }
161c7c78055SVincenzo Maffione 
162*9fd3f663SVincenzo Maffione static int32_t
163*9fd3f663SVincenzo Maffione parse_mem_id(const char *mem_id)
164*9fd3f663SVincenzo Maffione {
165*9fd3f663SVincenzo Maffione 	int32_t id;
166*9fd3f663SVincenzo Maffione 
167*9fd3f663SVincenzo Maffione 	if (mem_id == NULL)
168*9fd3f663SVincenzo Maffione 		return 0;
169*9fd3f663SVincenzo Maffione 	if (isdigit(*mem_id))
170*9fd3f663SVincenzo Maffione 		return atoi(mem_id);
171*9fd3f663SVincenzo Maffione 	id = nmreq_get_mem_id(&mem_id, nmctx_get());
172*9fd3f663SVincenzo Maffione 	if (id == 0) {
173*9fd3f663SVincenzo Maffione 		fprintf(stderr, "invalid format in '-m %s' (missing 'netmap:'?)\n", mem_id);
174*9fd3f663SVincenzo Maffione 		return -1;
175*9fd3f663SVincenzo Maffione 	}
176*9fd3f663SVincenzo Maffione 	return id;
177c7c78055SVincenzo Maffione }
178c7c78055SVincenzo Maffione 
179*9fd3f663SVincenzo Maffione static int
180*9fd3f663SVincenzo Maffione list_all(int fd, struct nmreq_header *hdr)
181*9fd3f663SVincenzo Maffione {
182*9fd3f663SVincenzo Maffione 	int error;
183*9fd3f663SVincenzo Maffione 	struct nmreq_vale_list *vale_list =
184*9fd3f663SVincenzo Maffione 		(struct nmreq_vale_list *)hdr->nr_body;
185*9fd3f663SVincenzo Maffione 
186*9fd3f663SVincenzo Maffione 	for (;;) {
187*9fd3f663SVincenzo Maffione 		hdr->nr_name[0] = '\0';
188*9fd3f663SVincenzo Maffione 		error = ioctl(fd, NIOCCTRL, hdr);
189*9fd3f663SVincenzo Maffione 		if (error < 0) {
190*9fd3f663SVincenzo Maffione 			if (errno == ENOENT)
191c7c78055SVincenzo Maffione 				break;
192c7c78055SVincenzo Maffione 
193*9fd3f663SVincenzo Maffione 			fprintf(stderr, "failed to list all: %s\n", strerror(errno));
194*9fd3f663SVincenzo Maffione 			return 1;
195*9fd3f663SVincenzo Maffione 		}
196*9fd3f663SVincenzo Maffione 		printf("%s bridge_idx %"PRIu16" port_idx %"PRIu32"\n", hdr->nr_name,
197*9fd3f663SVincenzo Maffione 				vale_list->nr_bridge_idx, vale_list->nr_port_idx);
198*9fd3f663SVincenzo Maffione 		vale_list->nr_port_idx++;
199*9fd3f663SVincenzo Maffione 	}
200*9fd3f663SVincenzo Maffione 	return 1;
201*9fd3f663SVincenzo Maffione }
202c7c78055SVincenzo Maffione 
203*9fd3f663SVincenzo Maffione static int
204*9fd3f663SVincenzo Maffione bdg_ctl(struct args *a)
205*9fd3f663SVincenzo Maffione {
206*9fd3f663SVincenzo Maffione 	struct nmreq_header hdr;
207*9fd3f663SVincenzo Maffione 	struct nmreq_vale_attach   vale_attach;
208*9fd3f663SVincenzo Maffione 	struct nmreq_vale_detach   vale_detach;
209*9fd3f663SVincenzo Maffione 	struct nmreq_vale_newif    vale_newif;
210*9fd3f663SVincenzo Maffione 	struct nmreq_vale_list     vale_list;
211*9fd3f663SVincenzo Maffione 	struct nmreq_vale_polling  vale_polling;
212*9fd3f663SVincenzo Maffione 	struct nmreq_port_info_get port_info_get;
213*9fd3f663SVincenzo Maffione 	int error = 0;
214*9fd3f663SVincenzo Maffione 	int fd;
215*9fd3f663SVincenzo Maffione 	int32_t mem_id;
216*9fd3f663SVincenzo Maffione 	const char *action = NULL;
217*9fd3f663SVincenzo Maffione 
218*9fd3f663SVincenzo Maffione 	fd = open("/dev/netmap", O_RDWR);
219*9fd3f663SVincenzo Maffione 	if (fd == -1) {
220*9fd3f663SVincenzo Maffione 		perror("/dev/netmap");
221*9fd3f663SVincenzo Maffione 		return 1;
222*9fd3f663SVincenzo Maffione 	}
223*9fd3f663SVincenzo Maffione 
224*9fd3f663SVincenzo Maffione 	bzero(&hdr, sizeof(hdr));
225*9fd3f663SVincenzo Maffione 	hdr.nr_version = NETMAP_API;
226*9fd3f663SVincenzo Maffione 	if (a->name != NULL) { /* might be NULL */
227*9fd3f663SVincenzo Maffione 		strncpy(hdr.nr_name, a->name, NETMAP_REQ_IFNAMSIZ - 1);
228*9fd3f663SVincenzo Maffione 		hdr.nr_name[NETMAP_REQ_IFNAMSIZ - 1] = '\0';
229*9fd3f663SVincenzo Maffione 	}
230*9fd3f663SVincenzo Maffione 	hdr.nr_reqtype = a->nr_reqtype;
231*9fd3f663SVincenzo Maffione 
232*9fd3f663SVincenzo Maffione 	switch (a->nr_reqtype) {
233*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_DELIF:
234*9fd3f663SVincenzo Maffione 		/* no body */
235*9fd3f663SVincenzo Maffione 		action = "remove";
236c7c78055SVincenzo Maffione 		break;
237c7c78055SVincenzo Maffione 
238*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_NEWIF:
239*9fd3f663SVincenzo Maffione 		memset(&vale_newif, 0, sizeof(vale_newif));
240*9fd3f663SVincenzo Maffione 		hdr.nr_body = (uintptr_t)&vale_newif;
241*9fd3f663SVincenzo Maffione 		parse_ring_config(a->config,
242*9fd3f663SVincenzo Maffione 				&vale_newif.nr_tx_slots,
243*9fd3f663SVincenzo Maffione 				&vale_newif.nr_rx_slots,
244*9fd3f663SVincenzo Maffione 				&vale_newif.nr_tx_rings,
245*9fd3f663SVincenzo Maffione 				&vale_newif.nr_rx_rings);
246*9fd3f663SVincenzo Maffione 		mem_id = parse_mem_id(a->mem_id);
247*9fd3f663SVincenzo Maffione 		if (mem_id < 0)
248*9fd3f663SVincenzo Maffione 			return 1;
249*9fd3f663SVincenzo Maffione 		vale_newif.nr_mem_id = mem_id;
250*9fd3f663SVincenzo Maffione 		action = "create";
251*9fd3f663SVincenzo Maffione 		break;
252*9fd3f663SVincenzo Maffione 
253*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_ATTACH:
254*9fd3f663SVincenzo Maffione 		memset(&vale_attach, 0, sizeof(vale_attach));
255*9fd3f663SVincenzo Maffione 		hdr.nr_body = (uintptr_t)&vale_attach;
256*9fd3f663SVincenzo Maffione 		vale_attach.reg.nr_mode = a->nr_mode;
257*9fd3f663SVincenzo Maffione 		parse_ring_config(a->config,
258*9fd3f663SVincenzo Maffione 				&vale_attach.reg.nr_tx_slots,
259*9fd3f663SVincenzo Maffione 				&vale_attach.reg.nr_rx_slots,
260*9fd3f663SVincenzo Maffione 				&vale_attach.reg.nr_tx_rings,
261*9fd3f663SVincenzo Maffione 				&vale_attach.reg.nr_rx_rings);
262*9fd3f663SVincenzo Maffione 		mem_id = parse_mem_id(a->mem_id);
263*9fd3f663SVincenzo Maffione 		if (mem_id < 0)
264*9fd3f663SVincenzo Maffione 			return 1;
265*9fd3f663SVincenzo Maffione 		vale_attach.reg.nr_mem_id = mem_id;
266*9fd3f663SVincenzo Maffione 		action = "attach";
267*9fd3f663SVincenzo Maffione 		break;
268*9fd3f663SVincenzo Maffione 
269*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_DETACH:
270*9fd3f663SVincenzo Maffione 		memset(&vale_detach, 0, sizeof(vale_detach));
271*9fd3f663SVincenzo Maffione 		hdr.nr_body = (uintptr_t)&vale_detach;
272*9fd3f663SVincenzo Maffione 		action = "detach";
273*9fd3f663SVincenzo Maffione 		break;
274*9fd3f663SVincenzo Maffione 
275*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_LIST:
276*9fd3f663SVincenzo Maffione 		memset(&vale_list, 0, sizeof(vale_list));
277*9fd3f663SVincenzo Maffione 		hdr.nr_body = (uintptr_t)&vale_list;
278*9fd3f663SVincenzo Maffione 		if (a->name == NULL) {
279*9fd3f663SVincenzo Maffione 			return list_all(fd, &hdr);
280*9fd3f663SVincenzo Maffione 		}
281*9fd3f663SVincenzo Maffione 		action = "list";
282*9fd3f663SVincenzo Maffione 		break;
283*9fd3f663SVincenzo Maffione 
284*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_POLLING_ENABLE:
285*9fd3f663SVincenzo Maffione 		action = "enable polling on";
286*9fd3f663SVincenzo Maffione 		/* fall through */
287*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_POLLING_DISABLE:
288*9fd3f663SVincenzo Maffione 		memset(&vale_polling, 0, sizeof(vale_polling));
289*9fd3f663SVincenzo Maffione 		hdr.nr_body = (uintptr_t)&vale_polling;
290*9fd3f663SVincenzo Maffione 		parse_poll_config(a->config, &vale_polling);
291*9fd3f663SVincenzo Maffione 		if (action == NULL)
292*9fd3f663SVincenzo Maffione 			action ="disable polling on";
293*9fd3f663SVincenzo Maffione 		break;
294*9fd3f663SVincenzo Maffione 
295*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_PORT_INFO_GET:
296*9fd3f663SVincenzo Maffione 		memset(&port_info_get, 0, sizeof(port_info_get));
297*9fd3f663SVincenzo Maffione 		hdr.nr_body = (uintptr_t)&port_info_get;
298*9fd3f663SVincenzo Maffione 		action = "obtain info for";
299*9fd3f663SVincenzo Maffione 		break;
300*9fd3f663SVincenzo Maffione 	}
301*9fd3f663SVincenzo Maffione 	error = ioctl(fd, NIOCCTRL, &hdr);
302*9fd3f663SVincenzo Maffione 	if (error < 0) {
303*9fd3f663SVincenzo Maffione 		fprintf(stderr, "failed to %s %s: %s\n",
304*9fd3f663SVincenzo Maffione 				action, a->name, strerror(errno));
305*9fd3f663SVincenzo Maffione 		return 1;
306*9fd3f663SVincenzo Maffione 	}
307*9fd3f663SVincenzo Maffione 	switch (hdr.nr_reqtype) {
308*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_NEWIF:
309*9fd3f663SVincenzo Maffione 		if (verbose) {
310*9fd3f663SVincenzo Maffione 			dump_newif(&vale_newif);
311*9fd3f663SVincenzo Maffione 		}
312*9fd3f663SVincenzo Maffione 		break;
313*9fd3f663SVincenzo Maffione 
314*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_ATTACH:
315*9fd3f663SVincenzo Maffione 		if (verbose) {
316*9fd3f663SVincenzo Maffione 			printf("port_index: %"PRIu32"\n", vale_attach.port_index);
317*9fd3f663SVincenzo Maffione 		}
318*9fd3f663SVincenzo Maffione 		break;
319*9fd3f663SVincenzo Maffione 
320*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_DETACH:
321*9fd3f663SVincenzo Maffione 		if (verbose) {
322*9fd3f663SVincenzo Maffione 			printf("port_index: %"PRIu32"\n", vale_detach.port_index);
323*9fd3f663SVincenzo Maffione 		}
324*9fd3f663SVincenzo Maffione 		break;
325*9fd3f663SVincenzo Maffione 
326*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_VALE_LIST:
327*9fd3f663SVincenzo Maffione 		dump_vale_list(&vale_list);
328*9fd3f663SVincenzo Maffione 		break;
329*9fd3f663SVincenzo Maffione 
330*9fd3f663SVincenzo Maffione 	case NETMAP_REQ_PORT_INFO_GET:
331*9fd3f663SVincenzo Maffione 		dump_port_info(&port_info_get);
332c7c78055SVincenzo Maffione 		break;
333c7c78055SVincenzo Maffione 	}
334c7c78055SVincenzo Maffione 	close(fd);
335c7c78055SVincenzo Maffione 	return error;
336c7c78055SVincenzo Maffione }
337c7c78055SVincenzo Maffione 
338c7c78055SVincenzo Maffione static void
339c7c78055SVincenzo Maffione usage(int errcode)
340c7c78055SVincenzo Maffione {
341c7c78055SVincenzo Maffione 	fprintf(stderr,
342c7c78055SVincenzo Maffione 	    "Usage:\n"
343*9fd3f663SVincenzo Maffione 	    "vale-ctl [arguments]\n"
344c7c78055SVincenzo Maffione 	    "\t-g interface	interface name to get info\n"
345c7c78055SVincenzo Maffione 	    "\t-d interface	interface name to be detached\n"
346c7c78055SVincenzo Maffione 	    "\t-a interface	interface name to be attached\n"
347c7c78055SVincenzo Maffione 	    "\t-h interface	interface name to be attached with the host stack\n"
348c7c78055SVincenzo Maffione 	    "\t-n interface	interface name to be created\n"
349c7c78055SVincenzo Maffione 	    "\t-r interface	interface name to be deleted\n"
350*9fd3f663SVincenzo Maffione 	    "\t-l vale-port	show bridge and port indices\n"
351c7c78055SVincenzo Maffione 	    "\t-C string ring/slot setting of an interface creating by -n\n"
352c7c78055SVincenzo Maffione 	    "\t-p interface start polling. Additional -C x,y,z configures\n"
353c7c78055SVincenzo Maffione 	    "\t\t x: 0 (REG_ALL_NIC) or 1 (REG_ONE_NIC),\n"
354c7c78055SVincenzo Maffione 	    "\t\t y: CPU core id for ALL_NIC and core/ring for ONE_NIC\n"
355c7c78055SVincenzo Maffione 	    "\t\t z: (ONE_NIC only) num of total cores/rings\n"
356c7c78055SVincenzo Maffione 	    "\t-P interface stop polling\n"
357*9fd3f663SVincenzo Maffione 	    "\t-m memid to use when creating a new interface\n"
358*9fd3f663SVincenzo Maffione 	    "\t-v increase verbosity\n"
359*9fd3f663SVincenzo Maffione 	    "with no arguments: list all existing vale ports\n");
360c7c78055SVincenzo Maffione 	exit(errcode);
361c7c78055SVincenzo Maffione }
362c7c78055SVincenzo Maffione 
363c7c78055SVincenzo Maffione int
364c7c78055SVincenzo Maffione main(int argc, char *argv[])
365c7c78055SVincenzo Maffione {
366*9fd3f663SVincenzo Maffione 	int ch;
367*9fd3f663SVincenzo Maffione 	struct args a = {
368*9fd3f663SVincenzo Maffione 		.name = NULL,
369*9fd3f663SVincenzo Maffione 		.config = NULL,
370*9fd3f663SVincenzo Maffione 		.mem_id = NULL,
371*9fd3f663SVincenzo Maffione 		.nr_reqtype = 0,
372*9fd3f663SVincenzo Maffione 		.nr_mode = NR_REG_ALL_NIC,
373*9fd3f663SVincenzo Maffione 	};
374c7c78055SVincenzo Maffione 
375*9fd3f663SVincenzo Maffione 	while ((ch = getopt(argc, argv, "d:a:h:g:l:n:r:C:p:P:m:v")) != -1) {
376c7c78055SVincenzo Maffione 		switch (ch) {
377c7c78055SVincenzo Maffione 		default:
378c7c78055SVincenzo Maffione 			fprintf(stderr, "bad option %c %s", ch, optarg);
379*9fd3f663SVincenzo Maffione 			usage(1);
380c7c78055SVincenzo Maffione 			break;
381c7c78055SVincenzo Maffione 		case 'd':
382*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_VALE_DETACH;
383*9fd3f663SVincenzo Maffione 			a.name = optarg;
384c7c78055SVincenzo Maffione 			break;
385c7c78055SVincenzo Maffione 		case 'a':
386*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_VALE_ATTACH;
387*9fd3f663SVincenzo Maffione 			a.nr_mode = NR_REG_ALL_NIC;
388*9fd3f663SVincenzo Maffione 			a.name = optarg;
389c7c78055SVincenzo Maffione 			break;
390c7c78055SVincenzo Maffione 		case 'h':
391*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_VALE_ATTACH;
392*9fd3f663SVincenzo Maffione 			a.nr_mode = NR_REG_NIC_SW;
393*9fd3f663SVincenzo Maffione 			a.name = optarg;
394c7c78055SVincenzo Maffione 			break;
395c7c78055SVincenzo Maffione 		case 'n':
396*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_VALE_NEWIF;
397*9fd3f663SVincenzo Maffione 			a.name = optarg;
398c7c78055SVincenzo Maffione 			break;
399c7c78055SVincenzo Maffione 		case 'r':
400*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_VALE_DELIF;
401*9fd3f663SVincenzo Maffione 			a.name = optarg;
402c7c78055SVincenzo Maffione 			break;
403c7c78055SVincenzo Maffione 		case 'g':
404*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_PORT_INFO_GET;
405*9fd3f663SVincenzo Maffione 			a.name = optarg;
406c7c78055SVincenzo Maffione 			break;
407c7c78055SVincenzo Maffione 		case 'l':
408*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_VALE_LIST;
409*9fd3f663SVincenzo Maffione 			a.name = optarg;
410*9fd3f663SVincenzo Maffione 			if (strncmp(a.name, NM_BDG_NAME, strlen(NM_BDG_NAME))) {
411*9fd3f663SVincenzo Maffione 				fprintf(stderr, "invalid vale port name: '%s'\n", a.name);
412*9fd3f663SVincenzo Maffione 				usage(1);
413*9fd3f663SVincenzo Maffione 			}
414c7c78055SVincenzo Maffione 			break;
415c7c78055SVincenzo Maffione 		case 'C':
416*9fd3f663SVincenzo Maffione 			a.config = optarg;
417c7c78055SVincenzo Maffione 			break;
418c7c78055SVincenzo Maffione 		case 'p':
419*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_VALE_POLLING_ENABLE;
420*9fd3f663SVincenzo Maffione 			a.name = optarg;
421c7c78055SVincenzo Maffione 			break;
422c7c78055SVincenzo Maffione 		case 'P':
423*9fd3f663SVincenzo Maffione 			a.nr_reqtype = NETMAP_REQ_VALE_POLLING_DISABLE;
424*9fd3f663SVincenzo Maffione 			a.name = optarg;
425c7c78055SVincenzo Maffione 			break;
426c7c78055SVincenzo Maffione 		case 'm':
427*9fd3f663SVincenzo Maffione 			a.mem_id = optarg;
428*9fd3f663SVincenzo Maffione 			break;
429*9fd3f663SVincenzo Maffione 		case 'v':
430*9fd3f663SVincenzo Maffione 			verbose++;
431c7c78055SVincenzo Maffione 			break;
432c7c78055SVincenzo Maffione 		}
433c7c78055SVincenzo Maffione 	}
434c7c78055SVincenzo Maffione 	if (optind != argc) {
435*9fd3f663SVincenzo Maffione 		usage(1);
436c7c78055SVincenzo Maffione 	}
437c7c78055SVincenzo Maffione 	if (argc == 1) {
438*9fd3f663SVincenzo Maffione 		a.nr_reqtype = NETMAP_REQ_VALE_LIST;
439*9fd3f663SVincenzo Maffione 		a.name = NULL;
440c7c78055SVincenzo Maffione 	}
441*9fd3f663SVincenzo Maffione 	if (!a.nr_reqtype) {
442*9fd3f663SVincenzo Maffione 		usage(1);
443*9fd3f663SVincenzo Maffione 	}
444*9fd3f663SVincenzo Maffione 	return bdg_ctl(&a);
445c7c78055SVincenzo Maffione }
446