static void netmap_read(evutil_socket_t fd, short event, void *data) { char *buf; int err, i, pkts, rx_rings; struct netmap_if *ifp; struct netmap_ring *nring; struct nm_if *nmif; nmif = (struct nm_if *)data; ifp = nmif->nm_if_ifp; rx_rings = ifp->ni_rx_rings; if (!nohostring && !nmif->nm_if_vale) rx_rings++; pkts = 0; for (i = 0; i < rx_rings; i++) { nring = NETMAP_RXRING(ifp, i); while (!nm_ring_empty(nring)) { buf = NETMAP_GET_BUF(nring); err = ether_input(nmif, i, buf, NETMAP_SLOT_LEN(nring)); /* Send the packet to hw <-> host bridge. */ if (!nohostring && err == 1) err = ether_bridge(nmif, i, buf, NETMAP_SLOT_LEN(nring)); NETMAP_RING_NEXT(nring); if (err < 0 || ++pkts == burst) goto done; } } done: if_netmap_txsync(); }
static void if_netmap_send(void *arg) { struct mbuf *m; struct if_netmap_softc *sc = (struct if_netmap_softc *)arg; struct ifnet *ifp = sc->ifp; struct uhi_pollfd pfd; uint32_t avail; uint32_t cur; u_int pktlen; int rv; int done; int pkts_sent; if (sc->cfg->cpu >= 0) sched_bind(sc->tx_thread.thr, sc->cfg->cpu); rv = if_netmap_txsync(sc->nm_host_ctx, NULL, NULL); if (rv == -1) { printf("could not sync tx descriptors before transmit\n"); } avail = if_netmap_txavail(sc->nm_host_ctx); sc->tx_thread.last_stop_check = ticks; done = 0; pkts_sent = 0; do { mtx_lock(&sc->tx_lock); sc->tx_pkts_to_send -= pkts_sent; while ((sc->tx_pkts_to_send == 0) && !done) if (EWOULDBLOCK == cv_timedwait(&sc->tx_cv, &sc->tx_lock, sc->stop_check_ticks)) done = if_netmap_stoppable_thread_check(&sc->tx_thread); mtx_unlock(&sc->tx_lock); if (done) break; pkts_sent = 0; IFQ_DRV_DEQUEUE(&ifp->if_snd, m); while (m) { while (0 == avail && !done) { memset(&pfd, 0, sizeof(pfd)); pfd.fd = sc->fd; pfd.events = UHI_POLLOUT; rv = uhi_poll(&pfd, 1, IF_NETMAP_THREAD_STOP_CHECK_MS); if (rv == 0) done = if_netmap_stoppable_thread_check(&sc->tx_thread); else if (rv == -1) printf("error from poll for transmit\n"); avail = if_netmap_txavail(sc->nm_host_ctx); } if (ticks - sc->tx_thread.last_stop_check >= sc->stop_check_ticks) done = if_netmap_stoppable_thread_check(&sc->tx_thread); if (done) break; cur = if_netmap_txcur(sc->nm_host_ctx); while (m && avail) { ifp->if_ocopies++; ifp->if_opackets++; avail--; pkts_sent++; pktlen = m_length(m, NULL); m_copydata(m, 0, pktlen, if_netmap_txslot(sc->nm_host_ctx, &cur, pktlen)); m_freem(m); IFQ_DRV_DEQUEUE(&ifp->if_snd, m); } rv = if_netmap_txsync(sc->nm_host_ctx, &avail, &cur); if (rv == -1) { printf("could not sync tx descriptors after transmit\n"); } avail = if_netmap_txavail(sc->nm_host_ctx); } } while (!done); if_netmap_stoppable_thread_done(&sc->tx_thread); }