Date: Thu, 27 Mar 2003 11:44:02 -0500 From: Bosko Milekic <bmilekic@unixdaemons.com> To: Mike Silbersack <silby@silby.com> Cc: cvs-all@freebsd.org Subject: Re: cvs commit: src/sys/conf options src/sys/netinet ip_output.c Message-ID: <20030327164402.GA15454@unixdaemons.com> In-Reply-To: <20030327013224.P7674@odysseus.silby.com> References: <200303260452.h2Q4quap015364@www.ambrisko.com> <20030326114030.U2075@odysseus.silby.com> <20030326183351.GJ57674@elvis.mu.org> <20030326130903.G2075@odysseus.silby.com> <20030327013224.P7674@odysseus.silby.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Can you please still use m_gethdr() or m_getcl() to do the allocations in the defragment function? Similarly, for > MCLBYTES, use m_getm(). Don't roll your own. On Thu, Mar 27, 2003 at 01:36:38AM -0600, Mike Silbersack wrote: > > Ok, I think I have m_defrag in a working state, please review. > > Changes from last time: > > - It supports infinitely long chains. > - It has a "goal" argument which is supposed to be a hint to tell m_defrag > how long the chain can be. It is currently ignored; someone may want to > honor this later for optimization purposes. > - I fixed up the error case in if_xl, it only runs if needed now > > At the top of the if_loop and if_xl patches are debugging code I used to > make it was working right, they're certainly not going in. > > m_defrag should be totally free of debug code. > > Dig in! > > Mike "Silby" Silbersack > diff -u -r /usr/src/sys.old/kern/uipc_mbuf.c /usr/src/sys/kern/uipc_mbuf.c > --- /usr/src/sys.old/kern/uipc_mbuf.c Tue Mar 25 19:51:44 2003 > +++ /usr/src/sys/kern/uipc_mbuf.c Thu Mar 27 01:32:36 2003 > @@ -52,6 +52,7 @@ > int max_protohdr; > int max_hdr; > int max_datalen; > +int m_defragcount; > > /* > * sysctl(8) exported objects > @@ -64,6 +65,8 @@ > SYSCTL_INT(_kern_ipc, KIPC_MAX_HDR, max_hdr, CTLFLAG_RW, &max_hdr, 0, ""); > SYSCTL_INT(_kern_ipc, KIPC_MAX_DATALEN, max_datalen, CTLFLAG_RW, > &max_datalen, 0, ""); > +SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragcount, CTLFLAG_RW, > + &m_defragcount, 0, ""); > > /* > * "Move" mbuf pkthdr from "from" to "to". > @@ -777,4 +780,66 @@ > if (last != NULL) > *last = m; > return (len); > +} > + > +/* > + * Defragment a mbuf chain, returning a new mbuf chain which is > + * comprised of some chain =< "goal". Return NULL if mbuf > + * allocation fails, rather than returning the still fragmented > + * chain. If a non-packet header is passed in, the original > + * mbuf (chain?) will be returned unharmed. > + * > + */ > +struct mbuf * > +m_defrag(struct mbuf *m0, int how, int goal) > +{ > + struct mbuf *m_new = NULL, *m_final = NULL; > + int progress = 0, length; > + > + if (!(m0->m_flags & M_PKTHDR)) > + return (m0); > + > + m_final = m_gethdr(how, MT_DATA); > + > + if (m_final == NULL) > + goto nospace; > + > + if (m_dup_pkthdr(m_final, m0, how) == NULL) > + goto nospace; > + > + m_new = m_final; > + > + while (progress < m0->m_pkthdr.len) { > + length = m0->m_pkthdr.len - progress; > + if (length > MCLBYTES) > + length = MCLBYTES; > + > + if (m_new == NULL) > + m_new = m_get(how, MT_DATA); > + > + if (length > MHLEN) { > + MCLGET(m_new, how); > + if ((m_new->m_flags & M_EXT) == 0) > + goto nospace; > + } > + > + m_copydata(m0, progress, length, mtod(m_new, caddr_t)); > + progress += length; > + m_new->m_len = length; > + if (m_new != m_final) > + m_cat(m_final, m_new); > + m_new = NULL; > + } > + m_freem(m0); > + m0 = m_final; > + m_defragcount++; > + return (m0); > +nospace: > + if (m0) > + m_freem(m0); > + if (m_new) > + m_free(m_new); > + if (m_final) > + m_freem(m_final); > + return (NULL); > } > diff -u -r /usr/src/sys.old/net/if_loop.c /usr/src/sys/net/if_loop.c > --- /usr/src/sys.old/net/if_loop.c Tue Mar 25 19:51:02 2003 > +++ /usr/src/sys/net/if_loop.c Thu Mar 27 01:37:45 2003 > @@ -192,6 +192,27 @@ > struct sockaddr *dst; > register struct rtentry *rt; > { > + struct mbuf *m_temp; > + int before = 0, after = 0; > + int lbefore = 0, lafter = 0; > + > + > + for (m_temp = m; m_temp != NULL; m_temp = m_temp->m_next) { > + lbefore += m_temp->m_len; > + before++; > + } > + > + if (before > 20) > + m = m_defrag(m, M_DONTWAIT, 1); > + > + for (m_temp = m; m_temp != NULL; m_temp = m_temp->m_next) { > + lafter += m_temp->m_len; > + after++; > + } > + > + if (before != after) > + printf("before: %i (%i) after: %i (%i)\n", before, lbefore, after, lafter); > + > if ((m->m_flags & M_PKTHDR) == 0) > panic("looutput no HDR"); > > diff -u -r /usr/src/sys.old/pci/if_xl.c /usr/src/sys/pci/if_xl.c > --- /usr/src/sys.old/pci/if_xl.c Tue Mar 25 19:50:52 2003 > +++ /usr/src/sys/pci/if_xl.c Thu Mar 27 01:01:02 2003 > @@ -2412,9 +2412,27 @@ > struct xl_chain *c; > struct mbuf *m_head; > { > - struct xl_frag *f = NULL; > int error; > - u_int32_t baddr, status; > + u_int32_t status; > + struct mbuf *m_temp; > + int lbefore = 0, lafter = 0; > + int before = 0, after = 0; > + > + for (m_temp = m_head; m_temp != NULL; m_temp = m_temp->m_next) { > + lbefore += m_temp->m_len; > + before++; > + } > + > + if (before > 5) > + m_head = m_defrag(m_head, M_DONTWAIT, 1); > + > + for (m_temp = m_head; m_temp != NULL; m_temp = m_temp->m_next) { > + lafter += m_temp->m_len; > + after++; > + } > + > + if (before != after) > + printf("before: %i (%i) after: %i (%i)\n", before, lbefore, after, lafter); > > /* > * Start packing the mbufs in this chain into > @@ -2439,35 +2457,21 @@ > * and would waste cycles. > */ > if (error) { > - struct mbuf *m_new; > + m_head = m_defrag(m_head, M_DONTWAIT, XL_MAXFRAGS); > > - m_new = m_head->m_pkthdr.len > MHLEN ? > - m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR) : > - m_gethdr(M_DONTWAIT, MT_DATA); > - if (m_new == NULL) { > - m_freem(m_head); > + if (m_head == NULL) { > printf("xl%d: no memory for tx list\n", sc->xl_unit); > return(1); > } > - m_copydata(m_head, 0, m_head->m_pkthdr.len, > - mtod(m_new, caddr_t)); > - m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len; > - m_freem(m_head); > - m_head = m_new; > - f = &c->xl_ptr->xl_frag[0]; > - error = bus_dmamap_load(sc->xl_mtag, c->xl_map, > - mtod(m_new, void *), MCLBYTES, xl_dma_map_addr, > - &baddr, 0); > + > + error = bus_dmamap_load_mbuf(sc->xl_mtag, c->xl_map, > + m_head, xl_dma_map_txbuf, c->xl_ptr, 0); > if (error) { > - m_freem(m_new); > + m_freem(m_head); > printf("xl%d: can't map mbuf (error %d)\n", > sc->xl_unit, error); > return(1); > } > - f->xl_addr = htole32(baddr); > - f->xl_len = htole32(m_new->m_len | XL_LAST_FRAG); > - c->xl_ptr->xl_status = htole32(m_new->m_len); > - c->xl_ptr->xl_next = 0; > } > > if (sc->xl_type == XL_TYPE_905B) { > diff -u -r /usr/src/sys.old/pci/if_xlreg.h /usr/src/sys/pci/if_xlreg.h > --- /usr/src/sys.old/pci/if_xlreg.h Tue Mar 25 19:50:52 2003 > +++ /usr/src/sys/pci/if_xlreg.h Tue Mar 25 21:28:53 2003 > @@ -420,7 +420,7 @@ > > #define XL_LAST_FRAG 0x80000000 > > -#define XL_MAXFRAGS 63 > +#define XL_MAXFRAGS 10 > #define XL_RX_LIST_CNT 128 > #define XL_TX_LIST_CNT 256 > #define XL_RX_LIST_SZ XL_RX_LIST_CNT * sizeof(struct xl_list_onefrag) > diff -u -r /usr/src/sys.old/sys/mbuf.h /usr/src/sys/sys/mbuf.h > --- /usr/src/sys.old/sys/mbuf.h Tue Mar 25 19:50:46 2003 > +++ /usr/src/sys/sys/mbuf.h Wed Mar 26 19:59:26 2003 > @@ -430,6 +430,7 @@ > struct mbuf *m_copym(struct mbuf *, int, int, int); > struct mbuf *m_copypacket(struct mbuf *, int); > void m_copy_pkthdr(struct mbuf *, struct mbuf *); > +struct mbuf *m_defrag(struct mbuf *, int, int); > struct mbuf *m_devget(char *, int, int, struct ifnet *, > void (*)(char *, caddr_t, u_int)); > struct mbuf *m_dup(struct mbuf *, int); -- Bosko Milekic bmilekic@unixdaemons.com bmilekic@FreeBSD.org
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030327164402.GA15454>