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
This commit is contained in:
parent
91c60ce828
commit
9fd3f663da
@ -5,4 +5,6 @@ MAN= valectl.8
|
||||
|
||||
WARNS?= 3
|
||||
|
||||
LIBADD= netmap
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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';
|
||||
static int32_t
|
||||
parse_mem_id(const char *mem_id)
|
||||
{
|
||||
int32_t id;
|
||||
|
||||
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_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_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;
|
||||
|
||||
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_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);
|
||||
}
|
||||
action = "list";
|
||||
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;
|
||||
|
||||
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_REQ_VALE_LIST:
|
||||
dump_vale_list(&vale_list);
|
||||
break;
|
||||
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user