#define KIPC_MAX_LINKHDR 4/* int: max length of link header (see sys/sysclt.h) */ #define KIPC_MAX_PROTOHDR 5/* int: max length of network header (see sys/sysclt.h)*/ int max_linkhdr = KIPC_MAX_LINKHDR; int max_protohdr = KIPC_MAX_PROTOHDR; /* Size of largest protocol layer header. */
/* __Userspace__ clust_mb_args will be passed as callback data to mb_ctor_clust *andmb_dtor_clust. *Note:Ihadtousestructclust_argsasanencapsulationforanmbufpointer. *structmbuf*clust_mb_args;doesnotwork.
*/ struct clust_args clust_mb_args;
/* The following setter function is not yet being enclosed within *#ifUSING_MBUF_CONSTRUCTOR-#endif,untilIhavethoroughlytested *mb_dtor_mbuf.Seecommentthere
*/
mbuf_mb_args.flags = 0;
mbuf_mb_args.type = type; #endif /* Mbuf master zone, zone_mbuf, has already been
* created in mbuf_initialize() */
mret = SCTP_ZONE_GET(zone_mbuf, struct mbuf); #ifdefined(SCTP_SIMPLE_ALLOCATOR)
mb_ctor_mbuf(mret, &mbuf_mb_args, 0); #endif /*mret = ((struct mbuf *)umem_cache_alloc(zone_mbuf, UMEM_DEFAULT));*/
/* There are cases when an object available in the current CPU's *loadedmagazineandinthosecasestheobject'sconstructorisnotapplied. *Ifthatisthecase,thenweareduplicatingconstructorinitializationhere, *sothatthembufisproperlyconstructedbeforereturningit.
*/ if (mret) { #if USING_MBUF_CONSTRUCTOR if (! (mret->m_type == type) ) {
mbuf_constructor_dup(mret, 0, type);
} #else
mbuf_constructor_dup(mret, 0, type); #endif
/* The following setter function is not yet being enclosed within *#ifUSING_MBUF_CONSTRUCTOR-#endif,untilIhavethoroughlytested *mb_dtor_mbuf.Seecommentthere
*/
mbuf_mb_args.flags = M_PKTHDR;
mbuf_mb_args.type = type; #endif
mret = SCTP_ZONE_GET(zone_mbuf, struct mbuf); #ifdefined(SCTP_SIMPLE_ALLOCATOR)
mb_ctor_mbuf(mret, &mbuf_mb_args, 0); #endif /*mret = ((struct mbuf *)umem_cache_alloc(zone_mbuf, UMEM_DEFAULT));*/ /* There are cases when an object available in the current CPU's *loadedmagazineandinthosecasestheobject'sconstructorisnotapplied. *Ifthatisthecase,thenweareduplicatingconstructorinitializationhere, *sothatthembufisproperlyconstructedbeforereturningit.
*/ if (mret) { #if USING_MBUF_CONSTRUCTOR if (! ((mret->m_flags & M_PKTHDR) && (mret->m_type == type)) ) {
mbuf_constructor_dup(mret, M_PKTHDR, type);
} #else
mbuf_constructor_dup(mret, M_PKTHDR, type); #endif
} return mret;
}
/* Book keeping. */
len -= size; if (mtail != NULL)
mtail->m_next = mb; else
nm = mb;
mtail = mb;
flags &= ~M_PKTHDR; /* Only valid on the first mbuf. */
} if (flags & M_EOR) {
mtail->m_flags |= M_EOR; /* Only valid on the last mbuf. */
}
/* If mbuf was supplied, append new chain to the end of it. */ if (m != NULL) { for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next);
mtail->m_next = nm;
mtail->m_flags &= ~M_EOR;
} else {
m = nm;
}
return (m);
}
/* *Copythecontentsofuiointoaproperlysizedmbufchain.
*/ struct mbuf *
m_uiotombuf(struct uio *uio, int how, int len, int align, int flags)
{ struct mbuf *m, *mb; int error, length;
ssize_t total; int progress = 0;
/* *lencanbezerooranarbitrarylargevalueboundby *thetotaldatasuppliedbytheuio.
*/ if (len > 0)
total = min(uio->uio_resid, len); else
total = uio->uio_resid; /* *Thesmallestunitreturnedbym_getm2()isasinglembuf *withpkthdr.Wecan'talignpastit.
*/ if (align >= MHLEN) return (NULL); /* *Giveusthefullallocationornothing. *Ifleniszeroreturnthesmallestemptymbuf.
*/
m = m_getm2(NULL, (int)max(total + align, 1), how, MT_DATA, flags, 0); if (m == NULL) return (NULL);
m->m_data += align;
/* Fill all mbufs with uio data and update header information. */ for (mb = m; mb != NULL; mb = mb->m_next) {
length = (int)min(M_TRAILINGSPACE(mb), total - progress);
error = uiomove(mtod(mb, void *), length, uio); if (error) {
m_freem(m); return (NULL);
}
/* mem is of type caddr_t. In sys/types.h we have typedef char * caddr_t; */ /* mb_dtor_clust is called at time of umem_cache_destroy() (the number of times *mb_dtor_clustiscalledisequaltothenumberofindividualmbufsallocated *fromzone_clust.Similarlyformb_dtor_mbuf). *Atthispointthefollowing: *structmbuf*m; *m=(structmbuf*)arg; *assert(*(m->m_ext.ref_cnt)==0);isnotmeaningfulsincem->m_ext.ref_cnt=NULL; *hasbeendoneinmb_free_ext().
*/
}
/* Unlink and free a packet tag. */ void
m_tag_delete(struct mbuf *m, struct m_tag *t)
{
KASSERT(m && t, ("m_tag_delete: null argument, m %p t %p", (void *)m, (void *)t));
m_tag_unlink(m, t);
m_tag_free(t);
}
/* Unlink and free a packet tag chain, starting from given tag. */ void
m_tag_delete_chain(struct mbuf *m, struct m_tag *t)
{
struct m_tag *p, *q;
KASSERT(m, ("m_tag_delete_chain: null mbuf")); if (t != NULL)
p = t; else
p = SLIST_FIRST(&m->m_pkthdr.tags); if (p == NULL) return; while ((q = SLIST_NEXT(p, m_tag_link)) != NULL)
m_tag_delete(m, q);
m_tag_delete(m, p);
}
/* Free the external attached storage if this *mbufistheonlyreferencetoit. *__Userspace__TODO:jumboframes *
*/ /* NOTE: We had the same code that SCTP_DECREMENT_AND_CHECK_REFCOUNT reducestoherebeforebuttheIPHONEmalloccommithadchanged thistocompareto0insteadof1(seenextline).Why? ...thiscausedahugememoryleakinLinux.
*/ #ifdef IPHONE if (atomic_fetchadd_int(m->m_ext.ref_cnt, -1) == 0) #else if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(m->m_ext.ref_cnt)) #endif
{ if (m->m_ext.ext_type == EXT_CLUSTER){ #ifdefined(SCTP_SIMPLE_ALLOCATOR)
mb_dtor_clust(m->m_ext.ext_buf, &clust_mb_args); #endif
SCTP_ZONE_FREE(zone_clust, m->m_ext.ext_buf);
SCTP_ZONE_FREE(zone_ext_refcnt, (u_int*)m->m_ext.ref_cnt);
m->m_ext.ref_cnt = NULL;
}
}
/* Taken from sys/kern/uipc_mbuf2.c */ struct mbuf *
m_pulldown(struct mbuf *m, int off, int len, int *offp)
{ struct mbuf *n, *o; int hlen, tlen, olen; int writable;
#ifdef PULLDOWN_DEBUG
{ struct mbuf *t;
SCTP_DEBUG_USR(SCTP_DEBUG_USR, "before:"); for (t = m; t; t = t->m_next)
SCTP_DEBUG_USR(SCTP_DEBUG_USR, " %d", t->m_len);
SCTP_DEBUG_USR(SCTP_DEBUG_USR, "\n");
} #endif
n = m; while (n != NULL && off > 0) { if (n->m_len > off) break;
off -= n->m_len;
n = n->m_next;
} /* be sure to point non-empty mbuf */ while (n != NULL && n->m_len == 0)
n = n->m_next; if (!n) {
m_freem(m); return NULL; /* mbuf chain too short */
}
/* *thetargetdataison<n,off>. *ifwegotenoughdataonthembuf"n",we'redone.
*/ if ((off == 0 || offp) && len <= n->m_len - off && writable) goto ok;
/* *whenlen<=n->m_len-offandoff!=0,itisaspecialcase. *lenbytesfrom<n,off>sitsinsinglembuf,butthecallerdoes *notlikethestartingposition(off). *chopthecurrentmbufintotwopieces,setoffto0.
*/ if (len <= n->m_len - off) {
o = m_dup1(n, off, n->m_len - off, M_NOWAIT); if (o == NULL) {
m_freem(m); return NULL; /* ENOBUFS */
}
n->m_len = off;
o->m_next = n->m_next;
n->m_next = o;
n = n->m_next;
off = 0; goto ok;
} /* *weneedtotakehlenfrom<n,off>andtlenfrom<n->m_next,0>, *andconstructcontiguousmbufwithm_len==len. *notethathlen+tlen==len,andtlen>0.
*/
hlen = n->m_len - off;
tlen = len - hlen;
/* *ensurethatwehaveenoughtrailingdataonmbufchain. *ifnot,wecandonothingaboutthechain.
*/
olen = 0; for (o = n->m_next; o != NULL; o = o->m_next)
olen += o->m_len; if (hlen + olen < len) {
m_freem(m); return NULL; /* mbuf chain too short */
}
int
m_tag_copy_chain(struct mbuf *to, struct mbuf *from, int how)
{ struct m_tag *p, *t, *tprev = NULL;
KASSERT(to && from, ("m_tag_copy_chain: null argument, to %p from %p", (void *)to, (void *)from));
m_tag_delete_chain(to, NULL);
SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) {
t = m_tag_copy(p, how); if (t == NULL) {
m_tag_delete_chain(to, NULL); return0;
} if (tprev == NULL)
SLIST_INSERT_HEAD(&to->m_pkthdr.tags, t, m_tag_link); else
SLIST_INSERT_AFTER(tprev, t, m_tag_link);
tprev = t;
} return1;
}
/* *Duplicate"from"'smbufpkthdrin"to". *"from"musthaveM_PKTHDRset,and"to"mustbeempty. *Inparticular,thisdoesadeepcopyofthepackettags.
*/ int
m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how)
{
KASSERT(to, ("m_dup_pkthdr: to is NULL"));
KASSERT(from, ("m_dup_pkthdr: from is NULL"));
to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT); if ((to->m_flags & M_EXT) == 0)
to->m_data = to->m_pktdat;
to->m_pkthdr = from->m_pkthdr;
SLIST_INIT(&to->m_pkthdr.tags); return (m_tag_copy_chain(to, from, MBTOM(how)));
}
/* Copy a single tag. */ struct m_tag *
m_tag_copy(struct m_tag *t, int how)
{ struct m_tag *p;
KASSERT(t, ("m_tag_copy: null tag"));
p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, how); if (p == NULL) return (NULL);
memcpy(p + 1, t + 1, t->m_tag_len); /* Copy the data */ return p;
}
/* Get a packet tag structure along with specified data following. */ struct m_tag *
m_tag_alloc(uint32_t cookie, int type, int len, int wait)
{ struct m_tag *t;
if (len < 0) return NULL;
t = malloc(len + sizeof(struct m_tag)); if (t == NULL) return NULL;
m_tag_setup(t, cookie, type, len);
t->m_tag_free = m_tag_free_default; return t;
}
/* *Copydatafromabufferbackintotheindicatedmbufchain, *starting"off"bytesfromthebeginning,extendingthembuf *chainifnecessary.
*/ void
m_copyback(struct mbuf *m0, int off, int len, caddr_t cp)
{ int mlen; struct mbuf *m = m0, *n; int totlen = 0;
if (m0 == NULL) return; while (off > (mlen = m->m_len)) {
off -= mlen;
totlen += mlen; if (m->m_next == NULL) {
n = m_get(M_NOWAIT, m->m_type); if (n == NULL) goto out;
memset(mtod(n, caddr_t), 0, MLEN);
n->m_len = min(MLEN, len + off);
m->m_next = n;
}
m = m->m_next;
} while (len > 0) {
mlen = min (m->m_len - off, len);
memcpy(off + mtod(m, caddr_t), cp, (u_int)mlen);
cp += mlen;
len -= mlen;
mlen += off;
off = 0;
totlen += mlen; if (len == 0) break; if (m->m_next == NULL) {
n = m_get(M_NOWAIT, m->m_type); if (n == NULL) break;
n->m_len = min(MLEN, len);
m->m_next = n;
}
m = m->m_next;
}
out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
m->m_pkthdr.len = totlen;
}
/* *Applyfunctionftothedatainanmbufchainstarting"off"bytesfrom *thebeginning,continuingfor"len"bytes.
*/ int
m_apply(struct mbuf *m, int off, int len, int (*f)(void *, void *, u_int), void *arg)
{
u_int count; int rval;
KASSERT(off >= 0, ("m_apply, negative off %d", off));
KASSERT(len >= 0, ("m_apply, negative len %d", len)); while (off > 0) {
KASSERT(m != NULL, ("m_apply, offset > size of mbuf chain")); if (off < m->m_len) break;
off -= m->m_len;
m = m->m_next;
} while (len > 0) {
KASSERT(m != NULL, ("m_apply, offset > size of mbuf chain"));
count = min(m->m_len - off, len);
rval = (*f)(arg, mtod(m, caddr_t) + off, count); if (rval) return (rval);
len -= count;
off = 0;
m = m->m_next;
} return (0);
}
/* *Lesser-usedpathforM_PREPEND: *allocatenewmbuftoprependtochain, *copyjunkalong.
*/ struct mbuf *
m_prepend(struct mbuf *m, int len, int how)
{ struct mbuf *mn;
if (m->m_flags & M_PKTHDR)
MGETHDR(mn, how, m->m_type); else
MGET(mn, how, m->m_type); if (mn == NULL) {
m_freem(m); return (NULL);
} if (m->m_flags & M_PKTHDR)
M_MOVE_PKTHDR(mn, m);
mn->m_next = m;
m = mn; if (m->m_flags & M_PKTHDR) { if (len < MHLEN)
MH_ALIGN(m, len);
} else { if (len < MLEN)
M_ALIGN(m, len);
}
m->m_len = len; return (m);
}
/* *Copydatafromanmbufchainstarting"off"bytesfromthebeginning, *continuingfor"len"bytes,intotheindicatedbuffer.
*/ void
m_copydata(conststruct mbuf *m, int off, int len, caddr_t cp)
{
u_int count;
KASSERT(off >= 0, ("m_copydata, negative off %d", off));
KASSERT(len >= 0, ("m_copydata, negative len %d", len)); while (off > 0) {
KASSERT(m != NULL, ("m_copydata, offset > size of mbuf chain")); if (off < m->m_len) break;
off -= m->m_len;
m = m->m_next;
} while (len > 0) {
KASSERT(m != NULL, ("m_copydata, length > size of mbuf chain"));
count = min(m->m_len - off, len);
memcpy(cp, mtod(m, caddr_t) + off, count);
len -= count;
cp += count;
off = 0;
m = m->m_next;
}
}
/* *Concatenatembufchainntom. *Bothchainsmustbeofthesametype(e.g.MT_DATA). *Anym_pkthdrisnotupdated.
*/ void
m_cat(struct mbuf *m, struct mbuf *n)
{ while (m->m_next)
m = m->m_next; while (n) { if (m->m_flags & M_EXT ||
m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { /* just join the two chains */
m->m_next = n; return;
} /* splat the data from one into the other */
memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t), (u_int)n->m_len);
m->m_len += n->m_len;
n = m_free(n);
}
}
void
m_adj(struct mbuf *mp, int req_len)
{ int len = req_len; struct mbuf *m; int count;
if ((m = mp) == NULL) return; if (len >= 0) { /* *Trimfromhead.
*/ while (m != NULL && len > 0) { if (m->m_len <= len) {
len -= m->m_len;
m->m_len = 0;
m = m->m_next;
} else {
m->m_len -= len;
m->m_data += len;
len = 0;
}
}
m = mp; if (mp->m_flags & M_PKTHDR)
m->m_pkthdr.len -= (req_len - len);
} else { /* *Trimfromtail.Scanthembufchain, *calculatingitslengthandfindingthelastmbuf. *Iftheadjustmentonlyaffectsthismbuf,thenjust *adjustandreturn.Otherwise,rescanandtruncate *aftertheremainingsize.
*/
len = -len;
count = 0; for (;;) {
count += m->m_len; if (m->m_next == (struct mbuf *)0) break;
m = m->m_next;
} if (m->m_len >= len) {
m->m_len -= len; if (mp->m_flags & M_PKTHDR)
mp->m_pkthdr.len -= len; return;
}
count -= len; if (count < 0)
count = 0; /* *Correctlengthforchainis"count". *Findthembufwithlastdata,adjustitslength, *andtossdatafromremainingmbufsonchain.
*/
m = mp; if (m->m_flags & M_PKTHDR)
m->m_pkthdr.len = count; for (; m; m = m->m_next) { if (m->m_len >= count) {
m->m_len = count; if (m->m_next != NULL) {
m_freem(m->m_next);
m->m_next = NULL;
} break;
}
count -= m->m_len;
}
}
}
/* m_split is used within sctp_handle_cookie_echo. */
/* *Partitionanmbufchainintwopieces,returningthetail-- *allbutthefirstlen0bytes.Incaseoffailure,itreturnsNULLand *attemptstorestorethechaintoitsoriginalstate. * *Notethattheresultingmbufsmightberead-only,becausethenew *mbufcanendupsharinganmbufclusterwiththeoriginalmbufif *the"breakingpoint"happenstoliewithinaclustermbuf.Usethe *M_WRITABLE()macrotocheckforthiscase.
*/ struct mbuf *
m_split(struct mbuf *m0, int len0, int wait)
{ struct mbuf *m, *n;
u_int len = len0, remain;
/* MBUF_CHECKSLEEP(wait); */ for (m = m0; m && (int)len > m->m_len; m = m->m_next)
len -= m->m_len; if (m == NULL) return (NULL);
remain = m->m_len - len; if (m0->m_flags & M_PKTHDR) {
MGETHDR(n, wait, m0->m_type); if (n == NULL) return (NULL);
n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
n->m_pkthdr.len = m0->m_pkthdr.len - len0;
m0->m_pkthdr.len = len0; if (m->m_flags & M_EXT) goto extpacket; if (remain > MHLEN) { /* m can't be the lead packet */
MH_ALIGN(n, 0);
n->m_next = m_split(m, len, wait); if (n->m_next == NULL) {
(void) m_free(n); return (NULL);
} else {
n->m_len = 0; return (n);
}
} else
MH_ALIGN(n, remain);
} elseif (remain == 0) {
n = m->m_next;
m->m_next = NULL; return (n);
} else {
MGET(n, wait, m->m_type); if (n == NULL) return (NULL);
M_ALIGN(n, remain);
}
extpacket: if (m->m_flags & M_EXT) {
n->m_data = m->m_data + len;
mb_dupcl(n, m);
} else {
memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + len, remain);
}
n->m_len = remain;
m->m_len = len;
n->m_next = m->m_next;
m->m_next = NULL; return (n);
}
int
pack_send_buffer(caddr_t buffer, struct mbuf* mb){
int count_to_copy; int total_count_copied = 0; int offset = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.