📄 uipc_mbuf.c
字号:
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; /* * Correct length for chain is "count". * Find the mbuf with last data, adjust its length, * and toss data from remaining mbufs on chain. */ 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; break; } count -= m->m_len; } while ((m = m->m_next)) m->m_len = 0; } }/********************************************************************************* m_pullup - ensure contiguous data area at the beginnig of an mbuf chain** Rearange an mbuf chain so that len bytes are contiguous* and in the data area of an mbuf (so that mtod and dtom* will work for a structure of size len). Returns the resulting* mbuf chain on success, frees it and returns null on failure.*/struct mbuf *m_pullup(n, len) register struct mbuf *n; int len; { register struct mbuf *m; register int count; int space; if (((n->m_data + len) < (n->m_extBuf + n->m_extSize)) && n->m_next) { if (n->m_len >= len) return (n); m = n; n = n->m_next; len -= m->m_len; } else { m = mBufClGet(M_DONTWAIT, n->m_type, len, TRUE); if (m == 0) goto bad; m->m_len = 0; if (n->m_flags & M_PKTHDR) { m->m_pkthdr = n->m_pkthdr; m->m_flags = n->m_flags; n->m_flags &= ~M_PKTHDR; } } space = (m->m_extBuf + m->m_extSize) - (m->m_data + m->m_len); do { count = min(min(max(len, max_protohdr), space), n->m_len); bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, (unsigned)count); len -= count; m->m_len += count; n->m_len -= count; space -= count; if (n->m_len) n->m_data += count; else n = m_free(n); } while (len > 0 && n); if (len > 0) { (void) m_free(m); goto bad; } m->m_next = n; return (m); bad: m_freem(n); MPFail++; return (0); }/********************************************************************************* m_devget - Routine to copy from device local memory into mbufs.** Routine to copy from device local memory into mbufs.* This routine copies the device local memory into mbufs according to the* specified width. The interface pointer is initialized as a part of the* packet header in the mbuf chain. The first mbuf in the chain is always* a packet header and contains the interface pointer. This field is used* when it is necessary to retrieve the interface pointer from the mbuf chain.* If a copy function pointer is given, this function uses that function* pointer. This is given to enable the hardware specific copy routines to be* used instead of system routines.**/struct mbuf * m_devget(buf, totlen, width, ifp, copy) char * buf; int totlen; int width; struct ifnet *ifp; void (*copy)(); { register struct mbuf *m; struct mbuf *top = NULL, **mp = ⊤ register int len; register char *cp; cp = buf; while (totlen > 0) { m = mBufClGet (M_DONTWAIT, MT_DATA, totlen, FALSE); if (m == NULL) { if (top != NULL) m_freem (top); return (NULL); } if (top == NULL) { m->m_flags |= M_PKTHDR; m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = totlen; len = min(totlen, m->m_extSize); /* length to copy */ if (m->m_extSize > max_hdr) { /* avoid costly m_prepends done in the context of tNetTask, * especially effective while forwarding packets. */ len = min (len, (m->m_extSize - max_linkhdr)); m->m_data += max_linkhdr; } } else { len = min(totlen, m->m_extSize); /* length to copy */ } m->m_len = len; /* initialize the length of mbuf */ if (copy) (*copy)(cp, mtod(m, caddr_t), (unsigned)len); else { switch (width) { case NONE: bcopy(cp, mtod(m, caddr_t), (unsigned)len); break; case 1: bcopyBytes (cp, mtod(m, caddr_t), len); break; case 2: bcopyWords (cp, mtod(m, caddr_t), (len + 1) >> 1); break; case 4: bcopyLongs (cp, mtod(m, caddr_t), (len + 3) >> 2); break; default: panic ("m_devget -- invalid mem copy width"); break; } } cp += len; /* advance the pointer */ *mp = m; mp = &m->m_next; /* advance the mbuf */ totlen -= len; /* decrment the total length */ } return (top); /* return the filled mbuf chain */ }#if 0 /* XXX *//* both m_copyback and m_copydata have to be reworked, these functions * are only used in rt_sock.c. They have been moved to rt_sock.c. * They have to be reworked and integrated into netBufLib.c *//* * Copy data from a buffer back into the indicated mbuf chain, * starting "off" bytes from the beginning, extending the mbuf * chain if necessary. */voidm_copyback(m0, off, len, cp) struct mbuf *m0; register int off; register int len; caddr_t cp;{ register int mlen; register struct mbuf *m = m0, *n; int totlen = 0; if (m0 == 0) return; while (off > (mlen = m->m_len)) { off -= mlen; totlen += mlen; if (m->m_next == 0) { n = m_getclr(M_DONTWAIT, m->m_type, CL_SIZE_128, TRUE); if (n == 0) goto out; n->m_len = min(n->m_extSize, len + off); m->m_next = n; } m = m->m_next; } while (len > 0) { mlen = min (m->m_len - off, len); bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); cp += mlen; len -= mlen; mlen += off; off = 0; totlen += mlen; if (len == 0) break; if (m->m_next == 0) { n = mBufClGet(M_DONTWAIT, m->m_type, CL_SIZE_128, TRUE); if (n == 0) break; n->m_len = min(n->m_extSize, 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;}/********************************************************************************* m_copydata - copy data from an mbuf chain into a buff* Copy data from an mbuf chain starting "off" bytes from the beginning,* continuing for "len" bytes, into the indicated buffer.*/void m_copydata(m, off, len, cp) register struct mbuf *m; register int off; register int len; caddr_t cp; { register unsigned count; if (off < 0 || len < 0) panic("m_copydata"); while (off > 0) { if (m == 0) panic("m_copydata"); if (off < m->m_len) break; off -= m->m_len; m = m->m_next; } while (len > 0) { if (m == 0) panic("m_copydata"); count = min(m->m_len - off, len); bcopy(mtod(m, caddr_t) + off, cp, count); len -= count; cp += count; off = 0; m = m->m_next; } }/* XXX merged with netMblkChainDup in netBufLib.c */LOCAL int MCFail; /* XXX temp variable pullup fails *//********************************************************************************* m_copym - make a copy of an mbuf chain.** Make a copy of an mbuf chain starting "off0" bytes from the beginning,* continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.* The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.*/struct mbuf * m_copym(m, off0, len, wait) register struct mbuf *m; int off0, wait; register int len; { register struct mbuf *n, **np; register int off = off0; struct mbuf *top; int copyhdr = 0; if (off < 0 || len < 0) panic("m_copym"); if (off == 0 && m->m_flags & M_PKTHDR) copyhdr = 1; while (off > 0) { if (m == 0) panic("m_copym"); if (off < m->m_len) break; off -= m->m_len; m = m->m_next; } np = ⊤ top = 0; while (len > 0) { if (m == 0) { if (len != M_COPYALL) panic("m_copym"); break; } n = mBlkGet(_pNetDpool, wait, m->m_type); if ((*np = n) == NULL) goto nospace; if (copyhdr) { n->m_pkthdr = m->m_pkthdr; if (len == M_COPYALL) n->m_pkthdr.len -= off0; else n->m_pkthdr.len = len; copyhdr = 0; } n->m_flags = m->m_flags; n->m_len = min(len, m->m_len - off); n->m_data = m->m_data + off; n->m_ext = m->m_ext; ++(n->m_extRefCnt); if (len != M_COPYALL) len -= n->m_len; off = 0; m = m->m_next; np = &n->m_next; } if (top == 0) MCFail++; return (top); nospace: m_freem(top); MCFail++; return (0); }/* * XXX merged with netMblkClFree & netMblkClChainFree in netBufLib.c * turned m_free and m_freem as macros in mbuf.h *//********************************************************************************* m_free - free the mBlk and cluster pair** This function frees the mBlk and also the cluster if the mBlk points to it.* This function returns a pointer to the next mBlk connected to the one that* is freed.** NOMANUAL* * RETURNS mBLK/NULL*/struct mbuf * m_free ( FAST struct mbuf * pMblk /* pointer to the mBlk to free */ ) { FAST struct mbuf * pMblkNext; /* pointer to the next mBlk */ NET_POOL_ID pNetPool; /* pointer to net pool */ if (pMblk->m_type == MT_FREE) panic("m_free"); pNetPool = MBLK_TO_NET_POOL(pMblk); pMblkNext = pMblk->m_next; /* free the cluster first if it is attached to the mBlk */ if (M_HASCL(pMblk)) clBlkFree (pMblk->pClBlk->pNetPool, pMblk->pClBlk); mBlkFree (pNetPool, pMblk); /* free the mBlk */ return (pMblkNext); }/********************************************************************************* m_freem - free a list of mbufs linked via m_next** N.B.: If MFREE macro changes in mbuf.h m_freem should also change* accordingly.*/void m_freem(m) FAST struct mbuf *m; { FAST struct mbuf *n; if (m == NULL) return; do { n = m_free (m); } while ((m = n)); }#endif /* XXX have to be reworked */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -