]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - tools/tools/netmap/vale-ctl.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / tools / tools / netmap / vale-ctl.c
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$ */
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 #include <stdlib.h>     /* atoi, free */
42
43 /* debug support */
44 #define ND(format, ...) do {} while(0)
45 #define D(format, ...)                                  \
46         fprintf(stderr, "%s [%d] " format "\n",         \
47         __FUNCTION__, __LINE__, ##__VA_ARGS__)
48
49 /* XXX cut and paste from pkt-gen.c because I'm not sure whether this
50  * program may include nm_util.h
51  */
52 void parse_nmr_config(const char* conf, struct nmreq *nmr)
53 {
54         char *w, *tok;
55         int i, v;
56
57         nmr->nr_tx_rings = nmr->nr_rx_rings = 0;
58         nmr->nr_tx_slots = nmr->nr_rx_slots = 0;
59         if (conf == NULL || ! *conf)
60                 return;
61         w = strdup(conf);
62         for (i = 0, tok = strtok(w, ","); tok; i++, tok = strtok(NULL, ",")) {
63                 v = atoi(tok);
64                 switch (i) {
65                 case 0:
66                         nmr->nr_tx_slots = nmr->nr_rx_slots = v;
67                         break;
68                 case 1:
69                         nmr->nr_rx_slots = v;
70                         break;
71                 case 2:
72                         nmr->nr_tx_rings = nmr->nr_rx_rings = v;
73                         break;
74                 case 3:
75                         nmr->nr_rx_rings = v;
76                         break;
77                 default:
78                         D("ignored config: %s", tok);
79                         break;
80                 }
81         }
82         D("txr %d txd %d rxr %d rxd %d",
83                         nmr->nr_tx_rings, nmr->nr_tx_slots,
84                         nmr->nr_rx_rings, nmr->nr_rx_slots);
85         free(w);
86 }
87
88 static int
89 bdg_ctl(const char *name, int nr_cmd, int nr_arg, char *nmr_config)
90 {
91         struct nmreq nmr;
92         int error = 0;
93         int fd = open("/dev/netmap", O_RDWR);
94
95         if (fd == -1) {
96                 D("Unable to open /dev/netmap");
97                 return -1;
98         }
99
100         bzero(&nmr, sizeof(nmr));
101         nmr.nr_version = NETMAP_API;
102         if (name != NULL) /* might be NULL */
103                 strncpy(nmr.nr_name, name, sizeof(nmr.nr_name));
104         nmr.nr_cmd = nr_cmd;
105         parse_nmr_config(nmr_config, &nmr);
106
107         switch (nr_cmd) {
108         case NETMAP_BDG_DELIF:
109         case NETMAP_BDG_NEWIF:
110                 error = ioctl(fd, NIOCREGIF, &nmr);
111                 if (error == -1) {
112                         ND("Unable to %s %s", nr_cmd == NETMAP_BDG_DELIF ? "delete":"create", name);
113                         perror(name);
114                 } else {
115                         ND("Success to %s %s", nr_cmd == NETMAP_BDG_DELIF ? "delete":"create", name);
116                 }
117                 break;
118         case NETMAP_BDG_ATTACH:
119         case NETMAP_BDG_DETACH:
120                 if (nr_arg && nr_arg != NETMAP_BDG_HOST)
121                         nr_arg = 0;
122                 nmr.nr_arg1 = nr_arg;
123                 error = ioctl(fd, NIOCREGIF, &nmr);
124                 if (error == -1) {
125                         ND("Unable to %s %s to the bridge", nr_cmd ==
126                             NETMAP_BDG_DETACH?"detach":"attach", name);
127                         perror(name);
128                 } else
129                         ND("Success to %s %s to the bridge", nr_cmd ==
130                             NETMAP_BDG_DETACH?"detach":"attach", name);
131                 break;
132
133         case NETMAP_BDG_LIST:
134                 if (strlen(nmr.nr_name)) { /* name to bridge/port info */
135                         error = ioctl(fd, NIOCGINFO, &nmr);
136                         if (error) {
137                                 ND("Unable to obtain info for %s", name);
138                                 perror(name);
139                         } else
140                                 D("%s at bridge:%d port:%d", name, nmr.nr_arg1,
141                                     nmr.nr_arg2);
142                         break;
143                 }
144
145                 /* scan all the bridges and ports */
146                 nmr.nr_arg1 = nmr.nr_arg2 = 0;
147                 for (; !ioctl(fd, NIOCGINFO, &nmr); nmr.nr_arg2++) {
148                         D("bridge:%d port:%d %s", nmr.nr_arg1, nmr.nr_arg2,
149                             nmr.nr_name);
150                         nmr.nr_name[0] = '\0';
151                 }
152
153                 break;
154
155         default: /* GINFO */
156                 nmr.nr_cmd = nmr.nr_arg1 = nmr.nr_arg2 = 0;
157                 error = ioctl(fd, NIOCGINFO, &nmr);
158                 if (error) {
159                         ND("Unable to get if info for %s", name);
160                         perror(name);
161                 } else
162                         D("%s: %d queues.", name, nmr.nr_rx_rings);
163                 break;
164         }
165         close(fd);
166         return error;
167 }
168
169 int
170 main(int argc, char *argv[])
171 {
172         int ch, nr_cmd = 0, nr_arg = 0;
173         const char *command = basename(argv[0]);
174         char *name = NULL, *nmr_config = NULL;
175
176         if (argc > 3) {
177 usage:
178                 fprintf(stderr,
179                         "Usage:\n"
180                         "%s arguments\n"
181                         "\t-g interface interface name to get info\n"
182                         "\t-d interface interface name to be detached\n"
183                         "\t-a interface interface name to be attached\n"
184                         "\t-h interface interface name to be attached with the host stack\n"
185                         "\t-n interface interface name to be created\n"
186                         "\t-r interface interface name to be deleted\n"
187                         "\t-l list all or specified bridge's interfaces (default)\n"
188                         "\t-C string ring/slot setting of an interface creating by -n\n"
189                         "", command);
190                 return 0;
191         }
192
193         while ((ch = getopt(argc, argv, "d:a:h:g:l:n:r:C:")) != -1) {
194                 name = optarg; /* default */
195                 switch (ch) {
196                 default:
197                         fprintf(stderr, "bad option %c %s", ch, optarg);
198                         goto usage;
199                 case 'd':
200                         nr_cmd = NETMAP_BDG_DETACH;
201                         break;
202                 case 'a':
203                         nr_cmd = NETMAP_BDG_ATTACH;
204                         break;
205                 case 'h':
206                         nr_cmd = NETMAP_BDG_ATTACH;
207                         nr_arg = NETMAP_BDG_HOST;
208                         break;
209                 case 'n':
210                         nr_cmd = NETMAP_BDG_NEWIF;
211                         break;
212                 case 'r':
213                         nr_cmd = NETMAP_BDG_DELIF;
214                         break;
215                 case 'g':
216                         nr_cmd = 0;
217                         break;
218                 case 'l':
219                         nr_cmd = NETMAP_BDG_LIST;
220                         if (optind < argc && argv[optind][0] == '-')
221                                 name = NULL;
222                         break;
223                 case 'C':
224                         nmr_config = strdup(optarg);
225                         break;
226                 }
227                 if (optind != argc) {
228                         // fprintf(stderr, "optind %d argc %d\n", optind, argc);
229                         goto usage;
230                 }
231         }
232         if (argc == 1)
233                 nr_cmd = NETMAP_BDG_LIST;
234         return bdg_ctl(name, nr_cmd, nr_arg, nmr_config) ? 1 : 0;
235 }