summaryrefslogtreecommitdiff
path: root/sys/dev/netmap/netmap_bdg.c
diff options
context:
space:
mode:
authorVincenzo Maffione <vmaffione@FreeBSD.org>2018-12-05 11:57:16 +0000
committerVincenzo Maffione <vmaffione@FreeBSD.org>2018-12-05 11:57:16 +0000
commitb6e66be22bdce2aadcf52ee6230faa1e6cd3f805 (patch)
treee9311c45835e19b2d58f105e0627078f15f1cd63 /sys/dev/netmap/netmap_bdg.c
parentabc73e04c2a0add60dea19c7aab5a0a4d51ab418 (diff)
Notes
Diffstat (limited to 'sys/dev/netmap/netmap_bdg.c')
-rw-r--r--sys/dev/netmap/netmap_bdg.c354
1 files changed, 96 insertions, 258 deletions
diff --git a/sys/dev/netmap/netmap_bdg.c b/sys/dev/netmap/netmap_bdg.c
index dd64b805cbf1..e70e67821afb 100644
--- a/sys/dev/netmap/netmap_bdg.c
+++ b/sys/dev/netmap/netmap_bdg.c
@@ -126,7 +126,7 @@ netmap_bdg_name(struct netmap_vp_adapter *vp)
* Right now we have a static array and deletions are protected
* by an exclusive lock.
*/
-static struct nm_bridge *nm_bridges;
+struct nm_bridge *nm_bridges;
#endif /* !CONFIG_NET_NS */
@@ -139,15 +139,15 @@ nm_is_id_char(const char c)
(c == '_');
}
-/* Validate the name of a VALE bridge port and return the
+/* Validate the name of a bdg port and return the
* position of the ":" character. */
static int
-nm_vale_name_validate(const char *name)
+nm_bdg_name_validate(const char *name, size_t prefixlen)
{
int colon_pos = -1;
int i;
- if (!name || strlen(name) < strlen(NM_BDG_NAME)) {
+ if (!name || strlen(name) < prefixlen) {
return -1;
}
@@ -186,9 +186,10 @@ nm_find_bridge(const char *name, int create, struct netmap_bdg_ops *ops)
netmap_bns_getbridges(&bridges, &num_bridges);
- namelen = nm_vale_name_validate(name);
+ namelen = nm_bdg_name_validate(name,
+ (ops != NULL ? strlen(ops->name) : 0));
if (namelen < 0) {
- D("invalid bridge name %s", name ? name : NULL);
+ nm_prerr("invalid bridge name %s", name ? name : NULL);
return NULL;
}
@@ -213,7 +214,7 @@ nm_find_bridge(const char *name, int create, struct netmap_bdg_ops *ops)
b->bdg_active_ports);
b->ht = nm_os_malloc(sizeof(struct nm_hash_ent) * NM_BDG_HASH);
if (b->ht == NULL) {
- D("failed to allocate hash table");
+ nm_prerr("failed to allocate hash table");
return NULL;
}
strncpy(b->bdg_basename, name, namelen);
@@ -222,7 +223,7 @@ nm_find_bridge(const char *name, int create, struct netmap_bdg_ops *ops)
for (i = 0; i < NM_BDG_MAXPORTS; i++)
b->bdg_port_index[i] = i;
/* set the default function */
- b->bdg_ops = ops;
+ b->bdg_ops = b->bdg_saved_ops = *ops;
b->private_data = b->ht;
b->bdg_flags = 0;
NM_BNS_GET(b);
@@ -240,12 +241,48 @@ netmap_bdg_free(struct nm_bridge *b)
ND("marking bridge %s as free", b->bdg_basename);
nm_os_free(b->ht);
- b->bdg_ops = NULL;
+ memset(&b->bdg_ops, 0, sizeof(b->bdg_ops));
+ memset(&b->bdg_saved_ops, 0, sizeof(b->bdg_saved_ops));
b->bdg_flags = 0;
NM_BNS_PUT(b);
return 0;
}
+/* Called by external kernel modules (e.g., Openvswitch).
+ * to modify the private data previously given to regops().
+ * 'name' may be just bridge's name (including ':' if it
+ * is not just NM_BDG_NAME).
+ * Called without NMG_LOCK.
+ */
+int
+netmap_bdg_update_private_data(const char *name, bdg_update_private_data_fn_t callback,
+ void *callback_data, void *auth_token)
+{
+ void *private_data = NULL;
+ struct nm_bridge *b;
+ int error = 0;
+
+ NMG_LOCK();
+ b = nm_find_bridge(name, 0 /* don't create */, NULL);
+ if (!b) {
+ error = EINVAL;
+ goto unlock_update_priv;
+ }
+ if (!nm_bdg_valid_auth_token(b, auth_token)) {
+ error = EACCES;
+ goto unlock_update_priv;
+ }
+ BDG_WLOCK(b);
+ private_data = callback(b->private_data, callback_data, &error);
+ b->private_data = private_data;
+ BDG_WUNLOCK(b);
+
+unlock_update_priv:
+ NMG_UNLOCK();
+ return error;
+}
+
+
/* remove from bridge b the ports in slots hw and sw
* (sw can be -1 if not needed)
@@ -267,8 +304,8 @@ netmap_bdg_detach_common(struct nm_bridge *b, int hw, int sw)
acquire BDG_WLOCK() and copy back the array.
*/
- if (netmap_verbose)
- D("detach %d and %d (lim %d)", hw, sw, lim);
+ if (netmap_debug & NM_DEBUG_BDG)
+ nm_prinf("detach %d and %d (lim %d)", hw, sw, lim);
/* make a copy of the list of active ports, update it,
* and then copy back within BDG_WLOCK().
*/
@@ -291,12 +328,12 @@ netmap_bdg_detach_common(struct nm_bridge *b, int hw, int sw)
}
}
if (hw >= 0 || sw >= 0) {
- D("XXX delete failed hw %d sw %d, should panic...", hw, sw);
+ nm_prerr("delete failed hw %d sw %d, should panic...", hw, sw);
}
BDG_WLOCK(b);
- if (b->bdg_ops->dtor)
- b->bdg_ops->dtor(b->bdg_ports[s_hw]);
+ if (b->bdg_ops.dtor)
+ b->bdg_ops.dtor(b->bdg_ports[s_hw]);
b->bdg_ports[s_hw] = NULL;
if (s_sw >= 0) {
b->bdg_ports[s_sw] = NULL;
@@ -402,7 +439,7 @@ netmap_get_bdg_na(struct nmreq_header *hdr, struct netmap_adapter **na,
/* yes we should, see if we have space to attach entries */
needed = 2; /* in some cases we only need 1 */
if (b->bdg_active_ports + needed >= NM_BDG_MAXPORTS) {
- D("bridge full %d, cannot create new port", b->bdg_active_ports);
+ nm_prerr("bridge full %d, cannot create new port", b->bdg_active_ports);
return ENOMEM;
}
/* record the next two ports available, but do not allocate yet */
@@ -428,9 +465,10 @@ netmap_get_bdg_na(struct nmreq_header *hdr, struct netmap_adapter **na,
}
/* bdg_netmap_attach creates a struct netmap_adapter */
- error = b->bdg_ops->vp_create(hdr, NULL, nmd, &vpna);
+ error = b->bdg_ops.vp_create(hdr, NULL, nmd, &vpna);
if (error) {
- D("error %d", error);
+ if (netmap_debug & NM_DEBUG_BDG)
+ nm_prerr("error %d", error);
goto out;
}
/* shortcut - we can skip get_hw_na(),
@@ -459,7 +497,7 @@ netmap_get_bdg_na(struct nmreq_header *hdr, struct netmap_adapter **na,
/* host adapter might not be created */
error = hw->nm_bdg_attach(nr_name, hw, b);
if (error == NM_NEED_BWRAP) {
- error = b->bdg_ops->bwrap_attach(nr_name, hw);
+ error = b->bdg_ops.bwrap_attach(nr_name, hw);
}
if (error)
goto out;
@@ -502,142 +540,13 @@ out:
return error;
}
-/* Process NETMAP_REQ_VALE_ATTACH.
- */
-int
-nm_bdg_ctl_attach(struct nmreq_header *hdr, void *auth_token)
-{
- struct nmreq_vale_attach *req =
- (struct nmreq_vale_attach *)(uintptr_t)hdr->nr_body;
- struct netmap_vp_adapter * vpna;
- struct netmap_adapter *na = NULL;
- struct netmap_mem_d *nmd = NULL;
- struct nm_bridge *b = NULL;
- int error;
-
- NMG_LOCK();
- /* permission check for modified bridges */
- b = nm_find_bridge(hdr->nr_name, 0 /* don't create */, NULL);
- if (b && !nm_bdg_valid_auth_token(b, auth_token)) {
- error = EACCES;
- goto unlock_exit;
- }
-
- if (req->reg.nr_mem_id) {
- nmd = netmap_mem_find(req->reg.nr_mem_id);
- if (nmd == NULL) {
- error = EINVAL;
- goto unlock_exit;
- }
- }
-
- /* check for existing one */
- error = netmap_get_vale_na(hdr, &na, nmd, 0);
- if (na) {
- error = EBUSY;
- goto unref_exit;
- }
- error = netmap_get_vale_na(hdr, &na,
- nmd, 1 /* create if not exists */);
- if (error) { /* no device */
- goto unlock_exit;
- }
-
- if (na == NULL) { /* VALE prefix missing */
- error = EINVAL;
- goto unlock_exit;
- }
-
- if (NETMAP_OWNED_BY_ANY(na)) {
- error = EBUSY;
- goto unref_exit;
- }
-
- if (na->nm_bdg_ctl) {
- /* nop for VALE ports. The bwrap needs to put the hwna
- * in netmap mode (see netmap_bwrap_bdg_ctl)
- */
- error = na->nm_bdg_ctl(hdr, na);
- if (error)
- goto unref_exit;
- ND("registered %s to netmap-mode", na->name);
- }
- vpna = (struct netmap_vp_adapter *)na;
- req->port_index = vpna->bdg_port;
- NMG_UNLOCK();
- return 0;
-
-unref_exit:
- netmap_adapter_put(na);
-unlock_exit:
- NMG_UNLOCK();
- return error;
-}
-static inline int
+int
nm_is_bwrap(struct netmap_adapter *na)
{
return na->nm_register == netmap_bwrap_reg;
}
-/* Process NETMAP_REQ_VALE_DETACH.
- */
-int
-nm_bdg_ctl_detach(struct nmreq_header *hdr, void *auth_token)
-{
- struct nmreq_vale_detach *nmreq_det = (void *)(uintptr_t)hdr->nr_body;
- struct netmap_vp_adapter *vpna;
- struct netmap_adapter *na;
- struct nm_bridge *b = NULL;
- int error;
-
- NMG_LOCK();
- /* permission check for modified bridges */
- b = nm_find_bridge(hdr->nr_name, 0 /* don't create */, NULL);
- if (b && !nm_bdg_valid_auth_token(b, auth_token)) {
- error = EACCES;
- goto unlock_exit;
- }
-
- error = netmap_get_vale_na(hdr, &na, NULL, 0 /* don't create */);
- if (error) { /* no device, or another bridge or user owns the device */
- goto unlock_exit;
- }
-
- if (na == NULL) { /* VALE prefix missing */
- error = EINVAL;
- goto unlock_exit;
- } else if (nm_is_bwrap(na) &&
- ((struct netmap_bwrap_adapter *)na)->na_polling_state) {
- /* Don't detach a NIC with polling */
- error = EBUSY;
- goto unref_exit;
- }
-
- vpna = (struct netmap_vp_adapter *)na;
- if (na->na_vp != vpna) {
- /* trying to detach first attach of VALE persistent port attached
- * to 2 bridges
- */
- error = EBUSY;
- goto unref_exit;
- }
- nmreq_det->port_index = vpna->bdg_port;
-
- if (na->nm_bdg_ctl) {
- /* remove the port from bridge. The bwrap
- * also needs to put the hwna in normal mode
- */
- error = na->nm_bdg_ctl(hdr, na);
- }
-
-unref_exit:
- netmap_adapter_put(na);
-unlock_exit:
- NMG_UNLOCK();
- return error;
-
-}
struct nm_bdg_polling_state;
struct
@@ -661,7 +570,7 @@ struct nm_bdg_polling_state {
};
static void
-netmap_bwrap_polling(void *data, int is_kthread)
+netmap_bwrap_polling(void *data)
{
struct nm_bdg_kthread *nbk = data;
struct netmap_bwrap_adapter *bna;
@@ -693,7 +602,6 @@ nm_bdg_create_kthreads(struct nm_bdg_polling_state *bps)
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 &&
@@ -703,8 +611,9 @@ nm_bdg_create_kthreads(struct nm_bdg_polling_state *bps)
t->bps = bps;
t->qfirst = all ? bps->qfirst /* must be 0 */: affinity;
t->qlast = all ? bps->qlast : t->qfirst + 1;
- D("kthread %d a:%u qf:%u ql:%u", i, affinity, t->qfirst,
- t->qlast);
+ if (netmap_verbose)
+ nm_prinf("kthread %d a:%u qf:%u ql:%u", i, affinity, t->qfirst,
+ t->qlast);
kcfg.type = i;
kcfg.worker_private = t;
@@ -732,7 +641,7 @@ nm_bdg_polling_start_kthreads(struct nm_bdg_polling_state *bps)
int error, i, j;
if (!bps) {
- D("polling is not configured");
+ nm_prerr("polling is not configured");
return EFAULT;
}
bps->stopped = false;
@@ -741,7 +650,7 @@ nm_bdg_polling_start_kthreads(struct nm_bdg_polling_state *bps)
struct nm_bdg_kthread *t = bps->kthreads + i;
error = nm_os_kctx_worker_start(t->nmk);
if (error) {
- D("error in nm_kthread_start()");
+ nm_prerr("error in nm_kthread_start(): %d", error);
goto cleanup;
}
}
@@ -784,10 +693,10 @@ get_polling_cfg(struct nmreq_vale_polling *req, struct netmap_adapter *na,
avail_cpus = nm_os_ncpus();
if (req_cpus == 0) {
- D("req_cpus must be > 0");
+ nm_prerr("req_cpus must be > 0");
return EINVAL;
} else if (req_cpus >= avail_cpus) {
- D("Cannot use all the CPUs in the system");
+ nm_prerr("Cannot use all the CPUs in the system");
return EINVAL;
}
@@ -797,7 +706,7 @@ get_polling_cfg(struct nmreq_vale_polling *req, struct netmap_adapter *na,
* For example, if nr_first_cpu_id=2 and nr_num_polling_cpus=2,
* ring 2 and 3 are polled by core 2 and 3, respectively. */
if (i + req_cpus > nma_get_nrings(na, NR_RX)) {
- D("Rings %u-%u not in range (have %d rings)",
+ nm_prerr("Rings %u-%u not in range (have %d rings)",
i, i + req_cpus, nma_get_nrings(na, NR_RX));
return EINVAL;
}
@@ -809,7 +718,7 @@ get_polling_cfg(struct nmreq_vale_polling *req, struct netmap_adapter *na,
/* Poll all the rings using a core specified by nr_first_cpu_id.
* the number of cores must be 1. */
if (req_cpus != 1) {
- D("ncpus must be 1 for NETMAP_POLLING_MODE_SINGLE_CPU "
+ nm_prerr("ncpus must be 1 for NETMAP_POLLING_MODE_SINGLE_CPU "
"(was %d)", req_cpus);
return EINVAL;
}
@@ -817,7 +726,7 @@ get_polling_cfg(struct nmreq_vale_polling *req, struct netmap_adapter *na,
qlast = nma_get_nrings(na, NR_RX);
core_from = i;
} else {
- D("Invalid polling mode");
+ nm_prerr("Invalid polling mode");
return EINVAL;
}
@@ -826,7 +735,7 @@ get_polling_cfg(struct nmreq_vale_polling *req, struct netmap_adapter *na,
bps->qlast = qlast;
bps->cpu_from = core_from;
bps->ncpus = req_cpus;
- D("%s qfirst %u qlast %u cpu_from %u ncpus %u",
+ nm_prinf("%s qfirst %u qlast %u cpu_from %u ncpus %u",
req->nr_mode == NETMAP_POLLING_MODE_MULTI_CPU ?
"MULTI" : "SINGLE",
qfirst, qlast, core_from, req_cpus);
@@ -842,7 +751,7 @@ nm_bdg_ctl_polling_start(struct nmreq_vale_polling *req, struct netmap_adapter *
bna = (struct netmap_bwrap_adapter *)na;
if (bna->na_polling_state) {
- D("ERROR adapter already in polling mode");
+ nm_prerr("ERROR adapter already in polling mode");
return EFAULT;
}
@@ -871,7 +780,7 @@ nm_bdg_ctl_polling_start(struct nmreq_vale_polling *req, struct netmap_adapter *
/* start kthread now */
error = nm_bdg_polling_start_kthreads(bps);
if (error) {
- D("ERROR nm_bdg_polling_start_kthread()");
+ nm_prerr("ERROR nm_bdg_polling_start_kthread()");
nm_os_free(bps->kthreads);
nm_os_free(bps);
bna->na_polling_state = NULL;
@@ -887,7 +796,7 @@ nm_bdg_ctl_polling_stop(struct netmap_adapter *na)
struct nm_bdg_polling_state *bps;
if (!bna->na_polling_state) {
- D("ERROR adapter is not in polling mode");
+ nm_prerr("ERROR adapter is not in polling mode");
return EFAULT;
}
bps = bna->na_polling_state;
@@ -932,86 +841,6 @@ nm_bdg_polling(struct nmreq_header *hdr)
return error;
}
-/* Process NETMAP_REQ_VALE_LIST. */
-int
-netmap_bdg_list(struct nmreq_header *hdr)
-{
- struct nmreq_vale_list *req =
- (struct nmreq_vale_list *)(uintptr_t)hdr->nr_body;
- int namelen = strlen(hdr->nr_name);
- struct nm_bridge *b, *bridges;
- struct netmap_vp_adapter *vpna;
- int error = 0, i, j;
- u_int num_bridges;
-
- netmap_bns_getbridges(&bridges, &num_bridges);
-
- /* this is used to enumerate bridges and ports */
- if (namelen) { /* look up indexes of bridge and port */
- if (strncmp(hdr->nr_name, NM_BDG_NAME,
- strlen(NM_BDG_NAME))) {
- return EINVAL;
- }
- NMG_LOCK();
- b = nm_find_bridge(hdr->nr_name, 0 /* don't create */, NULL);
- if (!b) {
- NMG_UNLOCK();
- return ENOENT;
- }
-
- req->nr_bridge_idx = b - bridges; /* bridge index */
- req->nr_port_idx = NM_BDG_NOPORT;
- for (j = 0; j < b->bdg_active_ports; j++) {
- i = b->bdg_port_index[j];
- vpna = b->bdg_ports[i];
- if (vpna == NULL) {
- D("This should not happen");
- continue;
- }
- /* the former and the latter identify a
- * virtual port and a NIC, respectively
- */
- if (!strcmp(vpna->up.name, hdr->nr_name)) {
- req->nr_port_idx = i; /* port index */
- break;
- }
- }
- NMG_UNLOCK();
- } else {
- /* return the first non-empty entry starting from
- * bridge nr_arg1 and port nr_arg2.
- *
- * Users can detect the end of the same bridge by
- * seeing the new and old value of nr_arg1, and can
- * detect the end of all the bridge by error != 0
- */
- i = req->nr_bridge_idx;
- j = req->nr_port_idx;
-
- NMG_LOCK();
- for (error = ENOENT; i < NM_BRIDGES; i++) {
- b = bridges + i;
- for ( ; j < NM_BDG_MAXPORTS; j++) {
- if (b->bdg_ports[j] == NULL)
- continue;
- vpna = b->bdg_ports[j];
- /* write back the VALE switch name */
- strncpy(hdr->nr_name, vpna->up.name,
- (size_t)IFNAMSIZ);
- error = 0;
- goto out;
- }
- j = 0; /* following bridges scan from 0 */
- }
- out:
- req->nr_bridge_idx = i;
- req->nr_port_idx = j;
- NMG_UNLOCK();
- }
-
- return error;
-}
-
/* Called by external kernel modules (e.g., Openvswitch).
* to set configure/lookup/dtor functions of a VALE instance.
* Register callbacks to the given bridge. 'name' may be just
@@ -1041,12 +870,19 @@ netmap_bdg_regops(const char *name, struct netmap_bdg_ops *bdg_ops, void *privat
if (!bdg_ops) {
/* resetting the bridge */
bzero(b->ht, sizeof(struct nm_hash_ent) * NM_BDG_HASH);
- b->bdg_ops = NULL;
+ b->bdg_ops = b->bdg_saved_ops;
b->private_data = b->ht;
} else {
/* modifying the bridge */
b->private_data = private_data;
- b->bdg_ops = bdg_ops;
+#define nm_bdg_override(m) if (bdg_ops->m) b->bdg_ops.m = bdg_ops->m
+ nm_bdg_override(lookup);
+ nm_bdg_override(config);
+ nm_bdg_override(dtor);
+ nm_bdg_override(vp_create);
+ nm_bdg_override(bwrap_attach);
+#undef nm_bdg_override
+
}
BDG_WUNLOCK(b);
@@ -1071,8 +907,8 @@ netmap_bdg_config(struct nm_ifreq *nr)
NMG_UNLOCK();
/* Don't call config() with NMG_LOCK() held */
BDG_RLOCK(b);
- if (b->bdg_ops->config != NULL)
- error = b->bdg_ops->config(nr);
+ if (b->bdg_ops.config != NULL)
+ error = b->bdg_ops.config(nr);
BDG_RUNLOCK(b);
return error;
}
@@ -1137,7 +973,7 @@ netmap_vp_rxsync_locked(struct netmap_kring *kring, int flags)
int n;
if (head > lim) {
- D("ouch dangerous reset!!!");
+ nm_prerr("ouch dangerous reset!!!");
n = netmap_ring_reinit(kring);
goto done;
}
@@ -1154,7 +990,7 @@ netmap_vp_rxsync_locked(struct netmap_kring *kring, int flags)
void *addr = NMB(na, slot);
if (addr == NETMAP_BUF_BASE(kring->na)) { /* bad buf */
- D("bad buffer index %d, ignore ?",
+ nm_prerr("bad buffer index %d, ignore ?",
slot->buf_idx);
}
slot->flags &= ~NS_BUF_CHANGED;
@@ -1283,8 +1119,8 @@ netmap_bwrap_intr_notify(struct netmap_kring *kring, int flags)
int ret = NM_IRQ_COMPLETED;
int error;
- if (netmap_verbose)
- D("%s %s 0x%x", na->name, kring->name, flags);
+ if (netmap_debug & NM_DEBUG_RXINTR)
+ nm_prinf("%s %s 0x%x", na->name, kring->name, flags);
bkring = vpna->up.tx_rings[ring_nr];
@@ -1293,8 +1129,8 @@ netmap_bwrap_intr_notify(struct netmap_kring *kring, int flags)
return EIO;
}
- if (netmap_verbose)
- D("%s head %d cur %d tail %d", na->name,
+ if (netmap_debug & NM_DEBUG_RXINTR)
+ nm_prinf("%s head %d cur %d tail %d", na->name,
kring->rhead, kring->rcur, kring->rtail);
/* simulate a user wakeup on the rx ring
@@ -1305,7 +1141,7 @@ netmap_bwrap_intr_notify(struct netmap_kring *kring, int flags)
goto put_out;
if (kring->nr_hwcur == kring->nr_hwtail) {
if (netmap_verbose)
- D("how strange, interrupt with no packets on %s",
+ nm_prerr("how strange, interrupt with no packets on %s",
na->name);
goto put_out;
}
@@ -1593,8 +1429,8 @@ netmap_bwrap_notify(struct netmap_kring *kring, int flags)
ND("%s[%d] PRE rx(c%3d t%3d l%3d) ring(h%3d c%3d t%3d) tx(c%3d ht%3d t%3d)",
na->name, ring_n,
kring->nr_hwcur, kring->nr_hwtail, kring->nkr_hwlease,
- ring->head, ring->cur, ring->tail,
- hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_ring->rtail);
+ kring->rhead, kring->rcur, kring->rtail,
+ hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_kring->rtail);
/* second step: the new packets are sent on the tx ring
* (which is actually the same ring)
*/
@@ -1612,7 +1448,7 @@ netmap_bwrap_notify(struct netmap_kring *kring, int flags)
ND("%s[%d] PST rx(c%3d t%3d l%3d) ring(h%3d c%3d t%3d) tx(c%3d ht%3d t%3d)",
na->name, ring_n,
kring->nr_hwcur, kring->nr_hwtail, kring->nkr_hwlease,
- ring->head, ring->cur, ring->tail,
+ kring->rhead, kring->rcur, kring->rtail,
hw_kring->nr_hwcur, hw_kring->nr_hwtail, hw_kring->rtail);
put_out:
nm_kr_put(hw_kring);
@@ -1688,7 +1524,7 @@ netmap_bwrap_attach_common(struct netmap_adapter *na,
/* make sure the NIC is not already in use */
if (NETMAP_OWNED_BY_ANY(hwna)) {
- D("NIC %s busy, cannot attach to bridge", hwna->name);
+ nm_prerr("NIC %s busy, cannot attach to bridge", hwna->name);
return EBUSY;
}
@@ -1756,6 +1592,8 @@ netmap_bwrap_attach_common(struct netmap_adapter *na,
hostna->na_flags = NAF_BUSY; /* prevent NIOCREGIF */
hostna->rx_buf_maxsize = hwna->rx_buf_maxsize;
}
+ if (hwna->na_flags & NAF_MOREFRAG)
+ na->na_flags |= NAF_MOREFRAG;
ND("%s<->%s txr %d txd %d rxr %d rxd %d",
na->name, ifp->if_xname,