aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/netmap/netmap_vale.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/netmap/netmap_vale.c')
-rw-r--r--sys/dev/netmap/netmap_vale.c231
1 files changed, 159 insertions, 72 deletions
diff --git a/sys/dev/netmap/netmap_vale.c b/sys/dev/netmap/netmap_vale.c
index 71b3aedddd46e..d20f384c48d7b 100644
--- a/sys/dev/netmap/netmap_vale.c
+++ b/sys/dev/netmap/netmap_vale.c
@@ -161,7 +161,8 @@ SYSCTL_DECL(_dev_netmap);
SYSCTL_INT(_dev_netmap, OID_AUTO, bridge_batch, CTLFLAG_RW, &bridge_batch, 0 , "");
SYSEND;
-static int netmap_vp_create(struct nmreq *, struct ifnet *, struct netmap_vp_adapter **);
+static int netmap_vp_create(struct nmreq *, struct ifnet *,
+ struct netmap_mem_d *nmd, struct netmap_vp_adapter **);
static int netmap_vp_reg(struct netmap_adapter *na, int onoff);
static int netmap_bwrap_reg(struct netmap_adapter *, int onoff);
@@ -393,7 +394,7 @@ nm_free_bdgfwd(struct netmap_adapter *na)
kring = na->tx_rings;
for (i = 0; i < nrings; i++) {
if (kring[i].nkr_ft) {
- free(kring[i].nkr_ft, M_DEVBUF);
+ nm_os_free(kring[i].nkr_ft);
kring[i].nkr_ft = NULL; /* protect from freeing twice */
}
}
@@ -423,7 +424,7 @@ nm_alloc_bdgfwd(struct netmap_adapter *na)
struct nm_bdg_q *dstq;
int j;
- ft = malloc(l, M_DEVBUF, M_NOWAIT | M_ZERO);
+ ft = nm_os_malloc(l);
if (!ft) {
nm_free_bdgfwd(na);
return ENOMEM;
@@ -538,6 +539,13 @@ netmap_vp_dtor(struct netmap_adapter *na)
if (b) {
netmap_bdg_detach_common(b, vpna->bdg_port, -1);
}
+
+ if (vpna->autodelete && na->ifp != NULL) {
+ ND("releasing %s", na->ifp->if_xname);
+ NMG_UNLOCK();
+ nm_os_vi_detach(na->ifp);
+ NMG_LOCK();
+ }
}
/* remove a persistent VALE port from the system */
@@ -545,6 +553,7 @@ static int
nm_vi_destroy(const char *name)
{
struct ifnet *ifp;
+ struct netmap_vp_adapter *vpna;
int error;
ifp = ifunit_ref(name);
@@ -557,18 +566,29 @@ nm_vi_destroy(const char *name)
goto err;
}
- if (NA(ifp)->na_refcount > 1) {
+ vpna = (struct netmap_vp_adapter *)NA(ifp);
+
+ /* we can only destroy ports that were created via NETMAP_BDG_NEWIF */
+ if (vpna->autodelete) {
+ error = EINVAL;
+ goto err;
+ }
+
+ /* also make sure that nobody is using the inferface */
+ if (NETMAP_OWNED_BY_ANY(&vpna->up) ||
+ vpna->up.na_refcount > 1 /* any ref besides the one in nm_vi_create()? */) {
error = EBUSY;
goto err;
}
+
NMG_UNLOCK();
D("destroying a persistent vale interface %s", ifp->if_xname);
/* Linux requires all the references are released
* before unregister
*/
- if_rele(ifp);
netmap_detach(ifp);
+ if_rele(ifp);
nm_os_vi_detach(ifp);
return 0;
@@ -578,15 +598,26 @@ err:
return error;
}
+static int
+nm_update_info(struct nmreq *nmr, struct netmap_adapter *na)
+{
+ nmr->nr_rx_rings = na->num_rx_rings;
+ nmr->nr_tx_rings = na->num_tx_rings;
+ nmr->nr_rx_slots = na->num_rx_desc;
+ nmr->nr_tx_slots = na->num_tx_desc;
+ return netmap_mem_get_info(na->nm_mem, &nmr->nr_memsize, NULL, &nmr->nr_arg2);
+}
+
/*
* Create a virtual interface registered to the system.
* The interface will be attached to a bridge later.
*/
-static int
-nm_vi_create(struct nmreq *nmr)
+int
+netmap_vi_create(struct nmreq *nmr, int autodelete)
{
struct ifnet *ifp;
struct netmap_vp_adapter *vpna;
+ struct netmap_mem_d *nmd = NULL;
int error;
/* don't include VALE prefix */
@@ -594,28 +625,64 @@ nm_vi_create(struct nmreq *nmr)
return EINVAL;
ifp = ifunit_ref(nmr->nr_name);
if (ifp) { /* already exist, cannot create new one */
+ error = EEXIST;
+ NMG_LOCK();
+ if (NM_NA_VALID(ifp)) {
+ int update_err = nm_update_info(nmr, NA(ifp));
+ if (update_err)
+ error = update_err;
+ }
+ NMG_UNLOCK();
if_rele(ifp);
- return EEXIST;
+ return error;
}
error = nm_os_vi_persist(nmr->nr_name, &ifp);
if (error)
return error;
NMG_LOCK();
+ if (nmr->nr_arg2) {
+ nmd = netmap_mem_find(nmr->nr_arg2);
+ if (nmd == NULL) {
+ error = EINVAL;
+ goto err_1;
+ }
+ }
/* netmap_vp_create creates a struct netmap_vp_adapter */
- error = netmap_vp_create(nmr, ifp, &vpna);
+ error = netmap_vp_create(nmr, ifp, nmd, &vpna);
if (error) {
D("error %d", error);
- nm_os_vi_detach(ifp);
- return error;
+ goto err_1;
}
/* persist-specific routines */
vpna->up.nm_bdg_ctl = netmap_vp_bdg_ctl;
- netmap_adapter_get(&vpna->up);
+ if (!autodelete) {
+ netmap_adapter_get(&vpna->up);
+ } else {
+ vpna->autodelete = 1;
+ }
NM_ATTACH_NA(ifp, &vpna->up);
+ /* return the updated info */
+ error = nm_update_info(nmr, &vpna->up);
+ if (error) {
+ goto err_2;
+ }
+ D("returning nr_arg2 %d", nmr->nr_arg2);
+ if (nmd)
+ netmap_mem_put(nmd);
NMG_UNLOCK();
D("created %s", ifp->if_xname);
return 0;
+
+err_2:
+ netmap_detach(ifp);
+err_1:
+ if (nmd)
+ netmap_mem_put(nmd);
+ NMG_UNLOCK();
+ nm_os_vi_detach(ifp);
+
+ return error;
}
/* Try to get a reference to a netmap adapter attached to a VALE switch.
@@ -628,11 +695,12 @@ nm_vi_create(struct nmreq *nmr)
* (*na != NULL && return == 0).
*/
int
-netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
+netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na,
+ struct netmap_mem_d *nmd, int create)
{
char *nr_name = nmr->nr_name;
const char *ifname;
- struct ifnet *ifp;
+ struct ifnet *ifp = NULL;
int error = 0;
struct netmap_vp_adapter *vpna, *hostna = NULL;
struct nm_bridge *b;
@@ -702,15 +770,15 @@ netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
*/
if (nmr->nr_cmd) {
/* nr_cmd must be 0 for a virtual port */
- return EINVAL;
+ error = EINVAL;
+ goto out;
}
/* bdg_netmap_attach creates a struct netmap_adapter */
- error = netmap_vp_create(nmr, NULL, &vpna);
+ error = netmap_vp_create(nmr, NULL, nmd, &vpna);
if (error) {
D("error %d", error);
- free(ifp, M_DEVBUF);
- return error;
+ goto out;
}
/* shortcut - we can skip get_hw_na(),
* ownership check and nm_bdg_attach()
@@ -718,7 +786,7 @@ netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
} else {
struct netmap_adapter *hw;
- error = netmap_get_hw_na(ifp, &hw);
+ error = netmap_get_hw_na(ifp, nmd, &hw);
if (error || hw == NULL)
goto out;
@@ -751,10 +819,10 @@ netmap_get_bdg_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
BDG_WUNLOCK(b);
*na = &vpna->up;
netmap_adapter_get(*na);
- return 0;
out:
- if_rele(ifp);
+ if (ifp)
+ if_rele(ifp);
return error;
}
@@ -765,11 +833,20 @@ static int
nm_bdg_ctl_attach(struct nmreq *nmr)
{
struct netmap_adapter *na;
+ struct netmap_mem_d *nmd = NULL;
int error;
NMG_LOCK();
- error = netmap_get_bdg_na(nmr, &na, 1 /* create if not exists */);
+ if (nmr->nr_arg2) {
+ nmd = netmap_mem_find(nmr->nr_arg2);
+ if (nmd == NULL) {
+ error = EINVAL;
+ goto unlock_exit;
+ }
+ }
+
+ error = netmap_get_bdg_na(nmr, &na, nmd, 1 /* create if not exists */);
if (error) /* no device */
goto unlock_exit;
@@ -816,7 +893,7 @@ nm_bdg_ctl_detach(struct nmreq *nmr)
int error;
NMG_LOCK();
- error = netmap_get_bdg_na(nmr, &na, 0 /* don't create */);
+ error = netmap_get_bdg_na(nmr, &na, NULL, 0 /* don't create */);
if (error) { /* no device, or another bridge or user owns the device */
goto unlock_exit;
}
@@ -848,7 +925,7 @@ unlock_exit:
struct nm_bdg_polling_state;
struct
nm_bdg_kthread {
- struct nm_kthread *nmk;
+ struct nm_kctx *nmk;
u_int qfirst;
u_int qlast;
struct nm_bdg_polling_state *bps;
@@ -867,7 +944,7 @@ struct nm_bdg_polling_state {
};
static void
-netmap_bwrap_polling(void *data)
+netmap_bwrap_polling(void *data, int is_kthread)
{
struct nm_bdg_kthread *nbk = data;
struct netmap_bwrap_adapter *bna;
@@ -890,16 +967,16 @@ netmap_bwrap_polling(void *data)
static int
nm_bdg_create_kthreads(struct nm_bdg_polling_state *bps)
{
- struct nm_kthread_cfg kcfg;
+ struct nm_kctx_cfg kcfg;
int i, j;
- bps->kthreads = malloc(sizeof(struct nm_bdg_kthread) * bps->ncpus,
- M_DEVBUF, M_NOWAIT | M_ZERO);
+ bps->kthreads = nm_os_malloc(sizeof(struct nm_bdg_kthread) * bps->ncpus);
if (bps->kthreads == NULL)
return ENOMEM;
bzero(&kcfg, sizeof(kcfg));
kcfg.worker_fn = netmap_bwrap_polling;
+ kcfg.use_kthread = 1;
for (i = 0; i < bps->ncpus; i++) {
struct nm_bdg_kthread *t = bps->kthreads + i;
int all = (bps->ncpus == 1 && bps->reg == NR_REG_ALL_NIC);
@@ -913,24 +990,24 @@ nm_bdg_create_kthreads(struct nm_bdg_polling_state *bps)
kcfg.type = i;
kcfg.worker_private = t;
- t->nmk = nm_os_kthread_create(&kcfg, 0, NULL);
+ t->nmk = nm_os_kctx_create(&kcfg, 0, NULL);
if (t->nmk == NULL) {
goto cleanup;
}
- nm_os_kthread_set_affinity(t->nmk, affinity);
+ nm_os_kctx_worker_setaff(t->nmk, affinity);
}
return 0;
cleanup:
for (j = 0; j < i; j++) {
struct nm_bdg_kthread *t = bps->kthreads + i;
- nm_os_kthread_delete(t->nmk);
+ nm_os_kctx_destroy(t->nmk);
}
- free(bps->kthreads, M_DEVBUF);
+ nm_os_free(bps->kthreads);
return EFAULT;
}
-/* a version of ptnetmap_start_kthreads() */
+/* A variant of ptnetmap_start_kthreads() */
static int
nm_bdg_polling_start_kthreads(struct nm_bdg_polling_state *bps)
{
@@ -944,7 +1021,7 @@ nm_bdg_polling_start_kthreads(struct nm_bdg_polling_state *bps)
for (i = 0; i < bps->ncpus; i++) {
struct nm_bdg_kthread *t = bps->kthreads + i;
- error = nm_os_kthread_start(t->nmk);
+ error = nm_os_kctx_worker_start(t->nmk);
if (error) {
D("error in nm_kthread_start()");
goto cleanup;
@@ -955,7 +1032,7 @@ nm_bdg_polling_start_kthreads(struct nm_bdg_polling_state *bps)
cleanup:
for (j = 0; j < i; j++) {
struct nm_bdg_kthread *t = bps->kthreads + i;
- nm_os_kthread_stop(t->nmk);
+ nm_os_kctx_worker_stop(t->nmk);
}
bps->stopped = true;
return error;
@@ -971,8 +1048,8 @@ nm_bdg_polling_stop_delete_kthreads(struct nm_bdg_polling_state *bps)
for (i = 0; i < bps->ncpus; i++) {
struct nm_bdg_kthread *t = bps->kthreads + i;
- nm_os_kthread_stop(t->nmk);
- nm_os_kthread_delete(t->nmk);
+ nm_os_kctx_worker_stop(t->nmk);
+ nm_os_kctx_destroy(t->nmk);
}
bps->stopped = true;
}
@@ -1050,19 +1127,19 @@ nm_bdg_ctl_polling_start(struct nmreq *nmr, struct netmap_adapter *na)
return EFAULT;
}
- bps = malloc(sizeof(*bps), M_DEVBUF, M_NOWAIT | M_ZERO);
+ bps = nm_os_malloc(sizeof(*bps));
if (!bps)
return ENOMEM;
bps->configured = false;
bps->stopped = true;
if (get_polling_cfg(nmr, na, bps)) {
- free(bps, M_DEVBUF);
+ nm_os_free(bps);
return EINVAL;
}
if (nm_bdg_create_kthreads(bps)) {
- free(bps, M_DEVBUF);
+ nm_os_free(bps);
return EFAULT;
}
@@ -1077,8 +1154,8 @@ nm_bdg_ctl_polling_start(struct nmreq *nmr, struct netmap_adapter *na)
error = nm_bdg_polling_start_kthreads(bps);
if (error) {
D("ERROR nm_bdg_polling_start_kthread()");
- free(bps->kthreads, M_DEVBUF);
- free(bps, M_DEVBUF);
+ nm_os_free(bps->kthreads);
+ nm_os_free(bps);
bna->na_polling_state = NULL;
if (bna->hwna->nm_intr)
bna->hwna->nm_intr(bna->hwna, 1);
@@ -1099,7 +1176,7 @@ nm_bdg_ctl_polling_stop(struct nmreq *nmr, struct netmap_adapter *na)
bps = bna->na_polling_state;
nm_bdg_polling_stop_delete_kthreads(bna->na_polling_state);
bps->configured = false;
- free(bps, M_DEVBUF);
+ nm_os_free(bps);
bna->na_polling_state = NULL;
/* reenable interrupt */
if (bna->hwna->nm_intr)
@@ -1130,7 +1207,7 @@ netmap_bdg_ctl(struct nmreq *nmr, struct netmap_bdg_ops *bdg_ops)
switch (cmd) {
case NETMAP_BDG_NEWIF:
- error = nm_vi_create(nmr);
+ error = netmap_vi_create(nmr, 0 /* no autodelete */);
break;
case NETMAP_BDG_DELIF:
@@ -1193,18 +1270,19 @@ netmap_bdg_ctl(struct nmreq *nmr, struct netmap_bdg_ops *bdg_ops)
NMG_LOCK();
for (error = ENOENT; i < NM_BRIDGES; i++) {
b = bridges + i;
- if (j >= b->bdg_active_ports) {
- j = 0; /* following bridges scan from 0 */
- continue;
+ for ( ; j < NM_BDG_MAXPORTS; j++) {
+ if (b->bdg_ports[j] == NULL)
+ continue;
+ vpna = b->bdg_ports[j];
+ strncpy(name, vpna->up.name, (size_t)IFNAMSIZ);
+ error = 0;
+ goto out;
}
- nmr->nr_arg1 = i;
- nmr->nr_arg2 = j;
- j = b->bdg_port_index[j];
- vpna = b->bdg_ports[j];
- strncpy(name, vpna->up.name, (size_t)IFNAMSIZ);
- error = 0;
- break;
+ j = 0; /* following bridges scan from 0 */
}
+ out:
+ nmr->nr_arg1 = i;
+ nmr->nr_arg2 = j;
NMG_UNLOCK();
}
break;
@@ -1238,7 +1316,7 @@ netmap_bdg_ctl(struct nmreq *nmr, struct netmap_bdg_ops *bdg_ops)
break;
}
NMG_LOCK();
- error = netmap_get_bdg_na(nmr, &na, 0);
+ error = netmap_get_bdg_na(nmr, &na, NULL, 0);
if (na && !error) {
vpna = (struct netmap_vp_adapter *)na;
na->virt_hdr_len = nmr->nr_arg1;
@@ -1256,7 +1334,7 @@ netmap_bdg_ctl(struct nmreq *nmr, struct netmap_bdg_ops *bdg_ops)
case NETMAP_BDG_POLLING_ON:
case NETMAP_BDG_POLLING_OFF:
NMG_LOCK();
- error = netmap_get_bdg_na(nmr, &na, 0);
+ error = netmap_get_bdg_na(nmr, &na, NULL, 0);
if (na && !error) {
if (!nm_is_bwrap(na)) {
error = EOPNOTSUPP;
@@ -1384,7 +1462,7 @@ nm_bdg_preflush(struct netmap_kring *kring, u_int end)
if (na->up.na_flags & NAF_BDG_MAYSLEEP)
BDG_RLOCK(b);
else if (!BDG_RTRYLOCK(b))
- return 0;
+ return j;
ND(5, "rlock acquired for %d packets", ((j > end ? lim+1 : 0) + end) - j);
ft = kring->nkr_ft;
@@ -1802,8 +1880,10 @@ nm_bdg_flush(struct nm_bdg_fwd *ft, u_int n, struct netmap_vp_adapter *na,
needed = d->bq_len + brddst->bq_len;
if (unlikely(dst_na->up.virt_hdr_len != na->up.virt_hdr_len)) {
- RD(3, "virt_hdr_mismatch, src %d dst %d", na->up.virt_hdr_len,
- dst_na->up.virt_hdr_len);
+ if (netmap_verbose) {
+ RD(3, "virt_hdr_mismatch, src %d dst %d", na->up.virt_hdr_len,
+ dst_na->up.virt_hdr_len);
+ }
/* There is a virtio-net header/offloadings mismatch between
* source and destination. The slower mismatch datapath will
* be used to cope with all the mismatches.
@@ -2125,14 +2205,16 @@ netmap_vp_bdg_attach(const char *name, struct netmap_adapter *na)
* Only persistent VALE ports have a non-null ifp.
*/
static int
-netmap_vp_create(struct nmreq *nmr, struct ifnet *ifp, struct netmap_vp_adapter **ret)
+netmap_vp_create(struct nmreq *nmr, struct ifnet *ifp,
+ struct netmap_mem_d *nmd,
+ struct netmap_vp_adapter **ret)
{
struct netmap_vp_adapter *vpna;
struct netmap_adapter *na;
- int error;
+ int error = 0;
u_int npipes = 0;
- vpna = malloc(sizeof(*vpna), M_DEVBUF, M_NOWAIT | M_ZERO);
+ vpna = nm_os_malloc(sizeof(*vpna));
if (vpna == NULL)
return ENOMEM;
@@ -2183,7 +2265,10 @@ netmap_vp_create(struct nmreq *nmr, struct ifnet *ifp, struct netmap_vp_adapter
na->nm_krings_create = netmap_vp_krings_create;
na->nm_krings_delete = netmap_vp_krings_delete;
na->nm_dtor = netmap_vp_dtor;
- na->nm_mem = netmap_mem_private_new(na->name,
+ D("nr_arg2 %d", nmr->nr_arg2);
+ na->nm_mem = nmd ?
+ netmap_mem_get(nmd):
+ netmap_mem_private_new(
na->num_tx_rings, na->num_tx_desc,
na->num_rx_rings, na->num_rx_desc,
nmr->nr_arg3, npipes, &error);
@@ -2199,8 +2284,8 @@ netmap_vp_create(struct nmreq *nmr, struct ifnet *ifp, struct netmap_vp_adapter
err:
if (na->nm_mem != NULL)
- netmap_mem_delete(na->nm_mem);
- free(vpna, M_DEVBUF);
+ netmap_mem_put(na->nm_mem);
+ nm_os_free(vpna);
return error;
}
@@ -2243,6 +2328,8 @@ netmap_bwrap_dtor(struct netmap_adapter *na)
struct nm_bridge *b = bna->up.na_bdg,
*bh = bna->host.na_bdg;
+ netmap_mem_put(bna->host.up.nm_mem);
+
if (b) {
netmap_bdg_detach_common(b, bna->up.bdg_port,
(bh ? bna->host.bdg_port : -1));
@@ -2644,7 +2731,7 @@ netmap_bwrap_attach(const char *nr_name, struct netmap_adapter *hwna)
return EBUSY;
}
- bna = malloc(sizeof(*bna), M_DEVBUF, M_NOWAIT | M_ZERO);
+ bna = nm_os_malloc(sizeof(*bna));
if (bna == NULL) {
return ENOMEM;
}
@@ -2652,6 +2739,7 @@ netmap_bwrap_attach(const char *nr_name, struct netmap_adapter *hwna)
na = &bna->up.up;
/* make bwrap ifp point to the real ifp */
na->ifp = hwna->ifp;
+ if_ref(na->ifp);
na->na_private = bna;
strncpy(na->name, nr_name, sizeof(na->name));
/* fill the ring data for the bwrap adapter with rx/tx meanings
@@ -2673,7 +2761,7 @@ netmap_bwrap_attach(const char *nr_name, struct netmap_adapter *hwna)
na->nm_notify = netmap_bwrap_notify;
na->nm_bdg_ctl = netmap_bwrap_bdg_ctl;
na->pdev = hwna->pdev;
- na->nm_mem = hwna->nm_mem;
+ na->nm_mem = netmap_mem_get(hwna->nm_mem);
na->virt_hdr_len = hwna->virt_hdr_len;
bna->up.retry = 1; /* XXX maybe this should depend on the hwna */
@@ -2697,7 +2785,7 @@ netmap_bwrap_attach(const char *nr_name, struct netmap_adapter *hwna)
// hostna->nm_txsync = netmap_bwrap_host_txsync;
// hostna->nm_rxsync = netmap_bwrap_host_rxsync;
hostna->nm_notify = netmap_bwrap_notify;
- hostna->nm_mem = na->nm_mem;
+ hostna->nm_mem = netmap_mem_get(na->nm_mem);
hostna->na_private = bna;
hostna->na_vp = &bna->up;
na->na_hostvp = hwna->na_hostvp =
@@ -2720,7 +2808,7 @@ netmap_bwrap_attach(const char *nr_name, struct netmap_adapter *hwna)
err_free:
hwna->na_vp = hwna->na_hostvp = NULL;
netmap_adapter_put(hwna);
- free(bna, M_DEVBUF);
+ nm_os_free(bna);
return error;
}
@@ -2731,8 +2819,7 @@ netmap_init_bridges2(u_int n)
int i;
struct nm_bridge *b;
- b = malloc(sizeof(struct nm_bridge) * n, M_DEVBUF,
- M_NOWAIT | M_ZERO);
+ b = nm_os_malloc(sizeof(struct nm_bridge) * n);
if (b == NULL)
return NULL;
for (i = 0; i < n; i++)
@@ -2750,7 +2837,7 @@ netmap_uninit_bridges2(struct nm_bridge *b, u_int n)
for (i = 0; i < n; i++)
BDG_RWDESTROY(&b[i]);
- free(b, M_DEVBUF);
+ nm_os_free(b);
}
int