aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/netmap/netmap_pipe.c
diff options
context:
space:
mode:
authorLuiz Otavio O Souza <loos@FreeBSD.org>2017-06-12 22:53:18 +0000
committerLuiz Otavio O Souza <loos@FreeBSD.org>2017-06-12 22:53:18 +0000
commitc3e9b4db8c059c049a20c15d337100a18051f780 (patch)
tree8fcdbddd29c4121bbfcbedff06f83250a208fbee /sys/dev/netmap/netmap_pipe.c
parent965ee74955c3f27a4595c98c3f05c48b204b5c0a (diff)
Notes
Diffstat (limited to 'sys/dev/netmap/netmap_pipe.c')
-rw-r--r--sys/dev/netmap/netmap_pipe.c93
1 files changed, 56 insertions, 37 deletions
diff --git a/sys/dev/netmap/netmap_pipe.c b/sys/dev/netmap/netmap_pipe.c
index f00f73f8b9b2..b48f4618794b 100644
--- a/sys/dev/netmap/netmap_pipe.c
+++ b/sys/dev/netmap/netmap_pipe.c
@@ -86,7 +86,7 @@ SYSEND;
static int
nm_pipe_alloc(struct netmap_adapter *na, u_int npipes)
{
- size_t len;
+ size_t old_len, len;
struct netmap_pipe_adapter **npa;
if (npipes <= na->na_max_pipes)
@@ -96,12 +96,9 @@ nm_pipe_alloc(struct netmap_adapter *na, u_int npipes)
if (npipes < na->na_next_pipe || npipes > NM_MAXPIPES)
return EINVAL;
+ old_len = sizeof(struct netmap_pipe_adapter *)*na->na_max_pipes;
len = sizeof(struct netmap_pipe_adapter *) * npipes;
-#ifndef _WIN32
- npa = realloc(na->na_pipes, len, M_DEVBUF, M_NOWAIT | M_ZERO);
-#else
- npa = realloc(na->na_pipes, len, sizeof(struct netmap_pipe_adapter *)*na->na_max_pipes);
-#endif
+ npa = nm_os_realloc(na->na_pipes, len, old_len);
if (npa == NULL)
return ENOMEM;
@@ -120,7 +117,7 @@ netmap_pipe_dealloc(struct netmap_adapter *na)
D("freeing not empty pipe array for %s (%d dangling pipes)!", na->name,
na->na_next_pipe);
}
- free(na->na_pipes, M_DEVBUF);
+ nm_os_free(na->na_pipes);
na->na_pipes = NULL;
na->na_max_pipes = 0;
na->na_next_pipe = 0;
@@ -175,7 +172,7 @@ netmap_pipe_remove(struct netmap_adapter *parent, struct netmap_pipe_adapter *na
parent->na_pipes[n] = NULL;
}
-static int
+int
netmap_pipe_txsync(struct netmap_kring *txkring, int flags)
{
struct netmap_kring *rxkring = txkring->pipe;
@@ -240,7 +237,7 @@ netmap_pipe_txsync(struct netmap_kring *txkring, int flags)
return 0;
}
-static int
+int
netmap_pipe_rxsync(struct netmap_kring *rxkring, int flags)
{
struct netmap_kring *txkring = rxkring->pipe;
@@ -289,7 +286,7 @@ netmap_pipe_rxsync(struct netmap_kring *rxkring, int flags)
*/
-/* netmap_pipe_krings_delete.
+/* netmap_pipe_krings_create.
*
* There are two cases:
*
@@ -320,7 +317,7 @@ netmap_pipe_krings_create(struct netmap_adapter *na)
int i;
/* case 1) above */
- D("%p: case 1, create both ends", na);
+ ND("%p: case 1, create both ends", na);
error = netmap_krings_create(na, 0);
if (error)
goto err;
@@ -334,8 +331,8 @@ netmap_pipe_krings_create(struct netmap_adapter *na)
for_rx_tx(t) {
enum txrx r = nm_txrx_swap(t); /* swap NR_TX <-> NR_RX */
for (i = 0; i < nma_get_nrings(na, t); i++) {
- NMR(na, t)[i].pipe = NMR(&pna->peer->up, r) + i;
- NMR(&pna->peer->up, r)[i].pipe = NMR(na, t) + i;
+ NMR(na, t)[i].pipe = NMR(ona, r) + i;
+ NMR(ona, r)[i].pipe = NMR(na, t) + i;
}
}
@@ -393,11 +390,11 @@ netmap_pipe_reg(struct netmap_adapter *na, int onoff)
ND("%p: onoff %d", na, onoff);
if (onoff) {
for_rx_tx(t) {
- for (i = 0; i < nma_get_nrings(na, t) + 1; i++) {
+ for (i = 0; i < nma_get_nrings(na, t); i++) {
struct netmap_kring *kring = &NMR(na, t)[i];
if (nm_kring_pending_on(kring)) {
- /* mark the partner ring as needed */
+ /* mark the peer ring as needed */
kring->pipe->nr_kflags |= NKR_NEEDRING;
}
}
@@ -432,7 +429,9 @@ netmap_pipe_reg(struct netmap_adapter *na, int onoff)
/* mark the peer ring as no longer needed by us
* (it may still be kept if sombody else is using it)
*/
- kring->pipe->nr_kflags &= ~NKR_NEEDRING;
+ if (kring->pipe) {
+ kring->pipe->nr_kflags &= ~NKR_NEEDRING;
+ }
}
}
}
@@ -441,7 +440,7 @@ netmap_pipe_reg(struct netmap_adapter *na, int onoff)
}
if (na->active_fds) {
- D("active_fds %d", na->active_fds);
+ ND("active_fds %d", na->active_fds);
return 0;
}
@@ -494,7 +493,7 @@ netmap_pipe_krings_delete(struct netmap_adapter *na)
return;
}
/* case 1) above */
- ND("%p: case 1, deleting everyhing", na);
+ ND("%p: case 1, deleting everything", na);
netmap_krings_delete(na); /* also zeroes tx_rings etc. */
ona = &pna->peer->up;
if (ona->tx_rings == NULL) {
@@ -511,7 +510,7 @@ netmap_pipe_dtor(struct netmap_adapter *na)
{
struct netmap_pipe_adapter *pna =
(struct netmap_pipe_adapter *)na;
- ND("%p", na);
+ ND("%p %p", na, pna->parent_ifp);
if (pna->peer_ref) {
ND("%p: clean up peer", na);
pna->peer_ref = 0;
@@ -519,12 +518,15 @@ netmap_pipe_dtor(struct netmap_adapter *na)
}
if (pna->role == NR_REG_PIPE_MASTER)
netmap_pipe_remove(pna->parent, pna);
+ if (pna->parent_ifp)
+ if_rele(pna->parent_ifp);
netmap_adapter_put(pna->parent);
pna->parent = NULL;
}
int
-netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
+netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na,
+ struct netmap_mem_d *nmd, int create)
{
struct nmreq pnmr;
struct netmap_adapter *pna; /* parent adapter */
@@ -532,7 +534,7 @@ netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
struct ifnet *ifp = NULL;
u_int pipe_id;
int role = nmr->nr_flags & NR_REG_MASK;
- int error;
+ int error, retries = 0;
ND("flags %x", nmr->nr_flags);
@@ -547,12 +549,28 @@ netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
memcpy(&pnmr.nr_name, nmr->nr_name, IFNAMSIZ);
/* pass to parent the requested number of pipes */
pnmr.nr_arg1 = nmr->nr_arg1;
- error = netmap_get_na(&pnmr, &pna, &ifp, create);
- if (error) {
- ND("parent lookup failed: %d", error);
- return error;
+ for (;;) {
+ int create_error;
+
+ error = netmap_get_na(&pnmr, &pna, &ifp, nmd, create);
+ if (!error)
+ break;
+ if (error != ENXIO || retries++) {
+ ND("parent lookup failed: %d", error);
+ return error;
+ }
+ ND("try to create a persistent vale port");
+ /* create a persistent vale port and try again */
+ NMG_UNLOCK();
+ create_error = netmap_vi_create(&pnmr, 1 /* autodelete */);
+ NMG_LOCK();
+ if (create_error && create_error != EEXIST) {
+ if (create_error != EOPNOTSUPP) {
+ D("failed to create a persistent vale port: %d", create_error);
+ }
+ return error;
+ }
}
- ND("found parent: %s", na->name);
if (NETMAP_OWNED_BY_KERN(pna)) {
ND("parent busy");
@@ -575,7 +593,7 @@ netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
/* the pipe we have found already holds a ref to the parent,
* so we need to drop the one we got from netmap_get_na()
*/
- netmap_adapter_put(pna);
+ netmap_unget_na(pna, ifp);
goto found;
}
ND("pipe %d not found, create %d", pipe_id, create);
@@ -587,7 +605,7 @@ netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
* The endpoint we were asked for holds a reference to
* the other one.
*/
- mna = malloc(sizeof(*mna), M_DEVBUF, M_NOWAIT | M_ZERO);
+ mna = nm_os_malloc(sizeof(*mna));
if (mna == NULL) {
error = ENOMEM;
goto put_out;
@@ -597,6 +615,7 @@ netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
mna->id = pipe_id;
mna->role = NR_REG_PIPE_MASTER;
mna->parent = pna;
+ mna->parent_ifp = ifp;
mna->up.nm_txsync = netmap_pipe_txsync;
mna->up.nm_rxsync = netmap_pipe_rxsync;
@@ -604,7 +623,8 @@ netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
mna->up.nm_dtor = netmap_pipe_dtor;
mna->up.nm_krings_create = netmap_pipe_krings_create;
mna->up.nm_krings_delete = netmap_pipe_krings_delete;
- mna->up.nm_mem = pna->nm_mem;
+ mna->up.nm_mem = netmap_mem_get(pna->nm_mem);
+ mna->up.na_flags |= NAF_MEM_OWNER;
mna->up.na_lut = pna->na_lut;
mna->up.num_tx_rings = 1;
@@ -624,13 +644,14 @@ netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
goto free_mna;
/* create the slave */
- sna = malloc(sizeof(*mna), M_DEVBUF, M_NOWAIT | M_ZERO);
+ sna = nm_os_malloc(sizeof(*mna));
if (sna == NULL) {
error = ENOMEM;
goto unregister_mna;
}
/* most fields are the same, copy from master and then fix */
*sna = *mna;
+ sna->up.nm_mem = netmap_mem_get(mna->up.nm_mem);
snprintf(sna->up.name, sizeof(sna->up.name), "%s}%d", pna->name, pipe_id);
sna->role = NR_REG_PIPE_SLAVE;
error = netmap_attach_common(&sna->up);
@@ -645,6 +666,9 @@ netmap_get_pipe_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
* need another one for the other endpoint we created
*/
netmap_adapter_get(pna);
+ /* likewise for the ifp, if any */
+ if (ifp)
+ if_ref(ifp);
if (role == NR_REG_PIPE_MASTER) {
req = mna;
@@ -667,19 +691,14 @@ found:
* It will be released by the req destructor
*/
- /* drop the ifp reference, if any */
- if (ifp) {
- if_rele(ifp);
- }
-
return 0;
free_sna:
- free(sna, M_DEVBUF);
+ nm_os_free(sna);
unregister_mna:
netmap_pipe_remove(pna, mna);
free_mna:
- free(mna, M_DEVBUF);
+ nm_os_free(mna);
put_out:
netmap_unget_na(pna, ifp);
return error;