2 * Copyright (C) 2013-2014 Michio Honda. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
28 #define NETMAP_WITH_LIBS
29 #include <net/netmap_user.h>
30 #include <net/netmap.h>
34 #include <inttypes.h> /* PRI* macros */
35 #include <string.h> /* strcmp */
36 #include <fcntl.h> /* open */
37 #include <unistd.h> /* close */
38 #include <sys/ioctl.h> /* ioctl */
39 #include <sys/param.h>
40 #include <sys/socket.h> /* apple needs sockaddr */
41 #include <net/if.h> /* ifreq */
42 #include <libgen.h> /* basename */
43 #include <stdlib.h> /* atoi, free */
45 /* XXX cut and paste from pkt-gen.c because I'm not sure whether this
46 * program may include nm_util.h
48 void parse_nmr_config(const char* conf, struct nmreq *nmr)
53 nmr->nr_tx_rings = nmr->nr_rx_rings = 0;
54 nmr->nr_tx_slots = nmr->nr_rx_slots = 0;
55 if (conf == NULL || ! *conf)
58 for (i = 0, tok = strtok(w, ","); tok; i++, tok = strtok(NULL, ",")) {
62 nmr->nr_tx_slots = nmr->nr_rx_slots = v;
68 nmr->nr_tx_rings = nmr->nr_rx_rings = v;
74 D("ignored config: %s", tok);
78 D("txr %d txd %d rxr %d rxd %d",
79 nmr->nr_tx_rings, nmr->nr_tx_slots,
80 nmr->nr_rx_rings, nmr->nr_rx_slots);
85 bdg_ctl(const char *name, int nr_cmd, int nr_arg, char *nmr_config)
89 int fd = open("/dev/netmap", O_RDWR);
92 D("Unable to open /dev/netmap");
96 bzero(&nmr, sizeof(nmr));
97 nmr.nr_version = NETMAP_API;
98 if (name != NULL) /* might be NULL */
99 strncpy(nmr.nr_name, name, sizeof(nmr.nr_name));
101 parse_nmr_config(nmr_config, &nmr);
104 case NETMAP_BDG_DELIF:
105 case NETMAP_BDG_NEWIF:
106 error = ioctl(fd, NIOCREGIF, &nmr);
108 ND("Unable to %s %s", nr_cmd == NETMAP_BDG_DELIF ? "delete":"create", name);
111 ND("Success to %s %s", nr_cmd == NETMAP_BDG_DELIF ? "delete":"create", name);
114 case NETMAP_BDG_ATTACH:
115 case NETMAP_BDG_DETACH:
116 nmr.nr_flags = NR_REG_ALL_NIC;
117 if (nr_arg && nr_arg != NETMAP_BDG_HOST) {
118 nmr.nr_flags = NR_REG_NIC_SW;
121 nmr.nr_arg1 = nr_arg;
122 error = ioctl(fd, NIOCREGIF, &nmr);
124 ND("Unable to %s %s to the bridge", nr_cmd ==
125 NETMAP_BDG_DETACH?"detach":"attach", name);
128 ND("Success to %s %s to the bridge", nr_cmd ==
129 NETMAP_BDG_DETACH?"detach":"attach", name);
132 case NETMAP_BDG_LIST:
133 if (strlen(nmr.nr_name)) { /* name to bridge/port info */
134 error = ioctl(fd, NIOCGINFO, &nmr);
136 ND("Unable to obtain info for %s", name);
139 D("%s at bridge:%d port:%d", name, nmr.nr_arg1,
144 /* scan all the bridges and ports */
145 nmr.nr_arg1 = nmr.nr_arg2 = 0;
146 for (; !ioctl(fd, NIOCGINFO, &nmr); nmr.nr_arg2++) {
147 D("bridge:%d port:%d %s", nmr.nr_arg1, nmr.nr_arg2,
149 nmr.nr_name[0] = '\0';
154 case NETMAP_BDG_POLLING_ON:
155 case NETMAP_BDG_POLLING_OFF:
156 /* We reuse nmreq fields as follows:
157 * nr_tx_slots: 0 and non-zero indicate REG_ALL_NIC
158 * REG_ONE_NIC, respectively.
159 * nr_rx_slots: CPU core index. This also indicates the
160 * first queue in the case of REG_ONE_NIC
161 * nr_tx_rings: (REG_ONE_NIC only) indicates the
162 * number of CPU cores or the last queue
164 nmr.nr_flags |= nmr.nr_tx_slots ?
165 NR_REG_ONE_NIC : NR_REG_ALL_NIC;
166 nmr.nr_ringid = nmr.nr_rx_slots;
167 /* number of cores/rings */
168 if (nmr.nr_flags == NR_REG_ALL_NIC)
171 nmr.nr_arg1 = nmr.nr_tx_rings;
173 error = ioctl(fd, NIOCREGIF, &nmr);
175 D("polling on %s %s", nmr.nr_name,
176 nr_cmd == NETMAP_BDG_POLLING_ON ?
177 "started" : "stopped");
179 D("polling on %s %s (err %d)", nmr.nr_name,
180 nr_cmd == NETMAP_BDG_POLLING_ON ?
181 "couldn't start" : "couldn't stop", error);
185 nmr.nr_cmd = nmr.nr_arg1 = nmr.nr_arg2 = 0;
186 error = ioctl(fd, NIOCGINFO, &nmr);
188 ND("Unable to get if info for %s", name);
191 D("%s: %d queues.", name, nmr.nr_rx_rings);
199 main(int argc, char *argv[])
201 int ch, nr_cmd = 0, nr_arg = 0;
202 const char *command = basename(argv[0]);
203 char *name = NULL, *nmr_config = NULL;
210 "\t-g interface interface name to get info\n"
211 "\t-d interface interface name to be detached\n"
212 "\t-a interface interface name to be attached\n"
213 "\t-h interface interface name to be attached with the host stack\n"
214 "\t-n interface interface name to be created\n"
215 "\t-r interface interface name to be deleted\n"
216 "\t-l list all or specified bridge's interfaces (default)\n"
217 "\t-C string ring/slot setting of an interface creating by -n\n"
218 "\t-p interface start polling. Additional -C x,y,z configures\n"
219 "\t\t x: 0 (REG_ALL_NIC) or 1 (REG_ONE_NIC),\n"
220 "\t\t y: CPU core id for ALL_NIC and core/ring for ONE_NIC\n"
221 "\t\t z: (ONE_NIC only) num of total cores/rings\n"
222 "\t-P interface stop polling\n"
227 while ((ch = getopt(argc, argv, "d:a:h:g:l:n:r:C:p:P:")) != -1) {
229 name = optarg; /* default */
232 fprintf(stderr, "bad option %c %s", ch, optarg);
235 nr_cmd = NETMAP_BDG_DETACH;
238 nr_cmd = NETMAP_BDG_ATTACH;
241 nr_cmd = NETMAP_BDG_ATTACH;
242 nr_arg = NETMAP_BDG_HOST;
245 nr_cmd = NETMAP_BDG_NEWIF;
248 nr_cmd = NETMAP_BDG_DELIF;
254 nr_cmd = NETMAP_BDG_LIST;
255 if (optind < argc && argv[optind][0] == '-')
259 nmr_config = strdup(optarg);
262 nr_cmd = NETMAP_BDG_POLLING_ON;
265 nr_cmd = NETMAP_BDG_POLLING_OFF;
269 if (optind != argc) {
270 // fprintf(stderr, "optind %d argc %d\n", optind, argc);
274 nr_cmd = NETMAP_BDG_LIST;
275 return bdg_ctl(name, nr_cmd, nr_arg, nmr_config) ? 1 : 0;