cvs commit: src/sys/conf options src/sys/netinet ip_output.c
Bosko Milekic
bmilekic at unixdaemons.com
Thu Mar 27 08:44:08 PST 2003
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 at unixdaemons.com
bmilekic at FreeBSD.org
More information about the cvs-src
mailing list