Date: Wed, 18 Feb 2009 18:27:48 +0000 (UTC) From: Doug Rabson <dfr@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r188754 - user/dfr/xenhvm/7/sys/dev/xen/netfront Message-ID: <200902181827.n1IIRmJA071293@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dfr Date: Wed Feb 18 18:27:48 2009 New Revision: 188754 URL: http://svn.freebsd.org/changeset/base/188754 Log: Eliminate the data copy on transmit and start getting ready to support TSO. Modified: user/dfr/xenhvm/7/sys/dev/xen/netfront/netfront.c Modified: user/dfr/xenhvm/7/sys/dev/xen/netfront/netfront.c ============================================================================== --- user/dfr/xenhvm/7/sys/dev/xen/netfront/netfront.c Wed Feb 18 18:25:16 2009 (r188753) +++ user/dfr/xenhvm/7/sys/dev/xen/netfront/netfront.c Wed Feb 18 18:27:48 2009 (r188754) @@ -95,6 +95,7 @@ static const int MODPARM_rx_copy = 1; static const int MODPARM_rx_flip = 0; #endif +#define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2) #define RX_COPY_THRESHOLD 256 #define net_ratelimit() 0 @@ -339,28 +340,6 @@ xennet_get_rx_ref(struct netfront_info * #define DPRINTK(fmt, args...) #endif -static __inline struct mbuf* -makembuf (struct mbuf *buf) -{ - struct mbuf *m = NULL; - - MGETHDR (m, M_DONTWAIT, MT_DATA); - - if (! m) - return 0; - - M_MOVE_PKTHDR(m, buf); - - m_cljget(m, M_DONTWAIT, MJUMPAGESIZE); - m->m_pkthdr.len = buf->m_pkthdr.len; - m->m_len = buf->m_len; - m_copydata(buf, 0, buf->m_pkthdr.len, mtod(m,caddr_t) ); - - m->m_ext.ext_args = (caddr_t *)(uintptr_t)(vtophys(mtod(m,caddr_t)) >> PAGE_SHIFT); - - return m; -} - /** * Read the 'mac' node at the given device's node in the store, and parse that * as colon-separated octets, placing result the given mac array. mac must be @@ -500,7 +479,7 @@ talk_to_backend(device_t dev, struct net message = "writing feature-sg"; goto abort_transaction; } -#ifdef HAVE_TSO +#if __FreeBSD_version >= 700000 err = xenbus_printf(xbt, node, "feature-gso-tcpv4", "%d", 1); if (err) { message = "writing feature-gso-tcpv4"; @@ -1007,7 +986,12 @@ xn_txeof(struct netfront_info *np) id = RING_GET_RESPONSE(&np->tx, i)->id; m = np->xn_cdata.xn_tx_chain[id]; - ifp->if_opackets++; + /* + * Increment packet count if this is the last + * mbuf of the chain. + */ + if (!m->m_next) + ifp->if_opackets++; KASSERT(m != NULL, ("mbuf not found in xn_tx_chain")); M_ASSERTVALID(m); if (unlikely(gnttab_query_foreign_access( @@ -1025,7 +1009,7 @@ xn_txeof(struct netfront_info *np) np->xn_cdata.xn_tx_chain[id] = NULL; add_id_to_freelist(np->xn_cdata.xn_tx_chain, id); - m_freem(m); + m_free(m); } np->tx.rsp_cons = prod; @@ -1320,13 +1304,14 @@ xn_start_locked(struct ifnet *ifp) { int otherend_id; unsigned short id; - struct mbuf *m_head, *new_m; + struct mbuf *m_head, *m; struct netfront_info *sc; netif_tx_request_t *tx; + netif_extra_info_t *extra; RING_IDX i; grant_ref_t ref; u_long mfn, tx_bytes; - int notify; + int notify, nfrags; sc = ifp->if_softc; otherend_id = xenbus_get_otherend_id(sc->xbdev); @@ -1346,36 +1331,95 @@ xn_start_locked(struct ifnet *ifp) break; } - id = get_id_from_freelist(sc->xn_cdata.xn_tx_chain); + + /* + * Defragment the mbuf if necessary. + */ + for (m = m_head, nfrags = 0; m; m = m->m_next) + nfrags++; + if (nfrags > MAX_SKB_FRAGS) { + m = m_defrag(m_head, M_DONTWAIT); + if (!m) { + m_freem(m_head); + break; + } + m_head = m; + } /* * Start packing the mbufs in this chain into * the fragment pointers. Stop when we run out * of fragments or hit the end of the mbuf chain. */ - new_m = makembuf(m_head); - tx = RING_GET_REQUEST(&sc->tx, i); - tx->id = id; - ref = gnttab_claim_grant_reference(&sc->gref_tx_head); - KASSERT((short)ref >= 0, ("Negative ref")); - mfn = virt_to_mfn(mtod(new_m, vm_offset_t)); - gnttab_grant_foreign_access_ref(ref, otherend_id, - mfn, GNTMAP_readonly); - tx->gref = sc->grant_tx_ref[id] = ref; - tx->size = new_m->m_pkthdr.len; - if (new_m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) - tx->flags = NETTXF_csum_blank | NETTXF_data_validated; - else + m = m_head; + extra = NULL; + for (m = m_head; m; m = m->m_next) { + tx = RING_GET_REQUEST(&sc->tx, i); + id = get_id_from_freelist(sc->xn_cdata.xn_tx_chain); + sc->xn_cdata.xn_tx_chain[id] = m; + tx->id = id; + ref = gnttab_claim_grant_reference(&sc->gref_tx_head); + KASSERT((short)ref >= 0, ("Negative ref")); + mfn = virt_to_mfn(mtod(m, vm_offset_t)); + gnttab_grant_foreign_access_ref(ref, otherend_id, + mfn, GNTMAP_readonly); + tx->gref = sc->grant_tx_ref[id] = ref; + tx->offset = mtod(m, vm_offset_t) & (PAGE_SIZE - 1); tx->flags = 0; - new_m->m_next = NULL; - new_m->m_nextpkt = NULL; + if (m == m_head) { + /* + * The first fragment has the entire packet + * size, subsequent fragments have just the + * fragment size. The backend works out the + * true size of the first fragment by + * subtracting the sizes of the other + * fragments. + */ + tx->size = m->m_pkthdr.len; - m_freem(m_head); + /* + * The first fragment contains the + * checksum flags and is optionally + * followed by extra data for TSO etc. + */ + if (m->m_pkthdr.csum_flags + & CSUM_DELAY_DATA) { + tx->flags |= (NETTXF_csum_blank + | NETTXF_data_validated); + } +#if __FreeBSD_version >= 700000 + if (m->m_pkthdr.csum_flags & CSUM_TSO) { + struct netif_extra_info *gso = + (struct netif_extra_info *) + RING_GET_REQUEST(&sc->tx, ++i); + + if (extra) + extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE; + else + tx->flags |= NETTXF_extra_info; + + gso->u.gso.size = m->m_pkthdr.len; + gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4; + gso->u.gso.pad = 0; + gso->u.gso.features = 0; + + gso->type = XEN_NETIF_EXTRA_TYPE_GSO; + gso->flags = 0; + extra = gso; + } +#endif + } else { + tx->size = m->m_len; + } + if (m->m_next) { + tx->flags |= NETTXF_more_data; + i++; + } + } - sc->xn_cdata.xn_tx_chain[id] = new_m; - BPF_MTAP(ifp, new_m); + BPF_MTAP(ifp, m_head); - sc->stats.tx_bytes += new_m->m_pkthdr.len; + sc->stats.tx_bytes += m_head->m_pkthdr.len; sc->stats.tx_packets++; } @@ -1518,11 +1562,14 @@ xn_ioctl(struct ifnet *ifp, u_long cmd, case SIOCSIFCAP: mask = ifr->ifr_reqcap ^ ifp->if_capenable; if (mask & IFCAP_HWCSUM) { - if (IFCAP_HWCSUM & ifp->if_capenable) - ifp->if_capenable &= ~IFCAP_HWCSUM; - else - ifp->if_capenable |= IFCAP_HWCSUM; + ifp->if_capenable ^= IFCAP_HWCSUM; } +#if __FreeBSD_version >= 700000 + if (mask & IFCAP_TSO4) { + ifp->if_capenable ^= IFCAP_TSO4; + /* XXX inform backend? */ + } +#endif error = 0; break; case SIOCADDMULTI: @@ -1733,6 +1780,9 @@ create_netdev(device_t dev) ifp->if_hwassist = XN_CSUM_FEATURES; ifp->if_capabilities = IFCAP_HWCSUM; +#if __FreeBSD_version >= 700000 + //ifp->if_capabilities |= IFCAP_TSO4; +#endif ifp->if_capenable = ifp->if_capabilities; ether_ifattach(ifp, np->mac);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902181827.n1IIRmJA071293>