diff --git a/sys/dev/virtual/vkernel/net/if_vke.c b/sys/dev/virtual/vkernel/net/if_vke.c index c09b36d..f74d5fe 100644 --- a/sys/dev/virtual/vkernel/net/if_vke.c +++ b/sys/dev/virtual/vkernel/net/if_vke.c @@ -66,16 +66,14 @@ #define VKE_CHUNK 8 /* number of mbufs to queue before interrupting */ -#define NETFIFOSIZE 256 -#define NETFIFOMASK (NETFIFOSIZE -1) -#define NETFIFOINDEX(u) ((u) & NETFIFOMASK) +#define NETFIFOINDEX(u, sc) ((u) & ((sc)->sc_ringsize - 1)) #define VKE_COTD_RUN 0 #define VKE_COTD_EXIT 1 #define VKE_COTD_DEAD 2 struct vke_fifo { - struct mbuf *array[NETFIFOSIZE]; + struct mbuf **array; int rindex; int windex; }; @@ -99,6 +97,8 @@ struct vke_softc { fifo_t sc_txfifo_done; fifo_t sc_rxfifo; + int sc_ringsize; + long cotd_ipackets; long cotd_oerrors; long cotd_opackets; @@ -157,11 +157,11 @@ vke_txfifo_done_enqueue(struct vke_softc *sc, struct mbuf *m) { fifo_t fifo = sc->sc_txfifo_done; - while (NETFIFOINDEX(fifo->windex + 1) == NETFIFOINDEX(fifo->rindex)) { + while (NETFIFOINDEX(fifo->windex + 1, sc) == NETFIFOINDEX(fifo->rindex, sc)) { usleep(20000); } - fifo->array[NETFIFOINDEX(fifo->windex)] = m; + fifo->array[NETFIFOINDEX(fifo->windex, sc)] = m; cpu_sfence(); ++fifo->windex; return (0); @@ -176,11 +176,11 @@ vke_txfifo_done_dequeue(struct vke_softc *sc, struct mbuf *nm) fifo_t fifo = sc->sc_txfifo_done; struct mbuf *m; - if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + if (NETFIFOINDEX(fifo->rindex, sc) == NETFIFOINDEX(fifo->windex, sc)) return (NULL); - m = fifo->array[NETFIFOINDEX(fifo->rindex)]; - fifo->array[NETFIFOINDEX(fifo->rindex)] = nm; + m = fifo->array[NETFIFOINDEX(fifo->rindex, sc)]; + fifo->array[NETFIFOINDEX(fifo->rindex, sc)] = nm; cpu_lfence(); ++fifo->rindex; return (m); @@ -194,10 +194,10 @@ vke_txfifo_enqueue(struct vke_softc *sc, struct mbuf *m) { fifo_t fifo = sc->sc_txfifo; - if (NETFIFOINDEX(fifo->windex + 1) == NETFIFOINDEX(fifo->rindex)) + if (NETFIFOINDEX(fifo->windex + 1, sc) == NETFIFOINDEX(fifo->rindex, sc)) return (-1); - fifo->array[NETFIFOINDEX(fifo->windex)] = m; + fifo->array[NETFIFOINDEX(fifo->windex, sc)] = m; cpu_sfence(); ++fifo->windex; @@ -214,11 +214,11 @@ vke_txfifo_dequeue(struct vke_softc *sc) fifo_t fifo = sc->sc_txfifo; struct mbuf *m; - if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + if (NETFIFOINDEX(fifo->rindex, sc) == NETFIFOINDEX(fifo->windex, sc)) return (NULL); - m = fifo->array[NETFIFOINDEX(fifo->rindex)]; - fifo->array[NETFIFOINDEX(fifo->rindex)] = NULL; + m = fifo->array[NETFIFOINDEX(fifo->rindex, sc)]; + fifo->array[NETFIFOINDEX(fifo->rindex, sc)] = NULL; cpu_lfence(); ++fifo->rindex; @@ -230,7 +230,7 @@ vke_txfifo_empty(struct vke_softc *sc) { fifo_t fifo = sc->sc_txfifo; - if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + if (NETFIFOINDEX(fifo->rindex, sc) == NETFIFOINDEX(fifo->windex, sc)) return (1); return(0); } @@ -246,11 +246,11 @@ vke_rxfifo_dequeue(struct vke_softc *sc, struct mbuf *newm) fifo_t fifo = sc->sc_rxfifo; struct mbuf *m; - if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + if (NETFIFOINDEX(fifo->rindex, sc) == NETFIFOINDEX(fifo->windex, sc)) return (NULL); - m = fifo->array[NETFIFOINDEX(fifo->rindex)]; - fifo->array[NETFIFOINDEX(fifo->rindex)] = newm; + m = fifo->array[NETFIFOINDEX(fifo->rindex, sc)]; + fifo->array[NETFIFOINDEX(fifo->rindex, sc)] = newm; cpu_lfence(); ++fifo->rindex; return (m); @@ -265,10 +265,10 @@ vke_rxfifo_sniff(struct vke_softc *sc) fifo_t fifo = sc->sc_rxfifo; struct mbuf *m; - if (NETFIFOINDEX(fifo->rindex) == NETFIFOINDEX(fifo->windex)) + if (NETFIFOINDEX(fifo->rindex, sc) == NETFIFOINDEX(fifo->windex, sc)) return (NULL); - m = fifo->array[NETFIFOINDEX(fifo->rindex)]; + m = fifo->array[NETFIFOINDEX(fifo->rindex, sc)]; cpu_lfence(); return (m); } @@ -278,6 +278,7 @@ vke_init(void *xsc) { struct vke_softc *sc = xsc; struct ifnet *ifp = &sc->arpcom.ac_if; + size_t ringsize = sc->sc_ringsize * sizeof(struct mbuf *); int i; ASSERT_SERIALIZED(ifp->if_serializer); @@ -287,11 +288,17 @@ vke_init(void *xsc) ifp->if_flags |= IFF_RUNNING; ifsq_clr_oactive(ifq_get_subq_default(&ifp->if_snd)); + /* + * Allocate memory for FIFO structures and mbufs. + */ sc->sc_txfifo = kmalloc(sizeof(*sc->sc_txfifo), M_DEVBUF, M_WAITOK); sc->sc_txfifo_done = kmalloc(sizeof(*sc->sc_txfifo_done), M_DEVBUF, M_WAITOK); - sc->sc_rxfifo = kmalloc(sizeof(*sc->sc_rxfifo), M_DEVBUF, M_WAITOK); - for (i = 0; i < NETFIFOSIZE; i++) { + sc->sc_txfifo->array = kmalloc(ringsize, M_DEVBUF, M_WAITOK | M_ZERO); + sc->sc_txfifo_done->array = kmalloc(ringsize, M_DEVBUF, M_WAITOK | M_ZERO); + sc->sc_rxfifo->array = kmalloc(ringsize, M_DEVBUF, M_WAITOK | M_ZERO); + + for (i = 0; i < sc->sc_ringsize; i++) { sc->sc_rxfifo->array[i] = m_getcl(MB_WAIT, MT_DATA, M_PKTHDR); sc->sc_txfifo->array[i] = NULL; sc->sc_txfifo_done->array[i] = NULL; @@ -443,7 +450,7 @@ vke_stop(struct vke_softc *sc) cothread_delete(&sc->cotd_rx); } - for (i = 0; i < NETFIFOSIZE; i++) { + for (i = 0; i < sc->sc_ringsize; i++) { if (sc->sc_rxfifo && sc->sc_rxfifo->array[i]) { m_freem(sc->sc_rxfifo->array[i]); sc->sc_rxfifo->array[i] = NULL; @@ -459,16 +466,22 @@ vke_stop(struct vke_softc *sc) } if (sc->sc_txfifo) { + if (sc->sc_txfifo->array) + kfree(sc->sc_txfifo->array, M_DEVBUF); kfree(sc->sc_txfifo, M_DEVBUF); sc->sc_txfifo = NULL; } if (sc->sc_txfifo_done) { + if (sc->sc_txfifo_done->array) + kfree(sc->sc_txfifo_done->array, M_DEVBUF); kfree(sc->sc_txfifo_done, M_DEVBUF); sc->sc_txfifo_done = NULL; } if (sc->sc_rxfifo) { + if (sc->sc_rxfifo->array) + kfree(sc->sc_rxfifo->array, M_DEVBUF); kfree(sc->sc_rxfifo, M_DEVBUF); sc->sc_rxfifo = NULL; } @@ -601,8 +614,8 @@ vke_rx_thread(cothread_t cotd) * Wait for the RX FIFO to be loaded with * empty mbufs. */ - if (NETFIFOINDEX(fifo->windex + 1) == - NETFIFOINDEX(fifo->rindex)) { + if (NETFIFOINDEX(fifo->windex + 1, sc) == + NETFIFOINDEX(fifo->rindex, sc)) { usleep(20000); continue; } @@ -610,7 +623,7 @@ vke_rx_thread(cothread_t cotd) /* * Load data into the rx fifo */ - m = fifo->array[NETFIFOINDEX(fifo->windex)]; + m = fifo->array[NETFIFOINDEX(fifo->windex, sc)]; if (m == NULL) continue; n = read(sc->sc_fd, mtod(m, void *), MCLBYTES); @@ -706,6 +719,7 @@ vke_attach(const struct vknetif_info *info, int unit) struct ifnet *ifp; struct tapinfo tapinfo; uint8_t enaddr[ETHER_ADDR_LEN]; + int nmbufs; int fd; KKASSERT(info->tap_fd >= 0); @@ -754,6 +768,19 @@ havemac: sc->sc_addr = info->netif_addr; sc->sc_mask = info->netif_mask; + /* + * Calculate the number of mbuf clusters we are going to use + * up to 50% of the total mbuf clusters available in the + * system. + * In the case our vkernel has so little mem that it can't + * allocate even VKE_CHUNK for every vke(4) device, just panic. + */ + nmbufs = nmbclusters / (NetifNum * 2); + sc->sc_ringsize = (1 << (fls(nmbufs) - 1)); + + KASSERT(sc->sc_ringsize >= VKE_CHUNK, + ("Not enough mbuf clusters for %d vke devices", NetifNum)); + ifp = &sc->arpcom.ac_if; if_initname(ifp, VKE_DEVNAME, sc->sc_unit); @@ -789,8 +816,8 @@ havemac: if (bootverbose && sc->sc_addr != 0) { if_printf(ifp, "pre-configured " - "address 0x%08x, netmask 0x%08x\n", - ntohl(sc->sc_addr), ntohl(sc->sc_mask)); + "address 0x%08x, netmask 0x%08x, %d mbuf clusters\n", + ntohl(sc->sc_addr), ntohl(sc->sc_mask), sc->sc_ringsize); } return 0;