svn commit: r367935 - head/usr.sbin/valectl

Vincenzo Maffione vmaffione at FreeBSD.org
Sun Nov 22 10:02:57 UTC 2020


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 <bsd.prog.mk>

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 <net/netmap_user.h>
-#include <net/netmap.h>
+#define LIBNETMAP_NOTHREADSAFE
+#include <libnetmap.h>
 
 #include <errno.h>
 #include <stdio.h>
@@ -42,14 +41,58 @@
 #include <libgen.h>	/* basename */
 #include <stdlib.h>	/* 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);
 }


More information about the svn-src-head mailing list