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