aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/netmap/netmap_monitor.c
diff options
context:
space:
mode:
authorLuigi Rizzo <luigi@FreeBSD.org>2016-10-16 14:13:32 +0000
committerLuigi Rizzo <luigi@FreeBSD.org>2016-10-16 14:13:32 +0000
commit37e3a6d349581b4dd0aebf24be7b1b159a698dcf (patch)
tree0e61deea141c9733af511b0485cf1fd0f2dd17ed /sys/dev/netmap/netmap_monitor.c
parent63f6b1a75a8e6e33e4f9d65571c6a221444d3b05 (diff)
Notes
Diffstat (limited to 'sys/dev/netmap/netmap_monitor.c')
-rw-r--r--sys/dev/netmap/netmap_monitor.c112
1 files changed, 74 insertions, 38 deletions
diff --git a/sys/dev/netmap/netmap_monitor.c b/sys/dev/netmap/netmap_monitor.c
index c303952417ff..5b4f9cdf61c0 100644
--- a/sys/dev/netmap/netmap_monitor.c
+++ b/sys/dev/netmap/netmap_monitor.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2014 Giuseppe Lettieri. All rights reserved.
+ * Copyright (C) 2014-2016 Giuseppe Lettieri
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -101,6 +102,8 @@
#warning OSX support is only partial
#include "osx_glue.h"
+#elif defined(_WIN32)
+#include "win_glue.h"
#else
#error Unsupported platform
@@ -151,13 +154,17 @@ netmap_monitor_rxsync(struct netmap_kring *kring, int flags)
}
/* nm_krings_create callbacks for monitors.
- * We could use the default netmap_hw_krings_zmon, but
- * we don't need the mbq.
*/
static int
netmap_monitor_krings_create(struct netmap_adapter *na)
{
- return netmap_krings_create(na, 0);
+ int error = netmap_krings_create(na, 0);
+ if (error)
+ return error;
+ /* override the host rings callbacks */
+ na->tx_rings[na->num_tx_rings].nm_sync = netmap_monitor_txsync;
+ na->rx_rings[na->num_rx_rings].nm_sync = netmap_monitor_rxsync;
+ return 0;
}
/* nm_krings_delete callback for monitors */
@@ -186,7 +193,11 @@ nm_monitor_alloc(struct netmap_kring *kring, u_int n)
return 0;
len = sizeof(struct netmap_kring *) * n;
+#ifndef _WIN32
nm = realloc(kring->monitors, len, M_DEVBUF, M_NOWAIT | M_ZERO);
+#else
+ nm = realloc(kring->monitors, len, sizeof(struct netmap_kring *)*kring->max_monitors);
+#endif
if (nm == NULL)
return ENOMEM;
@@ -229,10 +240,10 @@ static int netmap_monitor_parent_notify(struct netmap_kring *, int);
static int
netmap_monitor_add(struct netmap_kring *mkring, struct netmap_kring *kring, int zcopy)
{
- int error = 0;
+ int error = NM_IRQ_COMPLETED;
/* sinchronize with concurrently running nm_sync()s */
- nm_kr_get(kring);
+ nm_kr_stop(kring, NM_KR_LOCKED);
/* make sure the monitor array exists and is big enough */
error = nm_monitor_alloc(kring, kring->n_monitors + 1);
if (error)
@@ -242,7 +253,7 @@ netmap_monitor_add(struct netmap_kring *mkring, struct netmap_kring *kring, int
kring->n_monitors++;
if (kring->n_monitors == 1) {
/* this is the first monitor, intercept callbacks */
- D("%s: intercept callbacks on %s", mkring->name, kring->name);
+ ND("%s: intercept callbacks on %s", mkring->name, kring->name);
kring->mon_sync = kring->nm_sync;
/* zcopy monitors do not override nm_notify(), but
* we save the original one regardless, so that
@@ -265,7 +276,7 @@ netmap_monitor_add(struct netmap_kring *mkring, struct netmap_kring *kring, int
}
out:
- nm_kr_put(kring);
+ nm_kr_start(kring);
return error;
}
@@ -277,7 +288,7 @@ static void
netmap_monitor_del(struct netmap_kring *mkring, struct netmap_kring *kring)
{
/* sinchronize with concurrently running nm_sync()s */
- nm_kr_get(kring);
+ nm_kr_stop(kring, NM_KR_LOCKED);
kring->n_monitors--;
if (mkring->mon_pos != kring->n_monitors) {
kring->monitors[mkring->mon_pos] = kring->monitors[kring->n_monitors];
@@ -286,18 +297,18 @@ netmap_monitor_del(struct netmap_kring *mkring, struct netmap_kring *kring)
kring->monitors[kring->n_monitors] = NULL;
if (kring->n_monitors == 0) {
/* this was the last monitor, restore callbacks and delete monitor array */
- D("%s: restoring sync on %s: %p", mkring->name, kring->name, kring->mon_sync);
+ ND("%s: restoring sync on %s: %p", mkring->name, kring->name, kring->mon_sync);
kring->nm_sync = kring->mon_sync;
kring->mon_sync = NULL;
if (kring->tx == NR_RX) {
- D("%s: restoring notify on %s: %p",
+ ND("%s: restoring notify on %s: %p",
mkring->name, kring->name, kring->mon_notify);
kring->nm_notify = kring->mon_notify;
kring->mon_notify = NULL;
}
nm_monitor_dealloc(kring);
}
- nm_kr_put(kring);
+ nm_kr_start(kring);
}
@@ -316,7 +327,7 @@ netmap_monitor_stop(struct netmap_adapter *na)
for_rx_tx(t) {
u_int i;
- for (i = 0; i < nma_get_nrings(na, t); i++) {
+ for (i = 0; i < nma_get_nrings(na, t) + 1; i++) {
struct netmap_kring *kring = &NMR(na, t)[i];
u_int j;
@@ -360,23 +371,32 @@ netmap_monitor_reg_common(struct netmap_adapter *na, int onoff, int zmon)
for (i = priv->np_qfirst[t]; i < priv->np_qlast[t]; i++) {
kring = &NMR(pna, t)[i];
mkring = &na->rx_rings[i];
- netmap_monitor_add(mkring, kring, zmon);
+ if (nm_kring_pending_on(mkring)) {
+ netmap_monitor_add(mkring, kring, zmon);
+ mkring->nr_mode = NKR_NETMAP_ON;
+ }
}
}
}
na->na_flags |= NAF_NETMAP_ON;
} else {
- if (pna == NULL) {
- D("%s: parent left netmap mode, nothing to restore", na->name);
- return 0;
- }
- na->na_flags &= ~NAF_NETMAP_ON;
+ if (na->active_fds == 0)
+ na->na_flags &= ~NAF_NETMAP_ON;
for_rx_tx(t) {
if (mna->flags & nm_txrx2flag(t)) {
for (i = priv->np_qfirst[t]; i < priv->np_qlast[t]; i++) {
- kring = &NMR(pna, t)[i];
mkring = &na->rx_rings[i];
- netmap_monitor_del(mkring, kring);
+ if (nm_kring_pending_off(mkring)) {
+ mkring->nr_mode = NKR_NETMAP_OFF;
+ /* we cannot access the parent krings if the parent
+ * has left netmap mode. This is signaled by a NULL
+ * pna pointer
+ */
+ if (pna) {
+ kring = &NMR(pna, t)[i];
+ netmap_monitor_del(mkring, kring);
+ }
+ }
}
}
}
@@ -652,17 +672,27 @@ netmap_monitor_parent_rxsync(struct netmap_kring *kring, int flags)
static int
netmap_monitor_parent_notify(struct netmap_kring *kring, int flags)
{
+ int (*notify)(struct netmap_kring*, int);
ND(5, "%s %x", kring->name, flags);
/* ?xsync callbacks have tryget called by their callers
* (NIOCREGIF and poll()), but here we have to call it
* by ourself
*/
- if (nm_kr_tryget(kring))
- goto out;
- netmap_monitor_parent_rxsync(kring, NAF_FORCE_READ);
+ if (nm_kr_tryget(kring, 0, NULL)) {
+ /* in all cases, just skip the sync */
+ return NM_IRQ_COMPLETED;
+ }
+ if (kring->n_monitors > 0) {
+ netmap_monitor_parent_rxsync(kring, NAF_FORCE_READ);
+ notify = kring->mon_notify;
+ } else {
+ /* we are no longer monitoring this ring, so both
+ * mon_sync and mon_notify are NULL
+ */
+ notify = kring->nm_notify;
+ }
nm_kr_put(kring);
-out:
- return kring->mon_notify(kring, flags);
+ return notify(kring, flags);
}
@@ -691,18 +721,25 @@ netmap_get_monitor_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
struct nmreq pnmr;
struct netmap_adapter *pna; /* parent adapter */
struct netmap_monitor_adapter *mna;
+ struct ifnet *ifp = NULL;
int i, error;
enum txrx t;
int zcopy = (nmr->nr_flags & NR_ZCOPY_MON);
char monsuff[10] = "";
if ((nmr->nr_flags & (NR_MONITOR_TX | NR_MONITOR_RX)) == 0) {
+ if (nmr->nr_flags & NR_ZCOPY_MON) {
+ /* the flag makes no sense unless you are
+ * creating a monitor
+ */
+ return EINVAL;
+ }
ND("not a monitor");
return 0;
}
/* this is a request for a monitor adapter */
- D("flags %x", nmr->nr_flags);
+ ND("flags %x", nmr->nr_flags);
mna = malloc(sizeof(*mna), M_DEVBUF, M_NOWAIT | M_ZERO);
if (mna == NULL) {
@@ -716,13 +753,14 @@ netmap_get_monitor_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
* except other monitors.
*/
memcpy(&pnmr, nmr, sizeof(pnmr));
- pnmr.nr_flags &= ~(NR_MONITOR_TX | NR_MONITOR_RX);
- error = netmap_get_na(&pnmr, &pna, create);
+ pnmr.nr_flags &= ~(NR_MONITOR_TX | NR_MONITOR_RX | NR_ZCOPY_MON);
+ error = netmap_get_na(&pnmr, &pna, &ifp, create);
if (error) {
D("parent lookup failed: %d", error);
+ free(mna, M_DEVBUF);
return error;
}
- D("found parent: %s", pna->name);
+ ND("found parent: %s", pna->name);
if (!nm_netmap_on(pna)) {
/* parent not in netmap mode */
@@ -829,19 +867,17 @@ netmap_get_monitor_na(struct nmreq *nmr, struct netmap_adapter **na, int create)
*na = &mna->up;
netmap_adapter_get(*na);
- /* write the configuration back */
- nmr->nr_tx_rings = mna->up.num_tx_rings;
- nmr->nr_rx_rings = mna->up.num_rx_rings;
- nmr->nr_tx_slots = mna->up.num_tx_desc;
- nmr->nr_rx_slots = mna->up.num_rx_desc;
-
/* keep the reference to the parent */
- D("monitor ok");
+ ND("monitor ok");
+
+ /* drop the reference to the ifp, if any */
+ if (ifp)
+ if_rele(ifp);
return 0;
put_out:
- netmap_adapter_put(pna);
+ netmap_unget_na(pna, ifp);
free(mna, M_DEVBUF);
return error;
}