/* netmap_pipe_krings_delete. * * There are two cases: * * 1) state is * * usr1 --> e1 --> e2 * * and we are e1. We have to create both sets * of krings. * * 2) state is * * usr1 --> e1 --> e2 * * and we are e2. e1 is certainly registered and our * krings already exist. Nothing to do. */ static int netmap_pipe_krings_create(struct netmap_adapter *na) { struct netmap_pipe_adapter *pna = (struct netmap_pipe_adapter *)na; struct netmap_adapter *ona = &pna->peer->up; int error = 0; enum txrx t; if (pna->peer_ref) { int i; /* case 1) above */ D("%p: case 1, create both ends", na); error = netmap_krings_create(na, 0); if (error) goto err; /* create the krings of the other end */ error = netmap_krings_create(ona, 0); if (error) goto del_krings1; /* cross link the krings */ 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; } } }
/* common functions for the nm_register() callbacks of both kind of * monitors. */ static int netmap_monitor_reg_common(struct netmap_adapter *na, int onoff, int zmon) { struct netmap_monitor_adapter *mna = (struct netmap_monitor_adapter *)na; struct netmap_priv_d *priv = &mna->priv; struct netmap_adapter *pna = priv->np_na; struct netmap_kring *kring, *mkring; int i; enum txrx t; ND("%p: onoff %d", na, onoff); if (onoff) { if (pna == NULL) { /* parent left netmap mode, fatal */ D("%s: internal error", na->name); return ENXIO; } 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_add(mkring, kring, zmon); } } } na->na_flags |= NAF_NETMAP_ON; } else { if (pna == NULL) {
/* common functions for the nm_register() callbacks of both kind of * monitors. */ static int netmap_monitor_reg_common(struct netmap_adapter *na, int onoff, int zmon) { struct netmap_monitor_adapter *mna = (struct netmap_monitor_adapter *)na; struct netmap_priv_d *priv = &mna->priv; struct netmap_adapter *pna = priv->np_na; struct netmap_kring *kring, *mkring; int i; enum txrx t, s; ND("%p: onoff %d", na, onoff); if (onoff) { if (pna == NULL) { /* parent left netmap mode, fatal */ D("%s: internal error", na->name); return ENXIO; } for_rx_tx(t) { for (i = 0; i < nma_get_nrings(na, t) + 1; i++) { mkring = &NMR(na, t)[i]; if (!nm_kring_pending_on(mkring)) continue; mkring->nr_mode = NKR_NETMAP_ON; if (t == NR_TX) continue; for_rx_tx(s) { if (i > nma_get_nrings(pna, s)) continue; if (mna->flags & nm_txrx2flag(s)) { kring = &NMR(pna, s)[i]; netmap_monitor_add(mkring, kring, zmon); } } } } na->na_flags |= NAF_NETMAP_ON; } else { if (na->active_fds == 0)
/* This is called when the monitored adapter leaves netmap mode * (see netmap_do_unregif). * We need to notify the monitors that the monitored rings are gone. * We do this by setting their mna->priv.np_na to NULL. * Note that the rings are already stopped when this happens, so * no monitor ring callback can be active. */ void netmap_monitor_stop(struct netmap_adapter *na) { enum txrx t; for_rx_tx(t) { u_int i; for (i = 0; i < nma_get_nrings(na, t) + 1; i++) { struct netmap_kring *kring = &NMR(na, t)[i]; struct netmap_kring *zkring; u_int j; for (j = 0; j < kring->n_monitors; j++) { struct netmap_kring *mkring = kring->monitors[j]; struct netmap_monitor_adapter *mna = (struct netmap_monitor_adapter *)mkring->na; /* forget about this adapter */ if (mna->priv.np_na != NULL) { netmap_adapter_put(mna->priv.np_na); mna->priv.np_na = NULL; } } zkring = kring->zmon_list[kring->tx].next; if (zkring != NULL) { struct netmap_monitor_adapter *next = (struct netmap_monitor_adapter *)zkring->na; struct netmap_monitor_adapter *this = (struct netmap_monitor_adapter *)na; struct netmap_adapter *pna = this->priv.np_na; /* 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)) { /* we are a monitor ourselves and we may * need to pass down the reference to * the previous adapter in the chain */ netmap_adapter_get(pna); next->priv.np_na = pna; continue; } next->priv.np_na = NULL; } } } }
/* This is called when the monitored adapter leaves netmap mode * (see netmap_do_unregif). * We need to notify the monitors that the monitored rings are gone. * We do this by setting their mna->priv.np_na to NULL. * Note that the rings are already stopped when this happens, so * no monitor ring callback can be active. */ void netmap_monitor_stop(struct netmap_adapter *na) { enum txrx t; for_rx_tx(t) { u_int i; for (i = 0; i < nma_get_nrings(na, t); i++) { struct netmap_kring *kring = &NMR(na, t)[i]; u_int j; for (j = 0; j < kring->n_monitors; j++) { struct netmap_kring *mkring = kring->monitors[j]; struct netmap_monitor_adapter *mna = (struct netmap_monitor_adapter *)mkring->na; /* forget about this adapter */ mna->priv.np_na = NULL; } } } }