#ifndef _FBSD_COMPAT_SYS_MBUF_FBSD_H_
#define _FBSD_COMPAT_SYS_MBUF_FBSD_H_
#define M_START(m) \
(((m)->m_flags & M_EXT) ? (m)->m_ext.ext_buf : \
((m)->m_flags & M_PKTHDR) ? &(m)->m_pktdat[0] : \
&(m)->m_dat[0])
#define M_SIZE(m) \
(((m)->m_flags & M_EXT) ? (m)->m_ext.ext_size : \
((m)->m_flags & M_PKTHDR) ? MHLEN : \
MLEN)
static __inline void
m_align(struct mbuf *m, int len)
{
#ifdef INVARIANTS
const char *msg = "%s: not a virgin mbuf";
#endif
int adjust;
KASSERT(m->m_data == M_START(m), (msg, __func__));
adjust = M_SIZE(m) - len;
m->m_data += adjust &~ (sizeof(long)-1);
}
#define M_ALIGN(m, len) m_align(m, len)
#define MH_ALIGN(m, len) m_align(m, len)
#define MEXT_ALIGN(m, len) m_align(m, len)
#define M_WRITABLE(m) (!((m)->m_flags & M_RDONLY) && \
(!(((m)->m_flags & M_EXT)) || \
(m_extrefcnt(m) == 1)))
#define M_LEADINGSPACE(m) \
(M_WRITABLE(m) ? ((m)->m_data - M_START(m)) : 0)
#define M_TRAILINGROOM(m) ((M_START(m) + M_SIZE(m)) - ((m)->m_data + (m)->m_len))
#define M_TRAILINGSPACE(m) (M_WRITABLE(m) ? M_TRAILINGROOM(m) : 0)
#define M_PREPEND(m, plen, how) do { \
struct mbuf **_mmp = &(m); \
struct mbuf *_mm = *_mmp; \
int _mplen = (plen); \
int __mhow = (how); \
\
MBUF_CHECKSLEEP(how); \
if (M_LEADINGSPACE(_mm) >= _mplen) { \
_mm->m_data -= _mplen; \
_mm->m_len += _mplen; \
} else \
_mm = m_prepend(_mm, _mplen, __mhow); \
if (_mm != NULL && _mm->m_flags & M_PKTHDR) \
_mm->m_pkthdr.len += _mplen; \
*_mmp = _mm; \
} while (0)
static __inline void
m_clrprotoflags(struct mbuf *m)
{
while (m) {
m->m_flags &= ~M_PROTOFLAGS;
m = m->m_next;
}
}
static inline u_int
m_extrefcnt(struct mbuf *m)
{
KASSERT(m->m_flags & M_EXT, ("%s: M_EXT missing", __func__));
return ((m->m_ext.ext_flags & EXT_FLAG_EMBREF) ? m->m_ext.ext_count :
*m->m_ext.ext_cnt);
}
static __inline int
m_gettype(int size)
{
int type = 0;
switch (size) {
case MCLBYTES:
type = EXT_CLUSTER;
break;
#if MJUMPAGESIZE != MCLBYTES
case MJUMPAGESIZE:
type = EXT_JUMBOP;
break;
#endif
case MJUM9BYTES:
type = EXT_JUMBO9;
break;
default:
panic("%s: invalid cluster size %d", __func__, size);
}
return (type);
}
static __inline void
m_cljset(struct mbuf *m, void *cl, int type)
{
int size = 0;
switch (type) {
case EXT_CLUSTER:
size = MCLBYTES;
break;
#if MJUMPAGESIZE != MCLBYTES
case EXT_JUMBOP:
size = MJUMPAGESIZE;
break;
#endif
case EXT_JUMBO9:
size = MJUM9BYTES;
break;
default:
panic("%s: unknown cluster type %d", __func__, type);
break;
}
m->m_data = m->m_ext.ext_buf = (caddr_t)cl;
m->m_ext.ext_size = size;
m->m_ext.ext_type = type;
m->m_ext.ext_flags = EXT_FLAG_EMBREF;
m->m_ext.ext_count = 1;
m->m_flags |= M_EXT;
}
struct mbufq {
STAILQ_HEAD(, mbuf) mq_head;
int mq_len;
int mq_maxlen;
};
static inline void
mbufq_init(struct mbufq *mq, int maxlen)
{
STAILQ_INIT(&mq->mq_head);
mq->mq_maxlen = maxlen;
mq->mq_len = 0;
}
static inline struct mbuf *
mbufq_flush(struct mbufq *mq)
{
struct mbuf *m;
m = STAILQ_FIRST(&mq->mq_head);
STAILQ_INIT(&mq->mq_head);
mq->mq_len = 0;
return (m);
}
static inline void
mbufq_drain(struct mbufq *mq)
{
struct mbuf *m, *n;
n = mbufq_flush(mq);
while ((m = n) != NULL) {
n = STAILQ_NEXT(m, m_stailqpkt);
m_freem(m);
}
}
static inline struct mbuf *
mbufq_first(const struct mbufq *mq)
{
return (STAILQ_FIRST(&mq->mq_head));
}
static inline struct mbuf *
mbufq_last(const struct mbufq *mq)
{
return (STAILQ_LAST(&mq->mq_head, mbuf, m_stailqpkt));
}
static inline bool
mbufq_empty(const struct mbufq *mq)
{
return (mq->mq_len == 0);
}
static inline int
mbufq_full(const struct mbufq *mq)
{
return (mq->mq_maxlen > 0 && mq->mq_len >= mq->mq_maxlen);
}
static inline int
mbufq_len(const struct mbufq *mq)
{
return (mq->mq_len);
}
static inline int
mbufq_enqueue(struct mbufq *mq, struct mbuf *m)
{
if (mbufq_full(mq))
return (ENOBUFS);
STAILQ_INSERT_TAIL(&mq->mq_head, m, m_stailqpkt);
mq->mq_len++;
return (0);
}
static inline struct mbuf *
mbufq_dequeue(struct mbufq *mq)
{
struct mbuf *m;
m = STAILQ_FIRST(&mq->mq_head);
if (m) {
STAILQ_REMOVE_HEAD(&mq->mq_head, m_stailqpkt);
m->m_nextpkt = NULL;
mq->mq_len--;
}
return (m);
}
static inline void
mbufq_prepend(struct mbufq *mq, struct mbuf *m)
{
STAILQ_INSERT_HEAD(&mq->mq_head, m, m_stailqpkt);
mq->mq_len++;
}
static inline void
mbufq_concat(struct mbufq *mq_dst, struct mbufq *mq_src)
{
mq_dst->mq_len += mq_src->mq_len;
STAILQ_CONCAT(&mq_dst->mq_head, &mq_src->mq_head);
mq_src->mq_len = 0;
}
#endif