ip_output.c revision d3d50737e566cade9a08d73d2af95105ac7cd960
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A/* Copyright (c) 1990 Mentat Inc. */ 2N/A * There are two types of output functions for IP used for different 2N/A * - ip_output_simple() is when sending ICMP errors, TCP resets, etc when there 2N/A * is no context in the form of a conn_t. However, there is a 2N/A * ip_xmit_attr_t that the callers use to influence interface selection 2N/A * (needed for ICMP echo as well as IPv6 link-locals) and IPsec. 2N/A * - conn_ip_output() is used when sending packets with a conn_t and 2N/A * ip_set_destination has been called to cache information. In that case 2N/A * various socket options are recorded in the ip_xmit_attr_t and should 2N/A * be taken into account. 2N/A * The caller *must* have called conn_connect() or ip_attr_connect() 2N/A * before calling conn_ip_output(). The caller needs to redo that each time 2N/A * the destination IP address or port changes, as well as each time there is 2N/A * a change to any socket option that would modify how packets are routed out 2N/A * of the box (e.g., SO_DONTROUTE, IP_NEXTHOP, IP_BOUND_IF). 2N/A * The ULP caller has to serialize the use of a single ip_xmit_attr_t. 2N/A * We assert for that here. 2N/A /* We defer ipIfStatsHCOutRequests until an error or we have an ill */ 2N/A /* Note there is no ixa_nce when reject and blackhole routes */ 2N/A * Even on labeled systems we can have a NULL ixa_tsl e.g., 2N/A * If the ULP says the (old) IRE resulted in reachability we 2N/A * record this before determine whether to use a new IRE. 2N/A * No locking for performance reasons. 2N/A * Has routing changed since we cached the results of the lookup? 2N/A * This check captures all of: 2N/A * - the cached ire being deleted (by means of the special 2N/A * IRE_GENERATION_CONDEMNED) 2N/A * - A potentially better ire being added (ire_generation being 2N/A * - A deletion of the nexthop ire that was used when we did the 2N/A * - An addition of a potentially better nexthop ire. 2N/A * The last two are handled by walking and increasing the generation 2N/A * number on all dependant IREs in ire_flush_cache(). 2N/A * The check also handles all cases of RTF_REJECT and RTF_BLACKHOLE 2N/A * since we ensure that each time we set ixa_ire to such an IRE we 2N/A * make sure the ixa_ire_generation does not match (by using 2N/A * IRE_GENERATION_VERIFY). 2N/A /* ixa_dce might be condemned; use default one */ 2N/A * If the ncec changed then ip_verify_ire already set 2N/A * ixa->ixa_dce_generation = DCE_GENERATION_VERIFY; 2N/A * so we can recheck the interface mtu. 2N/A * Note that ire->ire_generation could already have changed. 2N/A * We catch that next time we send a packet. 2N/A * No need to lock access to ixa_nce since the ip_xmit_attr usage 2N/A * is single threaded. 2N/A * In case ZEROCOPY capability become not available, we 2N/A * copy the message and free the original one. We might 2N/A * be copying more data than needed but it doesn't hurt 2N/A * since such change rarely happens. 2N/A /* ixa_dce might be condemned; use default one */ 2N/A * Note that some other event could already have made 2N/A * the new nce condemned. We catch that next time we 2N/A * try to send a packet. 2N/A * If there is no per-destination dce_t then we have a reference to 2N/A * the default dce_t (which merely contains the dce_ipid). 2N/A * The generation check captures both the introduction of a 2N/A * per-destination dce_t (e.g., due to ICMP packet too big) and 2N/A * any change to the per-destination dce (including it becoming 2N/A * condemned by use of the special DCE_GENERATION_CONDEMNED). 2N/A * To avoid a periodic timer to increase the path MTU we 2N/A * look at dce_last_change_time each time we send a packet. 2N/A * Older than 20 minutes. Drop the path MTU information. 2N/A * Since the path MTU changes as a result of this, twiddle 2N/A * ixa_dce_generation to make us go through the dce 2N/A * verification code in conn_ip_output. 2N/A * Note that some other event could already have made the 2N/A * new dce's generation number change. 2N/A * We catch that next time we try to send a packet. 2N/A * An initial ixa_fragsize was set in ip_set_destination 2N/A * and we update it if any routing changes above. 2N/A * A change to ill_mtu with ifconfig will increase all dce_generation 2N/A * so that we will detect that with the generation check. 2N/A * Caller needs to make sure IXAF_VERIFY_SRC is not set if 2N/A /* Check if the IP source is still assigned to the host. */ 2N/A /* Don't send a packet with a source that isn't ours */ 2N/A /* The source is still valid - update the generation number */ 2N/A * We don't have an IRE when we fragment, hence ire_ob_pkt_count 2N/A * can only count the use prior to fragmentation. However the MIB 2N/A * counters on the ill will be incremented in post fragmentation. 2N/A * Based on ire_type and ire_flags call one of: 2N/A * ire_send_local_v* - for IRE_LOCAL and IRE_LOOPBACK 2N/A * ire_send_multirt_v* - if RTF_MULTIRT 2N/A * ire_send_noroute_v* - if RTF_REJECT or RTF_BLACHOLE 2N/A * ire_send_multicast_v* - for IRE_MULTICAST 2N/A * ire_send_broadcast_v4 - for IRE_BROADCAST 2N/A * ire_send_wire_v* - for the rest. 2N/A * Handle both IPv4 and IPv6. Sets the generation number 2N/A * to allow the caller to know when to call us again. 2N/A * Returns true if the source address in the packet is a valid source. 2N/A * We handle callers which try to send with a zero address (since we only 2N/A * get here if UNSPEC_SRC is not set). 2N/A * Need to grab the generation number before we check to 2N/A * avoid a race with a change to the set of local addresses. 2N/A * No lock needed since the thread which updates the set of local 2N/A * addresses use ipif/ill locks and exit those (hence a store memory 2N/A * barrier) before doing the atomic increase of ips_src_generation. 2N/A * Redo ip_select_route. 2N/A * Need to grab generation number as part of the lookup to 2N/A * Don't look for an nce for reject or blackhole. 2N/A * They have ire_generation set to IRE_GENERATION_VERIFY which 2N/A * makes conn_ip_output avoid references to ixa_nce. 2N/A /* The NCE could now be different */ 2N/A * Allocation failure. Make sure we redo ire/nce selection 2N/A * next time we send. 2N/A * Since the path MTU might change as a result of this 2N/A * route change, we twiddle ixa_dce_generation to 2N/A * make conn_ip_output go through the ip_verify_dce code. 2N/A /* Try to find a better ire */ 2N/A * The hardware offloading capabilities, for example LSO, of the 2N/A * interface might have changed, so do sanity verification here. 2N/A * Verify ZEROCOPY capability of underlying ill. Notify the ULP with 2N/A * any ZEROCOPY changes. In case ZEROCOPY capability is not available 2N/A * any more, return error so that conn_ip_output() can take care of 2N/A * the ZEROCOPY message properly. It's safe to continue send the 2N/A * message when ZEROCOPY newly become available. 2N/A * Since the path MTU might change as a result of this 2N/A * change, we twiddle ixa_dce_generation to 2N/A * make conn_ip_output go through the ip_verify_dce code. 2N/A /* Extract the (path) mtu from the dce, ncec_ill etc */ 2N/A * Tell ULP about PMTU changes - increase or decrease - by returning 2N/A * an error if IXAF_VERIFY_PMTU is set. In such case, ULP should update 2N/A * both ixa_pmtu and ixa_fragsize appropriately. 2N/A * If ULP doesn't set that flag then we need to update ixa_fragsize 2N/A * since routing could have changed the ill after after ixa_fragsize 2N/A * was set previously in the conn_ip_output path or in 2N/A * ip_set_destination. 2N/A * In case of LSO, ixa_fragsize might be greater than ixa_pmtu. 2N/A * In the case of a path MTU increase we send the packet after the 2N/A * notify to the ULP. 2N/A * Verify LSO usability. Keep the return value simple to indicate whether 2N/A * the LSO capability has changed. Handle both IPv4 and IPv6. 2N/A * Not unsable any more. 2N/A * Capability has changed, refresh the copy in ixa. 2N/A }
else {
/* Was not usable */ 2N/A * Verify ZEROCOPY usability. Keep the return value simple to indicate whether 2N/A * the ZEROCOPY capability has changed. Handle both IPv4 and IPv6. 2N/A * Not unsable any more. 2N/A }
else {
/* Was not usable */ 2N/A * When there is no conn_t context, this will send a packet. 2N/A * The caller must *not* have called conn_connect() or ip_attr_connect() 2N/A * before calling ip_output_simple(). 2N/A * Handles IPv4 and IPv6. Returns zero or an errno such as ENETUNREACH. 2N/A * Honors IXAF_SET_SOURCE. 2N/A * We acquire the ire and after calling ire_sendfn we release 2N/A * the hold on the ire. Ditto for the nce and dce. 2N/A * This assumes that the caller has set the following in ip_xmit_attr_t: 2N/A * ixa_tsl, ixa_zoneid, and ixa_ipst must always be set. 2N/A * If ixa_ifindex is non-zero it means send out that ill. (If it is 2N/A * an upper IPMP ill we load balance across the group; if a lower we send 2N/A * on that lower ill without load balancing.) 2N/A * IXAF_IS_IPV4 must be set correctly. 2N/A * If IXAF_IPSEC_SECURE is set then the ixa_ipsec_* fields must be set. 2N/A * If IXAF_NO_IPSEC is set we'd skip IPsec policy lookup. 2N/A * If neither of those two are set we do an IPsec policy lookup. 2N/A * We handle setting things like 2N/A * The caller may set ixa_xmit_hint, which is used for ECMP selection and 2N/A * transmit ring selecting in GLD. 2N/A * The caller must do an ixa_cleanup() to release any IPsec references 2N/A /* Update the label */ 2N/A * Even on labeled systems we can have a NULL ixa_tsl e.g., 2N/A /* Caller already set flags */ 2N/A * Assumes that source routed packets have already been massaged by 2N/A * the ULP (ip_massage_options) and as a result ipha_dst is the next 2N/A * hop in the source route. The final destination is used for IPsec 2N/A * policy and DCE lookup. 2N/A /* ire_ill might be NULL hence need to skip some code */ 2N/A /* No dce yet; use default one */ 2N/A /* Note that ipha_dst is only used for IRE_MULTICAST */ 2N/A /* Allocation failure? */ 2N/A /* Try finding a better IRE */ 2N/A /* Tried twice - drop packet */ 2N/A * For multicast with multirt we have a flag passed back from 2N/A * ire_lookup_multi_ill_v4 since we don't have an IRE for each 2N/A * possible multicast address. 2N/A * We also need a flag for multicast since we can't check 2N/A * whether RTF_MULTIRT is set in ixa_ire for multicast. 2N/A * Check for a dce_t with a path mtu. 2N/A * To avoid a periodic timer to increase the path MTU we 2N/A * look at dce_last_change_time each time we send a packet. 2N/A * Older than 20 minutes. Drop the path MTU information. 2N/A * We use use ire_nexthop_ill (and not ncec_ill) to avoid the under ipmp 2N/A * interface for source address selection. 2N/A * We use the final destination to get 2N/A * correct selection for source routed packets 2N/A /* If unreachable we have no ill but need some source */ 2N/A /* Check if the IP source is assigned to the host. */ 2N/A /* Don't send a packet with a source that isn't ours */ 2N/A * Check against global IPsec policy to set the AH/ESP attributes. 2N/A * IPsec will set IXAF_IPSEC_* and ixa_ipsec_* as appropriate. 2N/A /* MIB and ip_drop_packet already done */ 2N/A * We update the statistics on the most specific IRE i.e., the first 2N/A * We don't have an IRE when we fragment, hence ire_ob_pkt_count 2N/A * can only count the use prior to fragmentation. However the MIB 2N/A * counters on the ill will be incremented in post fragmentation. 2N/A * Based on ire_type and ire_flags call one of: 2N/A * ire_send_local_v4 - for IRE_LOCAL and IRE_LOOPBACK 2N/A * ire_send_multirt_v4 - if RTF_MULTIRT 2N/A * ire_send_noroute_v4 - if RTF_REJECT or RTF_BLACHOLE 2N/A * ire_send_multicast_v4 - for IRE_MULTICAST 2N/A * ire_send_broadcast_v4 - for IRE_BROADCAST 2N/A * ire_send_wire_v4 - for the rest. 2N/A * ire_sendfn() functions. 2N/A * These functions use the following xmit_attr: 2N/A * - ixa_fragsize - read to determine whether or not to fragment 2N/A * - IXAF_IPSEC_SECURE - to determine whether or not to invoke IPsec 2N/A * - ixa_ipsec_* are used inside IPsec 2N/A * - IXAF_SET_SOURCE - replace IP source in broadcast case. 2N/A * - IXAF_LOOPBACK_COPY - for multicast and broadcast 2N/A * ire_sendfn for IRE_LOCAL and IRE_LOOPBACK 2N/A * The checks for restrict_interzone_loopback are done in ire_route_recursive. 2N/A * No fragmentation, no nce, no application of IPsec, 2N/A * and no ipha_ident assignment. 2N/A * Note different order between IP provider and FW_HOOKS than in 2N/A * DTrace this as ip:::send. A packet blocked by FW_HOOKS will fire the 2N/A * send probe, but not the receive probe. 2N/A * Even if the destination was changed by the filter we use the 2N/A * forwarding decision that was made based on the address 2N/A /* Length could be different */ 2N/A * If a callback is enabled then we need to know the 2N/A * source and destination zoneids for the packet. We already 2N/A /* Shared-IP zone */ 2N/A /* Handle lo0 stats */ 2N/A /* Map ixa to ira including IPsec policies */ 2N/A * Even if the destination was changed by the filter we use the 2N/A * forwarding decision that was made based on the address 2N/A /* Length could be different */ 2N/A /* Destined to ire_zoneid - use that for fanout */ 2N/A * This updates ira_cred, ira_tsl and ira_free_flags based 2N/A * on the label. We don't expect this to ever fail for 2N/A * loopback packets, so we silently drop the packet should it 2N/A /* tsol_get_pkt_label sometimes does pullupmsg */ 2N/A /* We moved any IPsec refs from ixa to iras */ 2N/A * ire_sendfn for IRE_BROADCAST 2N/A * If the broadcast address is present on multiple ills and ixa_ifindex 2N/A * isn't set, then we generate 2N/A * a separate datagram (potentially with different source address) for 2N/A * those ills. In any case, only one copy is looped back to ip_input_v4. 2N/A * Unless ire_send_multirt_v4 already set a ttl, force the 2N/A * ttl to a smallish value. 2N/A * To avoid broadcast storms, we usually set the TTL to 1 for 2N/A * broadcasts. This can 2N/A * be overridden stack-wide through the ip_broadcast_ttl 2N/A * ndd tunable, or on a per-connection basis through the 2N/A * IP_BROADCAST_TTL socket option. 2N/A * will force ttl to one after we've set this. 2N/A * Make sure we get a loopback copy (after IPsec and frag) 2N/A * Skip hardware checksum so that loopback copy is checksumed. 2N/A /* Do we need to potentially generate multiple copies? */ 2N/A * Loop over all IRE_BROADCAST in the bucket (might only be one). 2N/A * Note that everything in the bucket has the same destination address. 2N/A /* We do the main IRE after the end of the loop */ 2N/A * Only IREs for the same IP address should be in the same 2N/A * But could have IRE_HOSTs in the case of CGTP. 2N/A * If we find any multirt routes we bail out of the loop 2N/A * and just do the single packet at the end; ip_postfrag_multirt 2N/A * will duplicate the packet. 2N/A * For IPMP we only send for the ipmp_ill. arp_nce_init() will 2N/A * ensure that this goes out on the cast_ill. 2N/A * Need to pick a different source address for each 2N/A * interface. If we have a global IPsec policy and 2N/A * no per-socket policy then we punt to 2N/A * ip_output_simple_v4 using a separate ip_xmit_attr_t. 2N/A /* Pick a new source address for each interface */ 2N/A * Check against global IPsec policy to set the AH/ESP 2N/A * attributes. IPsec will set IXAF_IPSEC_* and 2N/A * ixa_ipsec_* as appropriate. 2N/A * MIB and ip_drop_packet already 2N/A /* Make sure we have an NCE on this ill */ 2N/A * Ignore any errors here. We just collect the errno for 2N/A * the main ire below 2N/A /* Finally, the main one */ 2N/A * For IPMP we only send broadcasts on the ipmp_ill. 2N/A * Send a packet using a different source address and different 2N/A /* Limit the TTL on multirt packets */ 2N/A ip2dbg((
"ire_send_multirt_v4: forcing multicast " 2N/A "multirt TTL to 1 (was %d), dst 0x%08x\n",
2N/A * Need to ensure we don't increase the ttl should we go through 2N/A * ire_send_broadcast or multicast. 2N/A * ire_sendfn for IRE_MULTICAST 2N/A * The IRE_MULTICAST is the same whether or not multirt is in use. 2N/A * Hence we need special-case code. 2N/A * Check if anything in ip_input_v4 wants a copy of the transmitted 2N/A * packet (after IPsec and fragmentation) 2N/A * 1. Multicast routers always need a copy unless SO_DONTROUTE is set 2N/A * RSVP and the rsvp daemon is an example of a 2N/A * protocol and user level process that 2N/A * handles it's own routing. Hence, it uses the 2N/A * SO_DONTROUTE option to accomplish this. 2N/A * 2. If the sender has set IP_MULTICAST_LOOP, then we just 2N/A * check whether there are any receivers for the group on the ill 2N/A * (ignoring the zoneid). 2N/A * 3. If IP_MULTICAST_LOOP is not set, then we check if there are 2N/A * any members in other shared-IP zones. 2N/A * If such members exist, then we indicate that the sending zone 2N/A * shouldn't get a loopback copy to preserve the IP_MULTICAST_LOOP 2N/A * When we loopback we skip hardware checksum to make sure loopback 2N/A * copy is checksumed. 2N/A * Note that ire_ill is the upper in the case of IPMP. 2N/A * If this zone or any other zone has members then loopback 2N/A * This zone should not have a copy. But there are some other 2N/A * zones which might have members. 2N/A * Unless ire_send_multirt_v4 or icmp_output_hdrincl already set a ttl, 2N/A * force the ttl to the IP_MULTICAST_TTL value 2N/A * ire_sendfn for IREs with RTF_MULTIRT 2N/A /* We assign an IP ident for nice errors */ 2N/A /* A lack of a route as opposed to RTF_REJECT|BLACKHOLE */ 2N/A /* No error even for local senders - silent blackhole */ 2N/A * We need an ill_t for the ip_recv_attr_t even though this packet 2N/A * was never received and icmp_unreachable doesn't currently use 2N/A /* Map ixa to ira including IPsec policies */ 2N/A /* We moved any IPsec refs from ixa to iras */ 2N/A * Calculate a checksum ignoring any hardware capabilities 2N/A * Returns B_FALSE if the packet was too short for the checksum. Caller 2N/A * should free and do stats. 2N/A /* Just in case it contained garbage */ 2N/A * Calculate ULP checksum 2N/A * Zero out the checksum field to ensure proper 2N/A * checksum calculation. 2N/A /* ULP puts the checksum field is in the first mblk */ 2N/A * We accumulate the pseudo header checksum in cksum. 2N/A * This is pretty hairy code, so watch close. One 2N/A * thing to keep in mind is that UDP and TCP have 2N/A * stored their respective datagram lengths in their 2N/A * checksum fields. This lines things up real nice. 2N/A * For UDP/IPv4 a zero means that the packets wasn't checksummed. 2N/A /* Calculate IPv4 header checksum */ 2N/A * Calculate the ULP checksum - try to use hardware. 2N/A * In the case of MULTIRT, broadcast or multicast the 2N/A * IXAF_NO_HW_CKSUM is set in which case we use software. 2N/A * If the hardware supports IP header checksum offload; then clear the 2N/A * contents of IP header checksum field as expected by NIC. 2N/A * Do this only if we offloaded either full or partial sum. 2N/A * Returns B_FALSE if the packet was too short for the checksum. Caller 2N/A * should free and do stats. 2N/A * Calculate ULP checksum. Note that we don't use cksump and cksum 2N/A * if the ill has FULL support. 2N/A * Zero out the checksum field to ensure proper 2N/A * checksum calculation. 2N/A /* Calculate IPv4 header checksum */ 2N/A /* ULP puts the checksum field is in the first mblk */ 2N/A * Underlying interface supports hardware checksum offload for 2N/A * the payload; leave the payload checksum for the hardware to 2N/A * calculate. N.B: We only need to set up checksum info on the 2N/A * Hardware calculates pseudo-header, header and the 2N/A * payload checksums, so clear the checksum field in 2N/A * the protocol header. 2N/A * Partial checksum offload has been enabled. Fill 2N/A * the checksum field in the protocol header with the 2N/A * pseudo-header checksum value. 2N/A * We accumulate the pseudo header checksum in cksum. 2N/A * This is pretty hairy code, so watch close. One 2N/A * thing to keep in mind is that UDP and TCP have 2N/A * stored their respective datagram lengths in their 2N/A * checksum fields. This lines things up real nice. 2N/A * Offsets are relative to beginning of IP header. 2N/A /* Hardware capabilities include neither full nor partial IPv4 */ 2N/A * ire_sendfn for offlink and onlink destinations. 2N/A * Also called from the multicast, broadcast, multirt send functions. 2N/A * Assumes that the caller has a hold on the ire. 2N/A * This function doesn't care if the IRE just became condemned since that 2N/A * can happen at any time. 2N/A * Assign an ident value for this packet. There could be other 2N/A * threads targeting the same destination, so we have to arrange 2N/A * for a atomic increment. Note that we use a 32-bit atomic add 2N/A * because it has better performance than its 16-bit sibling. 2N/A * Normally ixa_extra_ident is 0, but in the case of LSO it will 2N/A * extraly construct. 2N/A * If running in cluster mode and if the source address 2N/A * belongs to a replicated service then vector through 2N/A * cl_inet_ipident vector to allocate ip identifier 2N/A * NOTE: This is a contract private interface with the 2N/A * Note: not correct with LSO since we can't allocate 2N/A * ixa_extra_ident+1 consecutive values. 2N/A * This might set b_band, thus the IPsec and fragmentation 2N/A * code in IP ensures that b_band is updated in the first mblk. 2N/A /* ip_process translates an IS_UNDER_IPMP */ 2N/A /* ip_drop_packet and MIB done */ 2N/A return (0);
/* Might just be delayed */ 2N/A * Verify any IPv4 options. 2N/A * The presense of IP options also forces the network stack to 2N/A * calculate the checksum in software. This is because: 2N/A * Wrap around: certain partial-checksum NICs (eri, ce) limit 2N/A * the size of "start offset" width to 6-bit. This effectively 2N/A * sets the largest value of the offset to 64-bytes, starting 2N/A * from the MAC header. When the cumulative MAC and IP headers 2N/A * exceed such limit, the offset will wrap around. This causes 2N/A * the checksum to be calculated at the wrong place. 2N/A * IPv4 source routing: none of the full-checksum capable NICs 2N/A * is capable of correctly handling the IPv4 source-routing 2N/A * option for purposes of calculating the pseudo-header; the 2N/A * actual destination is different from the destination in the 2N/A * header which is that of the next-hop. (This case may not be 2N/A * true for NICs which can parse IPv6 extension headers, but 2N/A * we choose to simplify the implementation by not offloading 2N/A * checksum when they are present.) 2N/A /* An IS_UNDER_IPMP ill is ok here */ 2N/A /* Packet has been consumed and ICMP error sent */ 2N/A * while we still have ixa_tsl 2N/A * Compute ULP checksum and IP header checksum 2N/A /* Calculate IPv4 header checksum */ 2N/A * If this packet would generate a icmp_frag_needed 2N/A * message, we need to handle it before we do the IPsec 2N/A * processing. Otherwise, we need to strip the IPsec 2N/A * headers before we send up the message to the ULPs 2N/A * which becomes messy and difficult. 2N/A * We check using IXAF_DONTFRAG. The DF bit in the header 2N/A * is not inspected - it will be copied to any generated 2N/A /* Generate ICMP and return error */ 2N/A /* Map ixa to ira including IPsec policies */ 2N/A /* We moved any IPsec refs from ixa to iras */ 2N/A * Pass in sufficient information so that 2N/A * IPsec can determine whether to fragment, and 2N/A * which function to call after fragmentation. 2N/A /* Compute ULP checksum and IP header checksum */ 2N/A /* An IS_UNDER_IPMP ill is ok here */ 2N/A /* Calculate IPv4 header checksum */ 2N/A * Send mp into ip_input 2N/A * Common for IPv4 and IPv6 2N/A /* Broadcast and multicast doesn't care about the squeue */ 2N/A /* Any references to clean up? No hold on ira */ 2N/A * Post fragmentation function for IRE_MULTICAST and IRE_BROADCAST which 2N/A * looks at the IXAF_LOOPBACK_COPY flag. 2N/A * Common for IPv4 and IPv6. 2N/A * If the loopback copy fails (due to no memory) but we send the packet out 2N/A * on the wire we return no failure. Only in the case we supress the wire 2N/A * sending do we take the loopback failure into account. 2N/A * Note that we do not perform DTRACE_IP7 and FW_HOOKS for the looped back copy. 2N/A * Those operations are performed on this packet in ip_xmit() and it would 2N/A * be odd to do it twice for the same packet. 2N/A * Check for IXAF_LOOPBACK_COPY - send a copy to ip as if the driver 2N/A * had looped it back 2N/A /* Failed to deliver the loopback copy. */ 2N/A * If TTL = 0 then only do the loopback to this host i.e. we are 2N/A * done. We are also done if this was the 2N/A * loopback interface since it is sufficient 2N/A * to loopback one copy of a multicast packet. 2N/A /* Loopback interface */ 2N/A * Post fragmentation function for RTF_MULTIRT routes. 2N/A * Since IRE_BROADCASTs can have RTF_MULTIRT, this function 2N/A * checks IXAF_LOOPBACK_COPY. 2N/A * If no packet is sent due to failures then we return an errno, but if at 2N/A * least one succeeded we return zero. 2N/A /* Check for IXAF_LOOPBACK_COPY */ 2N/A /* Failed to deliver the loopback copy. */ 2N/A * Loop over RTF_MULTIRT for ipha_dst in the same bucket. Send 2N/A * a copy to each one. 2N/A * Use the nce (nexthop) and ipha_dst to find the ire. 2N/A * MULTIRT is not designed to work with shared-IP zones thus we don't 2N/A * need to pass a zoneid or a label to the IRE lookup. 2N/A /* Broadcast and multicast case */ 2N/A * For broadcast we can have a mixture of IRE_BROADCAST and 2N/A * IRE_HOST due to the manually added IRE_HOSTs that are used 2N/A * to trigger the creation of the special CGTP broadcast routes. 2N/A * Thus we have to skip if ire_type doesn't match the original. 2N/A /* Do the ire argument one after the loop */ 2N/A * This ire might not have been picked by 2N/A * ire_route_recursive, in which case ire_dep might 2N/A * not have been setup yet. 2N/A * We kick ire_route_recursive to try to resolve 2N/A /* Pick the addr and type to use for arp_nce_init */ 2N/A /* If IPMP meta or under, then we just drop */ 2N/A /* Preserve HW checksum for this copy */ 2N/A /* Finally, the main one */ 2N/A * Verify local connectivity. This check is called by ULP fusion code. 2N/A * The generation number on an IRE_LOCAL or IRE_LOOPBACK only changes if 2N/A * the interface is brought down and back up. So we simply fail the local 2N/A * process. The caller, TCP Fusion, should unfuse the connection. 2N/A * Local process for ULP loopback, TCP Fusion. Handle both IPv4 and IPv6. 2N/A * The caller must call ip_output_verify_local() first. This function handles 2N/A * IPobs, FW_HOOKS, and/or IPsec cases sequentially. 2N/A * If a callback is enabled then we need to know the 2N/A * source and destination zoneids for the packet. We already 2N/A /* Shared-IP zone */ 2N/A /* FW_HOOKS: LOOPBACK_OUT */ 2N/A /* FW_HOOKS: LOOPBACK_IN */ 2N/A /* Inbound IPsec polocies */ 2N/A /* Map ixa to ira including IPsec policies. */ 2N/A * If a callback is enabled then we need to know the 2N/A * source and destination zoneids for the packet. We already 2N/A /* Shared-IP zone */ 2N/A /* FW_HOOKS: LOOPBACK_OUT */ 2N/A /* FW_HOOKS: LOOPBACK_IN */ 2N/A /* Inbound IPsec polocies */ 2N/A /* Map ixa to ira including IPsec policies. */