aboutsummaryrefslogtreecommitdiff
path: root/sys/net/netmap_user.h
diff options
context:
space:
mode:
authorVincenzo Maffione <vmaffione@FreeBSD.org>2018-04-12 07:20:50 +0000
committerVincenzo Maffione <vmaffione@FreeBSD.org>2018-04-12 07:20:50 +0000
commit2ff91c175eca50b7d0d9da6b31eae4109c034137 (patch)
tree15a4f8847a8cabd782f67326125c48fed4fdd27b /sys/net/netmap_user.h
parent66def52613043a86172a2ebe6feab214258fa2fa (diff)
downloadsrc-2ff91c175eca50b7d0d9da6b31eae4109c034137.tar.gz
src-2ff91c175eca50b7d0d9da6b31eae4109c034137.zip
netmap: align codebase to the current upstream (commit id 3fb001303718146)
Changelist: - Turn tx_rings and rx_rings arrays into arrays of pointers to kring structs. This patch includes fixes for ixv, ixl, ix, re, cxgbe, iflib, vtnet and ptnet drivers to cope with the change. - Generalize the nm_config() callback to accept a struct containing many parameters. - Introduce NKR_FAKERING to support buffers sharing (used for netmap pipes) - Improved API for external VALE modules. - Various bug fixes and improvements to the netmap memory allocator, including support for externally (userspace) allocated memory. - Refactoring of netmap pipes: now linked rings share the same netmap buffers, with a separate set of kring pointers (rhead, rcur, rtail). Buffer swapping does not need to happen anymore. - Large refactoring of the control API towards an extensible solution; the goal is to allow the addition of more commands and extension of existing ones (with new options) without the need of hacks or the risk of running out of configuration space. A new NIOCCTRL ioctl has been added to handle all the requests of the new control API, which cover all the functionalities so far supported. The netmap API bumps from 11 to 12 with this patch. Full backward compatibility is provided for the old control command (NIOCREGIF), by means of a new netmap_legacy module. Many parts of the old netmap.h header has now been moved to netmap_legacy.h (included by netmap.h). Approved by: hrs (mentor)
Notes
Notes: svn path=/head/; revision=332423
Diffstat (limited to 'sys/net/netmap_user.h')
-rw-r--r--sys/net/netmap_user.h286
1 files changed, 53 insertions, 233 deletions
diff --git a/sys/net/netmap_user.h b/sys/net/netmap_user.h
index 2c8d91a63b63..a314ca02b81c 100644
--- a/sys/net/netmap_user.h
+++ b/sys/net/netmap_user.h
@@ -100,7 +100,6 @@
#endif /* likely and unlikely */
#include <net/netmap.h>
-#include <net/netmap_virt.h> /* nmreq_pointer_get() */
/* helper macro */
#define _NETMAP_OFFSET(type, ptr, offset) \
@@ -115,7 +114,7 @@
nifp, (nifp)->ring_ofs[index + (nifp)->ni_tx_rings + 1] )
#define NETMAP_BUF(ring, index) \
- ((char *)(ring) + (ring)->buf_ofs + ((long)(index)*(ring)->nr_buf_size))
+ ((char *)(ring) + (ring)->buf_ofs + ((index)*(ring)->nr_buf_size))
#define NETMAP_BUF_IDX(ring, buf) \
( ((char *)(buf) - ((char *)(ring) + (ring)->buf_ofs) ) / \
@@ -225,7 +224,7 @@ struct nm_desc {
struct nm_desc *self; /* point to self if netmap. */
int fd;
void *mem;
- uint64_t memsize;
+ uint32_t memsize;
int done_mmap; /* set if mem is the result of mmap */
struct netmap_if * const nifp;
uint16_t first_tx_ring, last_tx_ring, cur_tx_ring;
@@ -351,7 +350,6 @@ enum {
NM_OPEN_ARG2 = 0x200000,
NM_OPEN_ARG3 = 0x400000,
NM_OPEN_RING_CFG = 0x800000, /* tx|rx rings|slots */
- NM_OPEN_EXTMEM = 0x1000000,
};
@@ -613,28 +611,9 @@ nm_is_identifier(const char *s, const char *e)
return 1;
}
-static void
-nm_init_offsets(struct nm_desc *d)
-{
- struct netmap_if *nifp = NETMAP_IF(d->mem, d->req.nr_offset);
- struct netmap_ring *r = NETMAP_RXRING(nifp, d->first_rx_ring);
- if ((void *)r == (void *)nifp) {
- /* the descriptor is open for TX only */
- r = NETMAP_TXRING(nifp, d->first_tx_ring);
- }
-
- *(struct netmap_if **)(uintptr_t)&(d->nifp) = nifp;
- *(struct netmap_ring **)(uintptr_t)&d->some_ring = r;
- *(void **)(uintptr_t)&d->buf_start = NETMAP_BUF(r, 0);
- *(void **)(uintptr_t)&d->buf_end =
- (char *)d->mem + d->memsize;
-}
-
#define MAXERRMSG 80
-#define NM_PARSE_OK 0
-#define NM_PARSE_MEMID 1
static int
-nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
+nm_parse(const char *ifname, struct nm_desc *d, char *err)
{
int is_vale;
const char *port = NULL;
@@ -648,13 +627,6 @@ nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
errno = 0;
- if (strncmp(ifname, "netmap:", 7) &&
- strncmp(ifname, NM_BDG_NAME, strlen(NM_BDG_NAME))) {
- snprintf(errmsg, MAXERRMSG, "invalid port name: %s", ifname);
- errno = EINVAL;
- goto fail;
- }
-
is_vale = (ifname[0] == 'v');
if (is_vale) {
port = index(ifname, ':');
@@ -685,13 +657,12 @@ nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
}
namelen = port - ifname;
- if (namelen >= sizeof(d->nr_name)) {
+ if (namelen >= sizeof(d->req.nr_name)) {
snprintf(errmsg, MAXERRMSG, "name too long");
goto fail;
}
- memcpy(d->nr_name, ifname, namelen);
- d->nr_name[namelen] = '\0';
- D("name %s", d->nr_name);
+ memcpy(d->req.nr_name, ifname, namelen);
+ d->req.nr_name[namelen] = '\0';
p_state = P_START;
nr_flags = NR_REG_ALL_NIC; /* default for no suffix */
@@ -789,28 +760,21 @@ nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
p_state = P_FLAGSOK;
break;
case P_MEMID:
- if (!memid_allowed) {
+ if (nr_arg2 != 0) {
snprintf(errmsg, MAXERRMSG, "double setting of memid");
goto fail;
}
num = strtol(port, (char **)&port, 10);
if (num <= 0) {
- ND("non-numeric memid %s (out = %p)", port, out);
- if (out == NULL)
- goto fail;
- *out = (char *)port;
- while (*port)
- port++;
- } else {
- nr_arg2 = num;
- memid_allowed = 0;
- p_state = P_RNGSFXOK;
+ snprintf(errmsg, MAXERRMSG, "invalid memid %ld, must be >0", num);
+ goto fail;
}
+ nr_arg2 = num;
+ p_state = P_RNGSFXOK;
break;
}
}
- if (p_state != P_START && p_state != P_RNGSFXOK &&
- p_state != P_FLAGSOK && p_state != P_MEMID) {
+ if (p_state != P_START && p_state != P_RNGSFXOK && p_state != P_FLAGSOK) {
snprintf(errmsg, MAXERRMSG, "unexpected end of port name");
goto fail;
}
@@ -820,117 +784,28 @@ nm_parse_one(const char *ifname, struct nmreq *d, char **out, int memid_allowed)
(nr_flags & NR_MONITOR_TX) ? "MONITOR_TX" : "",
(nr_flags & NR_MONITOR_RX) ? "MONITOR_RX" : "");
- d->nr_flags |= nr_flags;
- d->nr_ringid |= nr_ringid;
- d->nr_arg2 = nr_arg2;
+ d->req.nr_flags |= nr_flags;
+ d->req.nr_ringid |= nr_ringid;
+ d->req.nr_arg2 = nr_arg2;
+
+ d->self = d;
- return (p_state == P_MEMID) ? NM_PARSE_MEMID : NM_PARSE_OK;
+ return 0;
fail:
if (!errno)
errno = EINVAL;
- if (out)
- *out = strdup(errmsg);
+ if (err)
+ strncpy(err, errmsg, MAXERRMSG);
return -1;
}
-static int
-nm_interp_memid(const char *memid, struct nmreq *req, char **err)
-{
- int fd = -1;
- char errmsg[MAXERRMSG] = "";
- struct nmreq greq;
- off_t mapsize;
- struct netmap_pools_info *pi;
-
- /* first, try to look for a netmap port with this name */
- fd = open("/dev/netmap", O_RDONLY);
- if (fd < 0) {
- snprintf(errmsg, MAXERRMSG, "cannot open /dev/netmap: %s", strerror(errno));
- goto fail;
- }
- memset(&greq, 0, sizeof(greq));
- if (nm_parse_one(memid, &greq, err, 0) == NM_PARSE_OK) {
- greq.nr_version = NETMAP_API;
- if (ioctl(fd, NIOCGINFO, &greq) < 0) {
- if (errno == ENOENT || errno == ENXIO)
- goto try_external;
- snprintf(errmsg, MAXERRMSG, "cannot getinfo for %s: %s", memid, strerror(errno));
- goto fail;
- }
- req->nr_arg2 = greq.nr_arg2;
- close(fd);
- return 0;
- }
-try_external:
- D("trying with external memory");
- close(fd);
- fd = open(memid, O_RDWR);
- if (fd < 0) {
- snprintf(errmsg, MAXERRMSG, "cannot open %s: %s", memid, strerror(errno));
- goto fail;
- }
- mapsize = lseek(fd, 0, SEEK_END);
- if (mapsize < 0) {
- snprintf(errmsg, MAXERRMSG, "failed to obtain filesize of %s: %s", memid, strerror(errno));
- goto fail;
- }
- pi = mmap(0, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (pi == MAP_FAILED) {
- snprintf(errmsg, MAXERRMSG, "cannot map %s: %s", memid, strerror(errno));
- goto fail;
- }
- req->nr_cmd = NETMAP_POOLS_CREATE;
- pi->memsize = mapsize;
- nmreq_pointer_put(req, pi);
- D("mapped %zu bytes at %p from file %s", mapsize, pi, memid);
- return 0;
-
-fail:
- D("%s", errmsg);
- close(fd);
- if (err && !*err)
- *err = strdup(errmsg);
- return errno;
-}
-
-static int
-nm_parse(const char *ifname, struct nm_desc *d, char *errmsg)
-{
- char *err;
- switch (nm_parse_one(ifname, &d->req, &err, 1)) {
- case NM_PARSE_OK:
- D("parse OK");
- break;
- case NM_PARSE_MEMID:
- D("memid: %s", err);
- errno = nm_interp_memid(err, &d->req, &err);
- D("errno = %d", errno);
- if (!errno)
- break;
- /* fallthrough */
- default:
- D("error");
- strncpy(errmsg, err, MAXERRMSG);
- errmsg[MAXERRMSG-1] = '\0';
- free(err);
- return -1;
- }
- D("parsed name: %s", d->req.nr_name);
- d->self = d;
- return 0;
-}
-
/*
* Try to open, return descriptor if successful, NULL otherwise.
* An invalid netmap name will return errno = 0;
* You can pass a pointer to a pre-filled nm_desc to add special
* parameters. Flags is used as follows
- * NM_OPEN_NO_MMAP use the memory from arg, only
+ * NM_OPEN_NO_MMAP use the memory from arg, only XXX avoid mmap
* if the nr_arg2 (memory block) matches.
- * Special case: if arg is NULL, skip the
- * mmap entirely (maybe because you are going
- * to do it by yourself, or you plan to call
- * nm_mmap() only later)
* NM_OPEN_ARG1 use req.nr_arg1 from arg
* NM_OPEN_ARG2 use req.nr_arg2 from arg
* NM_OPEN_RING_CFG user ring config from arg
@@ -943,7 +818,6 @@ nm_open(const char *ifname, const struct nmreq *req,
const struct nm_desc *parent = arg;
char errmsg[MAXERRMSG] = "";
uint32_t nr_reg;
- struct netmap_pools_info *pi = NULL;
if (strncmp(ifname, "netmap:", 7) &&
strncmp(ifname, NM_BDG_NAME, strlen(NM_BDG_NAME))) {
@@ -964,60 +838,12 @@ nm_open(const char *ifname, const struct nmreq *req,
goto fail;
}
- if (req) {
+ if (req)
d->req = *req;
- } else {
- d->req.nr_arg1 = 4;
- d->req.nr_arg2 = 0;
- d->req.nr_arg3 = 0;
- }
if (!(new_flags & NM_OPEN_IFNAME)) {
- char *err;
- switch (nm_parse_one(ifname, &d->req, &err, 1)) {
- case NM_PARSE_OK:
- break;
- case NM_PARSE_MEMID:
- if ((new_flags & NM_OPEN_NO_MMAP) &&
- IS_NETMAP_DESC(parent)) {
- /* ignore the memid setting, since we are
- * going to use the parent's one
- */
- break;
- }
- errno = nm_interp_memid(err, &d->req, &err);
- if (!errno)
- break;
- /* fallthrough */
- default:
- strncpy(errmsg, err, MAXERRMSG);
- errmsg[MAXERRMSG-1] = '\0';
- free(err);
+ if (nm_parse(ifname, d, errmsg) < 0)
goto fail;
- }
- d->self = d;
- }
-
- /* compatibility checks for POOL_SCREATE and NM_OPEN flags
- * the first check may be dropped once we have a larger nreq
- */
- if (d->req.nr_cmd == NETMAP_POOLS_CREATE) {
- if (IS_NETMAP_DESC(parent)) {
- if (new_flags & (NM_OPEN_ARG1 | NM_OPEN_ARG2 | NM_OPEN_ARG3)) {
- snprintf(errmsg, MAXERRMSG,
- "POOLS_CREATE is incompatibile "
- "with NM_OPEN_ARG? flags");
- errno = EINVAL;
- goto fail;
- }
- if (new_flags & NM_OPEN_NO_MMAP) {
- snprintf(errmsg, MAXERRMSG,
- "POOLS_CREATE is incompatible "
- "with NM_OPEN_NO_MMAP flag");
- errno = EINVAL;
- goto fail;
- }
- }
}
d->req.nr_version = NETMAP_API;
@@ -1025,26 +851,18 @@ nm_open(const char *ifname, const struct nmreq *req,
/* optionally import info from parent */
if (IS_NETMAP_DESC(parent) && new_flags) {
- if (new_flags & NM_OPEN_EXTMEM) {
- if (parent->req.nr_cmd == NETMAP_POOLS_CREATE) {
- d->req.nr_cmd = NETMAP_POOLS_CREATE;
- nmreq_pointer_put(&d->req, nmreq_pointer_get(&parent->req));
- D("Warning: not overriding arg[1-3] since external memory is being used");
- new_flags &= ~(NM_OPEN_ARG1 | NM_OPEN_ARG2 | NM_OPEN_ARG3);
- }
- }
- if (new_flags & NM_OPEN_ARG1) {
+ if (new_flags & NM_OPEN_ARG1)
D("overriding ARG1 %d", parent->req.nr_arg1);
- d->req.nr_arg1 = parent->req.nr_arg1;
- }
- if (new_flags & (NM_OPEN_ARG2 | NM_OPEN_NO_MMAP)) {
+ d->req.nr_arg1 = new_flags & NM_OPEN_ARG1 ?
+ parent->req.nr_arg1 : 4;
+ if (new_flags & NM_OPEN_ARG2) {
D("overriding ARG2 %d", parent->req.nr_arg2);
- d->req.nr_arg2 = parent->req.nr_arg2;
+ d->req.nr_arg2 = parent->req.nr_arg2;
}
- if (new_flags & NM_OPEN_ARG3) {
+ if (new_flags & NM_OPEN_ARG3)
D("overriding ARG3 %d", parent->req.nr_arg3);
- d->req.nr_arg3 = parent->req.nr_arg3;
- }
+ d->req.nr_arg3 = new_flags & NM_OPEN_ARG3 ?
+ parent->req.nr_arg3 : 0;
if (new_flags & NM_OPEN_RING_CFG) {
D("overriding RING_CFG");
d->req.nr_tx_slots = parent->req.nr_tx_slots;
@@ -1065,28 +883,11 @@ nm_open(const char *ifname, const struct nmreq *req,
/* add the *XPOLL flags */
d->req.nr_ringid |= new_flags & (NETMAP_NO_TX_POLL | NETMAP_DO_RX_POLL);
- if (d->req.nr_cmd == NETMAP_POOLS_CREATE) {
- pi = nmreq_pointer_get(&d->req);
- }
-
if (ioctl(d->fd, NIOCREGIF, &d->req)) {
snprintf(errmsg, MAXERRMSG, "NIOCREGIF failed: %s", strerror(errno));
goto fail;
}
- if (pi != NULL) {
- d->mem = pi;
- d->memsize = pi->memsize;
- nm_init_offsets(d);
- } else if ((!(new_flags & NM_OPEN_NO_MMAP) || parent)) {
- /* if parent is defined, do nm_mmap() even if NM_OPEN_NO_MMAP is set */
- errno = nm_mmap(d, parent);
- if (errno) {
- snprintf(errmsg, MAXERRMSG, "mmap failed: %s", strerror(errno));
- goto fail;
- }
- }
-
nr_reg = d->req.nr_flags & NR_REG_MASK;
if (nr_reg == NR_REG_SW) { /* host stack */
@@ -1111,6 +912,13 @@ nm_open(const char *ifname, const struct nmreq *req,
d->first_rx_ring = d->last_rx_ring = 0;
}
+ /* if parent is defined, do nm_mmap() even if NM_OPEN_NO_MMAP is set */
+ if ((!(new_flags & NM_OPEN_NO_MMAP) || parent) && nm_mmap(d, parent)) {
+ snprintf(errmsg, MAXERRMSG, "mmap failed: %s", strerror(errno));
+ goto fail;
+ }
+
+
#ifdef DEBUG_NETMAP_USER
{ /* debugging code */
int i;
@@ -1151,8 +959,7 @@ nm_close(struct nm_desc *d)
*/
static void *__xxzt[] __attribute__ ((unused)) =
{ (void *)nm_open, (void *)nm_inject,
- (void *)nm_dispatch, (void *)nm_nextpkt,
- (void *)nm_parse } ;
+ (void *)nm_dispatch, (void *)nm_nextpkt } ;
if (d == NULL || d->self != d)
return EINVAL;
@@ -1189,8 +996,21 @@ nm_mmap(struct nm_desc *d, const struct nm_desc *parent)
}
d->done_mmap = 1;
}
+ {
+ struct netmap_if *nifp = NETMAP_IF(d->mem, d->req.nr_offset);
+ struct netmap_ring *r = NETMAP_RXRING(nifp, d->first_rx_ring);
+ if ((void *)r == (void *)nifp) {
+ /* the descriptor is open for TX only */
+ r = NETMAP_TXRING(nifp, d->first_tx_ring);
+ }
+
+ *(struct netmap_if **)(uintptr_t)&(d->nifp) = nifp;
+ *(struct netmap_ring **)(uintptr_t)&d->some_ring = r;
+ *(void **)(uintptr_t)&d->buf_start = NETMAP_BUF(r, 0);
+ *(void **)(uintptr_t)&d->buf_end =
+ (char *)d->mem + d->memsize;
+ }
- nm_init_offsets(d);
return 0;
fail: