cvs commit: src/sys/conf options src/sys/netinet ip_output.c
Mike Silbersack
silby at silby.com
Thu Mar 27 07:40:42 PST 2003
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
-------------- next part --------------
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);
More information about the cvs-src
mailing list