1/*
2 * Copyright 2009, Colin G��nther, coling@gmx.de.
3 * Copyright 2007, Hugo Santos. All Rights Reserved.
4 * Distributed under the terms of the MIT License.
5 */
6#ifndef _FBSD_COMPAT_SYS_MBUF_H_
7#define _FBSD_COMPAT_SYS_MBUF_H_
8
9
10#include <sys/queue.h>
11#include <sys/systm.h>
12#include <vm/uma.h>
13
14
15#define MHSIZE		__offsetof(struct mbuf, m_dat)
16#define MPKTHSIZE	__offsetof(struct mbuf, m_pktdat)
17#define MLEN		((int)(MSIZE - MHSIZE))
18#define MHLEN		((int)(MSIZE - MPKTHSIZE))
19
20#define MINCLSIZE	(MHLEN + 1)
21
22#define MBTOM(how)	(how)
23#define M_DONTWAIT	M_NOWAIT
24#define M_TRYWAIT	M_WAITOK
25#define M_WAIT		M_WAITOK
26
27/* mbuf types describing the content of the mbuf (including external storage). */
28#define MT_DATA		1
29#define	MT_NOINIT	255	/* not a type, a flag to allocate a non-initialized mbuf */
30
31/*
32 * mbuf flags of global significance and layer crossing.
33 * Those of only protocol/layer specific significance are to be mapped
34 * to M_PROTO[1-12] and cleared at layer handoff boundaries.
35 * NB: Limited to the lower 24 bits.
36 */
37#define	M_EXT		0x00000001 /* has associated external storage */
38#define	M_PKTHDR	0x00000002 /* start of record */
39#define	M_EOR		0x00000004 /* end of record */
40#define	M_RDONLY	0x00000008 /* associated data is marked read-only */
41#define	M_BCAST		0x00000010 /* send/received as link-level broadcast */
42#define	M_MCAST		0x00000020 /* send/received as link-level multicast */
43#define	M_PROMISC	0x00000040 /* packet was not for us */
44#define	M_VLANTAG	0x00000080 /* ether_vtag is valid */
45#define	M_UNUSED_8	0x00000100 /* --available-- */
46#define	M_NOFREE	0x00000200 /* do not free mbuf, embedded in cluster */
47
48#define	M_PROTO1	0x00001000 /* protocol-specific */
49#define	M_PROTO2	0x00002000 /* protocol-specific */
50#define	M_PROTO3	0x00004000 /* protocol-specific */
51#define	M_PROTO4	0x00008000 /* protocol-specific */
52#define	M_PROTO5	0x00010000 /* protocol-specific */
53#define	M_PROTO6	0x00020000 /* protocol-specific */
54#define	M_PROTO7	0x00040000 /* protocol-specific */
55#define	M_PROTO8	0x00080000 /* protocol-specific */
56#define	M_PROTO9	0x00100000 /* protocol-specific */
57#define	M_PROTO10	0x00200000 /* protocol-specific */
58#define	M_PROTO11	0x00400000 /* protocol-specific */
59#define	M_PROTO12	0x00800000 /* protocol-specific */
60
61#define	M_PROTOFLAGS \
62	(M_PROTO1|M_PROTO2|M_PROTO3|M_PROTO4|M_PROTO5|M_PROTO6|M_PROTO7|M_PROTO8|\
63	 M_PROTO9|M_PROTO10|M_PROTO11|M_PROTO12)
64	// Flags to purge when crossing layers.
65
66#define M_COPYFLAGS \
67	(M_PKTHDR|M_EOR|M_RDONLY|M_BCAST|M_MCAST|M_PROMISC|M_VLANTAG| \
68	 M_PROTOFLAGS)
69	// Flags preserved when copying m_pkthdr
70
71#define M_MOVE_PKTHDR(to, from)	m_move_pkthdr((to), (from))
72#define MGET(m, how, type)		((m) = m_get((how), (type)))
73#define MGETHDR(m, how, type)	((m) = m_gethdr((how), (type)))
74#define MCLGET(m, how)			m_clget((m), (how))
75#define m_getm(m, len, how, type)					\
76    m_getm2((m), (len), (how), (type), M_PKTHDR)
77
78#define mtod(m, type)	((type)((m)->m_data))
79#define	mtodo(m, o)	((void *)(((m)->m_data) + (o)))
80
81// Check if the supplied mbuf has a packet header, or else panic.
82#define M_ASSERTPKTHDR(m) KASSERT(m != NULL && m->m_flags & M_PKTHDR, \
83	("%s: no mbuf packet header!", __func__))
84
85
86/*
87 * Network interface cards are able to hash protocol fields (such as IPv4
88 * addresses and TCP port numbers) classify packets into flows.  These flows
89 * can then be used to maintain ordering while delivering packets to the OS
90 * via parallel input queues, as well as to provide a stateless affinity
91 * model.  NIC drivers can pass up the hash via m->m_pkthdr.flowid, and set
92 * m_flag fields to indicate how the hash should be interpreted by the
93 * network stack.
94 *
95 * Most NICs support RSS, which provides ordering and explicit affinity, and
96 * use the hash m_flag bits to indicate what header fields were covered by
97 * the hash.  M_HASHTYPE_OPAQUE and M_HASHTYPE_OPAQUE_HASH can be set by non-
98 * RSS cards or configurations that provide an opaque flow identifier, allowing
99 * for ordering and distribution without explicit affinity.  Additionally,
100 * M_HASHTYPE_OPAQUE_HASH indicates that the flow identifier has hash
101 * properties.
102 */
103#define	M_HASHTYPE_HASHPROP		0x80	/* has hash properties */
104#define	M_HASHTYPE_HASH(t)		(M_HASHTYPE_HASHPROP | (t))
105/* Microsoft RSS standard hash types */
106#define	M_HASHTYPE_NONE			0
107#define	M_HASHTYPE_RSS_IPV4		M_HASHTYPE_HASH(1) /* IPv4 2-tuple */
108#define	M_HASHTYPE_RSS_TCP_IPV4		M_HASHTYPE_HASH(2) /* TCPv4 4-tuple */
109#define	M_HASHTYPE_RSS_IPV6		M_HASHTYPE_HASH(3) /* IPv6 2-tuple */
110#define	M_HASHTYPE_RSS_TCP_IPV6		M_HASHTYPE_HASH(4) /* TCPv6 4-tuple */
111#define	M_HASHTYPE_RSS_IPV6_EX		M_HASHTYPE_HASH(5) /* IPv6 2-tuple +
112							    * ext hdrs */
113#define	M_HASHTYPE_RSS_TCP_IPV6_EX	M_HASHTYPE_HASH(6) /* TCPv6 4-tuple +
114							    * ext hdrs */
115/* Non-standard RSS hash types */
116#define	M_HASHTYPE_RSS_UDP_IPV4		M_HASHTYPE_HASH(7) /* IPv4 UDP 4-tuple*/
117#define	M_HASHTYPE_RSS_UDP_IPV4_EX	M_HASHTYPE_HASH(8) /* IPv4 UDP 4-tuple +
118							    * ext hdrs */
119#define	M_HASHTYPE_RSS_UDP_IPV6		M_HASHTYPE_HASH(9) /* IPv6 UDP 4-tuple*/
120#define	M_HASHTYPE_RSS_UDP_IPV6_EX	M_HASHTYPE_HASH(10)/* IPv6 UDP 4-tuple +
121							    * ext hdrs */
122
123#define	M_HASHTYPE_OPAQUE		63	/* ordering, not affinity */
124#define	M_HASHTYPE_OPAQUE_HASH		M_HASHTYPE_HASH(M_HASHTYPE_OPAQUE)
125						/* ordering+hash, not affinity*/
126
127#define	M_HASHTYPE_CLEAR(m)	((m)->m_pkthdr.rsstype = 0)
128#define	M_HASHTYPE_GET(m)	((m)->m_pkthdr.rsstype)
129#define	M_HASHTYPE_SET(m, v)	((m)->m_pkthdr.rsstype = (v))
130#define	M_HASHTYPE_TEST(m, v)	(M_HASHTYPE_GET(m) == (v))
131#define	M_HASHTYPE_ISHASH(m)	(M_HASHTYPE_GET(m) & M_HASHTYPE_HASHPROP)
132
133#define MBUF_CHECKSLEEP(how) do { } while (0)
134
135#define MTAG_PERSISTENT	0x800
136
137#define	M_COPYALL	1000000000
138	// Length to m_copy to copy all.
139
140#define EXT_CLUSTER		1		// 2048 bytes
141#define EXT_JUMBOP		4		// Page size
142#define EXT_JUMBO9		5		// 9 * 1024 bytes
143#define EXT_NET_DRV		100		// custom ext_buf provided by net driver
144
145#define EXT_EXTREF		255		// has externally maintained ext_cnt ptr
146
147/*
148 * Flags for external mbuf buffer types.
149 * NB: limited to the lower 24 bits.
150 */
151#define EXT_FLAG_EMBREF		0x000001	/* embedded ext_count */
152#define EXT_FLAG_EXTREF		0x000002	/* external ext_cnt, notyet */
153
154/* Flags indicating checksum, segmentation and other offload work */
155#define	CSUM_IP			0x00000001	/* IP header checksum offload */
156#define	CSUM_IP_UDP		0x00000002	/* UDP checksum offload */
157#define	CSUM_IP_TCP		0x00000004	/* TCP checksum offload */
158#define	CSUM_IP_SCTP		0x00000008	/* SCTP checksum offload */
159#define	CSUM_IP_TSO		0x00000010	/* TCP segmentation offload */
160#define	CSUM_IP_ISCSI		0x00000020	/* iSCSI checksum offload */
161
162#define	CSUM_IP6_UDP		0x00000200	/* UDP checksum offload */
163#define	CSUM_IP6_TCP		0x00000400	/* TCP checksum offload */
164#define	CSUM_IP6_SCTP		0x00000800	/* SCTP checksum offload */
165#define	CSUM_IP6_TSO		0x00001000	/* TCP segmentation offload */
166#define	CSUM_IP6_ISCSI		0x00002000	/* iSCSI checksum offload */
167
168/* Inbound checksum support where the checksum was verified by hardware. */
169#define	CSUM_L3_CALC		0x01000000	/* calculated layer 3 csum */
170#define	CSUM_L3_VALID		0x02000000	/* checksum is correct */
171#define	CSUM_L4_CALC		0x04000000	/* calculated layer 4 csum */
172#define	CSUM_L4_VALID		0x08000000	/* checksum is correct */
173#define	CSUM_L5_CALC		0x10000000	/* calculated layer 5 csum */
174#define	CSUM_L5_VALID		0x20000000	/* checksum is correct */
175#define	CSUM_COALESCED		0x40000000	/* contains merged segments */
176
177/* CSUM flags compatibility mappings. */
178#define	CSUM_IP_CHECKED		CSUM_L3_CALC
179#define	CSUM_IP_VALID		CSUM_L3_VALID
180#define	CSUM_DATA_VALID		CSUM_L4_VALID
181#define	CSUM_PSEUDO_HDR		CSUM_L4_CALC
182#define	CSUM_SCTP_VALID		CSUM_L4_VALID
183#define	CSUM_DELAY_DATA		(CSUM_TCP|CSUM_UDP)
184#define	CSUM_DELAY_IP		CSUM_IP		/* Only v4, no v6 IP hdr csum */
185#define	CSUM_DELAY_DATA_IPV6	(CSUM_TCP_IPV6|CSUM_UDP_IPV6)
186#define	CSUM_DATA_VALID_IPV6	CSUM_DATA_VALID
187#define	CSUM_TCP		CSUM_IP_TCP
188#define	CSUM_UDP		CSUM_IP_UDP
189#define	CSUM_SCTP		CSUM_IP_SCTP
190#define	CSUM_TSO		(CSUM_IP_TSO|CSUM_IP6_TSO)
191#define	CSUM_UDP_IPV6		CSUM_IP6_UDP
192#define	CSUM_TCP_IPV6		CSUM_IP6_TCP
193#define	CSUM_SCTP_IPV6		CSUM_IP6_SCTP
194
195
196#define MEXTADD(m, buf, size, free, arg1, arg2, flags, type) \
197	m_extadd((m), (caddr_t)(buf), (size), (free),(arg1),(arg2),(flags), (type))
198
199
200extern int max_linkhdr;
201extern int max_protohdr;
202extern int max_hdr;
203extern int max_datalen;		// MHLEN - max_hdr
204
205
206struct pkthdr {
207	struct ifnet*					rcvif;
208	SLIST_HEAD(packet_tags, m_tag)	tags;
209	int								len;
210
211	/* Layer crossing persistent information. */
212	uint32_t	flowid;		/* packet's 4-tuple system */
213	uint64_t	csum_flags;	/* checksum and offload features */
214	int			csum_data;
215	uint8_t		rsstype;		/* hash type */
216	uint16_t	tso_segsz;
217	uint16_t	ether_vtag;
218
219	/* Layer specific non-persistent local storage for reassembly, etc. */
220	union {
221		uintptr_t	unintptr[1];
222		void*		ptr;
223	} PH_loc;
224};
225
226struct m_tag {
227	SLIST_ENTRY(m_tag)	m_tag_link;		// List of packet tags
228	u_int16_t			m_tag_id;		// Tag ID
229	u_int16_t			m_tag_len;		// Length of data
230	u_int32_t			m_tag_cookie;	// ABI/Module ID
231	void				(*m_tag_free)(struct m_tag*);
232};
233
234struct m_ext {
235	union {
236		volatile u_int	 ext_count;	/* value of ref count info */
237		volatile u_int	*ext_cnt;	/* pointer to ref count info */
238	};
239	caddr_t		 ext_buf;	 /* start of buffer */
240	uint32_t	 ext_size;	 /* size of buffer, for ext_free */
241	uint32_t	 ext_type:8, /* type of external storage */
242			 ext_flags:24;	 /* external storage mbuf flags */
243};
244
245struct mbuf {
246	union {	/* next buffer in chain */
247		struct mbuf		*m_next;
248		SLIST_ENTRY(mbuf)	m_slist;
249		STAILQ_ENTRY(mbuf)	m_stailq;
250	};
251	union {	/* next chain in queue/record */
252		struct mbuf		*m_nextpkt;
253		SLIST_ENTRY(mbuf)	m_slistpkt;
254		STAILQ_ENTRY(mbuf)	m_stailqpkt;
255	};
256	caddr_t		 m_data;	/* location of data */
257	int32_t		 m_len;		/* amount of data in this mbuf */
258	uint32_t	 m_type:8,	/* type of data in this mbuf */
259			 m_flags:24;
260
261	union {
262		struct {
263			struct pkthdr	MH_pkthdr;
264			union {
265				struct m_ext	MH_ext;
266				char			MH_databuf[0] __aligned(8);
267			} MH_dat;
268		} MH;
269		char M_databuf[0] __aligned(8);
270	} M_dat;
271};
272
273/* The reason we use these really nasty macros, instead of naming the
274 * structs and unions properly like FreeBSD does ... is because of a
275 * GCC2 compiler bug. Specifically a parser bug: adding -O0 has no
276 * effect on this problem. */
277#define m_pkthdr	M_dat.MH.MH_pkthdr
278#define m_ext		M_dat.MH.MH_dat.MH_ext
279#define m_pktdat	M_dat.MH.MH_dat.MH_databuf
280#define m_dat		M_dat.M_databuf
281
282int				m_init(struct mbuf *m, int how, short type, int flags);
283int				m_pkthdr_init(struct mbuf *m, int how);
284
285void			m_catpkt(struct mbuf *m, struct mbuf *n);
286void			m_adj(struct mbuf*, int);
287int				m_append(struct mbuf*, int, c_caddr_t);
288void			m_cat(struct mbuf*, struct mbuf*);
289int				m_clget(struct mbuf*, int);
290void*			m_cljget(struct mbuf*, int, int);
291struct mbuf*	m_collapse(struct mbuf*, int, int);
292void			m_copyback(struct mbuf *m0, int off, int len, c_caddr_t cp);
293void			m_copydata(const struct mbuf*, int, int, caddr_t);
294struct mbuf*	m_copypacket(struct mbuf*, int);
295struct mbuf *	m_copym(struct mbuf *m, int off0, int len, int wait);
296struct mbuf*	m_defrag(struct mbuf*, int);
297struct mbuf*	m_devget(char*, int, int, struct ifnet*,
298	void(*) (char*, caddr_t, u_int));
299
300struct mbuf*	m_dup(const struct mbuf *m, int how);
301int				m_dup_pkthdr(struct mbuf *to, const struct mbuf *from, int how);
302
303void			m_demote_pkthdr(struct mbuf *m);
304void			m_demote(struct mbuf *m0, int all, int flags);
305
306void			m_extadd(struct mbuf *mb, caddr_t buf, u_int size,
307	void (*freef)(struct mbuf *, void *, void *), void *arg1, void *arg2,
308	int flags, int type);
309
310u_int			m_fixhdr(struct mbuf*);
311struct mbuf*	m_free(struct mbuf*);
312void			m_freem(struct mbuf*);
313struct mbuf*	m_get(int, short);
314struct mbuf*	m_get2(int size, int how, short type, int flags);
315struct mbuf *	m_getm2(struct mbuf *m, int len, int how, short type, int flags);
316struct mbuf*	m_gethdr(int, short);
317struct mbuf*	m_getjcl(int, short, int, int);
318u_int			m_length(struct mbuf*, struct mbuf**);
319struct mbuf*	m_getcl(int, short, int);
320void			m_move_pkthdr(struct mbuf*, struct mbuf*);
321struct mbuf*	m_prepend(struct mbuf*, int, int);
322struct mbuf*	m_pulldown(struct mbuf*, int, int, int*);
323struct mbuf*	m_pullup(struct mbuf*, int);
324struct mbuf*	m_split(struct mbuf*, int, int);
325struct mbuf*	m_unshare(struct mbuf*, int);
326
327struct m_tag*	m_tag_alloc(u_int32_t, int, int, int);
328void			m_tag_delete(struct mbuf*, struct m_tag*);
329void			m_tag_delete_chain(struct mbuf*, struct m_tag*);
330void			m_tag_free_default(struct m_tag*);
331struct m_tag*	m_tag_locate(struct mbuf*, u_int32_t, int, struct m_tag*);
332struct m_tag*	m_tag_copy(struct m_tag*, int);
333int				m_tag_copy_chain(struct mbuf *to, const struct mbuf *from, int how);
334void			m_tag_delete_nonpersistent(struct mbuf*);
335
336
337static inline void
338m_tag_setup(struct m_tag* tagPointer, u_int32_t cookie, int type, int length)
339{
340	tagPointer->m_tag_id = type;
341	tagPointer->m_tag_len = length;
342	tagPointer->m_tag_cookie = cookie;
343}
344
345
346static inline void
347m_tag_free(struct m_tag* tag)
348{
349	(*tag->m_tag_free)(tag);
350}
351
352
353static inline void
354m_tag_prepend(struct mbuf* memoryBuffer, struct m_tag* tag)
355{
356	SLIST_INSERT_HEAD(&memoryBuffer->m_pkthdr.tags, tag, m_tag_link);
357}
358
359
360static inline void
361m_tag_unlink(struct mbuf* memoryBuffer, struct m_tag* tag)
362{
363	SLIST_REMOVE(&memoryBuffer->m_pkthdr.tags, tag, m_tag, m_tag_link);
364}
365
366
367#include <sys/mbuf-fbsd.h>
368
369#endif	/* _FBSD_COMPAT_SYS_MBUF_H_ */
370