Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/netmap/netmap_monitor.c
Show First 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | |||||
* Note that the lock in netmap_zmon_parent_sync only protects | * Note that the lock in netmap_zmon_parent_sync only protects | ||||
* writers among themselves. Synchronization between writers | * writers among themselves. Synchronization between writers | ||||
* (i.e., netmap_zmon_parent_txsync and netmap_zmon_parent_rxsync) | * (i.e., netmap_zmon_parent_txsync and netmap_zmon_parent_rxsync) | ||||
* and readers (i.e., netmap_zmon_rxsync) relies on memory barriers. | * and readers (i.e., netmap_zmon_rxsync) relies on memory barriers. | ||||
*/ | */ | ||||
static int | static int | ||||
netmap_monitor_rxsync(struct netmap_kring *kring, int flags) | netmap_monitor_rxsync(struct netmap_kring *kring, int flags) | ||||
{ | { | ||||
struct netmap_monitor_adapter *mna = | |||||
(struct netmap_monitor_adapter *)kring->na; | |||||
if (unlikely(mna->priv.np_na == NULL)) { | |||||
/* parent left netmap mode */ | |||||
return EIO; | |||||
} | |||||
ND("%s %x", kring->name, flags); | ND("%s %x", kring->name, flags); | ||||
kring->nr_hwcur = kring->rhead; | kring->nr_hwcur = kring->rhead; | ||||
mb(); | mb(); | ||||
return 0; | return 0; | ||||
} | } | ||||
/* nm_krings_create callbacks for monitors. | /* nm_krings_create callbacks for monitors. | ||||
*/ | */ | ||||
static int | static int | ||||
netmap_monitor_krings_create(struct netmap_adapter *na) | netmap_monitor_krings_create(struct netmap_adapter *na) | ||||
{ | { | ||||
int error = netmap_krings_create(na, 0); | int error = netmap_krings_create(na, 0); | ||||
enum txrx t; | |||||
if (error) | if (error) | ||||
return error; | return error; | ||||
/* override the host rings callbacks */ | /* override the host rings callbacks */ | ||||
na->tx_rings[na->num_tx_rings]->nm_sync = netmap_monitor_txsync; | for_rx_tx(t) { | ||||
na->rx_rings[na->num_rx_rings]->nm_sync = netmap_monitor_rxsync; | int i; | ||||
u_int first = nma_get_nrings(na, t); | |||||
for (i = 0; i < nma_get_host_nrings(na, t); i++) { | |||||
struct netmap_kring *kring = NMR(na, t)[first + i]; | |||||
kring->nm_sync = t == NR_TX ? netmap_monitor_txsync : | |||||
netmap_monitor_rxsync; | |||||
} | |||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
/* nm_krings_delete callback for monitors */ | /* nm_krings_delete callback for monitors */ | ||||
static void | static void | ||||
netmap_monitor_krings_delete(struct netmap_adapter *na) | netmap_monitor_krings_delete(struct netmap_adapter *na) | ||||
{ | { | ||||
netmap_krings_delete(na); | netmap_krings_delete(na); | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
* nm_notify() callbacks in the monitored rings. | * nm_notify() callbacks in the monitored rings. | ||||
*/ | */ | ||||
static int netmap_zmon_parent_txsync(struct netmap_kring *, int); | static int netmap_zmon_parent_txsync(struct netmap_kring *, int); | ||||
static int netmap_zmon_parent_rxsync(struct netmap_kring *, int); | static int netmap_zmon_parent_rxsync(struct netmap_kring *, int); | ||||
static int netmap_monitor_parent_txsync(struct netmap_kring *, int); | static int netmap_monitor_parent_txsync(struct netmap_kring *, int); | ||||
static int netmap_monitor_parent_rxsync(struct netmap_kring *, int); | static int netmap_monitor_parent_rxsync(struct netmap_kring *, int); | ||||
static int netmap_monitor_parent_notify(struct netmap_kring *, int); | static int netmap_monitor_parent_notify(struct netmap_kring *, int); | ||||
static void | |||||
nm_monitor_intercept_callbacks(struct netmap_kring *kring) | |||||
{ | |||||
ND("intercept callbacks on %s", kring->name); | |||||
kring->mon_sync = kring->nm_sync; | |||||
kring->mon_notify = kring->nm_notify; | |||||
if (kring->tx == NR_TX) { | |||||
kring->nm_sync = netmap_monitor_parent_txsync; | |||||
} else { | |||||
kring->nm_sync = netmap_monitor_parent_rxsync; | |||||
kring->nm_notify = netmap_monitor_parent_notify; | |||||
kring->mon_tail = kring->nr_hwtail; | |||||
} | |||||
} | |||||
static void | |||||
nm_monitor_restore_callbacks(struct netmap_kring *kring) | |||||
{ | |||||
ND("restoring callbacks on %s", kring->name); | |||||
kring->nm_sync = kring->mon_sync; | |||||
kring->mon_sync = NULL; | |||||
if (kring->tx == NR_RX) { | |||||
kring->nm_notify = kring->mon_notify; | |||||
} | |||||
kring->mon_notify = NULL; | |||||
} | |||||
static struct netmap_kring * | |||||
nm_zmon_list_head(struct netmap_kring *mkring, enum txrx t) | |||||
{ | |||||
struct netmap_adapter *na = mkring->na; | |||||
struct netmap_kring *kring = mkring; | |||||
struct netmap_zmon_list *z = &kring->zmon_list[t]; | |||||
/* reach the head of the list */ | |||||
while (nm_is_zmon(na) && z->prev != NULL) { | |||||
kring = z->prev; | |||||
na = kring->na; | |||||
z = &kring->zmon_list[t]; | |||||
} | |||||
return nm_is_zmon(na) ? NULL : kring; | |||||
} | |||||
/* add the monitor mkring to the list of monitors of kring. | /* add the monitor mkring to the list of monitors of kring. | ||||
* If this is the first monitor, intercept the callbacks | * If this is the first monitor, intercept the callbacks | ||||
*/ | */ | ||||
static int | static int | ||||
netmap_monitor_add(struct netmap_kring *mkring, struct netmap_kring *kring, int zmon) | netmap_monitor_add(struct netmap_kring *mkring, struct netmap_kring *kring, int zmon) | ||||
{ | { | ||||
int error = NM_IRQ_COMPLETED; | int error = NM_IRQ_COMPLETED; | ||||
enum txrx t = kring->tx; | enum txrx t = kring->tx; | ||||
struct netmap_zmon_list *z = &kring->zmon_list[t]; | struct netmap_zmon_list *z = &kring->zmon_list[t]; | ||||
struct netmap_zmon_list *mz = &mkring->zmon_list[t]; | struct netmap_zmon_list *mz = &mkring->zmon_list[t]; | ||||
struct netmap_kring *ikring = kring; | |||||
/* a zero-copy monitor which is not the first in the list | /* a zero-copy monitor which is not the first in the list | ||||
* must monitor the previous monitor | * must monitor the previous monitor | ||||
*/ | */ | ||||
if (zmon && z->prev != NULL) | if (zmon && z->prev != NULL) | ||||
kring = z->prev; | ikring = z->prev; /* tail of the list */ | ||||
/* synchronize with concurrently running nm_sync()s */ | /* synchronize with concurrently running nm_sync()s */ | ||||
nm_kr_stop(kring, NM_KR_LOCKED); | nm_kr_stop(kring, NM_KR_LOCKED); | ||||
if (nm_monitor_none(kring)) { | if (nm_monitor_none(ikring)) { | ||||
/* this is the first monitor, intercept callbacks */ | /* this is the first monitor, intercept the callbacks */ | ||||
ND("intercept callbacks on %s", kring->name); | ND("%s: intercept callbacks on %s", mkring->name, ikring->name); | ||||
kring->mon_sync = kring->nm_sync; | nm_monitor_intercept_callbacks(ikring); | ||||
kring->mon_notify = kring->nm_notify; | |||||
if (kring->tx == NR_TX) { | |||||
kring->nm_sync = netmap_monitor_parent_txsync; | |||||
} else { | |||||
kring->nm_sync = netmap_monitor_parent_rxsync; | |||||
kring->nm_notify = netmap_monitor_parent_notify; | |||||
kring->mon_tail = kring->nr_hwtail; | |||||
} | } | ||||
} | |||||
if (zmon) { | if (zmon) { | ||||
/* append the zmon to the list */ | /* append the zmon to the list */ | ||||
struct netmap_monitor_adapter *mna = | ikring->zmon_list[t].next = mkring; | ||||
(struct netmap_monitor_adapter *)mkring->na; | z->prev = mkring; /* new tail */ | ||||
struct netmap_adapter *pna; | mz->prev = ikring; | ||||
mz->next = NULL; | |||||
if (z->prev != NULL) | /* grab a reference to the previous netmap adapter | ||||
z->prev->zmon_list[t].next = mkring; | |||||
mz->prev = z->prev; | |||||
z->prev = mkring; | |||||
if (z->next == NULL) | |||||
z->next = mkring; | |||||
/* grap a reference to the previous netmap adapter | |||||
* in the chain (this may be the monitored port | * in the chain (this may be the monitored port | ||||
* or another zero-copy monitor) | * or another zero-copy monitor) | ||||
*/ | */ | ||||
pna = kring->na; | netmap_adapter_get(ikring->na); | ||||
netmap_adapter_get(pna); | |||||
netmap_adapter_put(mna->priv.np_na); | |||||
mna->priv.np_na = pna; | |||||
} else { | } else { | ||||
/* make sure the monitor array exists and is big enough */ | /* make sure the monitor array exists and is big enough */ | ||||
error = nm_monitor_alloc(kring, kring->n_monitors + 1); | error = nm_monitor_alloc(kring, kring->n_monitors + 1); | ||||
if (error) | if (error) | ||||
goto out; | goto out; | ||||
kring->monitors[kring->n_monitors] = mkring; | kring->monitors[kring->n_monitors] = mkring; | ||||
mkring->mon_pos[kring->tx] = kring->n_monitors; | mkring->mon_pos[kring->tx] = kring->n_monitors; | ||||
kring->n_monitors++; | kring->n_monitors++; | ||||
} | } | ||||
out: | out: | ||||
nm_kr_start(kring); | nm_kr_start(kring); | ||||
return error; | return error; | ||||
} | } | ||||
/* remove the monitor mkring from the list of monitors of kring. | /* remove the monitor mkring from the list of monitors of kring. | ||||
* If this is the last monitor, restore the original callbacks | * If this is the last monitor, restore the original callbacks | ||||
*/ | */ | ||||
static void | static void | ||||
netmap_monitor_del(struct netmap_kring *mkring, struct netmap_kring *kring) | netmap_monitor_del(struct netmap_kring *mkring, struct netmap_kring *kring, enum txrx t) | ||||
{ | { | ||||
struct netmap_zmon_list *mz = &mkring->zmon_list[kring->tx]; | |||||
int zmon = nm_is_zmon(mkring->na); | int zmon = nm_is_zmon(mkring->na); | ||||
struct netmap_zmon_list *mz = &mkring->zmon_list[t]; | |||||
struct netmap_kring *ikring = kring; | |||||
if (zmon && mz->prev != NULL) | if (zmon) { | ||||
kring = mz->prev; | /* get to the head of the list */ | ||||
kring = nm_zmon_list_head(mkring, t); | |||||
ikring = mz->prev; | |||||
} | |||||
/* synchronize with concurrently running nm_sync()s */ | /* synchronize with concurrently running nm_sync()s | ||||
* if kring is NULL (orphaned list) the monitored port | |||||
* has exited netmap mode, so there is nothing to stop | |||||
*/ | |||||
if (kring != NULL) | |||||
nm_kr_stop(kring, NM_KR_LOCKED); | nm_kr_stop(kring, NM_KR_LOCKED); | ||||
if (zmon) { | if (zmon) { | ||||
/* remove the monitor from the list */ | /* remove the monitor from the list */ | ||||
if (mz->prev != NULL) | |||||
mz->prev->zmon_list[kring->tx].next = mz->next; | |||||
else | |||||
kring->zmon_list[kring->tx].next = mz->next; | |||||
if (mz->next != NULL) { | if (mz->next != NULL) { | ||||
mz->next->zmon_list[kring->tx].prev = mz->prev; | mz->next->zmon_list[t].prev = mz->prev; | ||||
} else { | /* we also need to let the next monitor drop the | ||||
kring->zmon_list[kring->tx].prev = mz->prev; | * reference to us and grab the reference to the | ||||
* previous ring owner, instead | |||||
*/ | |||||
if (mz->prev != NULL) | |||||
netmap_adapter_get(mz->prev->na); | |||||
netmap_adapter_put(mkring->na); | |||||
} else if (kring != NULL) { | |||||
/* in the monitored kring, prev is actually the | |||||
* pointer to the tail of the list | |||||
*/ | |||||
kring->zmon_list[t].prev = | |||||
(mz->prev != kring ? mz->prev : NULL); | |||||
} | } | ||||
if (mz->prev != NULL) { | |||||
netmap_adapter_put(mz->prev->na); | |||||
mz->prev->zmon_list[t].next = mz->next; | |||||
} | |||||
mz->prev = NULL; | |||||
mz->next = NULL; | |||||
} else { | } else { | ||||
/* this is a copy monitor */ | /* this is a copy monitor */ | ||||
uint32_t mon_pos = mkring->mon_pos[kring->tx]; | uint32_t mon_pos = mkring->mon_pos[kring->tx]; | ||||
kring->n_monitors--; | kring->n_monitors--; | ||||
if (mon_pos != kring->n_monitors) { | if (mon_pos != kring->n_monitors) { | ||||
kring->monitors[mon_pos] = | kring->monitors[mon_pos] = | ||||
kring->monitors[kring->n_monitors]; | kring->monitors[kring->n_monitors]; | ||||
kring->monitors[mon_pos]->mon_pos[kring->tx] = mon_pos; | kring->monitors[mon_pos]->mon_pos[kring->tx] = mon_pos; | ||||
} | } | ||||
kring->monitors[kring->n_monitors] = NULL; | kring->monitors[kring->n_monitors] = NULL; | ||||
if (kring->n_monitors == 0) { | if (kring->n_monitors == 0) { | ||||
nm_monitor_dealloc(kring); | nm_monitor_dealloc(kring); | ||||
} | } | ||||
} | } | ||||
if (nm_monitor_none(kring)) { | if (ikring != NULL && nm_monitor_none(ikring)) { | ||||
/* this was the last monitor, restore the callbacks */ | /* this was the last monitor, restore the callbacks */ | ||||
ND("%s: restoring sync on %s: %p", mkring->name, kring->name, | nm_monitor_restore_callbacks(ikring); | ||||
kring->mon_sync); | |||||
kring->nm_sync = kring->mon_sync; | |||||
kring->mon_sync = NULL; | |||||
if (kring->tx == NR_RX) { | |||||
ND("%s: restoring notify on %s: %p", | |||||
mkring->name, kring->name, kring->mon_notify); | |||||
kring->nm_notify = kring->mon_notify; | |||||
kring->mon_notify = NULL; | |||||
} | } | ||||
} | |||||
if (kring != NULL) | |||||
nm_kr_start(kring); | nm_kr_start(kring); | ||||
} | } | ||||
/* This is called when the monitored adapter leaves netmap mode | /* This is called when the monitored adapter leaves netmap mode | ||||
* (see netmap_do_unregif). | * (see netmap_do_unregif). | ||||
* We need to notify the monitors that the monitored rings are gone. | * We need to notify the monitors that the monitored rings are gone. | ||||
* We do this by setting their mna->priv.np_na to NULL. | * We do this by setting their mna->priv.np_na to NULL. | ||||
* Note that the rings are already stopped when this happens, so | * Note that the rings are already stopped when this happens, so | ||||
* no monitor ring callback can be active. | * no monitor ring callback can be active. | ||||
*/ | */ | ||||
void | void | ||||
netmap_monitor_stop(struct netmap_adapter *na) | netmap_monitor_stop(struct netmap_adapter *na) | ||||
{ | { | ||||
enum txrx t; | enum txrx t; | ||||
for_rx_tx(t) { | for_rx_tx(t) { | ||||
u_int i; | u_int i; | ||||
for (i = 0; i < nma_get_nrings(na, t) + 1; i++) { | for (i = 0; i < netmap_all_rings(na, t); i++) { | ||||
struct netmap_kring *kring = NMR(na, t)[i]; | struct netmap_kring *kring = NMR(na, t)[i]; | ||||
struct netmap_kring *zkring; | struct netmap_zmon_list *z = &kring->zmon_list[t]; | ||||
u_int j; | u_int j; | ||||
for (j = 0; j < kring->n_monitors; j++) { | for (j = 0; j < kring->n_monitors; j++) { | ||||
struct netmap_kring *mkring = | struct netmap_kring *mkring = | ||||
kring->monitors[j]; | kring->monitors[j]; | ||||
struct netmap_monitor_adapter *mna = | struct netmap_monitor_adapter *mna = | ||||
(struct netmap_monitor_adapter *)mkring->na; | (struct netmap_monitor_adapter *)mkring->na; | ||||
/* forget about this adapter */ | /* forget about this adapter */ | ||||
if (mna->priv.np_na != NULL) { | if (mna->priv.np_na != NULL) { | ||||
netmap_adapter_put(mna->priv.np_na); | netmap_adapter_put(mna->priv.np_na); | ||||
mna->priv.np_na = NULL; | mna->priv.np_na = NULL; | ||||
} | } | ||||
kring->monitors[j] = NULL; | |||||
} | } | ||||
zkring = kring->zmon_list[kring->tx].next; | if (!nm_is_zmon(na)) { | ||||
if (zkring != NULL) { | /* we are the head of at most one list */ | ||||
struct netmap_kring *zkring; | |||||
for (zkring = z->next; zkring != NULL; | |||||
zkring = zkring->zmon_list[t].next) | |||||
{ | |||||
struct netmap_monitor_adapter *next = | struct netmap_monitor_adapter *next = | ||||
(struct netmap_monitor_adapter *)zkring->na; | (struct netmap_monitor_adapter *)zkring->na; | ||||
struct netmap_monitor_adapter *this = | /* let the monitor forget about us */ | ||||
(struct netmap_monitor_adapter *)na; | netmap_adapter_put(next->priv.np_na); /* nop if null */ | ||||
struct netmap_adapter *pna = this->priv.np_na; | next->priv.np_na = NULL; | ||||
/* let the next monitor forget about us */ | |||||
if (next->priv.np_na != NULL) { | |||||
netmap_adapter_put(next->priv.np_na); | |||||
} | } | ||||
if (pna != NULL && nm_is_zmon(na)) { | /* orhpan the zmon list */ | ||||
/* we are a monitor ourselves and we may | if (z->next != NULL) | ||||
* need to pass down the reference to | z->next->zmon_list[t].prev = NULL; | ||||
* the previous adapter in the chain | z->next = NULL; | ||||
*/ | z->prev = NULL; | ||||
netmap_adapter_get(pna); | |||||
next->priv.np_na = pna; | |||||
continue; | |||||
} | } | ||||
next->priv.np_na = NULL; | |||||
if (!nm_monitor_none(kring)) { | |||||
kring->n_monitors = 0; | |||||
nm_monitor_dealloc(kring); | |||||
nm_monitor_restore_callbacks(kring); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* common functions for the nm_register() callbacks of both kind of | /* common functions for the nm_register() callbacks of both kind of | ||||
* monitors. | * monitors. | ||||
Show All 12 Lines | netmap_monitor_reg_common(struct netmap_adapter *na, int onoff, int zmon) | ||||
ND("%p: onoff %d", na, onoff); | ND("%p: onoff %d", na, onoff); | ||||
if (onoff) { | if (onoff) { | ||||
if (pna == NULL) { | if (pna == NULL) { | ||||
/* parent left netmap mode, fatal */ | /* parent left netmap mode, fatal */ | ||||
D("%s: internal error", na->name); | D("%s: internal error", na->name); | ||||
return ENXIO; | return ENXIO; | ||||
} | } | ||||
for_rx_tx(t) { | for_rx_tx(t) { | ||||
for (i = 0; i < nma_get_nrings(na, t) + 1; i++) { | for (i = 0; i < netmap_all_rings(na, t); i++) { | ||||
mkring = NMR(na, t)[i]; | mkring = NMR(na, t)[i]; | ||||
if (!nm_kring_pending_on(mkring)) | if (!nm_kring_pending_on(mkring)) | ||||
continue; | continue; | ||||
mkring->nr_mode = NKR_NETMAP_ON; | mkring->nr_mode = NKR_NETMAP_ON; | ||||
if (t == NR_TX) | if (t == NR_TX) | ||||
continue; | continue; | ||||
for_rx_tx(s) { | for_rx_tx(s) { | ||||
if (i > nma_get_nrings(pna, s)) | if (i > nma_get_nrings(pna, s)) | ||||
continue; | continue; | ||||
if (mna->flags & nm_txrx2flag(s)) { | if (mna->flags & nm_txrx2flag(s)) { | ||||
kring = NMR(pna, s)[i]; | kring = NMR(pna, s)[i]; | ||||
netmap_monitor_add(mkring, kring, zmon); | netmap_monitor_add(mkring, kring, zmon); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
na->na_flags |= NAF_NETMAP_ON; | na->na_flags |= NAF_NETMAP_ON; | ||||
} else { | } else { | ||||
if (na->active_fds == 0) | if (na->active_fds == 0) | ||||
na->na_flags &= ~NAF_NETMAP_ON; | na->na_flags &= ~NAF_NETMAP_ON; | ||||
for_rx_tx(t) { | for_rx_tx(t) { | ||||
for (i = 0; i < nma_get_nrings(na, t) + 1; i++) { | for (i = 0; i < netmap_all_rings(na, t); i++) { | ||||
mkring = NMR(na, t)[i]; | mkring = NMR(na, t)[i]; | ||||
if (!nm_kring_pending_off(mkring)) | if (!nm_kring_pending_off(mkring)) | ||||
continue; | continue; | ||||
mkring->nr_mode = NKR_NETMAP_OFF; | mkring->nr_mode = NKR_NETMAP_OFF; | ||||
if (t == NR_TX) | if (t == NR_TX) | ||||
continue; | continue; | ||||
/* we cannot access the parent krings if the parent | /* we cannot access the parent krings if the parent | ||||
* has left netmap mode. This is signaled by a NULL | * has left netmap mode. This is signaled by a NULL | ||||
* pna pointer | * pna pointer | ||||
*/ | */ | ||||
if (pna == NULL) | if (pna == NULL) | ||||
continue; | continue; | ||||
for_rx_tx(s) { | for_rx_tx(s) { | ||||
if (i > nma_get_nrings(pna, s)) | if (i > nma_get_nrings(pna, s)) | ||||
continue; | continue; | ||||
if (mna->flags & nm_txrx2flag(s)) { | if (mna->flags & nm_txrx2flag(s)) { | ||||
kring = NMR(pna, s)[i]; | kring = NMR(pna, s)[i]; | ||||
netmap_monitor_del(mkring, kring); | netmap_monitor_del(mkring, kring, s); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | for ( ; rel_slots; rel_slots--) { | ||||
ms->buf_idx = s->buf_idx; | ms->buf_idx = s->buf_idx; | ||||
s->buf_idx = tmp; | s->buf_idx = tmp; | ||||
ND(5, "beg %d buf_idx %d", beg, tmp); | ND(5, "beg %d buf_idx %d", beg, tmp); | ||||
tmp = ms->len; | tmp = ms->len; | ||||
ms->len = s->len; | ms->len = s->len; | ||||
s->len = tmp; | s->len = tmp; | ||||
ms->flags = s->flags; | |||||
s->flags |= NS_BUF_CHANGED; | s->flags |= NS_BUF_CHANGED; | ||||
beg = nm_next(beg, lim); | beg = nm_next(beg, lim); | ||||
i = nm_next(i, mlim); | i = nm_next(i, mlim); | ||||
} | } | ||||
mb(); | mb(); | ||||
mkring->nr_hwtail = i; | mkring->nr_hwtail = i; | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | for ( ; m; m--) { | ||||
if (unlikely(copy_len > max_len)) { | if (unlikely(copy_len > max_len)) { | ||||
RD(5, "%s->%s: truncating %d to %d", kring->name, | RD(5, "%s->%s: truncating %d to %d", kring->name, | ||||
mkring->name, copy_len, max_len); | mkring->name, copy_len, max_len); | ||||
copy_len = max_len; | copy_len = max_len; | ||||
} | } | ||||
memcpy(dst, src, copy_len); | memcpy(dst, src, copy_len); | ||||
ms->len = copy_len; | ms->len = copy_len; | ||||
ms->flags = s->flags; | |||||
sent++; | sent++; | ||||
beg = nm_next(beg, lim); | beg = nm_next(beg, lim); | ||||
i = nm_next(i, mlim); | i = nm_next(i, mlim); | ||||
} | } | ||||
mb(); | mb(); | ||||
mkring->nr_hwtail = i; | mkring->nr_hwtail = i; | ||||
out: | out: | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct nmreq_register *req = (struct nmreq_register *)(uintptr_t)hdr->nr_body; | struct nmreq_register *req = (struct nmreq_register *)(uintptr_t)hdr->nr_body; | ||||
struct nmreq_register preq; | struct nmreq_register preq; | ||||
struct netmap_adapter *pna; /* parent adapter */ | struct netmap_adapter *pna; /* parent adapter */ | ||||
struct netmap_monitor_adapter *mna; | struct netmap_monitor_adapter *mna; | ||||
struct ifnet *ifp = NULL; | struct ifnet *ifp = NULL; | ||||
int error; | int error; | ||||
int zcopy = (req->nr_flags & NR_ZCOPY_MON); | int zcopy = (req->nr_flags & NR_ZCOPY_MON); | ||||
char monsuff[10] = ""; | |||||
if (zcopy) { | if (zcopy) { | ||||
req->nr_flags |= (NR_MONITOR_TX | NR_MONITOR_RX); | req->nr_flags |= (NR_MONITOR_TX | NR_MONITOR_RX); | ||||
} | } | ||||
if ((req->nr_flags & (NR_MONITOR_TX | NR_MONITOR_RX)) == 0) { | if ((req->nr_flags & (NR_MONITOR_TX | NR_MONITOR_RX)) == 0) { | ||||
ND("not a monitor"); | ND("not a monitor"); | ||||
return 0; | return 0; | ||||
} | } | ||||
Show All 37 Lines | netmap_get_monitor_na(struct nmreq_header *hdr, struct netmap_adapter **na, | ||||
/* grab all the rings we need in the parent */ | /* grab all the rings we need in the parent */ | ||||
error = netmap_interp_ringid(&mna->priv, req->nr_mode, req->nr_ringid, | error = netmap_interp_ringid(&mna->priv, req->nr_mode, req->nr_ringid, | ||||
req->nr_flags); | req->nr_flags); | ||||
if (error) { | if (error) { | ||||
D("ringid error"); | D("ringid error"); | ||||
goto free_out; | goto free_out; | ||||
} | } | ||||
if (mna->priv.np_qlast[NR_TX] - mna->priv.np_qfirst[NR_TX] == 1) { | snprintf(mna->up.name, sizeof(mna->up.name), "%s/%s%s%s#%lu", pna->name, | ||||
snprintf(monsuff, 10, "-%d", mna->priv.np_qfirst[NR_TX]); | |||||
} | |||||
snprintf(mna->up.name, sizeof(mna->up.name), "%s%s/%s%s%s", pna->name, | |||||
monsuff, | |||||
zcopy ? "z" : "", | zcopy ? "z" : "", | ||||
(req->nr_flags & NR_MONITOR_RX) ? "r" : "", | (req->nr_flags & NR_MONITOR_RX) ? "r" : "", | ||||
(req->nr_flags & NR_MONITOR_TX) ? "t" : ""); | (req->nr_flags & NR_MONITOR_TX) ? "t" : "", | ||||
pna->monitor_id++); | |||||
/* the monitor supports the host rings iff the parent does */ | /* the monitor supports the host rings iff the parent does */ | ||||
mna->up.na_flags |= (pna->na_flags & NAF_HOST_RINGS); | mna->up.na_flags |= (pna->na_flags & NAF_HOST_RINGS); | ||||
/* a do-nothing txsync: monitors cannot be used to inject packets */ | /* a do-nothing txsync: monitors cannot be used to inject packets */ | ||||
mna->up.nm_txsync = netmap_monitor_txsync; | mna->up.nm_txsync = netmap_monitor_txsync; | ||||
mna->up.nm_rxsync = netmap_monitor_rxsync; | mna->up.nm_rxsync = netmap_monitor_rxsync; | ||||
mna->up.nm_krings_create = netmap_monitor_krings_create; | mna->up.nm_krings_create = netmap_monitor_krings_create; | ||||
mna->up.nm_krings_delete = netmap_monitor_krings_delete; | mna->up.nm_krings_delete = netmap_monitor_krings_delete; | ||||
▲ Show 20 Lines • Show All 73 Lines • Show Last 20 Lines |