/* 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; } } }
/* nm_krings_create callbacks for monitors. */ static int netmap_monitor_krings_create(struct netmap_adapter *na) { 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_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); }
/* 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, but they may be hidden. */ 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; if (pna->peer_ref) { int i; /* case 1) above */ D("%p: case 1, create everything", na); error = netmap_krings_create(na, 0); if (error) goto err; /* we also create all the rings, since we need to * update the save_ring pointers. * netmap_mem_rings_create (called by our caller) * will not create the rings again */ error = netmap_mem_rings_create(na); if (error) goto del_krings1; /* update our hidden ring pointers */ for (i = 0; i < na->num_tx_rings + 1; i++) na->tx_rings[i].save_ring = na->tx_rings[i].ring; for (i = 0; i < na->num_rx_rings + 1; i++) na->rx_rings[i].save_ring = na->rx_rings[i].ring; /* now, create krings and rings of the other end */ error = netmap_krings_create(ona, 0); if (error) goto del_rings1; error = netmap_mem_rings_create(ona); if (error) goto del_krings2; for (i = 0; i < ona->num_tx_rings + 1; i++) ona->tx_rings[i].save_ring = ona->tx_rings[i].ring; for (i = 0; i < ona->num_rx_rings + 1; i++) ona->rx_rings[i].save_ring = ona->rx_rings[i].ring; /* cross link the krings */ for (i = 0; i < na->num_tx_rings; i++) { na->tx_rings[i].pipe = pna->peer->up.rx_rings + i; na->rx_rings[i].pipe = pna->peer->up.tx_rings + i; pna->peer->up.tx_rings[i].pipe = na->rx_rings + i; pna->peer->up.rx_rings[i].pipe = na->tx_rings + i; } } else { int i; /* case 2) above */ /* recover the hidden rings */ ND("%p: case 2, hidden rings", na); for (i = 0; i < na->num_tx_rings + 1; i++) na->tx_rings[i].ring = na->tx_rings[i].save_ring; for (i = 0; i < na->num_rx_rings + 1; i++) na->rx_rings[i].ring = na->rx_rings[i].save_ring; } return 0; del_krings2: netmap_krings_delete(ona); del_rings1: netmap_mem_rings_delete(na); del_krings1: netmap_krings_delete(na); err: return error; }