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