* imported m_collapse()
* added an expected header dependency in rman.h git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28466 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -114,6 +114,7 @@ void m_move_pkthdr(struct mbuf *, struct mbuf *);
|
||||
u_int m_length(struct mbuf *m, struct mbuf **last);
|
||||
u_int m_fixhdr(struct mbuf *m);
|
||||
void m_cat(struct mbuf *m, struct mbuf *n);
|
||||
struct mbuf *m_collapse(struct mbuf *m, int how, int maxfrags);
|
||||
void m_copydata(const struct mbuf *m, int off, int len, caddr_t cp);
|
||||
|
||||
struct ifnet;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
|
||||
#define RF_ACTIVE 0x0002
|
||||
|
||||
@@ -520,3 +520,89 @@ m_copyback(struct mbuf *m0, int off, int len, caddr_t cp)
|
||||
out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
|
||||
m->m_pkthdr.len = totlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Defragment an mbuf chain, returning at most maxfrags separate
|
||||
* mbufs+clusters. If this is not possible NULL is returned and
|
||||
* the original mbuf chain is left in it's present (potentially
|
||||
* modified) state. We use two techniques: collapsing consecutive
|
||||
* mbufs and replacing consecutive mbufs by a cluster.
|
||||
*
|
||||
* NB: this should really be named m_defrag but that name is taken
|
||||
*/
|
||||
struct mbuf *
|
||||
m_collapse(struct mbuf *m0, int how, int maxfrags)
|
||||
{
|
||||
struct mbuf *m, *n, *n2, **prev;
|
||||
u_int curfrags;
|
||||
|
||||
/*
|
||||
* Calculate the current number of frags.
|
||||
*/
|
||||
curfrags = 0;
|
||||
for (m = m0; m != NULL; m = m->m_next)
|
||||
curfrags++;
|
||||
/*
|
||||
* First, try to collapse mbufs. Note that we always collapse
|
||||
* towards the front so we don't need to deal with moving the
|
||||
* pkthdr. This may be suboptimal if the first mbuf has much
|
||||
* less data than the following.
|
||||
*/
|
||||
m = m0;
|
||||
again:
|
||||
for (;;) {
|
||||
n = m->m_next;
|
||||
if (n == NULL)
|
||||
break;
|
||||
if ((m->m_flags & M_RDONLY) == 0 &&
|
||||
n->m_len < M_TRAILINGSPACE(m)) {
|
||||
bcopy(mtod(n, void *), mtod(m, char *) + m->m_len,
|
||||
n->m_len);
|
||||
m->m_len += n->m_len;
|
||||
m->m_next = n->m_next;
|
||||
m_free(n);
|
||||
if (--curfrags <= maxfrags)
|
||||
return m0;
|
||||
} else
|
||||
m = n;
|
||||
}
|
||||
KASSERT(maxfrags > 1,
|
||||
("maxfrags %u, but normal collapse failed", maxfrags));
|
||||
/*
|
||||
* Collapse consecutive mbufs to a cluster.
|
||||
*/
|
||||
prev = &m0->m_next; /* NB: not the first mbuf */
|
||||
while ((n = *prev) != NULL) {
|
||||
if ((n2 = n->m_next) != NULL &&
|
||||
n->m_len + n2->m_len < MCLBYTES) {
|
||||
m = m_getcl(how, MT_DATA, 0);
|
||||
if (m == NULL)
|
||||
goto bad;
|
||||
bcopy(mtod(n, void *), mtod(m, void *), n->m_len);
|
||||
bcopy(mtod(n2, void *), mtod(m, char *) + n->m_len,
|
||||
n2->m_len);
|
||||
m->m_len = n->m_len + n2->m_len;
|
||||
m->m_next = n2->m_next;
|
||||
*prev = m;
|
||||
m_free(n);
|
||||
m_free(n2);
|
||||
if (--curfrags <= maxfrags) /* +1 cl -2 mbufs */
|
||||
return m0;
|
||||
/*
|
||||
* Still not there, try the normal collapse
|
||||
* again before we allocate another cluster.
|
||||
*/
|
||||
goto again;
|
||||
}
|
||||
prev = &n->m_next;
|
||||
}
|
||||
/*
|
||||
* No place where we can collapse to a cluster; punt.
|
||||
* This can occur if, for example, you request 2 frags
|
||||
* but the packet requires that both be clusters (we
|
||||
* never reallocate the first mbuf to avoid moving the
|
||||
* packet header).
|
||||
*/
|
||||
bad:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user