Index: sys/mbuf.h =================================================================== --- sys/mbuf.h (revision 254953) +++ sys/mbuf.h (working copy) @@ -53,12 +53,16 @@ * externally and attach it to the mbuf in a way similar to that of mbuf * clusters. * + * NB: These calculation do not take actual compiler-induced alignment and + * padding inside the complete struct mbuf into account. Appropriate attention + * is required when changing members of struct mbuf. + * * MLEN is data length in a normal mbuf. * MHLEN is data length in an mbuf with pktheader. * MINCLSIZE is a smallest amount of data that should be put into cluster. */ -#define MLEN ((int)(MSIZE - sizeof(struct m_hdr))) -#define MHLEN ((int)(MLEN - sizeof(struct pkthdr))) +#define MLEN ((int)(MSIZE - sizeof(struct mh_hdr))) +#define MHLEN ((int)(MLEN - sizeof(struct mh_pkthdr))) #define MINCLSIZE (MHLEN + 1) #ifdef _KERNEL @@ -67,7 +71,7 @@ * type: * * mtod(m, t) -- Convert mbuf pointer to data pointer of correct type. - * mtodo(m, o) -- Same as above but with offset 'o' into data. + * mtodo(m, o) -- Same as above but with offset 'o' into data. */ #define mtod(m, t) ((t)((m)->m_data)) #define mtodo(m, o) ((void *)(((m)->m_data) + (o))) @@ -84,10 +88,10 @@ /* * Header present at the beginning of every mbuf. - * Size ILP32: 20 + * Size ILP32: 24 * LP64: 32 */ -struct m_hdr { +struct mh_hdr { struct mbuf *mh_next; /* next buffer in chain */ struct mbuf *mh_nextpkt; /* next chain in queue/record */ caddr_t mh_data; /* location of data */ @@ -94,10 +98,15 @@ int32_t mh_len; /* amount of data in this mbuf */ uint32_t mh_type:8, /* type of data in this mbuf */ mh_flags:24; /* flags; see below */ +#if !defined(__LP64__) + uint32_t mh_pad; /* pad for 64bit alignment */ +#endif }; /* * Packet tag structure (see below for details). + * Size ILP32: 16 + * LP64: 24 */ struct m_tag { SLIST_ENTRY(m_tag) m_tag_link; /* List of packet tags */ @@ -112,7 +121,7 @@ * Size ILP32: 48 * LP64: 56 */ -struct pkthdr { +struct mh_pkthdr { struct ifnet *rcvif; /* rcv interface */ SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */ int32_t len; /* total packet length */ @@ -159,7 +168,7 @@ * Size ILP32: 28 * LP64: 48 */ -struct m_ext { +struct mh_ext { volatile u_int *ref_cnt; /* pointer to ref count info */ caddr_t ext_buf; /* start of buffer */ uint32_t ext_size; /* size of buffer, for ext_free */ @@ -176,18 +185,18 @@ * purposes. */ struct mbuf { - struct m_hdr m_hdr; + struct mh_hdr m_hdr; union { struct { - struct pkthdr MH_pkthdr; /* M_PKTHDR set */ + struct mh_pkthdr MH_pkthdr; /* M_PKTHDR set */ union { - struct m_ext MH_ext; /* M_EXT set */ + struct mh_ext MH_ext; /* M_EXT set */ char MH_databuf[MHLEN]; } MH_dat; } MH; char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */ } M_dat; -}; +} __aligned(sizeof(uint64_t)); #define m_next m_hdr.mh_next #define m_len m_hdr.mh_len #define m_data m_hdr.mh_data Index: kern/uipc_mbuf.c =================================================================== --- kern/uipc_mbuf.c (revision 254953) +++ kern/uipc_mbuf.c (working copy) @@ -85,6 +85,17 @@ #endif /* + * Ensure the correct size of various mbuf parameters. It could be off due + * to compiler-induced padding and alignment artifacts. + */ +CTASSERT(sizeof(struct mbuf) == MSIZE); +CTASSERT(sizeof(((struct mbuf *)0)->m_hdr) == sizeof(struct mh_hdr)); +CTASSERT(sizeof(((struct mbuf *)0)->m_pkthdr) == sizeof(struct mh_pkthdr)); +CTASSERT(sizeof(((struct mbuf *)0)->m_ext) == sizeof(struct mh_ext)); +CTASSERT(sizeof(((struct mbuf *)0)->m_dat) == MLEN); +CTASSERT(sizeof(((struct mbuf *)0)->m_pktdat) == MHLEN); + +/* * m_get2() allocates minimum mbuf that would fit "size" argument. */ struct mbuf * @@ -389,7 +400,7 @@ if (m->m_flags & M_PKTHDR) { m_tag_delete_chain(m, NULL); m->m_flags &= ~M_PKTHDR; - bzero(&m->m_pkthdr, sizeof(struct pkthdr)); + bzero(&m->m_pkthdr, sizeof(struct mh_pkthdr)); } if (m != m0 && m->m_nextpkt != NULL) { KASSERT(m->m_nextpkt == NULL,