ip_impl.h revision 2535:b66cbb80977f
1189251Ssam/*
2189251Ssam * CDDL HEADER START
3189251Ssam *
4189251Ssam * The contents of this file are subject to the terms of the
5189251Ssam * Common Development and Distribution License (the "License").
6189251Ssam * You may not use this file except in compliance with the License.
7189251Ssam *
8189251Ssam * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9189251Ssam * or http://www.opensolaris.org/os/licensing.
10189251Ssam * See the License for the specific language governing permissions
11189251Ssam * and limitations under the License.
12189251Ssam *
13189251Ssam * When distributing Covered Code, include this CDDL HEADER in each
14189251Ssam * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15189251Ssam * If applicable, add the following below this CDDL HEADER, with the
16189251Ssam * fields enclosed by brackets "[]" replaced with your own identifying
17189251Ssam * information: Portions Copyright [yyyy] [name of copyright owner]
18189251Ssam *
19189251Ssam * CDDL HEADER END
20189251Ssam */
21189251Ssam/*
22189251Ssam * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23189251Ssam * Use is subject to license terms.
24189251Ssam */
25189251Ssam
26189251Ssam#ifndef	_INET_IP_IMPL_H
27189251Ssam#define	_INET_IP_IMPL_H
28189251Ssam
29189251Ssam#pragma ident	"%Z%%M%	%I%	%E% SMI"
30189251Ssam
31189251Ssam/*
32189251Ssam * IP implementation private declarations.  These interfaces are
33189251Ssam * used to build the IP module and are not meant to be accessed
34189251Ssam * by any modules except IP itself.  They are undocumented and are
35189251Ssam * subject to change without notice.
36189251Ssam */
37189251Ssam
38189251Ssam#ifdef	__cplusplus
39189251Ssamextern "C" {
40189251Ssam#endif
41189251Ssam
42189251Ssam#ifdef _KERNEL
43189251Ssam
44189251Ssam#define	IP_MOD_ID		5701
45189251Ssam
46189251Ssam#ifdef	_BIG_ENDIAN
47189251Ssam#define	IP_HDR_CSUM_TTL_ADJUST	256
48189251Ssam#define	IP_TCP_CSUM_COMP	IPPROTO_TCP
49189251Ssam#define	IP_UDP_CSUM_COMP	IPPROTO_UDP
50189251Ssam#else
51189251Ssam#define	IP_HDR_CSUM_TTL_ADJUST	1
52189251Ssam#define	IP_TCP_CSUM_COMP	(IPPROTO_TCP << 8)
53189251Ssam#define	IP_UDP_CSUM_COMP	(IPPROTO_UDP << 8)
54189251Ssam#endif
55189251Ssam
56189251Ssam#define	TCP_CHECKSUM_OFFSET	16
57189251Ssam#define	TCP_CHECKSUM_SIZE	2
58189251Ssam
59189251Ssam#define	UDP_CHECKSUM_OFFSET	6
60189251Ssam#define	UDP_CHECKSUM_SIZE	2
61189251Ssam
62189251Ssam#define	IPH_TCPH_CHECKSUMP(ipha, hlen)	\
63189251Ssam	((uint16_t *)(((uchar_t *)(ipha)) + ((hlen) + TCP_CHECKSUM_OFFSET)))
64189251Ssam
65189251Ssam#define	IPH_UDPH_CHECKSUMP(ipha, hlen)	\
66189251Ssam	((uint16_t *)(((uchar_t *)(ipha)) + ((hlen) + UDP_CHECKSUM_OFFSET)))
67189251Ssam
68189251Ssam#define	ILL_HCKSUM_CAPABLE(ill)		\
69189251Ssam	(((ill)->ill_capabilities & ILL_CAPAB_HCKSUM) != 0)
70189251Ssam/*
71189251Ssam * Macro that performs software checksum calculation on the IP header.
72189251Ssam */
73189251Ssam#define	IP_HDR_CKSUM(ipha, sum, v_hlen_tos_len, ttl_protocol) {		\
74189251Ssam	(sum) += (ttl_protocol) + (ipha)->ipha_ident +			\
75189251Ssam	    ((v_hlen_tos_len) >> 16) +					\
76189251Ssam	    ((v_hlen_tos_len) & 0xFFFF) +				\
77189251Ssam	    (ipha)->ipha_fragment_offset_and_flags;			\
78189251Ssam	(sum) = (((sum) & 0xFFFF) + ((sum) >> 16));			\
79189251Ssam	(sum) = ~((sum) + ((sum) >> 16));				\
80189251Ssam	(ipha)->ipha_hdr_checksum = (uint16_t)(sum);			\
81189251Ssam}
82189251Ssam
83189251Ssam#define	IS_IP_HDR_HWCKSUM(ipsec, mp, ill)				\
84189251Ssam	((!ipsec) && (DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM) &&		\
85189251Ssam	ILL_HCKSUM_CAPABLE(ill) && dohwcksum)
86189251Ssam
87189251Ssam/*
88189251Ssam * This macro acts as a wrapper around IP_CKSUM_XMIT_FAST, and it performs
89189251Ssam * several checks on the IRE and ILL (among other things) in order to see
90189251Ssam * whether or not hardware checksum offload is allowed for the outgoing
91189251Ssam * packet.  It assumes that the caller has held a reference to the IRE.
92189251Ssam */
93189251Ssam#define	IP_CKSUM_XMIT(ill, ire, mp, ihp, up, proto, start, end,		\
94189251Ssam	    max_frag, ipsec_len, pseudo) {				\
95189251Ssam	uint32_t _hck_flags;						\
96189251Ssam	/*								\
97189251Ssam	 * We offload checksum calculation to hardware when IPsec isn't	\
98189251Ssam	 * present and if fragmentation isn't required.  We also check	\
99189251Ssam	 * if M_DATA fastpath is safe to be used on the	corresponding	\
100189251Ssam	 * IRE; this check is performed without grabbing ire_lock but	\
101189251Ssam	 * instead by holding a reference to it.  This is sufficient	\
102189251Ssam	 * for IRE_CACHE; for IRE_BROADCAST on non-Ethernet links, the	\
103189251Ssam	 * DL_NOTE_FASTPATH_FLUSH indication could come up from the	\
104189251Ssam	 * driver and trigger the IRE (hence fp_mp) deletion.  This is	\
105189251Ssam	 * why only IRE_CACHE type is eligible for offload.		\
106189251Ssam	 *								\
107189251Ssam	 * The presense of IP options also forces the network stack to	\
108189251Ssam	 * calculate the checksum in software.  This is because:	\
109189251Ssam	 *								\
110189251Ssam	 * Wrap around: certain partial-checksum NICs (eri, ce) limit	\
111189251Ssam	 * the size of "start offset" width to 6-bit.  This effectively	\
112189251Ssam	 * sets the largest value of the offset to 64-bytes, starting	\
113189251Ssam	 * from the MAC header.  When the cumulative MAC and IP headers	\
114189251Ssam	 * exceed such limit, the offset will wrap around.  This causes	\
115189251Ssam	 * the checksum to be calculated at the wrong place.		\
116189251Ssam	 *								\
117189251Ssam	 * IPv4 source routing: none of the full-checksum capable NICs	\
118189251Ssam	 * is capable of correctly handling the	IPv4 source-routing	\
119189251Ssam	 * option for purposes of calculating the pseudo-header; the	\
120189251Ssam	 * actual destination is different from the destination in the	\
121189251Ssam	 * header which is that of the next-hop.  (This case may not be	\
122189251Ssam	 * true for NICs which can parse IPv6 extension headers, but	\
123189251Ssam	 * we choose to simplify the implementation by not offloading	\
124189251Ssam	 * checksum when they are present.)				\
125189251Ssam	 *								\
126189251Ssam	 */								\
127189251Ssam	if ((ill) != NULL && ILL_HCKSUM_CAPABLE(ill) &&			\
128189251Ssam	    !((ire)->ire_flags & RTF_MULTIRT) &&			\
129189251Ssam	    (!((ire)->ire_type & (IRE_BROADCAST|IRE_MIPRTUN)) ||	\
130189251Ssam	    (ill)->ill_type == IFT_ETHER) &&				\
131189251Ssam	    (ipsec_len) == 0 &&						\
132189251Ssam	    (((ire)->ire_ipversion == IPV4_VERSION &&			\
133189251Ssam	    (start) == IP_SIMPLE_HDR_LENGTH &&				\
134189251Ssam	    ((ire)->ire_nce != NULL &&					\
135189251Ssam	    (ire)->ire_nce->nce_fp_mp != NULL &&	\
136189251Ssam	    MBLKHEAD(mp) >= MBLKL((ire)->ire_nce->nce_fp_mp))) ||	\
137189251Ssam	    ((ire)->ire_ipversion == IPV6_VERSION &&			\
138189251Ssam	    (start) == IPV6_HDR_LEN &&					\
139189251Ssam	    (ire)->ire_nce->nce_fp_mp != NULL &&			\
140189251Ssam	    MBLKHEAD(mp) >= MBLKL((ire)->ire_nce->nce_fp_mp))) &&	\
141189251Ssam	    (max_frag) >= (uint_t)((end) + (ipsec_len)) &&		\
142189251Ssam	    dohwcksum) {						\
143189251Ssam		_hck_flags = (ill)->ill_hcksum_capab->ill_hcksum_txflags; \
144189251Ssam	} else {							\
145189251Ssam		_hck_flags = 0;						\
146189251Ssam	}								\
147209158Srpaulo	IP_CKSUM_XMIT_FAST((ire)->ire_ipversion, _hck_flags, mp, ihp,	\
148189251Ssam	    up, proto, start, end, pseudo);				\
149189251Ssam}
150189251Ssam
151189251Ssam/*
152189251Ssam * Based on the device capabilities, this macro either marks an outgoing
153189251Ssam * packet with hardware checksum offload information or calculate the
154189251Ssam * checksum in software.  If the latter is performed, the checksum field
155189251Ssam * of the dblk is cleared; otherwise it will be non-zero and contain the
156189251Ssam * necessary flag(s) for the driver.
157189251Ssam */
158189251Ssam#define	IP_CKSUM_XMIT_FAST(ipver, hck_flags, mp, ihp, up, proto, start,	\
159189251Ssam	    end, pseudo) {						\
160189251Ssam	uint32_t _sum;							\
161189251Ssam	/*								\
162189251Ssam	 * Underlying interface supports hardware checksum offload for	\
163189251Ssam	 * the payload; leave the payload checksum for the hardware to	\
164189251Ssam	 * calculate.  N.B: We only need to set up checksum info on the	\
165189251Ssam	 * first mblk.							\
166189251Ssam	 */								\
167189251Ssam	DB_CKSUMFLAGS(mp) = 0;						\
168189251Ssam	if (((ipver) == IPV4_VERSION &&					\
169189251Ssam	    ((hck_flags) & HCKSUM_INET_FULL_V4)) ||			\
170189251Ssam	    ((ipver) == IPV6_VERSION &&					\
171189251Ssam	    ((hck_flags) & HCKSUM_INET_FULL_V6))) {			\
172189251Ssam		/*							\
173189251Ssam		 * Hardware calculates pseudo-header, header and the	\
174189251Ssam		 * payload checksums, so clear the checksum field in	\
175189251Ssam		 * the protocol header.					\
176189251Ssam		 */							\
177189251Ssam		*(up) = 0;						\
178189251Ssam		DB_CKSUMFLAGS(mp) |= HCK_FULLCKSUM;			\
179189251Ssam	} else if ((hck_flags) & HCKSUM_INET_PARTIAL)  {		\
180189251Ssam		/*							\
181189251Ssam		 * Partial checksum offload has been enabled.  Fill	\
182189251Ssam		 * the checksum field in the protocl header with the	\
183189251Ssam		 * pseudo-header checksum value.			\
184189251Ssam		 */							\
185189251Ssam		_sum = ((proto) == IPPROTO_UDP) ?			\
186189251Ssam		    IP_UDP_CSUM_COMP : IP_TCP_CSUM_COMP;		\
187189251Ssam		_sum += *(up) + (pseudo);				\
188189251Ssam		_sum = (_sum & 0xFFFF) + (_sum >> 16);			\
189189251Ssam		*(up) = (_sum & 0xFFFF) + (_sum >> 16);			\
190189251Ssam		/*							\
191189251Ssam		 * Offsets are relative to beginning of IP header.	\
192189251Ssam		 */							\
193189251Ssam		DB_CKSUMSTART(mp) = (start);				\
194189251Ssam		DB_CKSUMSTUFF(mp) = ((proto) == IPPROTO_UDP) ?		\
195189251Ssam		    (start) + UDP_CHECKSUM_OFFSET :			\
196189251Ssam		    (start) + TCP_CHECKSUM_OFFSET;			\
197189251Ssam		DB_CKSUMEND(mp) = (end);				\
198189251Ssam		DB_CKSUMFLAGS(mp) |= HCK_PARTIALCKSUM;			\
199189251Ssam	} else {							\
200189251Ssam		/*							\
201189251Ssam		 * Software checksumming.				\
202189251Ssam		 */							\
203189251Ssam		_sum = ((proto) == IPPROTO_UDP) ?			\
204189251Ssam		    IP_UDP_CSUM_COMP : IP_TCP_CSUM_COMP;		\
205189251Ssam		_sum += (pseudo);					\
206189251Ssam		_sum = IP_CSUM(mp, start, _sum);			\
207189251Ssam		*(up) = (uint16_t)(_sum ? _sum : ~_sum);		\
208189251Ssam	}								\
209189251Ssam	/*								\
210189251Ssam	 * Hardware supports IP header checksum offload; clear the	\
211189251Ssam	 * contents of IP header checksum field as expected by NIC.	\
212189251Ssam	 * Do this only if we offloaded either full or partial sum.	\
213189251Ssam	 */								\
214189251Ssam	if ((ipver) == IPV4_VERSION && DB_CKSUMFLAGS(mp) != 0 &&	\
215189251Ssam	    ((hck_flags) & HCKSUM_IPHDRCKSUM)) {			\
216189251Ssam		DB_CKSUMFLAGS(mp) |= HCK_IPV4_HDRCKSUM;			\
217189251Ssam		((ipha_t *)(ihp))->ipha_hdr_checksum = 0;		\
218189251Ssam	}								\
219189251Ssam}
220189251Ssam
221189251Ssam/*
222189251Ssam * Macro to inspect the checksum of a fully-reassembled incoming datagram.
223189251Ssam */
224189251Ssam#define	IP_CKSUM_RECV_REASS(hck_flags, off, pseudo, sum, err) {		\
225189251Ssam	(err) = B_FALSE;						\
226189251Ssam	if ((hck_flags) & HCK_FULLCKSUM) {				\
227189251Ssam		/*							\
228189251Ssam		 * The sum of all fragment checksums should		\
229189251Ssam		 * result in -0 (0xFFFF) or otherwise invalid.		\
230189251Ssam		 */							\
231189251Ssam		if ((sum) != 0xFFFF)					\
232189251Ssam			(err) = B_TRUE;					\
233189251Ssam	} else if ((hck_flags) & HCK_PARTIALCKSUM) {			\
234189251Ssam		(sum) += (pseudo);					\
235189251Ssam		(sum) = ((sum) & 0xFFFF) + ((sum) >> 16);		\
236189251Ssam		(sum) = ((sum) & 0xFFFF) + ((sum) >> 16);		\
237189251Ssam		if (~(sum) & 0xFFFF)					\
238189251Ssam			(err) = B_TRUE;					\
239189251Ssam	} else if (((sum) = IP_CSUM(mp, off, pseudo)) != 0) {		\
240189251Ssam		(err) = B_TRUE;						\
241189251Ssam	}								\
242189251Ssam}
243189251Ssam
244189251Ssam/*
245189251Ssam * This macro inspects an incoming packet to see if the checksum value
246189251Ssam * contained in it is valid; if the hardware has provided the information,
247189251Ssam * the value is verified, otherwise it performs software checksumming.
248189251Ssam * The checksum value is returned to caller.
249189251Ssam */
250189251Ssam#define	IP_CKSUM_RECV(hck_flags, sum, cksum_start, ulph_off, mp, mp1, err) { \
251189251Ssam	int32_t _len;							\
252189251Ssam									\
253189251Ssam	(err) = B_FALSE;						\
254189251Ssam	if ((hck_flags) & HCK_FULLCKSUM) {				\
255189251Ssam		/*							\
256189251Ssam		 * Full checksum has been computed by the hardware	\
257189251Ssam		 * and has been attached.  If the driver wants us to	\
258189251Ssam		 * verify the correctness of the attached value, in	\
259189251Ssam		 * order to protect against faulty hardware, compare	\
260189251Ssam		 * it against -0 (0xFFFF) to see if it's valid.		\
261189251Ssam		 */							\
262189251Ssam		(sum) = DB_CKSUM16(mp);					\
263189251Ssam		if (!((hck_flags) & HCK_FULLCKSUM_OK) && (sum) != 0xFFFF) \
264189251Ssam			(err) = B_TRUE;					\
265189251Ssam	} else if (((hck_flags) & HCK_PARTIALCKSUM) &&			\
266189251Ssam	    ((mp1) == NULL || (mp1)->b_cont == NULL) &&			\
267189251Ssam	    (ulph_off) >= DB_CKSUMSTART(mp) &&				\
268189251Ssam	    ((_len = (ulph_off) - DB_CKSUMSTART(mp)) & 1) == 0) {	\
269189251Ssam		uint32_t _adj;						\
270189251Ssam		/*							\
271189251Ssam		 * Partial checksum has been calculated by hardware	\
272189251Ssam		 * and attached to the packet; in addition, any		\
273189251Ssam		 * prepended extraneous data is even byte aligned,	\
274189251Ssam		 * and there are at most two mblks associated with	\
275189251Ssam		 * the packet.  If any such data exists, we adjust	\
276189251Ssam		 * the checksum; also take care any postpended data.	\
277189251Ssam		 */							\
278189251Ssam		IP_ADJCKSUM_PARTIAL(cksum_start, mp, mp1, _len, _adj);	\
279189251Ssam		/*							\
280189251Ssam		 * One's complement subtract extraneous checksum	\
281189251Ssam		 */							\
282189251Ssam		(sum) += DB_CKSUM16(mp);				\
283189251Ssam		if (_adj >= (sum))					\
284189251Ssam			(sum) = ~(_adj - (sum)) & 0xFFFF;		\
285189251Ssam		else							\
286189251Ssam			(sum) -= _adj;					\
287189251Ssam		(sum) = ((sum) & 0xFFFF) + ((int)(sum) >> 16);		\
288189251Ssam		(sum) = ((sum) & 0xFFFF) + ((int)(sum) >> 16);		\
289189251Ssam		if (~(sum) & 0xFFFF)					\
290189251Ssam			(err) = B_TRUE;					\
291189251Ssam	} else if (((sum) = IP_CSUM(mp, ulph_off, sum)) != 0) {		\
292189251Ssam		(err) = B_TRUE;						\
293189251Ssam	}								\
294189251Ssam}
295189251Ssam
296189251Ssam/*
297189251Ssam * Macro to adjust a given checksum value depending on any prepended
298189251Ssam * or postpended data on the packet.  It expects the start offset to
299189251Ssam * begin at an even boundary and that the packet consists of at most
300189251Ssam * two mblks.
301189251Ssam */
302189251Ssam#define	IP_ADJCKSUM_PARTIAL(cksum_start, mp, mp1, len, adj) {		\
303189251Ssam	/*								\
304189251Ssam	 * Prepended extraneous data; adjust checksum.			\
305189251Ssam	 */								\
306189251Ssam	if ((len) > 0)							\
307189251Ssam		(adj) = IP_BCSUM_PARTIAL(cksum_start, len, 0);		\
308189251Ssam	else								\
309189251Ssam		(adj) = 0;						\
310189251Ssam	/*								\
311189251Ssam	 * len is now the total length of mblk(s)			\
312189251Ssam	 */								\
313189251Ssam	(len) = MBLKL(mp);						\
314189251Ssam	if ((mp1) == NULL)						\
315189251Ssam		(mp1) = (mp);						\
316189251Ssam	else								\
317189251Ssam		(len) += MBLKL(mp1);					\
318189251Ssam	/*								\
319189251Ssam	 * Postpended extraneous data; adjust checksum.			\
320189251Ssam	 */								\
321189251Ssam	if (((len) = (DB_CKSUMEND(mp) - len)) > 0) {			\
322189251Ssam		uint32_t _pad;						\
323189251Ssam									\
324189251Ssam		_pad = IP_BCSUM_PARTIAL((mp1)->b_wptr, len, 0);		\
325189251Ssam		/*							\
326189251Ssam		 * If the postpended extraneous data was odd		\
327189251Ssam		 * byte aligned, swap resulting checksum bytes.		\
328189251Ssam		 */							\
329189251Ssam		if ((uintptr_t)(mp1)->b_wptr & 1)			\
330189251Ssam			(adj) += ((_pad << 8) & 0xFFFF) | (_pad >> 8);	\
331189251Ssam		else							\
332189251Ssam			(adj) += _pad;					\
333189251Ssam		(adj) = ((adj) & 0xFFFF) + ((int)(adj) >> 16);		\
334189251Ssam	}								\
335189251Ssam}
336189251Ssam
337189251Ssam#define	ILL_MDT_CAPABLE(ill)		\
338189251Ssam	(((ill)->ill_capabilities & ILL_CAPAB_MDT) != 0)
339189251Ssam
340189251Ssam/*
341189251Ssam * ioctl identifier and structure for Multidata Transmit update
342189251Ssam * private M_CTL communication from IP to ULP.
343189251Ssam */
344189251Ssam#define	MDT_IOC_INFO_UPDATE	(('M' << 8) + 1020)
345189251Ssam
346189251Ssamtypedef struct ip_mdt_info_s {
347189251Ssam	uint_t	mdt_info_id;	/* MDT_IOC_INFO_UPDATE */
348189251Ssam	ill_mdt_capab_t	mdt_capab; /* ILL MDT capabilities */
349189251Ssam} ip_mdt_info_t;
350189251Ssam
351189251Ssam/*
352189251Ssam * Macro that determines whether or not a given ILL is allowed for MDT.
353189251Ssam */
354189251Ssam#define	ILL_MDT_USABLE(ill)						\
355189251Ssam	(ILL_MDT_CAPABLE(ill) &&					\
356189251Ssam	ill->ill_mdt_capab != NULL &&					\
357189251Ssam	ill->ill_mdt_capab->ill_mdt_version == MDT_VERSION_2 &&		\
358189251Ssam	ill->ill_mdt_capab->ill_mdt_on != 0)
359189251Ssam
360189251Ssam/*
361189251Ssam * Macro that determines whether or not a given CONN may be considered
362189251Ssam * for fast path prior to proceeding further with Multidata.
363189251Ssam */
364189251Ssam#define	CONN_IS_MD_FASTPATH(connp)	\
365189251Ssam	((connp)->conn_dontroute == 0 &&	/* SO_DONTROUTE */	\
366189251Ssam	!((connp)->conn_nexthop_set) &&		/* IP_NEXTHOP */	\
367189251Ssam	(connp)->conn_nofailover_ill == NULL &&	/* IPIF_NOFAILOVER */	\
368189251Ssam	(connp)->conn_xmit_if_ill == NULL &&	/* IP_XMIT_IF */	\
369189251Ssam	(connp)->conn_outgoing_pill == NULL &&	/* IP{V6}_BOUND_PIF */	\
370189251Ssam	(connp)->conn_outgoing_ill == NULL)	/* IP{V6}_BOUND_IF */
371189251Ssam
372189251Ssam/* Definitons for fragmenting IP packets using MDT. */
373189251Ssam
374189251Ssam/*
375189251Ssam * Smaller and private version of pdescinfo_t used specifically for IP,
376189251Ssam * which allows for only a single payload span per packet.
377189251Ssam */
378189251Ssamtypedef struct ip_pdescinfo_s PDESCINFO_STRUCT(2)	ip_pdescinfo_t;
379189251Ssam
380189251Ssam/*
381189251Ssam * Macro version of ip_can_frag_mdt() which avoids the function call if we
382189251Ssam * only examine a single message block.
383189251Ssam */
384189251Ssam#define	IP_CAN_FRAG_MDT(mp, hdr_len, len)			\
385189251Ssam	(((mp)->b_cont == NULL) ?				\
386189251Ssam	(MBLKL(mp) >= ((hdr_len) + ip_wput_frag_mdt_min)) :	\
387189251Ssam	ip_can_frag_mdt((mp), (hdr_len), (len)))
388189251Ssam
389189251Ssam/*
390189251Ssam * Macro that determines whether or not a given IPC requires
391189251Ssam * outbound IPSEC processing.
392189251Ssam */
393189251Ssam#define	CONN_IPSEC_OUT_ENCAPSULATED(connp)	\
394189251Ssam	((connp)->conn_out_enforce_policy ||	\
395189251Ssam	((connp)->conn_latch != NULL &&		\
396189251Ssam	(connp)->conn_latch->ipl_out_policy != NULL))
397189251Ssam
398189251Ssam/*
399189251Ssam * These are used by the synchronous streams code in tcp and udp.
400189251Ssam * When we set the flags for a wakeup from a synchronous stream we
401189251Ssam * always set RSLEEP in sd_wakeq, even if we have a read thread waiting
402189251Ssam * to do the io. This is in case the read thread gets interrupted
403189251Ssam * before completing the io. The RSLEEP flag in sd_wakeq is used to
404189251Ssam * indicate that there is data available at the synchronous barrier.
405189251Ssam * The assumption is that subsequent functions calls through rwnext()
406189251Ssam * will reset sd_wakeq appropriately.
407189251Ssam */
408189251Ssam#define	STR_WAKEUP_CLEAR(stp) {						\
409189251Ssam	mutex_enter(&stp->sd_lock);					\
410189251Ssam	stp->sd_wakeq &= ~RSLEEP;					\
411189251Ssam	mutex_exit(&stp->sd_lock);					\
412189251Ssam}
413189251Ssam
414189251Ssam#define	STR_WAKEUP_SET(stp) {						\
415189251Ssam	mutex_enter(&stp->sd_lock);					\
416189251Ssam	if (stp->sd_flag & RSLEEP) {					\
417189251Ssam		stp->sd_flag &= ~RSLEEP;				\
418189251Ssam		cv_broadcast(&_RD(stp->sd_wrq)->q_wait);		\
419189251Ssam	}								\
420189251Ssam	stp->sd_wakeq |= RSLEEP;					\
421189251Ssam	mutex_exit(&stp->sd_lock);					\
422189251Ssam}
423189251Ssam
424189251Ssam#define	STR_SENDSIG(stp) {						\
425189251Ssam	int _events;							\
426189251Ssam	mutex_enter(&stp->sd_lock);					\
427189251Ssam	if ((_events = stp->sd_sigflags & (S_INPUT | S_RDNORM)) != 0)	\
428189251Ssam		strsendsig(stp->sd_siglist, _events, 0, 0);		\
429189251Ssam	if (stp->sd_rput_opt & SR_POLLIN) {				\
430189251Ssam		stp->sd_rput_opt &= ~SR_POLLIN;				\
431189251Ssam		mutex_exit(&stp->sd_lock);				\
432189251Ssam		pollwakeup(&stp->sd_pollist, POLLIN | POLLRDNORM);	\
433189251Ssam	} else {							\
434189251Ssam		mutex_exit(&stp->sd_lock);				\
435189251Ssam	}								\
436189251Ssam}
437189251Ssam
438189251Ssam#define	CONN_UDP_SYNCSTR(connp)						\
439189251Ssam	(IPCL_IS_UDP(connp) && (connp)->conn_udp->udp_direct_sockfs)
440189251Ssam
441189251Ssam/*
442189251Ssam * Macro that checks whether or not a particular UDP conn is
443189251Ssam * flow-controlling on the read-side.  If udp module is directly
444189251Ssam * above ip, check to see if the drain queue is full; note here
445189251Ssam * that we check this without any lock protection because this
446189251Ssam * is a coarse granularity inbound flow-control.  If the module
447189251Ssam * above ip is not udp, then use canputnext to determine the
448189251Ssam * flow-control.
449189251Ssam *
450189251Ssam * Note that these checks are done after the conn is found in
451189251Ssam * the UDP fanout table.  A UDP conn in that table may have its
452189251Ssam * IPCL_UDP bit cleared from the conn_flags when the application
453189251Ssam * pops the udp module without issuing an unbind; in this case
454 * IP will still receive packets for the conn and deliver it
455 * upstream via putnext.  This is the reason why we have to test
456 * against IPCL_UDP.
457 */
458#define	CONN_UDP_FLOWCTLD(connp)					\
459	((CONN_UDP_SYNCSTR(connp) &&					\
460	(connp)->conn_udp->udp_drain_qfull) ||				\
461	(!CONN_UDP_SYNCSTR(connp) && !canputnext((connp)->conn_rq)))
462
463/*
464 * Macro that delivers a given message upstream; if udp module
465 * is directly above ip, the message is passed directly into
466 * the stream-less entry point.  Otherwise putnext is used.
467 */
468#define	CONN_UDP_RECV(connp, mp) {					\
469	if (IPCL_IS_UDP(connp))						\
470		udp_conn_recv(connp, mp);				\
471	else								\
472		putnext((connp)->conn_rq, mp);				\
473}
474
475#define	ILL_DLS_CAPABLE(ill)	\
476	(((ill)->ill_capabilities &		\
477	(ILL_CAPAB_POLL|ILL_CAPAB_SOFT_RING)) != 0)
478
479/*
480 * Macro that hands off one or more messages directly to DLD
481 * when the interface is marked with ILL_CAPAB_POLL.
482 */
483#define	IP_DLS_ILL_TX(ill, mp) {					\
484	ill_dls_capab_t *ill_dls = ill->ill_dls_capab;		\
485	ASSERT(ILL_DLS_CAPABLE(ill));					\
486	ASSERT(ill_dls != NULL);					\
487	ASSERT(ill_dls->ill_tx != NULL);				\
488	ASSERT(ill_dls->ill_tx_handle != NULL);			\
489	ill_dls->ill_tx(ill_dls->ill_tx_handle, mp);			\
490}
491
492extern int	ip_wput_frag_mdt_min;
493extern boolean_t ip_can_frag_mdt(mblk_t *, ssize_t, ssize_t);
494
495#endif	/* _KERNEL */
496
497#ifdef	__cplusplus
498}
499#endif
500
501#endif	/* _INET_IP_IMPL_H */
502