diff options
author | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2019-10-31 21:01:34 +0000 |
---|---|---|
committer | Vincenzo Maffione <vmaffione@FreeBSD.org> | 2019-10-31 21:01:34 +0000 |
commit | c7c780553187d5a8ccb6d17e03c43e0c6daf8ecc (patch) | |
tree | 8a20db04f73da22e1832607a5267f5ae30699c33 /usr.sbin/valectl | |
parent | 2e5f9189bb92b6f77ed7ac4608a058e69e2b5bee (diff) | |
download | src-test2-c7c780553187d5a8ccb6d17e03c43e0c6daf8ecc.tar.gz src-test2-c7c780553187d5a8ccb6d17e03c43e0c6daf8ecc.zip |
Notes
Diffstat (limited to 'usr.sbin/valectl')
-rw-r--r-- | usr.sbin/valectl/Makefile | 8 | ||||
-rw-r--r-- | usr.sbin/valectl/valectl.8 | 163 | ||||
-rw-r--r-- | usr.sbin/valectl/valectl.c | 280 |
3 files changed, 451 insertions, 0 deletions
diff --git a/usr.sbin/valectl/Makefile b/usr.sbin/valectl/Makefile new file mode 100644 index 000000000000..026646948c0e --- /dev/null +++ b/usr.sbin/valectl/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +PROG= valectl +MAN= valectl.8 + +WARNS?= 3 + +.include <bsd.prog.mk> diff --git a/usr.sbin/valectl/valectl.8 b/usr.sbin/valectl/valectl.8 new file mode 100644 index 000000000000..4b5a80897825 --- /dev/null +++ b/usr.sbin/valectl/valectl.8 @@ -0,0 +1,163 @@ +.\" Copyright (c) 2016 Michio Honda. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 26, 2019 +.Dt VALECTL 8 +.Os +.Sh NAME +.Nm valectl +.Nd manage VALE switches provided by netmap +.Sh SYNOPSIS +.Bk -words +.Bl -tag -width "valectl" +.It Nm +.Op Fl g Ar valeSSS:PPP +.Op Fl a Ar valeSSS:interface +.Op Fl h Ar valeSSS:interface +.Op Fl d Ar valeSSS:interface +.Op Fl n Ar interface +.Op Fl r Ar interface +.Op Fl l Ar valeSSS:PPP +.Op Fl l +.Op Fl p Ar valeSSS:PPP +.Op Fl P Ar valeSSS:PPP +.Op Fl C Ar spec +.Op Fl m Ar memid +.El +.Ek +.Sh DESCRIPTION +.Nm +manages and inspects +.Xr vale 4 +switches, for instance attaching and detaching interfaces, creating +and deleting persistent VALE ports, or listing the existing switches +and their ports. +In the following, +.Ar valeSSS +is the name of a VALE switch, while +.Ar valeSSS:PPP +is the name of a VALE port of +.Ar valeSSS . +.Pp +When issued without options it lists all the existing switch ports together +with their internal bridge number and port number. +.Bl -tag -width Ds +.It Fl g Ar valeSSS:PPP +Print the number of receive rings of +.Ar valeSSS:PPP . +.It Fl a Ar valeSSS:interface +Attach +.Ar interface +(which must be an existing network interface) to +.Ar valeSSS +and detach it from the host stack. +.It Fl h Ar valeSSS:interface +Attach +.Ar interface +(which must be an existing network interface) to +.Ar valeSSS +while keeping it attached to the host stack. +More precisely, packets coming from +the host stack and directed to the interface will go through the switch, where +they can still reach the interface if the switch rules allow it. +Conversely, packets coming from the interface will go through the switch and, +if appropriate, will reach the host stack. +.It Fl d Ar valeSSS:interface +Detach +.Ar interface +from +.Ar valeSSS . +.It Fl n Ar interface +Create a new persistent VALE port with name +.Ar interface . +The name must be different from any other network interface +already present in the system. +.It Fl d Ar interface +Destroy the persistent VALE port with name +.Ar inteface . +.It Fl l Ar valeSSS:PPP +Show the internal bridge number and port number of the given switch port. +.It Fl p Ar valeSSS:PPP +Enable polling mode for +.Ar valeSSS:PPP . +In polling mode, a dedicated kernel thread is spawned to handle packets +received from +.Ar valeSSS:PPP +and push them into the switch. +The kernel thread busy waits on the switch port rather than relying on +interrupts or notifications. +Polling mode can only be used on physical NICs attached to a VALE switch. +.It Fl P Ar valeSSS:PPP +Disable polling mode for +.Ar valeSSS:PPP . +.It Fl C Ar x | Ar x,y | Ar x,y,z | Ar x,y,z,w +When used in conjunction with +.Fl n +it supplies the number of tx and rx rings and slots. +The full format with four numbers gives, in order, number of tx slots, number +of rx slots, number of tx rings and number of rx rings. +The form with three numbers uses +.Ar z +for both the number of tx and the number of rx rings. +The forms with less than two numbers use the default values for the number +of rings. +The form with two numbers supplies the numbers of tx and rx slots. +The form with only one number uses +.Ar x +for both the number of tx and the number of rx slots. +.Pp +When used in conjunction with +.Fl p +only the first three forms are used. +The first number may be either 0 or 1. +If 0, then all interface rings will be polled by a single thread, running +on the core id given by the second number (the third number, if present, +must be 1). +If the first number is 1, then the ring identified by the second number will +be polled by the core with the same id. +If a third number is given, then this is repeated for as many consecutive +rings and cores. +.It Fl m Ar memid +Used in conjunction with +.Fl n +supplies the netmap memory region identifier to use together with the newly +created persistent VALE port. +These ports use a private memory region by default. +Using this option you can let them share memory with other ports. +Pass 1 as +.Ar memid +to use the global memory region already shared by all +harware netmap ports. +.El +.Sh SEE ALSO +.Xr netmap 4 , +.Xr vale 4 +.Sh AUTHORS +.An -nosplit +.Nm +was written by +.An Michio Honda +at NetApp. diff --git a/usr.sbin/valectl/valectl.c b/usr.sbin/valectl/valectl.c new file mode 100644 index 000000000000..1e19dfef9e4d --- /dev/null +++ b/usr.sbin/valectl/valectl.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2013-2014 Michio Honda. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $FreeBSD$ */ + +#define NETMAP_WITH_LIBS +#include <net/netmap_user.h> +#include <net/netmap.h> + +#include <errno.h> +#include <stdio.h> +#include <inttypes.h> /* PRI* macros */ +#include <string.h> /* strcmp */ +#include <fcntl.h> /* open */ +#include <unistd.h> /* close */ +#include <sys/ioctl.h> /* ioctl */ +#include <sys/param.h> +#include <sys/socket.h> /* apple needs sockaddr */ +#include <net/if.h> /* ifreq */ +#include <libgen.h> /* basename */ +#include <stdlib.h> /* atoi, free */ + +static void +parse_nmr_config(const char* conf, struct nmreq *nmr) +{ + char *w, *tok; + int i, v; + + nmr->nr_tx_rings = nmr->nr_rx_rings = 0; + nmr->nr_tx_slots = nmr->nr_rx_slots = 0; + if (conf == NULL || ! *conf) + return; + w = strdup(conf); + for (i = 0, tok = strtok(w, ","); tok; i++, tok = strtok(NULL, ",")) { + v = atoi(tok); + switch (i) { + case 0: + nmr->nr_tx_slots = nmr->nr_rx_slots = v; + break; + case 1: + nmr->nr_rx_slots = v; + break; + case 2: + nmr->nr_tx_rings = nmr->nr_rx_rings = v; + break; + case 3: + nmr->nr_rx_rings = v; + break; + default: + D("ignored config: %s", tok); + break; + } + } + D("txr %d txd %d rxr %d rxd %d", + nmr->nr_tx_rings, nmr->nr_tx_slots, + nmr->nr_rx_rings, nmr->nr_rx_slots); + free(w); +} + +static int +bdg_ctl(const char *name, int nr_cmd, int nr_arg, char *nmr_config, int nr_arg2) +{ + struct nmreq nmr; + int error = 0; + int fd = open("/dev/netmap", O_RDWR); + + if (fd == -1) { + D("Unable to open /dev/netmap"); + return -1; + } + + bzero(&nmr, sizeof(nmr)); + nmr.nr_version = NETMAP_API; + if (name != NULL) /* might be NULL */ + strncpy(nmr.nr_name, name, sizeof(nmr.nr_name)-1); + nmr.nr_cmd = nr_cmd; + parse_nmr_config(nmr_config, &nmr); + nmr.nr_arg2 = nr_arg2; + + switch (nr_cmd) { + case NETMAP_BDG_DELIF: + case NETMAP_BDG_NEWIF: + error = ioctl(fd, NIOCREGIF, &nmr); + if (error == -1) { + ND("Unable to %s %s", nr_cmd == NETMAP_BDG_DELIF ? "delete":"create", name); + perror(name); + } else { + ND("Success to %s %s", nr_cmd == NETMAP_BDG_DELIF ? "delete":"create", name); + } + break; + case NETMAP_BDG_ATTACH: + case NETMAP_BDG_DETACH: + nmr.nr_flags = NR_REG_ALL_NIC; + if (nr_arg && nr_arg != NETMAP_BDG_HOST) { + nmr.nr_flags = NR_REG_NIC_SW; + nr_arg = 0; + } + nmr.nr_arg1 = nr_arg; + error = ioctl(fd, NIOCREGIF, &nmr); + if (error == -1) { + ND("Unable to %s %s to the bridge", nr_cmd == + NETMAP_BDG_DETACH?"detach":"attach", name); + perror(name); + } else + ND("Success to %s %s to the bridge", nr_cmd == + NETMAP_BDG_DETACH?"detach":"attach", name); + break; + + case NETMAP_BDG_LIST: + if (strlen(nmr.nr_name)) { /* name to bridge/port info */ + error = ioctl(fd, NIOCGINFO, &nmr); + if (error) { + ND("Unable to obtain info for %s", name); + perror(name); + } else + D("%s at bridge:%d port:%d", name, nmr.nr_arg1, + nmr.nr_arg2); + break; + } + + /* scan all the bridges and ports */ + nmr.nr_arg1 = nmr.nr_arg2 = 0; + for (; !ioctl(fd, NIOCGINFO, &nmr); nmr.nr_arg2++) { + D("bridge:%d port:%d %s", nmr.nr_arg1, nmr.nr_arg2, + nmr.nr_name); + nmr.nr_name[0] = '\0'; + } + + break; + + case NETMAP_BDG_POLLING_ON: + case NETMAP_BDG_POLLING_OFF: + /* We reuse nmreq fields as follows: + * nr_tx_slots: 0 and non-zero indicate REG_ALL_NIC + * REG_ONE_NIC, respectively. + * nr_rx_slots: CPU core index. This also indicates the + * first queue in the case of REG_ONE_NIC + * nr_tx_rings: (REG_ONE_NIC only) indicates the + * number of CPU cores or the last queue + */ + nmr.nr_flags |= nmr.nr_tx_slots ? + NR_REG_ONE_NIC : NR_REG_ALL_NIC; + nmr.nr_ringid = nmr.nr_rx_slots; + /* number of cores/rings */ + if (nmr.nr_flags == NR_REG_ALL_NIC) + nmr.nr_arg1 = 1; + else + nmr.nr_arg1 = nmr.nr_tx_rings; + + error = ioctl(fd, NIOCREGIF, &nmr); + if (!error) + D("polling on %s %s", nmr.nr_name, + nr_cmd == NETMAP_BDG_POLLING_ON ? + "started" : "stopped"); + else + D("polling on %s %s (err %d)", nmr.nr_name, + nr_cmd == NETMAP_BDG_POLLING_ON ? + "couldn't start" : "couldn't stop", error); + break; + + default: /* GINFO */ + nmr.nr_cmd = nmr.nr_arg1 = nmr.nr_arg2 = 0; + error = ioctl(fd, NIOCGINFO, &nmr); + if (error) { + ND("Unable to get if info for %s", name); + perror(name); + } else + D("%s: %d queues.", name, nmr.nr_rx_rings); + break; + } + close(fd); + return error; +} + +static void +usage(int errcode) +{ + fprintf(stderr, + "Usage:\n" + "valectl arguments\n" + "\t-g interface interface name to get info\n" + "\t-d interface interface name to be detached\n" + "\t-a interface interface name to be attached\n" + "\t-h interface interface name to be attached with the host stack\n" + "\t-n interface interface name to be created\n" + "\t-r interface interface name to be deleted\n" + "\t-l list all or specified bridge's interfaces (default)\n" + "\t-C string ring/slot setting of an interface creating by -n\n" + "\t-p interface start polling. Additional -C x,y,z configures\n" + "\t\t x: 0 (REG_ALL_NIC) or 1 (REG_ONE_NIC),\n" + "\t\t y: CPU core id for ALL_NIC and core/ring for ONE_NIC\n" + "\t\t z: (ONE_NIC only) num of total cores/rings\n" + "\t-P interface stop polling\n" + "\t-m memid to use when creating a new interface\n"); + exit(errcode); +} + +int +main(int argc, char *argv[]) +{ + int ch, nr_cmd = 0, nr_arg = 0; + char *name = NULL, *nmr_config = NULL; + int nr_arg2 = 0; + + while ((ch = getopt(argc, argv, "d:a:h:g:l:n:r:C:p:P:m:")) != -1) { + if (ch != 'C' && ch != 'm') + name = optarg; /* default */ + switch (ch) { + default: + fprintf(stderr, "bad option %c %s", ch, optarg); + usage(-1); + break; + case 'd': + nr_cmd = NETMAP_BDG_DETACH; + break; + case 'a': + nr_cmd = NETMAP_BDG_ATTACH; + break; + case 'h': + nr_cmd = NETMAP_BDG_ATTACH; + nr_arg = NETMAP_BDG_HOST; + break; + case 'n': + nr_cmd = NETMAP_BDG_NEWIF; + break; + case 'r': + nr_cmd = NETMAP_BDG_DELIF; + break; + case 'g': + nr_cmd = 0; + break; + case 'l': + nr_cmd = NETMAP_BDG_LIST; + break; + case 'C': + nmr_config = strdup(optarg); + break; + case 'p': + nr_cmd = NETMAP_BDG_POLLING_ON; + break; + case 'P': + nr_cmd = NETMAP_BDG_POLLING_OFF; + break; + case 'm': + nr_arg2 = atoi(optarg); + break; + } + } + if (optind != argc) { + // fprintf(stderr, "optind %d argc %d\n", optind, argc); + usage(-1); + } + if (argc == 1) { + nr_cmd = NETMAP_BDG_LIST; + name = NULL; + } + return bdg_ctl(name, nr_cmd, nr_arg, nmr_config, nr_arg2) ? 1 : 0; +} |