From owner-svn-src-all@freebsd.org Sun Nov 22 10:02:57 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id A5CEC2EB6BF; Sun, 22 Nov 2020 10:02:57 +0000 (UTC) (envelope-from vmaffione@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Cf5Sd4Hf6z4pRp; Sun, 22 Nov 2020 10:02:57 +0000 (UTC) (envelope-from vmaffione@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 85F8C180FB; Sun, 22 Nov 2020 10:02:57 +0000 (UTC) (envelope-from vmaffione@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 0AMA2vjI038298; Sun, 22 Nov 2020 10:02:57 GMT (envelope-from vmaffione@FreeBSD.org) Received: (from vmaffione@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 0AMA2vsV038297; Sun, 22 Nov 2020 10:02:57 GMT (envelope-from vmaffione@FreeBSD.org) Message-Id: <202011221002.0AMA2vsV038297@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: vmaffione set sender to vmaffione@FreeBSD.org using -f From: Vincenzo Maffione Date: Sun, 22 Nov 2020 10:02:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r367935 - head/usr.sbin/valectl X-SVN-Group: head X-SVN-Commit-Author: vmaffione X-SVN-Commit-Paths: head/usr.sbin/valectl X-SVN-Commit-Revision: 367935 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 22 Nov 2020 10:02:57 -0000 Author: vmaffione Date: Sun Nov 22 10:02:56 2020 New Revision: 367935 URL: https://svnweb.freebsd.org/changeset/base/367935 Log: netmap: valectl: switch to libnetmap Use the newer libnetmap (included in base) rather than the older nm_open()/nm_close() defined in netmap_user.h MFC after: 3 days Modified: head/usr.sbin/valectl/Makefile head/usr.sbin/valectl/valectl.c Modified: head/usr.sbin/valectl/Makefile ============================================================================== --- head/usr.sbin/valectl/Makefile Sun Nov 22 09:38:01 2020 (r367934) +++ head/usr.sbin/valectl/Makefile Sun Nov 22 10:02:56 2020 (r367935) @@ -5,4 +5,6 @@ MAN= valectl.8 WARNS?= 3 +LIBADD= netmap + .include Modified: head/usr.sbin/valectl/valectl.c ============================================================================== --- head/usr.sbin/valectl/valectl.c Sun Nov 22 09:38:01 2020 (r367934) +++ head/usr.sbin/valectl/valectl.c Sun Nov 22 10:02:56 2020 (r367935) @@ -25,9 +25,8 @@ /* $FreeBSD$ */ -#define NETMAP_WITH_LIBS -#include -#include +#define LIBNETMAP_NOTHREADSAFE +#include #include #include @@ -42,14 +41,58 @@ #include /* basename */ #include /* atoi, free */ +int verbose; + +struct args { + const char *name; + const char *config; + const char *mem_id; + + uint16_t nr_reqtype; + uint32_t nr_mode; +}; + static void -parse_nmr_config(const char* conf, struct nmreq *nmr) +dump_port_info(struct nmreq_port_info_get *v) { + printf("memsize: %"PRIu64"\n", v->nr_memsize); + printf("tx_slots: %"PRIu32"\n", v->nr_tx_slots); + printf("rx_slots: %"PRIu32"\n", v->nr_rx_slots); + printf("tx_rings: %"PRIu16"\n", v->nr_tx_rings); + printf("rx_rings %"PRIu16"\n", v->nr_rx_rings); + printf("mem_id: %"PRIu16"\n", v->nr_mem_id); +} + +static void +dump_newif(struct nmreq_vale_newif *v) +{ + printf("tx_slots: %"PRIu32"\n", v->nr_tx_slots); + printf("rx_slots: %"PRIu32"\n", v->nr_rx_slots); + printf("tx_rings: %"PRIu16"\n", v->nr_tx_rings); + printf("rx_ring: %"PRIu16"\n", v->nr_rx_rings); + printf("mem_id: %"PRIu16"\n", v->nr_mem_id); +} + +static void +dump_vale_list(struct nmreq_vale_list *v) +{ + printf("bridge_idx: %"PRIu16"\n", v->nr_bridge_idx); + printf("port_idx: %"PRIu16"\n", v->nr_port_idx); +} + + +static void +parse_ring_config(const char* conf, + uint32_t *nr_tx_slots, + uint32_t *nr_rx_slots, + uint16_t *nr_tx_rings, + uint16_t *nr_rx_rings) +{ char *w, *tok; int i, v; - nmr->nr_tx_rings = nmr->nr_rx_rings = 0; - nmr->nr_tx_slots = nmr->nr_rx_slots = 0; + *nr_tx_rings = *nr_rx_rings = 0; + *nr_tx_slots = *nr_rx_slots = 0; if (conf == NULL || ! *conf) return; w = strdup(conf); @@ -57,137 +100,235 @@ parse_nmr_config(const char* conf, struct nmreq *nmr) v = atoi(tok); switch (i) { case 0: - nmr->nr_tx_slots = nmr->nr_rx_slots = v; + *nr_tx_slots = *nr_rx_slots = v; break; case 1: - nmr->nr_rx_slots = v; + *nr_rx_slots = v; break; case 2: - nmr->nr_tx_rings = nmr->nr_rx_rings = v; + *nr_tx_rings = *nr_rx_rings = v; break; case 3: - nmr->nr_rx_rings = v; + *nr_rx_rings = v; break; default: - D("ignored config: %s", tok); + fprintf(stderr, "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); + ND("txr %d txd %d rxr %d rxd %d", + *nr_tx_rings, *nr_tx_slots, + *nr_rx_rings, *nr_rx_slots); free(w); } static int -bdg_ctl(const char *name, int nr_cmd, int nr_arg, char *nmr_config, int nr_arg2) +parse_poll_config(const char *conf, struct nmreq_vale_polling *v) { - struct nmreq nmr; - int error = 0; - int fd = open("/dev/netmap", O_RDWR); + char *w, *tok; + int i, p; - if (fd == -1) { - D("Unable to open /dev/netmap"); + if (conf == NULL || ! *conf) { + fprintf(stderr, "invalid null/empty config\n"); return -1; } + w = strdup(conf); + for (i = 0, tok = strtok(w, ","); tok; i++, tok = strtok(NULL, ",")) { + p = atoi(tok); + switch (i) { + case 0: + v->nr_mode = p ? NETMAP_POLLING_MODE_MULTI_CPU : + NETMAP_POLLING_MODE_SINGLE_CPU; + break; + case 1: + v->nr_first_cpu_id = p; + break; + case 2: + if (v->nr_mode != NETMAP_POLLING_MODE_MULTI_CPU) { + fprintf(stderr, "too many numbers in '%s'\n", conf); + return -1; + } + v->nr_num_polling_cpus = p; + break; + case 3: + fprintf(stderr, "too many numbers in '%s'\n", conf); + return -1; + } + } + free(w); + return 0; +} - 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; +static int32_t +parse_mem_id(const char *mem_id) +{ + int32_t id; - 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); + if (mem_id == NULL) + return 0; + if (isdigit(*mem_id)) + return atoi(mem_id); + id = nmreq_get_mem_id(&mem_id, nmctx_get()); + if (id == 0) { + fprintf(stderr, "invalid format in '-m %s' (missing 'netmap:'?)\n", mem_id); + return -1; + } + return id; +} + +static int +list_all(int fd, struct nmreq_header *hdr) +{ + int error; + struct nmreq_vale_list *vale_list = + (struct nmreq_vale_list *)hdr->nr_body; + + for (;;) { + hdr->nr_name[0] = '\0'; + error = ioctl(fd, NIOCCTRL, hdr); + if (error < 0) { + if (errno == ENOENT) + break; + + fprintf(stderr, "failed to list all: %s\n", strerror(errno)); + return 1; } + printf("%s bridge_idx %"PRIu16" port_idx %"PRIu32"\n", hdr->nr_name, + vale_list->nr_bridge_idx, vale_list->nr_port_idx); + vale_list->nr_port_idx++; + } + return 1; +} + +static int +bdg_ctl(struct args *a) +{ + struct nmreq_header hdr; + struct nmreq_vale_attach vale_attach; + struct nmreq_vale_detach vale_detach; + struct nmreq_vale_newif vale_newif; + struct nmreq_vale_list vale_list; + struct nmreq_vale_polling vale_polling; + struct nmreq_port_info_get port_info_get; + int error = 0; + int fd; + int32_t mem_id; + const char *action = NULL; + + fd = open("/dev/netmap", O_RDWR); + if (fd == -1) { + perror("/dev/netmap"); + return 1; + } + + bzero(&hdr, sizeof(hdr)); + hdr.nr_version = NETMAP_API; + if (a->name != NULL) { /* might be NULL */ + strncpy(hdr.nr_name, a->name, NETMAP_REQ_IFNAMSIZ - 1); + hdr.nr_name[NETMAP_REQ_IFNAMSIZ - 1] = '\0'; + } + hdr.nr_reqtype = a->nr_reqtype; + + switch (a->nr_reqtype) { + case NETMAP_REQ_VALE_DELIF: + /* no body */ + action = "remove"; 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; + + case NETMAP_REQ_VALE_NEWIF: + memset(&vale_newif, 0, sizeof(vale_newif)); + hdr.nr_body = (uintptr_t)&vale_newif; + parse_ring_config(a->config, + &vale_newif.nr_tx_slots, + &vale_newif.nr_rx_slots, + &vale_newif.nr_tx_rings, + &vale_newif.nr_rx_rings); + mem_id = parse_mem_id(a->mem_id); + if (mem_id < 0) + return 1; + vale_newif.nr_mem_id = mem_id; + action = "create"; + break; + + case NETMAP_REQ_VALE_ATTACH: + memset(&vale_attach, 0, sizeof(vale_attach)); + hdr.nr_body = (uintptr_t)&vale_attach; + vale_attach.reg.nr_mode = a->nr_mode; + parse_ring_config(a->config, + &vale_attach.reg.nr_tx_slots, + &vale_attach.reg.nr_rx_slots, + &vale_attach.reg.nr_tx_rings, + &vale_attach.reg.nr_rx_rings); + mem_id = parse_mem_id(a->mem_id); + if (mem_id < 0) + return 1; + vale_attach.reg.nr_mem_id = mem_id; + action = "attach"; + break; + + case NETMAP_REQ_VALE_DETACH: + memset(&vale_detach, 0, sizeof(vale_detach)); + hdr.nr_body = (uintptr_t)&vale_detach; + action = "detach"; + break; + + case NETMAP_REQ_VALE_LIST: + memset(&vale_list, 0, sizeof(vale_list)); + hdr.nr_body = (uintptr_t)&vale_list; + if (a->name == NULL) { + return list_all(fd, &hdr); } - 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); + action = "list"; 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; + case NETMAP_REQ_VALE_POLLING_ENABLE: + action = "enable polling on"; + /* fall through */ + case NETMAP_REQ_VALE_POLLING_DISABLE: + memset(&vale_polling, 0, sizeof(vale_polling)); + hdr.nr_body = (uintptr_t)&vale_polling; + parse_poll_config(a->config, &vale_polling); + if (action == NULL) + action ="disable polling on"; + break; + + case NETMAP_REQ_PORT_INFO_GET: + memset(&port_info_get, 0, sizeof(port_info_get)); + hdr.nr_body = (uintptr_t)&port_info_get; + action = "obtain info for"; + break; + } + error = ioctl(fd, NIOCCTRL, &hdr); + if (error < 0) { + fprintf(stderr, "failed to %s %s: %s\n", + action, a->name, strerror(errno)); + return 1; + } + switch (hdr.nr_reqtype) { + case NETMAP_REQ_VALE_NEWIF: + if (verbose) { + dump_newif(&vale_newif); } + 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'; + case NETMAP_REQ_VALE_ATTACH: + if (verbose) { + printf("port_index: %"PRIu32"\n", vale_attach.port_index); } + break; + case NETMAP_REQ_VALE_DETACH: + if (verbose) { + printf("port_index: %"PRIu32"\n", vale_detach.port_index); + } 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); + case NETMAP_REQ_VALE_LIST: + dump_vale_list(&vale_list); 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); + case NETMAP_REQ_PORT_INFO_GET: + dump_port_info(&port_info_get); break; } close(fd); @@ -199,82 +340,106 @@ usage(int errcode) { fprintf(stderr, "Usage:\n" - "valectl arguments\n" + "vale-ctl [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-l vale-port show bridge and port indices\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"); + "\t-m memid to use when creating a new interface\n" + "\t-v increase verbosity\n" + "with no arguments: list all existing vale ports\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; + int ch; + struct args a = { + .name = NULL, + .config = NULL, + .mem_id = NULL, + .nr_reqtype = 0, + .nr_mode = NR_REG_ALL_NIC, + }; - 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 */ + while ((ch = getopt(argc, argv, "d:a:h:g:l:n:r:C:p:P:m:v")) != -1) { switch (ch) { default: fprintf(stderr, "bad option %c %s", ch, optarg); - usage(-1); + usage(1); break; case 'd': - nr_cmd = NETMAP_BDG_DETACH; + a.nr_reqtype = NETMAP_REQ_VALE_DETACH; + a.name = optarg; break; case 'a': - nr_cmd = NETMAP_BDG_ATTACH; + a.nr_reqtype = NETMAP_REQ_VALE_ATTACH; + a.nr_mode = NR_REG_ALL_NIC; + a.name = optarg; break; case 'h': - nr_cmd = NETMAP_BDG_ATTACH; - nr_arg = NETMAP_BDG_HOST; + a.nr_reqtype = NETMAP_REQ_VALE_ATTACH; + a.nr_mode = NR_REG_NIC_SW; + a.name = optarg; break; case 'n': - nr_cmd = NETMAP_BDG_NEWIF; + a.nr_reqtype = NETMAP_REQ_VALE_NEWIF; + a.name = optarg; break; case 'r': - nr_cmd = NETMAP_BDG_DELIF; + a.nr_reqtype = NETMAP_REQ_VALE_DELIF; + a.name = optarg; break; case 'g': - nr_cmd = 0; + a.nr_reqtype = NETMAP_REQ_PORT_INFO_GET; + a.name = optarg; break; case 'l': - nr_cmd = NETMAP_BDG_LIST; + a.nr_reqtype = NETMAP_REQ_VALE_LIST; + a.name = optarg; + if (strncmp(a.name, NM_BDG_NAME, strlen(NM_BDG_NAME))) { + fprintf(stderr, "invalid vale port name: '%s'\n", a.name); + usage(1); + } break; case 'C': - nmr_config = strdup(optarg); + a.config = optarg; break; case 'p': - nr_cmd = NETMAP_BDG_POLLING_ON; + a.nr_reqtype = NETMAP_REQ_VALE_POLLING_ENABLE; + a.name = optarg; break; case 'P': - nr_cmd = NETMAP_BDG_POLLING_OFF; + a.nr_reqtype = NETMAP_REQ_VALE_POLLING_DISABLE; + a.name = optarg; break; case 'm': - nr_arg2 = atoi(optarg); + a.mem_id = optarg; break; + case 'v': + verbose++; + break; } } if (optind != argc) { - // fprintf(stderr, "optind %d argc %d\n", optind, argc); - usage(-1); + usage(1); } if (argc == 1) { - nr_cmd = NETMAP_BDG_LIST; - name = NULL; + a.nr_reqtype = NETMAP_REQ_VALE_LIST; + a.name = NULL; } - return bdg_ctl(name, nr_cmd, nr_arg, nmr_config, nr_arg2) ? 1 : 0; + if (!a.nr_reqtype) { + usage(1); + } + return bdg_ctl(&a); }