4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved.
26 * Copyright 2018 Joyent, Inc.
27 * Copyright 2024 Oxide Computer Company
29 /* Copyright (c) 1990 Mentat Inc. */
31 #include <sys/types.h>
32 #include <sys/stream.h>
33 #include <sys/strsubr.h>
35 #include <sys/strsun.h>
38 #include <sys/sunddi.h>
39 #include <sys/cmn_err.h>
40 #include <sys/debug.h>
41 #include <sys/atomic.h>
43 #include <sys/systm.h>
44 #include <sys/param.h>
47 #include <sys/socket.h>
50 #include <net/if_arp.h>
51 #include <net/route.h>
52 #include <sys/sockio.h>
53 #include <netinet/in.h>
54 #include <net/if_dl.h>
56 #include <inet/common.h>
58 #include <inet/mib2.h>
61 #include <inet/snmpcom.h>
62 #include <inet/kstatcom.h>
64 #include <netinet/igmp_var.h>
65 #include <netinet/ip6.h>
66 #include <netinet/icmp6.h>
67 #include <netinet/sctp.h>
70 #include <inet/ip_impl.h>
72 #include <inet/ip6_asp.h>
74 #include <inet/ip_multi.h>
75 #include <inet/ip_if.h>
76 #include <inet/ip_ire.h>
77 #include <inet/ip_ftable.h>
78 #include <inet/ip_rts.h>
79 #include <inet/optcom.h>
80 #include <inet/ip_ndp.h>
81 #include <inet/ip_listutils.h>
82 #include <netinet/igmp.h>
83 #include <netinet/ip_mroute.h>
84 #include <inet/ipp_common.h>
86 #include <net/pfkeyv2.h>
87 #include <inet/sadb.h>
88 #include <inet/ipsec_impl.h>
89 #include <inet/ipdrop.h>
90 #include <inet/ip_netinfo.h>
92 #include <sys/pattr.h>
93 #include <inet/ipclassifier.h>
94 #include <inet/sctp_ip.h>
95 #include <inet/sctp/sctp_impl.h>
96 #include <inet/udp_impl.h>
97 #include <sys/sunddi.h>
99 #include <sys/tsol/label.h>
100 #include <sys/tsol/tnet.h>
103 extern boolean_t skip_sctp_cksum
;
107 ip_output_simple_v6(mblk_t
*mp
, ip_xmit_attr_t
*ixa
)
110 in6_addr_t firsthop
; /* In IP header */
111 in6_addr_t dst
; /* End of source route, or ip6_dst if none */
118 iaflags_t ixaflags
= ixa
->ixa_flags
;
119 ip_stack_t
*ipst
= ixa
->ixa_ipst
;
121 boolean_t repeat
= B_FALSE
;
122 boolean_t multirt
= B_FALSE
;
126 ip6h
= (ip6_t
*)mp
->b_rptr
;
127 ASSERT(IPH_HDR_VERSION(ip6h
) == IPV6_VERSION
);
129 ASSERT(ixa
->ixa_nce
== NULL
);
131 ixa
->ixa_pktlen
= ntohs(ip6h
->ip6_plen
) + IPV6_HDR_LEN
;
132 ASSERT(ixa
->ixa_pktlen
== msgdsize(mp
));
133 if (!ip_hdr_length_nexthdr_v6(mp
, ip6h
, &ixa
->ixa_ip_hdr_length
,
135 /* Malformed packet */
136 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsHCOutRequests
);
137 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsOutDiscards
);
138 ip_drop_output("ipIfStatsOutDiscards", mp
, NULL
);
142 ixa
->ixa_protocol
= *nexthdrp
;
145 * Assumes that source routed packets have already been massaged by
146 * the ULP (ip_massage_options_v6) and as a result ip6_dst is the next
147 * hop in the source route. The final destination is used for IPsec
148 * policy and DCE lookup.
150 firsthop
= ip6h
->ip6_dst
;
151 dst
= ip_get_dst_v6(ip6h
, mp
, NULL
);
155 setsrc
= ipv6_all_zeros
;
156 ire
= ip_select_route_v6(&firsthop
, ip6h
->ip6_src
, ixa
, NULL
, &setsrc
,
158 ASSERT(ire
!= NULL
); /* IRE_NOROUTE if none found */
160 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsHCOutRequests
);
161 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsOutDiscards
);
162 ip_drop_output("ipIfStatsOutDiscards", mp
, NULL
);
167 if (ire
->ire_flags
& (RTF_BLACKHOLE
|RTF_REJECT
)) {
168 /* ire_ill might be NULL hence need to skip some code */
169 if (ixaflags
& IXAF_SET_SOURCE
)
170 ip6h
->ip6_src
= ipv6_loopback
;
171 ixa
->ixa_fragsize
= IP_MAXPACKET
;
172 ire
->ire_ob_pkt_count
++;
173 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsHCOutRequests
);
174 /* No dce yet; use default one */
175 error
= (ire
->ire_sendfn
)(ire
, mp
, ip6h
, ixa
,
176 &ipst
->ips_dce_default
->dce_ident
);
180 /* Note that ip6_dst is only used for IRE_MULTICAST */
181 nce
= ire_to_nce(ire
, INADDR_ANY
, &ip6h
->ip6_dst
);
183 /* Allocation failure? */
184 ip_drop_output("ire_to_nce", mp
, ill
);
189 if (nce
->nce_is_condemned
) {
192 nce1
= ire_handle_condemned_nce(nce
, ire
, NULL
, ip6h
, B_TRUE
);
196 /* Try finding a better IRE */
201 /* Tried twice - drop packet */
202 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsOutDiscards
);
203 ip_drop_output("No nce", mp
, ill
);
211 * For multicast with multirt we have a flag passed back from
212 * ire_lookup_multi_ill_v6 since we don't have an IRE for each
213 * possible multicast address.
214 * We also need a flag for multicast since we can't check
215 * whether RTF_MULTIRT is set in ixa_ire for multicast.
218 ixa
->ixa_postfragfn
= ip_postfrag_multirt_v6
;
219 ixa
->ixa_flags
|= IXAF_MULTIRT_MULTICAST
;
221 ixa
->ixa_postfragfn
= ire
->ire_postfragfn
;
222 ixa
->ixa_flags
&= ~IXAF_MULTIRT_MULTICAST
;
224 ASSERT(ixa
->ixa_nce
== NULL
);
228 * Check for a dce_t with a path mtu.
231 if (IN6_IS_ADDR_LINKSCOPE(&dst
))
232 ifindex
= nce
->nce_common
->ncec_ill
->ill_phyint
->phyint_ifindex
;
234 dce
= dce_lookup_v6(&dst
, ifindex
, ipst
, NULL
);
237 if (!(ixaflags
& IXAF_PMTU_DISCOVERY
)) {
238 ixa
->ixa_fragsize
= IPV6_MIN_MTU
;
239 } else if (dce
->dce_flags
& DCEF_PMTU
) {
241 * To avoid a periodic timer to increase the path MTU we
242 * look at dce_last_change_time each time we send a packet.
244 now
= ddi_get_lbolt64();
245 if (TICK_TO_SEC(now
) - dce
->dce_last_change_time
>
246 ipst
->ips_ip_pathmtu_interval
) {
248 * Older than 20 minutes. Drop the path MTU information.
250 mutex_enter(&dce
->dce_lock
);
251 dce
->dce_flags
&= ~DCEF_PMTU
;
252 dce
->dce_last_change_time
= TICK_TO_SEC(now
);
253 mutex_exit(&dce
->dce_lock
);
254 dce_increment_generation(dce
);
255 ixa
->ixa_fragsize
= ip_get_base_mtu(nce
->nce_ill
, ire
);
259 fragsize
= ip_get_base_mtu(nce
->nce_ill
, ire
);
260 if (fragsize
> dce
->dce_pmtu
)
261 fragsize
= dce
->dce_pmtu
;
262 ixa
->ixa_fragsize
= fragsize
;
265 ixa
->ixa_fragsize
= ip_get_base_mtu(nce
->nce_ill
, ire
);
269 * We use use ire_nexthop_ill (and not ncec_ill) to avoid the under ipmp
270 * interface for source address selection.
272 ill
= ire_nexthop_ill(ire
);
274 if (ixaflags
& IXAF_SET_SOURCE
) {
278 * We use the final destination to get
279 * correct selection for source routed packets
282 /* If unreachable we have no ill but need some source */
287 error
= ip_select_source_v6(ill
, &setsrc
, &dst
,
288 ixa
->ixa_zoneid
, ipst
, B_FALSE
,
289 ixa
->ixa_src_preferences
, &src
, NULL
, NULL
);
292 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsHCOutRequests
);
293 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsOutDiscards
);
294 ip_drop_output("ipIfStatsOutDiscards - no source",
300 } else if (ixaflags
& IXAF_VERIFY_SOURCE
) {
301 /* Check if the IP source is assigned to the host. */
302 if (!ip_verify_src(mp
, ixa
, NULL
)) {
303 /* Don't send a packet with a source that isn't ours */
304 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsHCOutRequests
);
305 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsOutDiscards
);
306 ip_drop_output("ipIfStatsOutDiscards - invalid source",
309 error
= EADDRNOTAVAIL
;
315 * Check against global IPsec policy to set the AH/ESP attributes.
316 * IPsec will set IXAF_IPSEC_* and ixa_ipsec_* as appropriate.
318 if (!(ixaflags
& (IXAF_NO_IPSEC
|IXAF_IPSEC_SECURE
))) {
319 ASSERT(ixa
->ixa_ipsec_policy
== NULL
);
320 mp
= ip_output_attach_policy(mp
, NULL
, ip6h
, NULL
, ixa
);
322 /* MIB and ip_drop_packet already done */
323 return (EHOSTUNREACH
); /* IPsec policy failure */
328 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsHCOutRequests
);
330 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsHCOutRequests
);
334 * We update the statistics on the most specific IRE i.e., the first
336 * We don't have an IRE when we fragment, hence ire_ob_pkt_count
337 * can only count the use prior to fragmentation. However the MIB
338 * counters on the ill will be incremented in post fragmentation.
340 ire
->ire_ob_pkt_count
++;
343 * Based on ire_type and ire_flags call one of:
344 * ire_send_local_v6 - for IRE_LOCAL and IRE_LOOPBACK
345 * ire_send_multirt_v6 - if RTF_MULTIRT
346 * ire_send_noroute_v6 - if RTF_REJECT or RTF_BLACHOLE
347 * ire_send_multicast_v6 - for IRE_MULTICAST
348 * ire_send_wire_v6 - for the rest.
350 error
= (ire
->ire_sendfn
)(ire
, mp
, ip6h
, ixa
, &dce
->dce_ident
);
357 if (ixa
->ixa_nce
!= NULL
)
358 nce_refrele(ixa
->ixa_nce
);
364 * ire_sendfn() functions.
365 * These functions use the following xmit_attr:
366 * - ixa_fragsize - read to determine whether or not to fragment
367 * - IXAF_IPSEC_SECURE - to determine whether or not to invoke IPsec
368 * - ixa_ipsec_* are used inside IPsec
369 * - IXAF_LOOPBACK_COPY - for multicast
374 * ire_sendfn for IRE_LOCAL and IRE_LOOPBACK
376 * The checks for restrict_interzone_loopback are done in ire_route_recursive.
380 ire_send_local_v6(ire_t
*ire
, mblk_t
*mp
, void *iph_arg
,
381 ip_xmit_attr_t
*ixa
, uint32_t *identp
)
383 ip6_t
*ip6h
= (ip6_t
*)iph_arg
;
384 ip_stack_t
*ipst
= ixa
->ixa_ipst
;
385 ill_t
*ill
= ire
->ire_ill
;
386 ip_recv_attr_t iras
; /* NOTE: No bzero for performance */
387 uint_t pktlen
= ixa
->ixa_pktlen
;
390 * No fragmentation, no nce, and no application of IPsec.
393 * Note different order between IP provider and FW_HOOKS than in
398 * DTrace this as ip:::send. A packet blocked by FW_HOOKS will fire the
399 * send probe, but not the receive probe.
401 DTRACE_IP7(send
, mblk_t
*, mp
, conn_t
*, NULL
, void_ip_t
*,
402 ip6h
, __dtrace_ipsr_ill_t
*, ill
, ipha_t
*, NULL
, ip6_t
*, ip6h
,
405 DTRACE_PROBE4(ip6__loopback__out__start
,
406 ill_t
*, NULL
, ill_t
*, ill
,
407 ip6_t
*, ip6h
, mblk_t
*, mp
);
409 if (HOOKS6_INTERESTED_LOOPBACK_OUT(ipst
)) {
412 FW_HOOKS(ipst
->ips_ip6_loopback_out_event
,
413 ipst
->ips_ipv6firewall_loopback_out
,
414 NULL
, ill
, ip6h
, mp
, mp
, 0, ipst
, error
);
416 DTRACE_PROBE1(ip6__loopback__out__end
, mblk_t
*, mp
);
421 * Even if the destination was changed by the filter we use the
422 * forwarding decision that was made based on the address
423 * in ip_output/ip_set_destination.
425 /* Length could be different */
426 ip6h
= (ip6_t
*)mp
->b_rptr
;
427 pktlen
= ntohs(ip6h
->ip6_plen
) + IPV6_HDR_LEN
;
431 * If a callback is enabled then we need to know the
432 * source and destination zoneids for the packet. We already
435 if (ipst
->ips_ip6_observe
.he_interested
) {
436 zoneid_t szone
, dzone
;
437 zoneid_t stackzoneid
;
439 stackzoneid
= netstackid_to_zoneid(
440 ipst
->ips_netstack
->netstack_stackid
);
442 if (stackzoneid
== GLOBAL_ZONEID
) {
444 dzone
= ire
->ire_zoneid
;
445 szone
= ixa
->ixa_zoneid
;
447 szone
= dzone
= stackzoneid
;
449 ipobs_hook(mp
, IPOBS_HOOK_LOCAL
, szone
, dzone
, ill
, ipst
);
452 /* Handle lo0 stats */
453 ipst
->ips_loopback_packets
++;
456 * Update output mib stats. Note that we can't move into the icmp
457 * sender (icmp_output etc) since they don't know the ill and the
460 if (ixa
->ixa_protocol
== IPPROTO_ICMPV6
) {
463 icmp6
= (icmp6_t
*)((uchar_t
*)ip6h
+ ixa
->ixa_ip_hdr_length
);
464 icmp_update_out_mib_v6(ill
, icmp6
);
467 DTRACE_PROBE4(ip6__loopback__in__start
,
468 ill_t
*, ill
, ill_t
*, NULL
,
469 ip6_t
*, ip6h
, mblk_t
*, mp
);
471 if (HOOKS6_INTERESTED_LOOPBACK_IN(ipst
)) {
474 FW_HOOKS(ipst
->ips_ip6_loopback_in_event
,
475 ipst
->ips_ipv6firewall_loopback_in
,
476 ill
, NULL
, ip6h
, mp
, mp
, 0, ipst
, error
);
478 DTRACE_PROBE1(ip6__loopback__in__end
, mblk_t
*, mp
);
483 * Even if the destination was changed by the filter we use the
484 * forwarding decision that was made based on the address
485 * in ip_output/ip_set_destination.
487 /* Length could be different */
488 ip6h
= (ip6_t
*)mp
->b_rptr
;
489 pktlen
= ntohs(ip6h
->ip6_plen
) + IPV6_HDR_LEN
;
492 DTRACE_IP7(receive
, mblk_t
*, mp
, conn_t
*, NULL
, void_ip_t
*,
493 ip6h
, __dtrace_ipsr_ill_t
*, ill
, ipha_t
*, NULL
, ip6_t
*, ip6h
,
496 /* Map ixa to ira including IPsec policies */
497 ipsec_out_to_in(ixa
, ill
, &iras
);
498 iras
.ira_pktlen
= pktlen
;
499 iras
.ira_ttl
= ip6h
->ip6_hlim
;
501 ire
->ire_ib_pkt_count
++;
502 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsHCInReceives
);
503 UPDATE_MIB(ill
->ill_ip_mib
, ipIfStatsHCInOctets
, pktlen
);
505 /* Destined to ire_zoneid - use that for fanout */
506 iras
.ira_zoneid
= ire
->ire_zoneid
;
508 if (is_system_labeled()) {
509 iras
.ira_flags
|= IRAF_SYSTEM_LABELED
;
512 * This updates ira_cred, ira_tsl and ira_free_flags based
513 * on the label. We don't expect this to ever fail for
514 * loopback packets, so we silently drop the packet should it
517 if (!tsol_get_pkt_label(mp
, IPV6_VERSION
, &iras
)) {
518 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsInDiscards
);
519 ip_drop_input("tsol_get_pkt_label", mp
, ill
);
523 ASSERT(iras
.ira_tsl
!= NULL
);
525 /* tsol_get_pkt_label sometimes does pullupmsg */
526 ip6h
= (ip6_t
*)mp
->b_rptr
;
529 ip_fanout_v6(mp
, ip6h
, &iras
);
531 /* We moved any IPsec refs from ixa to iras */
532 ira_cleanup(&iras
, B_FALSE
);
537 multirt_check_v6(ire_t
*ire
, ip6_t
*ip6h
, ip_xmit_attr_t
*ixa
)
539 ip_stack_t
*ipst
= ixa
->ixa_ipst
;
541 /* Limit the TTL on multirt packets. Do this even if IPV6_HOPLIMIT */
542 if (ire
->ire_type
& IRE_MULTICAST
) {
543 if (ip6h
->ip6_hops
> 1) {
544 ip2dbg(("ire_send_multirt_v6: forcing multicast "
545 "multirt TTL to 1 (was %d)\n", ip6h
->ip6_hops
));
548 ixa
->ixa_flags
|= IXAF_NO_TTL_CHANGE
;
549 } else if ((ipst
->ips_ip_multirt_ttl
> 0) &&
550 (ip6h
->ip6_hops
> ipst
->ips_ip_multirt_ttl
)) {
551 ip6h
->ip6_hops
= ipst
->ips_ip_multirt_ttl
;
553 * Need to ensure we don't increase the ttl should we go through
554 * ire_send_multicast.
556 ixa
->ixa_flags
|= IXAF_NO_TTL_CHANGE
;
559 /* For IPv6 this also needs to insert a fragment header */
560 ixa
->ixa_flags
|= IXAF_IPV6_ADD_FRAGHDR
;
564 * ire_sendfn for IRE_MULTICAST
566 * Note that we do path MTU discovery by default for IPv6 multicast. But
567 * since unconnected UDP and RAW sockets don't set IXAF_PMTU_DISCOVERY
568 * only connected sockets get this by default.
571 ire_send_multicast_v6(ire_t
*ire
, mblk_t
*mp
, void *iph_arg
,
572 ip_xmit_attr_t
*ixa
, uint32_t *identp
)
574 ip6_t
*ip6h
= (ip6_t
*)iph_arg
;
575 ip_stack_t
*ipst
= ixa
->ixa_ipst
;
576 ill_t
*ill
= ire
->ire_ill
;
577 iaflags_t ixaflags
= ixa
->ixa_flags
;
580 * The IRE_MULTICAST is the same whether or not multirt is in use.
581 * Hence we need special-case code.
583 if (ixaflags
& IXAF_MULTIRT_MULTICAST
)
584 multirt_check_v6(ire
, ip6h
, ixa
);
587 * Check if anything in ip_input_v6 wants a copy of the transmitted
588 * packet (after IPsec and fragmentation)
590 * 1. Multicast routers always need a copy unless SO_DONTROUTE is set
591 * RSVP and the rsvp daemon is an example of a
592 * protocol and user level process that
593 * handles it's own routing. Hence, it uses the
594 * SO_DONTROUTE option to accomplish this.
595 * 2. If the sender has set IP_MULTICAST_LOOP, then we just
596 * check whether there are any receivers for the group on the ill
597 * (ignoring the zoneid).
598 * 3. If IP_MULTICAST_LOOP is not set, then we check if there are
599 * any members in other shared-IP zones.
600 * If such members exist, then we indicate that the sending zone
601 * shouldn't get a loopback copy to preserve the IP_MULTICAST_LOOP
604 * When we loopback we skip hardware checksum to make sure loopback
605 * copy is checksumed.
607 * Note that ire_ill is the upper in the case of IPMP.
609 ixa
->ixa_flags
&= ~(IXAF_LOOPBACK_COPY
| IXAF_NO_HW_CKSUM
);
610 if (ipst
->ips_ip_g_mrouter
&& ill
->ill_mrouter_cnt
> 0 &&
611 !(ixaflags
& IXAF_DONTROUTE
)) {
612 ixa
->ixa_flags
|= IXAF_LOOPBACK_COPY
| IXAF_NO_HW_CKSUM
;
613 } else if (ixaflags
& IXAF_MULTICAST_LOOP
) {
615 * If this zone or any other zone has members then loopback
618 if (ill_hasmembers_v6(ill
, &ip6h
->ip6_dst
))
619 ixa
->ixa_flags
|= IXAF_LOOPBACK_COPY
| IXAF_NO_HW_CKSUM
;
620 } else if (ipst
->ips_netstack
->netstack_numzones
> 1) {
622 * This zone should not have a copy. But there are some other
623 * zones which might have members.
625 if (ill_hasmembers_otherzones_v6(ill
, &ip6h
->ip6_dst
,
627 ixa
->ixa_flags
|= IXAF_NO_LOOP_ZONEID_SET
;
628 ixa
->ixa_no_loop_zoneid
= ixa
->ixa_zoneid
;
629 ixa
->ixa_flags
|= IXAF_LOOPBACK_COPY
| IXAF_NO_HW_CKSUM
;
634 * Unless IPV6_HOPLIMIT or ire_send_multirt_v6 already set a ttl,
635 * force the ttl to the IP_MULTICAST_TTL value
637 if (!(ixaflags
& IXAF_NO_TTL_CHANGE
)) {
638 ip6h
->ip6_hops
= ixa
->ixa_multicast_ttl
;
641 return (ire_send_wire_v6(ire
, mp
, ip6h
, ixa
, identp
));
645 * ire_sendfn for IREs with RTF_MULTIRT
648 ire_send_multirt_v6(ire_t
*ire
, mblk_t
*mp
, void *iph_arg
,
649 ip_xmit_attr_t
*ixa
, uint32_t *identp
)
651 ip6_t
*ip6h
= (ip6_t
*)iph_arg
;
653 multirt_check_v6(ire
, ip6h
, ixa
);
655 if (ire
->ire_type
& IRE_MULTICAST
)
656 return (ire_send_multicast_v6(ire
, mp
, ip6h
, ixa
, identp
));
658 return (ire_send_wire_v6(ire
, mp
, ip6h
, ixa
, identp
));
662 * ire_sendfn for IREs with RTF_REJECT/RTF_BLACKHOLE, including IRE_NOROUTE
666 ire_send_noroute_v6(ire_t
*ire
, mblk_t
*mp
, void *iph_arg
,
667 ip_xmit_attr_t
*ixa
, uint32_t *identp
)
669 ip6_t
*ip6h
= (ip6_t
*)iph_arg
;
670 ip_stack_t
*ipst
= ixa
->ixa_ipst
;
675 BUMP_MIB(&ipst
->ips_ip_mib
, ipIfStatsOutNoRoutes
);
677 if (ire
->ire_type
& IRE_NOROUTE
) {
678 /* A lack of a route as opposed to RTF_REJECT|BLACKHOLE */
679 ip_rts_change_v6(RTM_MISS
, &ip6h
->ip6_dst
, 0, 0, 0, 0, 0, 0,
683 if (ire
->ire_flags
& RTF_BLACKHOLE
) {
684 ip_drop_output("ipIfStatsOutNoRoutes RTF_BLACKHOLE", mp
, NULL
);
686 /* No error even for local senders - silent blackhole */
689 ip_drop_output("ipIfStatsOutNoRoutes RTF_REJECT", mp
, NULL
);
692 * We need an ill_t for the ip_recv_attr_t even though this packet
693 * was never received and icmp_unreachable doesn't currently use
696 ill
= ill_lookup_on_name("lo0", B_FALSE
,
697 !(ixa
->ixa_flags
& IRAF_IS_IPV4
), &dummy
, ipst
);
700 return (EHOSTUNREACH
);
703 bzero(&iras
, sizeof (iras
));
704 /* Map ixa to ira including IPsec policies */
705 ipsec_out_to_in(ixa
, ill
, &iras
);
707 icmp_unreachable_v6(mp
, ICMP6_DST_UNREACH_NOROUTE
, B_FALSE
, &iras
);
708 /* We moved any IPsec refs from ixa to iras */
709 ira_cleanup(&iras
, B_FALSE
);
712 return (EHOSTUNREACH
);
716 * Calculate a checksum ignoring any hardware capabilities
718 * Returns B_FALSE if the packet was too short for the checksum. Caller
719 * should free and do stats.
722 ip_output_sw_cksum_v6(mblk_t
*mp
, ip6_t
*ip6h
, ip_xmit_attr_t
*ixa
)
724 ip_stack_t
*ipst
= ixa
->ixa_ipst
;
725 uint_t pktlen
= ixa
->ixa_pktlen
;
728 uint8_t protocol
= ixa
->ixa_protocol
;
729 uint16_t ip_hdr_length
= ixa
->ixa_ip_hdr_length
;
731 #define iphs ((uint16_t *)ip6h)
733 /* Just in case it contained garbage */
734 DB_CKSUMFLAGS(mp
) &= ~HCK_FLAGS
;
737 * Calculate ULP checksum
739 if (protocol
== IPPROTO_TCP
) {
740 cksump
= IPH_TCPH_CHECKSUMP(ip6h
, ip_hdr_length
);
741 cksum
= IP_TCP_CSUM_COMP
;
742 } else if (protocol
== IPPROTO_UDP
) {
743 cksump
= IPH_UDPH_CHECKSUMP(ip6h
, ip_hdr_length
);
744 cksum
= IP_UDP_CSUM_COMP
;
745 } else if (protocol
== IPPROTO_SCTP
) {
748 ASSERT(MBLKL(mp
) >= (ip_hdr_length
+ sizeof (*sctph
)));
749 sctph
= (sctp_hdr_t
*)(mp
->b_rptr
+ ip_hdr_length
);
751 * Zero out the checksum field to ensure proper
752 * checksum calculation.
754 sctph
->sh_chksum
= 0;
756 if (!skip_sctp_cksum
)
758 sctph
->sh_chksum
= sctp_cksum(mp
, ip_hdr_length
);
760 } else if (ixa
->ixa_flags
& IXAF_SET_RAW_CKSUM
) {
762 * icmp has placed length and routing
763 * header adjustment in the checksum field.
765 cksump
= (uint16_t *)(((uint8_t *)ip6h
) + ip_hdr_length
+
766 ixa
->ixa_raw_cksum_offset
);
767 cksum
= htons(protocol
);
768 } else if (protocol
== IPPROTO_ICMPV6
) {
769 cksump
= IPH_ICMPV6_CHECKSUMP(ip6h
, ip_hdr_length
);
770 cksum
= IP_ICMPV6_CSUM_COMP
; /* Pseudo-header cksum */
775 /* ULP puts the checksum field is in the first mblk */
776 ASSERT(((uchar_t
*)cksump
) + sizeof (uint16_t) <= mp
->b_wptr
);
779 * We accumulate the pseudo header checksum in cksum.
780 * This is pretty hairy code, so watch close. One
781 * thing to keep in mind is that UDP and TCP have
782 * stored their respective datagram lengths in their
783 * checksum fields. This lines things up real nice.
785 cksum
+= iphs
[4] + iphs
[5] + iphs
[6] + iphs
[7] +
786 iphs
[8] + iphs
[9] + iphs
[10] + iphs
[11] +
787 iphs
[12] + iphs
[13] + iphs
[14] + iphs
[15] +
788 iphs
[16] + iphs
[17] + iphs
[18] + iphs
[19];
789 cksum
= IP_CSUM(mp
, ip_hdr_length
, cksum
);
792 * For UDP/IPv6 a zero UDP checksum is not allowed.
795 if (protocol
== IPPROTO_UDP
&& cksum
== 0)
800 IP6_STAT(ipst
, ip6_out_sw_cksum
);
801 IP6_STAT_UPDATE(ipst
, ip6_out_sw_cksum_bytes
, pktlen
);
803 /* No IP header checksum for IPv6 */
809 /* There are drivers that can't do partial checksum for ICMPv6 */
810 int nxge_cksum_workaround
= 1;
813 * Calculate the ULP checksum - try to use hardware.
814 * In the case of MULTIRT or multicast the
815 * IXAF_NO_HW_CKSUM is set in which case we use software.
817 * Returns B_FALSE if the packet was too short for the checksum. Caller
818 * should free and do stats.
821 ip_output_cksum_v6(iaflags_t ixaflags
, mblk_t
*mp
, ip6_t
*ip6h
,
822 ip_xmit_attr_t
*ixa
, ill_t
*ill
)
824 uint_t pktlen
= ixa
->ixa_pktlen
;
828 uint8_t protocol
= ixa
->ixa_protocol
;
829 uint16_t ip_hdr_length
= ixa
->ixa_ip_hdr_length
;
831 #define iphs ((uint16_t *)ip6h)
833 if ((ixaflags
& IXAF_NO_HW_CKSUM
) || !ILL_HCKSUM_CAPABLE(ill
) ||
835 return (ip_output_sw_cksum_v6(mp
, ip6h
, ixa
));
839 * Calculate ULP checksum. Note that we don't use cksump and cksum
840 * if the ill has FULL support.
842 if (protocol
== IPPROTO_TCP
) {
843 cksump
= IPH_TCPH_CHECKSUMP(ip6h
, ip_hdr_length
);
844 cksum
= IP_TCP_CSUM_COMP
; /* Pseudo-header cksum */
845 } else if (protocol
== IPPROTO_UDP
) {
846 cksump
= IPH_UDPH_CHECKSUMP(ip6h
, ip_hdr_length
);
847 cksum
= IP_UDP_CSUM_COMP
; /* Pseudo-header cksum */
848 } else if (protocol
== IPPROTO_SCTP
) {
851 ASSERT(MBLKL(mp
) >= (ip_hdr_length
+ sizeof (*sctph
)));
852 sctph
= (sctp_hdr_t
*)(mp
->b_rptr
+ ip_hdr_length
);
854 * Zero out the checksum field to ensure proper
855 * checksum calculation.
857 sctph
->sh_chksum
= 0;
859 if (!skip_sctp_cksum
)
861 sctph
->sh_chksum
= sctp_cksum(mp
, ip_hdr_length
);
863 } else if (ixa
->ixa_flags
& IXAF_SET_RAW_CKSUM
) {
865 * icmp has placed length and routing
866 * header adjustment in the checksum field.
868 cksump
= (uint16_t *)(((uint8_t *)ip6h
) + ip_hdr_length
+
869 ixa
->ixa_raw_cksum_offset
);
870 cksum
= htons(protocol
);
871 } else if (protocol
== IPPROTO_ICMPV6
) {
873 * Currently we assume no HW support for ICMP checksum calc.
875 * When HW support is advertised for ICMP, we'll want the
876 * following to be set:
877 * cksump = IPH_ICMPV6_CHECKSUMP(ip6h, ip_hdr_length);
878 * cksum = IP_ICMPV6_CSUM_COMP; Pseudo-header cksum
881 return (ip_output_sw_cksum_v6(mp
, ip6h
, ixa
));
884 /* No IP header checksum for IPv6 */
888 /* ULP puts the checksum field is in the first mblk */
889 ASSERT(((uchar_t
*)cksump
) + sizeof (uint16_t) <= mp
->b_wptr
);
892 * Underlying interface supports hardware checksum offload for
893 * the payload; leave the payload checksum for the hardware to
894 * calculate. N.B: We only need to set up checksum info on the
897 hck_flags
= ill
->ill_hcksum_capab
->ill_hcksum_txflags
;
899 DB_CKSUMFLAGS(mp
) &= ~HCK_FLAGS
;
900 if (hck_flags
& HCKSUM_INET_FULL_V6
) {
902 * Hardware calculates pseudo-header, header and the
903 * payload checksums, so clear the checksum field in
904 * the protocol header.
907 DB_CKSUMFLAGS(mp
) |= HCK_FULLCKSUM
;
910 if (((hck_flags
) & HCKSUM_INET_PARTIAL
) &&
911 (protocol
!= IPPROTO_ICMPV6
|| !nxge_cksum_workaround
)) {
913 * Partial checksum offload has been enabled. Fill
914 * the checksum field in the protocol header with the
915 * pseudo-header checksum value.
917 * We accumulate the pseudo header checksum in cksum.
918 * This is pretty hairy code, so watch close. One
919 * thing to keep in mind is that UDP and TCP have
920 * stored their respective datagram lengths in their
921 * checksum fields. This lines things up real nice.
923 cksum
+= iphs
[4] + iphs
[5] + iphs
[6] + iphs
[7] +
924 iphs
[8] + iphs
[9] + iphs
[10] + iphs
[11] +
925 iphs
[12] + iphs
[13] + iphs
[14] + iphs
[15] +
926 iphs
[16] + iphs
[17] + iphs
[18] + iphs
[19];
928 cksum
= (cksum
& 0xFFFF) + (cksum
>> 16);
929 *(cksump
) = (cksum
& 0xFFFF) + (cksum
>> 16);
932 * Offsets are relative to beginning of IP header.
934 DB_CKSUMSTART(mp
) = ip_hdr_length
;
935 DB_CKSUMSTUFF(mp
) = (uint8_t *)cksump
- (uint8_t *)ip6h
;
936 DB_CKSUMEND(mp
) = pktlen
;
937 DB_CKSUMFLAGS(mp
) |= HCK_PARTIALCKSUM
;
940 /* Hardware capabilities include neither full nor partial IPv6 */
941 return (ip_output_sw_cksum_v6(mp
, ip6h
, ixa
));
946 * ire_sendfn for offlink and onlink destinations.
947 * Also called from the multicast, and multirt send functions.
949 * Assumes that the caller has a hold on the ire.
951 * This function doesn't care if the IRE just became condemned since that
952 * can happen at any time.
956 ire_send_wire_v6(ire_t
*ire
, mblk_t
*mp
, void *iph_arg
,
957 ip_xmit_attr_t
*ixa
, uint32_t *identp
)
959 ip_stack_t
*ipst
= ixa
->ixa_ipst
;
960 ip6_t
*ip6h
= (ip6_t
*)iph_arg
;
961 iaflags_t ixaflags
= ixa
->ixa_flags
;
963 uint32_t pktlen
= ixa
->ixa_pktlen
;
965 ASSERT(ixa
->ixa_nce
!= NULL
);
966 ill
= ixa
->ixa_nce
->nce_ill
;
969 * Update output mib stats. Note that we can't move into the icmp
970 * sender (icmp_output etc) since they don't know the ill and the
973 * With IPMP we record the stats on the upper ill.
975 if (ixa
->ixa_protocol
== IPPROTO_ICMPV6
) {
978 icmp6
= (icmp6_t
*)((uchar_t
*)ip6h
+ ixa
->ixa_ip_hdr_length
);
979 icmp_update_out_mib_v6(ixa
->ixa_nce
->nce_common
->ncec_ill
,
983 if (ixaflags
& IXAF_DONTROUTE
)
987 * This might set b_band, thus the IPsec and fragmentation
988 * code in IP ensures that b_band is updated in the first mblk.
990 if (IPP_ENABLED(IPP_LOCAL_OUT
, ipst
)) {
991 /* ip_process translates an IS_UNDER_IPMP */
992 mp
= ip_process(IPP_LOCAL_OUT
, mp
, ill
, ill
);
994 /* ip_drop_packet and MIB done */
995 return (0); /* Might just be delayed */
1000 * To handle IPsec/iptun's labeling needs we need to tag packets
1001 * while we still have ixa_tsl
1003 if (is_system_labeled() && ixa
->ixa_tsl
!= NULL
&&
1004 (ill
->ill_mactype
== DL_6TO4
|| ill
->ill_mactype
== DL_IPV4
||
1005 ill
->ill_mactype
== DL_IPV6
)) {
1008 newcr
= copycred_from_tslabel(ixa
->ixa_cred
, ixa
->ixa_tsl
,
1010 if (newcr
== NULL
) {
1011 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsOutDiscards
);
1012 ip_drop_output("ipIfStatsOutDiscards - newcr",
1017 mblk_setcred(mp
, newcr
, NOPID
);
1018 crfree(newcr
); /* mblk_setcred did its own crhold */
1022 * IXAF_IPV6_ADD_FRAGHDR is set for CGTP so that we will add a
1023 * fragment header without fragmenting. CGTP on the receiver will
1024 * filter duplicates on the ident field.
1026 if (pktlen
> ixa
->ixa_fragsize
||
1027 (ixaflags
& (IXAF_IPSEC_SECURE
|IXAF_IPV6_ADD_FRAGHDR
))) {
1030 if (ixaflags
& IXAF_IPSEC_SECURE
)
1031 pktlen
+= ipsec_out_extra_length(ixa
);
1033 if (pktlen
> IP_MAXPACKET
)
1036 if (ixaflags
& IXAF_SET_ULP_CKSUM
) {
1038 * Compute ULP checksum using software
1040 if (!ip_output_sw_cksum_v6(mp
, ip6h
, ixa
)) {
1041 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsOutDiscards
);
1042 ip_drop_output("ipIfStatsOutDiscards", mp
, ill
);
1046 /* Avoid checksum again below if we only add fraghdr */
1047 ixaflags
&= ~IXAF_SET_ULP_CKSUM
;
1051 * If we need a fragment header, pick the ident and insert
1052 * the header before IPsec to we have a place to store
1055 if ((ixaflags
& IXAF_IPV6_ADD_FRAGHDR
) ||
1056 pktlen
> ixa
->ixa_fragsize
) {
1058 * If this packet would generate a icmp_frag_needed
1059 * message, we need to handle it before we do the IPsec
1060 * processing. Otherwise, we need to strip the IPsec
1061 * headers before we send up the message to the ULPs
1062 * which becomes messy and difficult.
1064 if ((pktlen
> ixa
->ixa_fragsize
) &&
1065 (ixaflags
& IXAF_DONTFRAG
)) {
1066 /* Generate ICMP and return error */
1067 ip_recv_attr_t iras
;
1069 DTRACE_PROBE4(ip6__fragsize__fail
,
1070 uint_t
, pktlen
, uint_t
, ixa
->ixa_fragsize
,
1071 uint_t
, ixa
->ixa_pktlen
,
1072 uint_t
, ixa
->ixa_pmtu
);
1074 bzero(&iras
, sizeof (iras
));
1075 /* Map ixa to ira including IPsec policies */
1076 ipsec_out_to_in(ixa
, ill
, &iras
);
1077 iras
.ira_ttl
= ip6h
->ip6_hlim
;
1079 ip_drop_output("ICMP6_PKT_TOO_BIG", mp
, ill
);
1080 icmp_pkt2big_v6(mp
, ixa
->ixa_fragsize
, B_TRUE
,
1082 /* We moved any IPsec refs from ixa to iras */
1083 ira_cleanup(&iras
, B_FALSE
);
1086 DTRACE_PROBE4(ip6__fragsize__ok
, uint_t
, pktlen
,
1087 uint_t
, ixa
->ixa_fragsize
, uint_t
, ixa
->ixa_pktlen
,
1088 uint_t
, ixa
->ixa_pmtu
);
1090 * Assign an ident value for this packet. There could
1091 * be other threads targeting the same destination, so
1092 * we have to arrange for a atomic increment.
1093 * Normally ixa_extra_ident is 0, but in the case of
1094 * LSO it will be the number of TCP segments that the
1095 * driver/hardware will extraly construct.
1097 * Note that cl_inet_ipident has only been used for
1098 * IPv4. We don't use it here.
1100 ident
= atomic_add_32_nv(identp
, ixa
->ixa_extra_ident
+
1102 ixa
->ixa_ident
= ident
; /* In case we do IPsec */
1104 if (ixaflags
& IXAF_IPSEC_SECURE
) {
1106 * Pass in sufficient information so that
1107 * IPsec can determine whether to fragment, and
1108 * which function to call after fragmentation.
1110 return (ipsec_out_process(mp
, ixa
));
1113 mp
= ip_fraghdr_add_v6(mp
, ident
, ixa
);
1115 /* MIB and ip_drop_output already done */
1118 ASSERT(pktlen
== ixa
->ixa_pktlen
);
1119 pktlen
+= sizeof (ip6_frag_t
);
1121 if (pktlen
> ixa
->ixa_fragsize
) {
1122 return (ip_fragment_v6(mp
, ixa
->ixa_nce
, ixaflags
,
1123 pktlen
, ixa
->ixa_fragsize
,
1124 ixa
->ixa_xmit_hint
, ixa
->ixa_zoneid
,
1125 ixa
->ixa_no_loop_zoneid
, ixa
->ixa_postfragfn
,
1129 if (ixaflags
& IXAF_SET_ULP_CKSUM
) {
1130 /* Compute ULP checksum and IP header checksum */
1131 /* An IS_UNDER_IPMP ill is ok here */
1132 if (!ip_output_cksum_v6(ixaflags
, mp
, ip6h
, ixa
, ill
)) {
1133 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsOutDiscards
);
1134 ip_drop_output("ipIfStatsOutDiscards", mp
, ill
);
1139 return ((ixa
->ixa_postfragfn
)(mp
, ixa
->ixa_nce
, ixaflags
,
1140 pktlen
, ixa
->ixa_xmit_hint
, ixa
->ixa_zoneid
,
1141 ixa
->ixa_no_loop_zoneid
, &ixa
->ixa_cookie
));
1145 * Post fragmentation function for RTF_MULTIRT routes.
1146 * Since IRE_MULTICASTs might have RTF_MULTIRT, this function
1147 * checks IXAF_LOOPBACK_COPY.
1149 * If no packet is sent due to failures then we return an errno, but if at
1150 * least one succeeded we return zero.
1153 ip_postfrag_multirt_v6(mblk_t
*mp
, nce_t
*nce
, iaflags_t ixaflags
,
1154 uint_t pkt_len
, uint32_t xmit_hint
, zoneid_t szone
, zoneid_t nolzid
,
1155 uintptr_t *ixacookie
)
1158 ip6_t
*ip6h
= (ip6_t
*)mp
->b_rptr
;
1163 ill_t
*ill
= nce
->nce_ill
;
1165 ip_stack_t
*ipst
= ill
->ill_ipst
;
1172 ASSERT(!(ixaflags
& IXAF_IS_IPV4
));
1174 /* Check for IXAF_LOOPBACK_COPY */
1175 if (ixaflags
& IXAF_LOOPBACK_COPY
) {
1180 /* Failed to deliver the loopback copy. */
1181 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsOutDiscards
);
1182 ip_drop_output("ipIfStatsOutDiscards", mp
, ill
);
1185 ip_postfrag_loopback(mp1
, nce
, ixaflags
, pkt_len
,
1191 * Loop over RTF_MULTIRT for ip6_dst in the same bucket. Send
1192 * a copy to each one.
1193 * Use the nce (nexthop) and ip6_dst to find the ire.
1195 * MULTIRT is not designed to work with shared-IP zones thus we don't
1196 * need to pass a zoneid or a label to the IRE lookup.
1198 if (IN6_ARE_ADDR_EQUAL(&nce
->nce_addr
, &ip6h
->ip6_dst
)) {
1199 /* Broadcast and multicast case */
1200 ire
= ire_ftable_lookup_v6(&ip6h
->ip6_dst
, 0, 0, 0, NULL
,
1201 ALL_ZONES
, NULL
, MATCH_IRE_DSTONLY
, 0, ipst
, NULL
);
1204 ire
= ire_ftable_lookup_v6(&ip6h
->ip6_dst
, 0, &nce
->nce_addr
,
1205 0, NULL
, ALL_ZONES
, NULL
, MATCH_IRE_GW
, 0, ipst
, NULL
);
1209 (ire
->ire_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) ||
1210 !(ire
->ire_flags
& RTF_MULTIRT
)) {
1212 ip_drop_output("ip_postfrag_multirt didn't find route",
1216 return (ENETUNREACH
);
1219 irb
= ire
->ire_bucket
;
1221 for (ire1
= irb
->irb_ire
; ire1
!= NULL
; ire1
= ire1
->ire_next
) {
1222 if (IRE_IS_CONDEMNED(ire1
) ||
1223 !(ire1
->ire_flags
& RTF_MULTIRT
))
1226 /* Note: When IPv6 uses radix tree we don't need this check */
1227 if (!IN6_ARE_ADDR_EQUAL(&ire
->ire_addr_v6
, &ire1
->ire_addr_v6
))
1230 /* Do the ire argument one after the loop */
1234 ill1
= ire_nexthop_ill(ire1
);
1237 * This ire might not have been picked by
1238 * ire_route_recursive, in which case ire_dep might
1239 * not have been setup yet.
1240 * We kick ire_route_recursive to try to resolve
1244 uint_t match_flags
= MATCH_IRE_DSTONLY
;
1246 if (ire1
->ire_ill
!= NULL
)
1247 match_flags
|= MATCH_IRE_ILL
;
1248 ire2
= ire_route_recursive_impl_v6(ire1
,
1249 &ire1
->ire_addr_v6
, ire1
->ire_type
, ire1
->ire_ill
,
1250 ire1
->ire_zoneid
, NULL
, match_flags
,
1251 IRR_ALLOCATE
, 0, ipst
, NULL
, NULL
, NULL
);
1254 ill1
= ire_nexthop_ill(ire1
);
1257 BUMP_MIB(ill
->ill_ip_mib
, ipIfStatsOutDiscards
);
1258 ip_drop_output("ipIfStatsOutDiscards - no ill",
1260 error
= ENETUNREACH
;
1263 /* Pick the addr and type to use for ndp_nce_init */
1264 if (nce
->nce_common
->ncec_flags
& NCE_F_MCAST
) {
1265 ire_type
= IRE_MULTICAST
;
1266 nexthop
= ip6h
->ip6_dst
;
1268 ire_type
= ire1
->ire_type
; /* Doesn't matter */
1269 nexthop
= ire1
->ire_gateway_addr_v6
;
1272 /* If IPMP meta or under, then we just drop */
1273 if (ill1
->ill_grp
!= NULL
) {
1274 BUMP_MIB(ill1
->ill_ip_mib
, ipIfStatsOutDiscards
);
1275 ip_drop_output("ipIfStatsOutDiscards - IPMP",
1278 error
= ENETUNREACH
;
1282 nce1
= ndp_nce_init(ill1
, &nexthop
, ire_type
);
1284 BUMP_MIB(ill1
->ill_ip_mib
, ipIfStatsOutDiscards
);
1285 ip_drop_output("ipIfStatsOutDiscards - no nce",
1293 BUMP_MIB(ill1
->ill_ip_mib
, ipIfStatsOutDiscards
);
1294 ip_drop_output("ipIfStatsOutDiscards", mp
, ill1
);
1300 /* Preserve HW checksum for this copy */
1301 DB_CKSUMSTART(mp1
) = DB_CKSUMSTART(mp
);
1302 DB_CKSUMSTUFF(mp1
) = DB_CKSUMSTUFF(mp
);
1303 DB_CKSUMEND(mp1
) = DB_CKSUMEND(mp
);
1304 DB_CKSUMFLAGS(mp1
) = DB_CKSUMFLAGS(mp
);
1305 DB_LSOMSS(mp1
) = DB_LSOMSS(mp
);
1307 ire1
->ire_ob_pkt_count
++;
1308 err
= ip_xmit(mp1
, nce1
, ixaflags
, pkt_len
, xmit_hint
, szone
,
1319 /* Finally, the main one */
1320 err
= ip_xmit(mp
, nce
, ixaflags
, pkt_len
, xmit_hint
, szone
, 0,