changeset 741 | 40027a3621ac |
parent 679 | f2c9450b58f4 |
child 1145 | 98865ed5c2e7 |
740:70e4862c9a1a | 741:40027a3621ac |
---|---|
56 #include <sys/atomic.h> |
56 #include <sys/atomic.h> |
57 #include <sys/iphada.h> |
57 #include <sys/iphada.h> |
58 #include <sys/policy.h> |
58 #include <sys/policy.h> |
59 #include <net/if.h> |
59 #include <net/if.h> |
60 #include <net/if_arp.h> |
60 #include <net/if_arp.h> |
61 #include <net/if_types.h> |
|
61 #include <net/route.h> |
62 #include <net/route.h> |
62 #include <net/if_dl.h> |
63 #include <net/if_dl.h> |
63 #include <sys/sockio.h> |
64 #include <sys/sockio.h> |
64 #include <netinet/in.h> |
65 #include <netinet/in.h> |
65 #include <netinet/ip6.h> |
66 #include <netinet/ip6.h> |
72 #include <inet/nd.h> |
73 #include <inet/nd.h> |
73 #include <inet/arp.h> |
74 #include <inet/arp.h> |
74 #include <inet/snmpcom.h> |
75 #include <inet/snmpcom.h> |
75 |
76 |
76 #include <inet/ip.h> |
77 #include <inet/ip.h> |
78 #include <inet/ip_impl.h> |
|
77 #include <inet/ip6.h> |
79 #include <inet/ip6.h> |
78 #include <inet/ip6_asp.h> |
80 #include <inet/ip6_asp.h> |
79 #include <inet/tcp.h> |
81 #include <inet/tcp.h> |
82 #include <inet/tcp_impl.h> |
|
83 #include <inet/udp_impl.h> |
|
80 #include <inet/ipp_common.h> |
84 #include <inet/ipp_common.h> |
81 |
85 |
82 #include <inet/ip_multi.h> |
86 #include <inet/ip_multi.h> |
83 #include <inet/ip_if.h> |
87 #include <inet/ip_if.h> |
84 #include <inet/ip_ire.h> |
88 #include <inet/ip_ire.h> |
101 extern squeue_func_t ip_input_proc; |
105 extern squeue_func_t ip_input_proc; |
102 |
106 |
103 /* |
107 /* |
104 * IP statistics. |
108 * IP statistics. |
105 */ |
109 */ |
106 #define IP6_STAT(x) (ip6_statistics.x.value.ui64++) |
110 #define IP6_STAT(x) (ip6_statistics.x.value.ui64++) |
111 #define IP6_STAT_UPDATE(x, n) (ip6_statistics.x.value.ui64 += (n)) |
|
107 |
112 |
108 typedef struct ip6_stat { |
113 typedef struct ip6_stat { |
109 kstat_named_t ip6_udp_fast_path; |
114 kstat_named_t ip6_udp_fast_path; |
110 kstat_named_t ip6_udp_slow_path; |
115 kstat_named_t ip6_udp_slow_path; |
111 kstat_named_t ip6_udp_fannorm; |
116 kstat_named_t ip6_udp_fannorm; |
112 kstat_named_t ip6_udp_fanmb; |
117 kstat_named_t ip6_udp_fanmb; |
118 kstat_named_t ip6_out_sw_cksum; |
|
119 kstat_named_t ip6_in_sw_cksum; |
|
120 kstat_named_t ip6_tcp_in_full_hw_cksum_err; |
|
121 kstat_named_t ip6_tcp_in_part_hw_cksum_err; |
|
122 kstat_named_t ip6_tcp_in_sw_cksum_err; |
|
123 kstat_named_t ip6_tcp_out_sw_cksum_bytes; |
|
124 kstat_named_t ip6_udp_in_full_hw_cksum_err; |
|
125 kstat_named_t ip6_udp_in_part_hw_cksum_err; |
|
126 kstat_named_t ip6_udp_in_sw_cksum_err; |
|
127 kstat_named_t ip6_udp_out_sw_cksum_bytes; |
|
128 kstat_named_t ip6_frag_mdt_pkt_out; |
|
129 kstat_named_t ip6_frag_mdt_discarded; |
|
130 kstat_named_t ip6_frag_mdt_allocfail; |
|
131 kstat_named_t ip6_frag_mdt_addpdescfail; |
|
132 kstat_named_t ip6_frag_mdt_allocd; |
|
113 } ip6_stat_t; |
133 } ip6_stat_t; |
114 |
134 |
115 static ip6_stat_t ip6_statistics = { |
135 static ip6_stat_t ip6_statistics = { |
116 { "ip6_udp_fast_path", KSTAT_DATA_UINT64 }, |
136 { "ip6_udp_fast_path", KSTAT_DATA_UINT64 }, |
117 { "ip6_udp_slow_path", KSTAT_DATA_UINT64 }, |
137 { "ip6_udp_slow_path", KSTAT_DATA_UINT64 }, |
118 { "ip6_udp_fannorm", KSTAT_DATA_UINT64 }, |
138 { "ip6_udp_fannorm", KSTAT_DATA_UINT64 }, |
119 { "ip6_udp_fanmb", KSTAT_DATA_UINT64 }, |
139 { "ip6_udp_fanmb", KSTAT_DATA_UINT64 }, |
140 { "ip6_out_sw_cksum", KSTAT_DATA_UINT64 }, |
|
141 { "ip6_in_sw_cksum", KSTAT_DATA_UINT64 }, |
|
142 { "ip6_tcp_in_full_hw_cksum_err", KSTAT_DATA_UINT64 }, |
|
143 { "ip6_tcp_in_part_hw_cksum_err", KSTAT_DATA_UINT64 }, |
|
144 { "ip6_tcp_in_sw_cksum_err", KSTAT_DATA_UINT64 }, |
|
145 { "ip6_tcp_out_sw_cksum_bytes", KSTAT_DATA_UINT64 }, |
|
146 { "ip6_udp_in_full_hw_cksum_err", KSTAT_DATA_UINT64 }, |
|
147 { "ip6_udp_in_part_hw_cksum_err", KSTAT_DATA_UINT64 }, |
|
148 { "ip6_udp_in_sw_cksum_err", KSTAT_DATA_UINT64 }, |
|
149 { "ip6_udp_out_sw_cksum_bytes", KSTAT_DATA_UINT64 }, |
|
150 { "ip6_frag_mdt_pkt_out", KSTAT_DATA_UINT64 }, |
|
151 { "ip6_frag_mdt_discarded", KSTAT_DATA_UINT64 }, |
|
152 { "ip6_frag_mdt_allocfail", KSTAT_DATA_UINT64 }, |
|
153 { "ip6_frag_mdt_addpdescfail", KSTAT_DATA_UINT64 }, |
|
154 { "ip6_frag_mdt_allocd", KSTAT_DATA_UINT64 }, |
|
120 }; |
155 }; |
121 |
156 |
122 static kstat_t *ip6_kstat; |
157 static kstat_t *ip6_kstat; |
123 |
158 |
124 /* |
159 /* |
219 static void ip_fanout_udp_v6(queue_t *, mblk_t *, ip6_t *, uint32_t, |
254 static void ip_fanout_udp_v6(queue_t *, mblk_t *, ip6_t *, uint32_t, |
220 ill_t *, ill_t *, uint_t, boolean_t, zoneid_t); |
255 ill_t *, ill_t *, uint_t, boolean_t, zoneid_t); |
221 static int ip_process_options_v6(queue_t *, mblk_t *, ip6_t *, |
256 static int ip_process_options_v6(queue_t *, mblk_t *, ip6_t *, |
222 uint8_t *, uint_t, uint8_t); |
257 uint8_t *, uint_t, uint8_t); |
223 static mblk_t *ip_rput_frag_v6(queue_t *, mblk_t *, ip6_t *, |
258 static mblk_t *ip_rput_frag_v6(queue_t *, mblk_t *, ip6_t *, |
224 ip6_frag_t *, uint_t, uint_t *); |
259 ip6_frag_t *, uint_t, uint_t *, uint32_t *, uint16_t *); |
225 static boolean_t ip_source_routed_v6(ip6_t *, mblk_t *); |
260 static boolean_t ip_source_routed_v6(ip6_t *, mblk_t *); |
226 static void ip_wput_ire_v6(queue_t *, mblk_t *, ire_t *, int, int, |
261 static void ip_wput_ire_v6(queue_t *, mblk_t *, ire_t *, int, int, |
227 conn_t *, int, int, int); |
262 conn_t *, int, int, int); |
228 static boolean_t ip_ulp_cando_pkt2big(int); |
263 static boolean_t ip_ulp_cando_pkt2big(int); |
229 |
264 |
2300 } |
2335 } |
2301 if (protocol == IPPROTO_TCP) |
2336 if (protocol == IPPROTO_TCP) |
2302 connp->conn_recv = tcp_input; |
2337 connp->conn_recv = tcp_input; |
2303 } |
2338 } |
2304 /* Update qinfo if v4/v6 changed */ |
2339 /* Update qinfo if v4/v6 changed */ |
2305 if ((orig_pkt_isv6 != connp->conn_pkt_isv6) && !IS_TCP_CONN(connp)) { |
2340 if ((orig_pkt_isv6 != connp->conn_pkt_isv6) && |
2341 !(IPCL_IS_TCP(connp) || IPCL_IS_UDP(connp))) { |
|
2306 if (connp->conn_pkt_isv6) |
2342 if (connp->conn_pkt_isv6) |
2307 ip_setqinfo(RD(q), IPV6_MINOR, B_TRUE); |
2343 ip_setqinfo(RD(q), IPV6_MINOR, B_TRUE); |
2308 else |
2344 else |
2309 ip_setqinfo(RD(q), IPV4_MINOR, B_TRUE); |
2345 ip_setqinfo(RD(q), IPV4_MINOR, B_TRUE); |
2310 } |
2346 } |
2529 static void |
2565 static void |
2530 ip_bind_connected_resume_v6(ipsq_t *ipsq, queue_t *q, mblk_t *mp, |
2566 ip_bind_connected_resume_v6(ipsq_t *ipsq, queue_t *q, mblk_t *mp, |
2531 void *dummy_arg) |
2567 void *dummy_arg) |
2532 { |
2568 { |
2533 conn_t *connp = NULL; |
2569 conn_t *connp = NULL; |
2534 tcp_t *tcp; |
|
2535 t_scalar_t prim; |
2570 t_scalar_t prim; |
2536 |
2571 |
2537 ASSERT(DB_TYPE(mp) == M_PROTO || DB_TYPE(mp) == M_PCPROTO); |
2572 ASSERT(DB_TYPE(mp) == M_PROTO || DB_TYPE(mp) == M_PCPROTO); |
2538 |
2573 |
2539 if (CONN_Q(q)) |
2574 if (CONN_Q(q)) |
2541 ASSERT(connp != NULL); |
2576 ASSERT(connp != NULL); |
2542 |
2577 |
2543 prim = ((union T_primitives *)mp->b_rptr)->type; |
2578 prim = ((union T_primitives *)mp->b_rptr)->type; |
2544 ASSERT(prim == O_T_BIND_REQ || prim == T_BIND_REQ); |
2579 ASSERT(prim == O_T_BIND_REQ || prim == T_BIND_REQ); |
2545 |
2580 |
2546 tcp = connp->conn_tcp; |
2581 if (IPCL_IS_TCP(connp)) { |
2547 if (tcp != NULL) { |
|
2548 /* Pass sticky_ipp for scope_id and pktinfo */ |
2582 /* Pass sticky_ipp for scope_id and pktinfo */ |
2549 mp = ip_bind_v6(q, mp, connp, &tcp->tcp_sticky_ipp); |
2583 mp = ip_bind_v6(q, mp, connp, &connp->conn_tcp->tcp_sticky_ipp); |
2550 } else { |
2584 } else { |
2551 /* For UDP and ICMP */ |
2585 /* For UDP and ICMP */ |
2552 mp = ip_bind_v6(q, mp, connp, NULL); |
2586 mp = ip_bind_v6(q, mp, connp, NULL); |
2553 } |
2587 } |
2554 if (mp != NULL) { |
2588 if (mp != NULL) { |
2555 if (tcp != NULL) { |
2589 if (IPCL_IS_TCP(connp)) { |
2556 CONN_INC_REF(connp); |
2590 CONN_INC_REF(connp); |
2557 squeue_fill(connp->conn_sqp, mp, |
2591 squeue_fill(connp->conn_sqp, mp, ip_resume_tcp_bind, |
2558 ip_resume_tcp_bind, connp, SQTAG_TCP_RPUTOTHER); |
2592 connp, SQTAG_TCP_RPUTOTHER); |
2559 return; |
2593 } else if (IPCL_IS_UDP(connp)) { |
2594 udp_resume_bind(connp, mp); |
|
2560 } else { |
2595 } else { |
2561 qreply(q, mp); |
2596 qreply(q, mp); |
2562 } |
2597 CONN_OPER_PENDING_DONE(connp); |
2563 CONN_OPER_PENDING_DONE(connp); |
2598 } |
2564 } |
2599 } |
2565 } |
2600 } |
2566 |
2601 |
2567 /* |
2602 /* |
2568 * Verify that both the source and destination addresses |
2603 * Verify that both the source and destination addresses |
2717 * IRE during Multidata packet transmission in tcp_multisend(). |
2752 * IRE during Multidata packet transmission in tcp_multisend(). |
2718 */ |
2753 */ |
2719 if (ip_multidata_outbound && !ipsec_policy_set && dst_ire != NULL && |
2754 if (ip_multidata_outbound && !ipsec_policy_set && dst_ire != NULL && |
2720 !(dst_ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST)) && |
2755 !(dst_ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST)) && |
2721 (md_ill = ire_to_ill(dst_ire), md_ill != NULL) && |
2756 (md_ill = ire_to_ill(dst_ire), md_ill != NULL) && |
2722 (md_ill->ill_capabilities & ILL_CAPAB_MDT)) { |
2757 ILL_MDT_CAPABLE(md_ill)) { |
2723 md_dst_ire = dst_ire; |
2758 md_dst_ire = dst_ire; |
2724 IRE_REFHOLD(md_dst_ire); |
2759 IRE_REFHOLD(md_dst_ire); |
2725 } |
2760 } |
2726 |
2761 |
2727 if (dst_ire != NULL && |
2762 if (dst_ire != NULL && |
2934 * The addresses have been verified. Time to insert in |
2969 * The addresses have been verified. Time to insert in |
2935 * the correct fanout list. |
2970 * the correct fanout list. |
2936 */ |
2971 */ |
2937 error = ipcl_conn_insert_v6(connp, protocol, v6src, v6dst, |
2972 error = ipcl_conn_insert_v6(connp, protocol, v6src, v6dst, |
2938 connp->conn_ports, |
2973 connp->conn_ports, |
2939 IS_TCP_CONN(connp) ? connp->conn_tcp->tcp_bound_if : 0); |
2974 IPCL_IS_TCP(connp) ? connp->conn_tcp->tcp_bound_if : 0); |
2940 } |
2975 } |
2941 if (error == 0) { |
2976 if (error == 0) { |
2942 connp->conn_fully_bound = B_TRUE; |
2977 connp->conn_fully_bound = B_TRUE; |
2943 /* |
2978 /* |
2944 * Our initial checks for MDT have passed; the IRE is not |
2979 * Our initial checks for MDT have passed; the IRE is not |
3409 uint32_t ill_index; |
3444 uint32_t ill_index; |
3410 |
3445 |
3411 ASSERT((dp->db_struioflag & STRUIO_IP) == 0); |
3446 ASSERT((dp->db_struioflag & STRUIO_IP) == 0); |
3412 |
3447 |
3413 /* Initiate IPPf processing, if needed. */ |
3448 /* Initiate IPPf processing, if needed. */ |
3414 if (IPP_ENABLED(IPP_LOCAL_IN) && |
3449 if (IPP_ENABLED(IPP_LOCAL_IN) && (flags & IP6_NO_IPPOLICY)) { |
3415 (flags & (IP6_NO_IPPOLICY|IP6_IN_NOCKSUM))) { |
|
3416 ill_index = ill->ill_phyint->phyint_ifindex; |
3450 ill_index = ill->ill_phyint->phyint_ifindex; |
3417 ip_process(IPP_LOCAL_IN, &first_mp, ill_index); |
3451 ip_process(IPP_LOCAL_IN, &first_mp, ill_index); |
3418 if (first_mp == NULL) { |
3452 if (first_mp == NULL) { |
3419 if (connp != NULL) |
3453 if (connp != NULL) |
3420 CONN_DEC_REF(connp); |
3454 CONN_DEC_REF(connp); |
3445 } else { |
3479 } else { |
3446 sqp = IP_SQUEUE_GET(lbolt); |
3480 sqp = IP_SQUEUE_GET(lbolt); |
3447 } |
3481 } |
3448 |
3482 |
3449 mp->b_datap->db_struioflag |= STRUIO_EAGER; |
3483 mp->b_datap->db_struioflag |= STRUIO_EAGER; |
3450 mp->b_datap->db_cksumstart = (intptr_t)sqp; |
3484 DB_CKSUMSTART(mp) = (intptr_t)sqp; |
3451 |
3485 |
3452 /* |
3486 /* |
3453 * db_cksumstuff is unused in the incoming |
3487 * db_cksumstuff is unused in the incoming |
3454 * path; Thus store the ifindex here. It will |
3488 * path; Thus store the ifindex here. It will |
3455 * be cleared in tcp_conn_create_v6(). |
3489 * be cleared in tcp_conn_create_v6(). |
3456 */ |
3490 */ |
3457 mp->b_datap->db_cksumstuff = |
3491 DB_CKSUMSTUFF(mp) = |
3458 (intptr_t)ill->ill_phyint->phyint_ifindex; |
3492 (intptr_t)ill->ill_phyint->phyint_ifindex; |
3459 syn_present = B_TRUE; |
3493 syn_present = B_TRUE; |
3460 } |
3494 } |
3461 } |
3495 } |
3462 |
3496 |
3585 static void |
3619 static void |
3586 ip_fanout_udp_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h, uint32_t ports, |
3620 ip_fanout_udp_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h, uint32_t ports, |
3587 ill_t *ill, ill_t *inill, uint_t flags, boolean_t mctl_present, |
3621 ill_t *ill, ill_t *inill, uint_t flags, boolean_t mctl_present, |
3588 zoneid_t zoneid) |
3622 zoneid_t zoneid) |
3589 { |
3623 { |
3590 queue_t *rq; |
|
3591 uint32_t dstport, srcport; |
3624 uint32_t dstport, srcport; |
3592 in6_addr_t dst; |
3625 in6_addr_t dst; |
3593 mblk_t *first_mp; |
3626 mblk_t *first_mp; |
3594 boolean_t secure; |
3627 boolean_t secure; |
3595 conn_t *connp; |
3628 conn_t *connp; |
3635 goto notfound; |
3668 goto notfound; |
3636 |
3669 |
3637 /* Found a client */ |
3670 /* Found a client */ |
3638 CONN_INC_REF(connp); |
3671 CONN_INC_REF(connp); |
3639 mutex_exit(&connfp->connf_lock); |
3672 mutex_exit(&connfp->connf_lock); |
3640 rq = connp->conn_rq; |
3673 |
3641 |
3674 if (CONN_UDP_FLOWCTLD(connp)) { |
3642 if (!canputnext(rq)) { |
|
3643 freemsg(first_mp); |
3675 freemsg(first_mp); |
3644 BUMP_MIB(ill->ill_ip6_mib, udpInOverflows); |
3676 BUMP_MIB(ill->ill_ip6_mib, udpInOverflows); |
3645 CONN_DEC_REF(connp); |
3677 CONN_DEC_REF(connp); |
3646 return; |
3678 return; |
3647 } |
3679 } |
3689 } else { |
3721 } else { |
3690 first_mp = mp; |
3722 first_mp = mp; |
3691 } |
3723 } |
3692 } |
3724 } |
3693 BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers); |
3725 BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers); |
3694 putnext(rq, mp); |
3726 |
3727 /* Send it upstream */ |
|
3728 CONN_UDP_RECV(connp, mp); |
|
3729 |
|
3695 IP6_STAT(ip6_udp_fannorm); |
3730 IP6_STAT(ip6_udp_fannorm); |
3696 CONN_DEC_REF(connp); |
3731 CONN_DEC_REF(connp); |
3697 if (mctl_present) |
3732 if (mctl_present) |
3698 freeb(first_mp); |
3733 freeb(first_mp); |
3699 return; |
3734 return; |
3744 break; |
3779 break; |
3745 } |
3780 } |
3746 mp1 = mctl_present ? first_mp1->b_cont : first_mp1; |
3781 mp1 = mctl_present ? first_mp1->b_cont : first_mp1; |
3747 CONN_INC_REF(connp); |
3782 CONN_INC_REF(connp); |
3748 mutex_exit(&connfp->connf_lock); |
3783 mutex_exit(&connfp->connf_lock); |
3749 rq = connp->conn_rq; |
|
3750 /* |
3784 /* |
3751 * For link-local always add ifindex so that transport |
3785 * For link-local always add ifindex so that transport |
3752 * can set sin6_scope_id. Avoid it for ICMP error |
3786 * can set sin6_scope_id. Avoid it for ICMP error |
3753 * fanout. |
3787 * fanout. |
3754 */ |
3788 */ |
3760 } |
3794 } |
3761 if (mp1 == NULL) { |
3795 if (mp1 == NULL) { |
3762 BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards); |
3796 BUMP_MIB(ill->ill_ip6_mib, ipv6InDiscards); |
3763 goto next_one; |
3797 goto next_one; |
3764 } |
3798 } |
3765 if (!canputnext(rq)) { |
3799 if (CONN_UDP_FLOWCTLD(connp)) { |
3766 BUMP_MIB(ill->ill_ip6_mib, udpInOverflows); |
3800 BUMP_MIB(ill->ill_ip6_mib, udpInOverflows); |
3767 freemsg(mp1); |
3801 freemsg(mp1); |
3768 goto next_one; |
3802 goto next_one; |
3769 } |
3803 } |
3770 |
3804 |
3776 } |
3810 } |
3777 if (first_mp1 != NULL) { |
3811 if (first_mp1 != NULL) { |
3778 if (mctl_present) |
3812 if (mctl_present) |
3779 freeb(first_mp1); |
3813 freeb(first_mp1); |
3780 BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers); |
3814 BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers); |
3781 putnext(rq, mp1); |
3815 |
3816 /* Send it upstream */ |
|
3817 CONN_UDP_RECV(connp, mp1); |
|
3782 } |
3818 } |
3783 next_one: |
3819 next_one: |
3784 mutex_enter(&connfp->connf_lock); |
3820 mutex_enter(&connfp->connf_lock); |
3785 /* Follow the next pointer before releasing the conn. */ |
3821 /* Follow the next pointer before releasing the conn. */ |
3786 next_conn = connp->conn_next; |
3822 next_conn = connp->conn_next; |
3789 connp = next_conn; |
3825 connp = next_conn; |
3790 } |
3826 } |
3791 |
3827 |
3792 /* Last one. Send it upstream. */ |
3828 /* Last one. Send it upstream. */ |
3793 mutex_exit(&connfp->connf_lock); |
3829 mutex_exit(&connfp->connf_lock); |
3794 rq = connp->conn_rq; |
|
3795 |
3830 |
3796 /* Initiate IPPF processing */ |
3831 /* Initiate IPPF processing */ |
3797 if (IP6_IN_IPP(flags)) { |
3832 if (IP6_IN_IPP(flags)) { |
3798 uint_t ifindex; |
3833 uint_t ifindex; |
3799 |
3834 |
3828 first_mp->b_cont = mp; |
3863 first_mp->b_cont = mp; |
3829 } else { |
3864 } else { |
3830 first_mp = mp; |
3865 first_mp = mp; |
3831 } |
3866 } |
3832 } |
3867 } |
3833 if (!canputnext(rq)) { |
3868 if (CONN_UDP_FLOWCTLD(connp)) { |
3834 BUMP_MIB(ill->ill_ip6_mib, udpInOverflows); |
3869 BUMP_MIB(ill->ill_ip6_mib, udpInOverflows); |
3835 freemsg(mp); |
3870 freemsg(mp); |
3836 } else { |
3871 } else { |
3837 if (CONN_INBOUND_POLICY_PRESENT_V6(connp) || secure) { |
3872 if (CONN_INBOUND_POLICY_PRESENT_V6(connp) || secure) { |
3838 first_mp = ipsec_check_inbound_policy(first_mp, |
3873 first_mp = ipsec_check_inbound_policy(first_mp, |
3842 CONN_DEC_REF(connp); |
3877 CONN_DEC_REF(connp); |
3843 return; |
3878 return; |
3844 } |
3879 } |
3845 } |
3880 } |
3846 BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers); |
3881 BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers); |
3847 putnext(rq, mp); |
3882 |
3883 /* Send it upstream */ |
|
3884 CONN_UDP_RECV(connp, mp); |
|
3848 } |
3885 } |
3849 IP6_STAT(ip6_udp_fanmb); |
3886 IP6_STAT(ip6_udp_fanmb); |
3850 CONN_DEC_REF(connp); |
3887 CONN_DEC_REF(connp); |
3851 if (mctl_present) |
3888 if (mctl_present) |
3852 freeb(first_mp); |
3889 freeb(first_mp); |
6445 * because the ill has been cleaned up and things hanging |
6482 * because the ill has been cleaned up and things hanging |
6446 * off the ill have been freed. |
6483 * off the ill have been freed. |
6447 */ |
6484 */ |
6448 if ((mp->b_datap->db_type != M_PCPROTO) || |
6485 if ((mp->b_datap->db_type != M_PCPROTO) || |
6449 (dl->dl_primitive == DL_UNITDATA_IND)) { |
6486 (dl->dl_primitive == DL_UNITDATA_IND)) { |
6450 ip_ioctl_freemsg(mp); |
6487 inet_freemsg(mp); |
6451 return; |
6488 return; |
6452 } |
6489 } |
6453 } |
6490 } |
6454 |
6491 |
6455 switch (mp->b_datap->db_type) { |
6492 switch (mp->b_datap->db_type) { |
6833 boolean_t mctl_present; |
6870 boolean_t mctl_present; |
6834 mblk_t *first_mp; |
6871 mblk_t *first_mp; |
6835 mblk_t *first_mp1; |
6872 mblk_t *first_mp1; |
6836 boolean_t no_forward; |
6873 boolean_t no_forward; |
6837 ip6_hbh_t *hbhhdr; |
6874 ip6_hbh_t *hbhhdr; |
6838 boolean_t no_cksum = (flags & IP6_IN_NOCKSUM); |
|
6839 boolean_t ll_multicast = (flags & IP6_IN_LLMCAST); |
6875 boolean_t ll_multicast = (flags & IP6_IN_LLMCAST); |
6840 conn_t *connp; |
6876 conn_t *connp; |
6841 int off; |
|
6842 ilm_t *ilm; |
6877 ilm_t *ilm; |
6843 uint32_t ports; |
6878 uint32_t ports; |
6844 uint_t ipif_id = 0; |
6879 uint_t ipif_id = 0; |
6845 zoneid_t zoneid = GLOBAL_ZONEID; |
6880 zoneid_t zoneid = GLOBAL_ZONEID; |
6881 uint16_t hck_flags, reass_hck_flags; |
|
6882 uint32_t reass_sum; |
|
6883 boolean_t cksum_err; |
|
6884 mblk_t *mp1; |
|
6846 |
6885 |
6847 EXTRACT_PKT_MP(mp, first_mp, mctl_present); |
6886 EXTRACT_PKT_MP(mp, first_mp, mctl_present); |
6848 |
6887 |
6849 if (hada_mp != NULL) { |
6888 if (hada_mp != NULL) { |
6850 /* |
6889 /* |
6897 return; |
6936 return; |
6898 } |
6937 } |
6899 pkt_len -= diff; |
6938 pkt_len -= diff; |
6900 } |
6939 } |
6901 |
6940 |
6902 /* |
6941 if (ILL_HCKSUM_CAPABLE(ill) && !mctl_present && dohwcksum) |
6903 * XXX When zero-copy support is added, this turning off of |
6942 hck_flags = DB_CKSUMFLAGS(mp); |
6904 * checksum flag will need to be done more selectively. |
6943 else |
6905 */ |
6944 hck_flags = 0; |
6906 mp->b_datap->db_struioun.cksum.flags &= ~HCK_PARTIALCKSUM; |
6945 |
6946 /* Clear checksum flags in case we need to forward */ |
|
6947 DB_CKSUMFLAGS(mp) = 0; |
|
6948 reass_sum = reass_hck_flags = 0; |
|
6907 |
6949 |
6908 nexthdr = ip6h->ip6_nxt; |
6950 nexthdr = ip6h->ip6_nxt; |
6909 |
6951 |
6910 prev_nexthdr_offset = (uint_t)((uchar_t *)&ip6h->ip6_nxt - |
6952 prev_nexthdr_offset = (uint_t)((uchar_t *)&ip6h->ip6_nxt - |
6911 (uchar_t *)ip6h); |
6953 (uchar_t *)ip6h); |
7166 return; |
7208 return; |
7167 } |
7209 } |
7168 /* TBD add site-local check at site boundary? */ |
7210 /* TBD add site-local check at site boundary? */ |
7169 } else if (ipv6_send_redirects) { |
7211 } else if (ipv6_send_redirects) { |
7170 in6_addr_t *v6targ; |
7212 in6_addr_t *v6targ; |
7171 mblk_t *mp1; |
|
7172 in6_addr_t gw_addr_v6; |
7213 in6_addr_t gw_addr_v6; |
7173 ire_t *src_ire_v6 = NULL; |
7214 ire_t *src_ire_v6 = NULL; |
7174 |
7215 |
7175 /* |
7216 /* |
7176 * Don't send a redirect when forwarding a source |
7217 * Don't send a redirect when forwarding a source |
7311 for (; ; ) { |
7352 for (; ; ) { |
7312 switch (nexthdr) { |
7353 switch (nexthdr) { |
7313 case IPPROTO_TCP: { |
7354 case IPPROTO_TCP: { |
7314 uint16_t *up; |
7355 uint16_t *up; |
7315 uint32_t sum; |
7356 uint32_t sum; |
7316 dblk_t *dp; |
|
7317 int offset; |
7357 int offset; |
7318 |
7358 |
7319 hdr_len = pkt_len - remlen; |
7359 hdr_len = pkt_len - remlen; |
7320 |
7360 |
7321 if (hada_mp != NULL) { |
7361 if (hada_mp != NULL) { |
7334 BUMP_MIB(ill->ill_ip6_mib, |
7374 BUMP_MIB(ill->ill_ip6_mib, |
7335 ipv6InDiscards); |
7375 ipv6InDiscards); |
7336 freemsg(first_mp); |
7376 freemsg(first_mp); |
7337 return; |
7377 return; |
7338 } |
7378 } |
7379 hck_flags = 0; |
|
7339 ip6h = (ip6_t *)mp->b_rptr; |
7380 ip6h = (ip6_t *)mp->b_rptr; |
7340 whereptr = (uint8_t *)ip6h + hdr_len; |
7381 whereptr = (uint8_t *)ip6h + hdr_len; |
7341 } |
7382 } |
7342 /* |
7383 /* |
7343 * Extract the offset field from the TCP header. |
7384 * Extract the offset field from the TCP header. |
7366 BUMP_MIB(ill->ill_ip6_mib, |
7407 BUMP_MIB(ill->ill_ip6_mib, |
7367 ipv6InDiscards); |
7408 ipv6InDiscards); |
7368 freemsg(first_mp); |
7409 freemsg(first_mp); |
7369 return; |
7410 return; |
7370 } |
7411 } |
7412 hck_flags = 0; |
|
7371 ip6h = (ip6_t *)mp->b_rptr; |
7413 ip6h = (ip6_t *)mp->b_rptr; |
7372 whereptr = (uint8_t *)ip6h + hdr_len; |
7414 whereptr = (uint8_t *)ip6h + hdr_len; |
7373 } |
7415 } |
7374 } |
|
7375 |
|
7376 /* |
|
7377 * If packet is being looped back locally checksums |
|
7378 * aren't used |
|
7379 */ |
|
7380 if (no_cksum) { |
|
7381 if (mp->b_datap->db_type == M_DATA) { |
|
7382 /* |
|
7383 * M_DATA mblk, so init mblk (chain) |
|
7384 * for no struio(). |
|
7385 */ |
|
7386 mblk_t *mp1 = mp; |
|
7387 |
|
7388 do { |
|
7389 mp1->b_datap->db_struioflag = 0; |
|
7390 } while ((mp1 = mp1->b_cont) != NULL); |
|
7391 } |
|
7392 goto tcp_fanout; |
|
7393 } |
7416 } |
7394 |
7417 |
7395 up = (uint16_t *)&ip6h->ip6_src; |
7418 up = (uint16_t *)&ip6h->ip6_src; |
7396 /* |
7419 /* |
7397 * TCP checksum calculation. First sum up the |
7420 * TCP checksum calculation. First sum up the |
7398 * pseudo-header fields: |
7421 * pseudo-header fields: |
7399 * - Source IPv6 address |
7422 * - Source IPv6 address |
7400 * - Destination IPv6 address |
7423 * - Destination IPv6 address |
7401 * - TCP payload length |
7424 * - TCP payload length |
7402 * - TCP protocol ID |
7425 * - TCP protocol ID |
7403 * XXX need zero-copy support here |
|
7404 */ |
7426 */ |
7405 sum = htons(IPPROTO_TCP + remlen) + |
7427 sum = htons(IPPROTO_TCP + remlen) + |
7406 up[0] + up[1] + up[2] + up[3] + |
7428 up[0] + up[1] + up[2] + up[3] + |
7407 up[4] + up[5] + up[6] + up[7] + |
7429 up[4] + up[5] + up[6] + up[7] + |
7408 up[8] + up[9] + up[10] + up[11] + |
7430 up[8] + up[9] + up[10] + up[11] + |
7409 up[12] + up[13] + up[14] + up[15]; |
7431 up[12] + up[13] + up[14] + up[15]; |
7432 |
|
7433 /* Fold initial sum */ |
|
7410 sum = (sum & 0xffff) + (sum >> 16); |
7434 sum = (sum & 0xffff) + (sum >> 16); |
7411 dp = mp->b_datap; |
7435 |
7412 if (dp->db_type != M_DATA || dp->db_ref > 1) { |
7436 mp1 = mp->b_cont; |
7413 /* |
7437 |
7414 * Not M_DATA mblk or its a dup, so do the |
7438 if ((hck_flags & (HCK_FULLCKSUM|HCK_PARTIALCKSUM)) == 0) |
7415 * checksum now. |
7439 IP6_STAT(ip6_in_sw_cksum); |
7416 */ |
7440 |
7417 sum = IP_CSUM(mp, hdr_len, sum); |
7441 IP_CKSUM_RECV(hck_flags, sum, (uchar_t *) |
7418 if (sum) { |
7442 ((uchar_t *)mp->b_rptr + DB_CKSUMSTART(mp)), |
7419 /* checksum failed */ |
7443 (int32_t)(whereptr - (uchar_t *)mp->b_rptr), |
7420 ip1dbg(("ip_rput_data_v6: TCP checksum" |
7444 mp, mp1, cksum_err); |
7421 " failed %x off %d\n", |
7445 |
7422 sum, hdr_len)); |
7446 if (cksum_err) { |
7423 BUMP_MIB(&ip_mib, tcpInErrs); |
7447 BUMP_MIB(&ip_mib, tcpInErrs); |
7424 freemsg(first_mp); |
7448 |
7425 return; |
7449 if (hck_flags & HCK_FULLCKSUM) |
7426 } |
7450 IP6_STAT(ip6_tcp_in_full_hw_cksum_err); |
7427 } else { |
7451 else if (hck_flags & HCK_PARTIALCKSUM) |
7428 /* |
7452 IP6_STAT(ip6_tcp_in_part_hw_cksum_err); |
7429 * M_DATA mblk and not a dup |
7453 else |
7430 * compute checksum here |
7454 IP6_STAT(ip6_tcp_in_sw_cksum_err); |
7431 */ |
7455 |
7432 off = (int)(whereptr - mp->b_rptr); |
7456 freemsg(first_mp); |
7433 |
7457 return; |
7434 if (IP_CSUM(mp, off, sum)) { |
|
7435 BUMP_MIB(&ip_mib, tcpInErrs); |
|
7436 ipcsumdbg("ip_rput_data_v6 " |
|
7437 "swcksumerr\n", mp); |
|
7438 freemsg(first_mp); |
|
7439 return; |
|
7440 } |
|
7441 } |
7458 } |
7442 tcp_fanout: |
7459 tcp_fanout: |
7443 ip_fanout_tcp_v6(q, first_mp, ip6h, ill, inill, |
7460 ip_fanout_tcp_v6(q, first_mp, ip6h, ill, inill, |
7444 (flags|IP_FF_SEND_ICMP|IP_FF_SYN_ADDIRE| |
7461 (flags|IP_FF_SEND_ICMP|IP_FF_SYN_ADDIRE| |
7445 IP_FF_IP6INFO), hdr_len, mctl_present, zoneid); |
7462 IP_FF_IP6INFO), hdr_len, mctl_present, zoneid); |
7466 ip6h = (ip6_t *)mp->b_rptr; |
7483 ip6h = (ip6_t *)mp->b_rptr; |
7467 whereptr = (uint8_t *)ip6h + hdr_len; |
7484 whereptr = (uint8_t *)ip6h + hdr_len; |
7468 } |
7485 } |
7469 |
7486 |
7470 sctph = (sctp_hdr_t *)(mp->b_rptr + hdr_len); |
7487 sctph = (sctp_hdr_t *)(mp->b_rptr + hdr_len); |
7471 if (!no_cksum) { |
7488 /* checksum */ |
7472 /* checksum */ |
7489 pktsum = sctph->sh_chksum; |
7473 pktsum = sctph->sh_chksum; |
7490 sctph->sh_chksum = 0; |
7474 sctph->sh_chksum = 0; |
7491 calcsum = sctp_cksum(mp, hdr_len); |
7475 calcsum = sctp_cksum(mp, hdr_len); |
7492 if (calcsum != pktsum) { |
7476 if (calcsum != pktsum) { |
7493 BUMP_MIB(&sctp_mib, sctpChecksumError); |
7477 BUMP_MIB(&sctp_mib, sctpChecksumError); |
7494 freemsg(mp); |
7478 freemsg(mp); |
7495 return; |
7479 return; |
7496 } |
7480 } |
7497 sctph->sh_chksum = pktsum; |
7481 sctph->sh_chksum = pktsum; |
|
7482 } |
|
7483 ports = *(uint32_t *)(mp->b_rptr + hdr_len); |
7498 ports = *(uint32_t *)(mp->b_rptr + hdr_len); |
7484 if ((connp = sctp_find_conn(&ip6h->ip6_src, |
7499 if ((connp = sctp_find_conn(&ip6h->ip6_src, |
7485 &ip6h->ip6_dst, ports, ipif_id, zoneid)) == NULL) { |
7500 &ip6h->ip6_dst, ports, ipif_id, zoneid)) == NULL) { |
7486 ip_fanout_sctp_raw(first_mp, ill, |
7501 ip_fanout_sctp_raw(first_mp, ill, |
7487 (ipha_t *)ip6h, B_FALSE, ports, |
7502 (ipha_t *)ip6h, B_FALSE, ports, |
7498 case IPPROTO_UDP: { |
7513 case IPPROTO_UDP: { |
7499 uint16_t *up; |
7514 uint16_t *up; |
7500 uint32_t sum; |
7515 uint32_t sum; |
7501 |
7516 |
7502 hdr_len = pkt_len - remlen; |
7517 hdr_len = pkt_len - remlen; |
7503 |
|
7504 #define UDPH_SIZE 8 |
|
7505 |
7518 |
7506 if (hada_mp != NULL) { |
7519 if (hada_mp != NULL) { |
7507 ip0dbg(("udp hada drop\n")); |
7520 ip0dbg(("udp hada drop\n")); |
7508 goto hada_drop; |
7521 goto hada_drop; |
7509 } |
7522 } |
7517 BUMP_MIB(ill->ill_ip6_mib, |
7530 BUMP_MIB(ill->ill_ip6_mib, |
7518 ipv6InDiscards); |
7531 ipv6InDiscards); |
7519 freemsg(first_mp); |
7532 freemsg(first_mp); |
7520 return; |
7533 return; |
7521 } |
7534 } |
7535 hck_flags = 0; |
|
7522 ip6h = (ip6_t *)mp->b_rptr; |
7536 ip6h = (ip6_t *)mp->b_rptr; |
7523 whereptr = (uint8_t *)ip6h + hdr_len; |
7537 whereptr = (uint8_t *)ip6h + hdr_len; |
7524 } |
7538 } |
7525 #undef UDPH_SIZE |
|
7526 /* |
|
7527 * If packet is being looped back locally checksums |
|
7528 * aren't used |
|
7529 */ |
|
7530 if (no_cksum) |
|
7531 goto udp_fanout; |
|
7532 |
7539 |
7533 /* |
7540 /* |
7534 * Before going through the regular checksum |
7541 * Before going through the regular checksum |
7535 * calculation, make sure the received checksum |
7542 * calculation, make sure the received checksum |
7536 * is non-zero. RFC 2460 says, a 0x0000 checksum |
7543 * is non-zero. RFC 2460 says, a 0x0000 checksum |
7566 up[0] + up[1] + up[2] + up[3] + |
7573 up[0] + up[1] + up[2] + up[3] + |
7567 up[4] + up[5] + up[6] + up[7] + |
7574 up[4] + up[5] + up[6] + up[7] + |
7568 up[8] + up[9] + up[10] + up[11] + |
7575 up[8] + up[9] + up[10] + up[11] + |
7569 up[12] + up[13] + up[14] + up[15]; |
7576 up[12] + up[13] + up[14] + up[15]; |
7570 |
7577 |
7578 /* Fold initial sum */ |
|
7571 sum = (sum & 0xffff) + (sum >> 16); |
7579 sum = (sum & 0xffff) + (sum >> 16); |
7572 /* Next sum in the UDP packet */ |
7580 |
7573 sum = IP_CSUM(mp, hdr_len, sum); |
7581 if (reass_hck_flags != 0) { |
7574 if (sum) { |
7582 hck_flags = reass_hck_flags; |
7575 /* UDP checksum failed */ |
7583 |
7576 ip1dbg(("ip_rput_data_v6: UDP checksum " |
7584 IP_CKSUM_RECV_REASS(hck_flags, |
7577 "failed %x\n", |
7585 (int32_t)(whereptr - (uchar_t *)mp->b_rptr), |
7578 sum)); |
7586 sum, reass_sum, cksum_err); |
7587 } else { |
|
7588 mp1 = mp->b_cont; |
|
7589 |
|
7590 IP_CKSUM_RECV(hck_flags, sum, (uchar_t *) |
|
7591 ((uchar_t *)mp->b_rptr + DB_CKSUMSTART(mp)), |
|
7592 (int32_t)(whereptr - (uchar_t *)mp->b_rptr), |
|
7593 mp, mp1, cksum_err); |
|
7594 } |
|
7595 |
|
7596 if ((hck_flags & (HCK_FULLCKSUM|HCK_PARTIALCKSUM)) == 0) |
|
7597 IP6_STAT(ip6_in_sw_cksum); |
|
7598 |
|
7599 if (cksum_err) { |
|
7579 BUMP_MIB(ill->ill_ip6_mib, udpInCksumErrs); |
7600 BUMP_MIB(ill->ill_ip6_mib, udpInCksumErrs); |
7601 |
|
7602 if (hck_flags & HCK_FULLCKSUM) |
|
7603 IP6_STAT(ip6_udp_in_full_hw_cksum_err); |
|
7604 else if (hck_flags & HCK_PARTIALCKSUM) |
|
7605 IP6_STAT(ip6_udp_in_part_hw_cksum_err); |
|
7606 else |
|
7607 IP6_STAT(ip6_udp_in_sw_cksum_err); |
|
7608 |
|
7580 freemsg(first_mp); |
7609 freemsg(first_mp); |
7581 return; |
7610 return; |
7582 } |
7611 } |
7583 goto udp_fanout; |
7612 goto udp_fanout; |
7584 } |
7613 } |
7589 |
7618 |
7590 if (hada_mp != NULL) { |
7619 if (hada_mp != NULL) { |
7591 ip0dbg(("icmp hada drop\n")); |
7620 ip0dbg(("icmp hada drop\n")); |
7592 goto hada_drop; |
7621 goto hada_drop; |
7593 } |
7622 } |
7594 |
|
7595 /* |
|
7596 * If packet is being looped back locally checksums |
|
7597 * aren't used |
|
7598 */ |
|
7599 if (no_cksum) |
|
7600 goto icmp_fanout; |
|
7601 |
7623 |
7602 up = (uint16_t *)&ip6h->ip6_src; |
7624 up = (uint16_t *)&ip6h->ip6_src; |
7603 sum = htons(IPPROTO_ICMPV6 + remlen) + |
7625 sum = htons(IPPROTO_ICMPV6 + remlen) + |
7604 up[0] + up[1] + up[2] + up[3] + |
7626 up[0] + up[1] + up[2] + up[3] + |
7605 up[4] + up[5] + up[6] + up[7] + |
7627 up[4] + up[5] + up[6] + up[7] + |
7606 up[8] + up[9] + up[10] + up[11] + |
7628 up[8] + up[9] + up[10] + up[11] + |
7607 up[12] + up[13] + up[14] + up[15]; |
7629 up[12] + up[13] + up[14] + up[15]; |
7608 sum = (sum & 0xffff) + (sum >> 16); |
7630 sum = (sum & 0xffff) + (sum >> 16); |
7609 sum = IP_CSUM(mp, hdr_len, sum); |
7631 sum = IP_CSUM(mp, hdr_len, sum); |
7610 if (sum) { |
7632 if (sum != 0) { |
7611 /* IPv6 ICMP checksum failed */ |
7633 /* IPv6 ICMP checksum failed */ |
7612 ip1dbg(("ip_rput_data_v6: ICMPv6 checksum " |
7634 ip1dbg(("ip_rput_data_v6: ICMPv6 checksum " |
7613 "failed %x\n", |
7635 "failed %x\n", |
7614 sum)); |
7636 sum)); |
7615 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInMsgs); |
7637 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInMsgs); |
7793 BUMP_MIB(ill->ill_ip6_mib, |
7815 BUMP_MIB(ill->ill_ip6_mib, |
7794 ipv6InDiscards); |
7816 ipv6InDiscards); |
7795 freemsg(mp); |
7817 freemsg(mp); |
7796 return; |
7818 return; |
7797 } |
7819 } |
7820 hck_flags = 0; |
|
7798 ip6h = (ip6_t *)mp->b_rptr; |
7821 ip6h = (ip6_t *)mp->b_rptr; |
7799 whereptr = (uint8_t *)ip6h + pkt_len - remlen; |
7822 whereptr = (uint8_t *)ip6h + pkt_len - remlen; |
7800 } |
7823 } |
7801 |
7824 |
7802 fraghdr = (ip6_frag_t *)whereptr; |
7825 fraghdr = (ip6_frag_t *)whereptr; |
7818 freemsg(mp); |
7841 freemsg(mp); |
7819 return; |
7842 return; |
7820 } |
7843 } |
7821 } |
7844 } |
7822 |
7845 |
7846 /* Restore the flags */ |
|
7847 DB_CKSUMFLAGS(mp) = hck_flags; |
|
7848 |
|
7823 mp = ip_rput_frag_v6(q, mp, ip6h, fraghdr, |
7849 mp = ip_rput_frag_v6(q, mp, ip6h, fraghdr, |
7824 remlen - used, &prev_nexthdr_offset); |
7850 remlen - used, &prev_nexthdr_offset, |
7851 &reass_sum, &reass_hck_flags); |
|
7825 if (mp == NULL) { |
7852 if (mp == NULL) { |
7826 /* Reassembly is still pending */ |
7853 /* Reassembly is still pending */ |
7827 return; |
7854 return; |
7828 } |
7855 } |
7829 /* The first mblk are the headers before the frag hdr */ |
7856 /* The first mblk are the headers before the frag hdr */ |
8030 (flags|IP_FF_SEND_ICMP|IP_FF_IP6INFO), mctl_present, |
8057 (flags|IP_FF_SEND_ICMP|IP_FF_IP6INFO), mctl_present, |
8031 zoneid); |
8058 zoneid); |
8032 return; |
8059 return; |
8033 } |
8060 } |
8034 |
8061 |
8035 if (!canputnext(connp->conn_upq)) { |
8062 if (CONN_UDP_FLOWCTLD(connp)) { |
8036 freemsg(first_mp); |
8063 freemsg(first_mp); |
8037 BUMP_MIB(ill->ill_ip6_mib, udpInOverflows); |
8064 BUMP_MIB(ill->ill_ip6_mib, udpInOverflows); |
8038 CONN_DEC_REF(connp); |
8065 CONN_DEC_REF(connp); |
8039 return; |
8066 return; |
8040 } |
8067 } |
8060 } |
8087 } |
8061 |
8088 |
8062 IP6_STAT(ip6_udp_fast_path); |
8089 IP6_STAT(ip6_udp_fast_path); |
8063 BUMP_MIB(ill->ill_ip6_mib, ipv6InReceives); |
8090 BUMP_MIB(ill->ill_ip6_mib, ipv6InReceives); |
8064 BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers); |
8091 BUMP_MIB(ill->ill_ip6_mib, ipv6InDelivers); |
8065 putnext(connp->conn_upq, mp); |
8092 |
8093 /* Send it upstream */ |
|
8094 CONN_UDP_RECV(connp, mp); |
|
8066 |
8095 |
8067 CONN_DEC_REF(connp); |
8096 CONN_DEC_REF(connp); |
8068 freemsg(hada_mp); |
8097 freemsg(hada_mp); |
8069 return; |
8098 return; |
8070 |
8099 |
8084 * of the preceding header. This is needed to patch the previous header's |
8113 * of the preceding header. This is needed to patch the previous header's |
8085 * nexthdr field when reassembly completes. |
8114 * nexthdr field when reassembly completes. |
8086 */ |
8115 */ |
8087 static mblk_t * |
8116 static mblk_t * |
8088 ip_rput_frag_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h, |
8117 ip_rput_frag_v6(queue_t *q, mblk_t *mp, ip6_t *ip6h, |
8089 ip6_frag_t *fraghdr, uint_t remlen, uint_t *prev_nexthdr_offset) |
8118 ip6_frag_t *fraghdr, uint_t remlen, uint_t *prev_nexthdr_offset, |
8119 uint32_t *cksum_val, uint16_t *cksum_flags) |
|
8090 { |
8120 { |
8091 ill_t *ill = (ill_t *)q->q_ptr; |
8121 ill_t *ill = (ill_t *)q->q_ptr; |
8092 uint32_t ident = ntohl(fraghdr->ip6f_ident); |
8122 uint32_t ident = ntohl(fraghdr->ip6f_ident); |
8093 uint16_t offset; |
8123 uint16_t offset; |
8094 boolean_t more_frags; |
8124 boolean_t more_frags; |
8105 uint8_t ecn_info = 0; |
8135 uint8_t ecn_info = 0; |
8106 size_t msg_len; |
8136 size_t msg_len; |
8107 mblk_t *tail_mp; |
8137 mblk_t *tail_mp; |
8108 mblk_t *t_mp; |
8138 mblk_t *t_mp; |
8109 boolean_t pruned = B_FALSE; |
8139 boolean_t pruned = B_FALSE; |
8140 uint32_t sum_val; |
|
8141 uint16_t sum_flags; |
|
8142 |
|
8143 |
|
8144 if (cksum_val != NULL) |
|
8145 *cksum_val = 0; |
|
8146 if (cksum_flags != NULL) |
|
8147 *cksum_flags = 0; |
|
8148 |
|
8149 /* |
|
8150 * We utilize hardware computed checksum info only for UDP since |
|
8151 * IP fragmentation is a normal occurence for the protocol. In |
|
8152 * addition, checksum offload support for IP fragments carrying |
|
8153 * UDP payload is commonly implemented across network adapters. |
|
8154 */ |
|
8155 ASSERT(ill != NULL); |
|
8156 if (nexthdr == IPPROTO_UDP && dohwcksum && ILL_HCKSUM_CAPABLE(ill) && |
|
8157 (DB_CKSUMFLAGS(mp) & (HCK_FULLCKSUM | HCK_PARTIALCKSUM))) { |
|
8158 mblk_t *mp1 = mp->b_cont; |
|
8159 int32_t len; |
|
8160 |
|
8161 /* Record checksum information from the packet */ |
|
8162 sum_val = (uint32_t)DB_CKSUM16(mp); |
|
8163 sum_flags = DB_CKSUMFLAGS(mp); |
|
8164 |
|
8165 /* fragmented payload offset from beginning of mblk */ |
|
8166 offset = (uint16_t)((uchar_t *)&fraghdr[1] - mp->b_rptr); |
|
8167 |
|
8168 if ((sum_flags & HCK_PARTIALCKSUM) && |
|
8169 (mp1 == NULL || mp1->b_cont == NULL) && |
|
8170 offset >= (uint16_t)DB_CKSUMSTART(mp) && |
|
8171 ((len = offset - (uint16_t)DB_CKSUMSTART(mp)) & 1) == 0) { |
|
8172 uint32_t adj; |
|
8173 /* |
|
8174 * Partial checksum has been calculated by hardware |
|
8175 * and attached to the packet; in addition, any |
|
8176 * prepended extraneous data is even byte aligned. |
|
8177 * If any such data exists, we adjust the checksum; |
|
8178 * this would also handle any postpended data. |
|
8179 */ |
|
8180 IP_ADJCKSUM_PARTIAL(mp->b_rptr + DB_CKSUMSTART(mp), |
|
8181 mp, mp1, len, adj); |
|
8182 |
|
8183 /* One's complement subtract extraneous checksum */ |
|
8184 if (adj >= sum_val) |
|
8185 sum_val = ~(adj - sum_val) & 0xFFFF; |
|
8186 else |
|
8187 sum_val -= adj; |
|
8188 } |
|
8189 } else { |
|
8190 sum_val = 0; |
|
8191 sum_flags = 0; |
|
8192 } |
|
8193 |
|
8194 /* Clear hardware checksumming flag */ |
|
8195 DB_CKSUMFLAGS(mp) = 0; |
|
8110 |
8196 |
8111 /* |
8197 /* |
8112 * Note: Fragment offset in header is in 8-octet units. |
8198 * Note: Fragment offset in header is in 8-octet units. |
8113 * Clearing least significant 3 bits not only extracts |
8199 * Clearing least significant 3 bits not only extracts |
8114 * it but also gets it in units of octets. |
8200 * it but also gets it in units of octets. |
8157 |
8243 |
8158 /* |
8244 /* |
8159 * Drop the fragmented as early as possible, if |
8245 * Drop the fragmented as early as possible, if |
8160 * we don't have resource(s) to re-assemble. |
8246 * we don't have resource(s) to re-assemble. |
8161 */ |
8247 */ |
8162 |
|
8163 if (ip_reass_queue_bytes == 0) { |
8248 if (ip_reass_queue_bytes == 0) { |
8164 freemsg(mp); |
8249 freemsg(mp); |
8165 return (NULL); |
8250 return (NULL); |
8166 } |
8251 } |
8167 |
8252 |
8181 * IP ident field. The ILL frag hash table was allocated |
8266 * IP ident field. The ILL frag hash table was allocated |
8182 * as a timer block at the time the ILL was created. Whenever |
8267 * as a timer block at the time the ILL was created. Whenever |
8183 * there is anything on the reassembly queue, the timer will |
8268 * there is anything on the reassembly queue, the timer will |
8184 * be running. |
8269 * be running. |
8185 */ |
8270 */ |
8186 msg_len = mp->b_datap->db_lim - mp->b_datap->db_base; |
8271 msg_len = MBLKSIZE(mp); |
8187 tail_mp = mp; |
8272 tail_mp = mp; |
8188 while (tail_mp->b_cont != NULL) { |
8273 while (tail_mp->b_cont != NULL) { |
8189 tail_mp = tail_mp->b_cont; |
8274 tail_mp = tail_mp->b_cont; |
8190 msg_len += tail_mp->b_datap->db_lim - |
8275 msg_len += MBLKSIZE(tail_mp); |
8191 tail_mp->b_datap->db_base; |
|
8192 } |
8276 } |
8193 /* |
8277 /* |
8194 * If the reassembly list for this ILL will get too big |
8278 * If the reassembly list for this ILL will get too big |
8195 * prune it. |
8279 * prune it. |
8196 */ |
8280 */ |
8285 ipf->ipf_v6dst = *v6dst_ptr; |
8369 ipf->ipf_v6dst = *v6dst_ptr; |
8286 /* Record reassembly start time. */ |
8370 /* Record reassembly start time. */ |
8287 ipf->ipf_timestamp = gethrestime_sec(); |
8371 ipf->ipf_timestamp = gethrestime_sec(); |
8288 /* Record ipf generation and account for frag header */ |
8372 /* Record ipf generation and account for frag header */ |
8289 ipf->ipf_gen = ill->ill_ipf_gen++; |
8373 ipf->ipf_gen = ill->ill_ipf_gen++; |
8290 ipf->ipf_count = mp1->b_datap->db_lim - mp1->b_datap->db_base; |
8374 ipf->ipf_count = MBLKSIZE(mp1); |
8291 ipf->ipf_protocol = nexthdr; |
8375 ipf->ipf_protocol = nexthdr; |
8292 ipf->ipf_nf_hdr_len = 0; |
8376 ipf->ipf_nf_hdr_len = 0; |
8293 ipf->ipf_prev_nexthdr_offset = 0; |
8377 ipf->ipf_prev_nexthdr_offset = 0; |
8294 ipf->ipf_last_frag_seen = B_FALSE; |
8378 ipf->ipf_last_frag_seen = B_FALSE; |
8295 ipf->ipf_ecn = ecn_info; |
8379 ipf->ipf_ecn = ecn_info; |
8296 ipf->ipf_num_dups = 0; |
8380 ipf->ipf_num_dups = 0; |
8297 ipfb->ipfb_frag_pkts++; |
8381 ipfb->ipfb_frag_pkts++; |
8382 ipf->ipf_checksum = 0; |
|
8383 ipf->ipf_checksum_flags = 0; |
|
8384 |
|
8385 /* Store checksum value in fragment header */ |
|
8386 if (sum_flags != 0) { |
|
8387 sum_val = (sum_val & 0xFFFF) + (sum_val >> 16); |
|
8388 sum_val = (sum_val & 0xFFFF) + (sum_val >> 16); |
|
8389 ipf->ipf_checksum = sum_val; |
|
8390 ipf->ipf_checksum_flags = sum_flags; |
|
8391 } |
|
8298 |
8392 |
8299 /* |
8393 /* |
8300 * We handle reassembly two ways. In the easy case, |
8394 * We handle reassembly two ways. In the easy case, |
8301 * where all the fragments show up in order, we do |
8395 * where all the fragments show up in order, we do |
8302 * minimal bookkeeping, and just clip new pieces on |
8396 * minimal bookkeeping, and just clip new pieces on |
8324 /* |
8418 /* |
8325 * ipf_end == 0 means that we have given up |
8419 * ipf_end == 0 means that we have given up |
8326 * on easy reassembly. |
8420 * on easy reassembly. |
8327 */ |
8421 */ |
8328 ipf->ipf_end = 0; |
8422 ipf->ipf_end = 0; |
8423 |
|
8424 /* Forget checksum offload from now on */ |
|
8425 ipf->ipf_checksum_flags = 0; |
|
8426 |
|
8329 /* |
8427 /* |
8330 * ipf_hole_cnt is set by ip_reassemble. |
8428 * ipf_hole_cnt is set by ip_reassemble. |
8331 * ipf_count is updated by ip_reassemble. |
8429 * ipf_count is updated by ip_reassemble. |
8332 * No need to check for return value here |
8430 * No need to check for return value here |
8333 * as we don't expect reassembly to complete or |
8431 * as we don't expect reassembly to complete or |
8344 /* If the frag timer wasn't already going, start it. */ |
8442 /* If the frag timer wasn't already going, start it. */ |
8345 mutex_enter(&ill->ill_lock); |
8443 mutex_enter(&ill->ill_lock); |
8346 ill_frag_timer_start(ill); |
8444 ill_frag_timer_start(ill); |
8347 mutex_exit(&ill->ill_lock); |
8445 mutex_exit(&ill->ill_lock); |
8348 goto partial_reass_done; |
8446 goto partial_reass_done; |
8447 } |
|
8448 |
|
8449 /* |
|
8450 * If the packet's flag has changed (it could be coming up |
|
8451 * from an interface different than the previous, therefore |
|
8452 * possibly different checksum capability), then forget about |
|
8453 * any stored checksum states. Otherwise add the value to |
|
8454 * the existing one stored in the fragment header. |
|
8455 */ |
|
8456 if (sum_flags != 0 && sum_flags == ipf->ipf_checksum_flags) { |
|
8457 sum_val += ipf->ipf_checksum; |
|
8458 sum_val = (sum_val & 0xFFFF) + (sum_val >> 16); |
|
8459 sum_val = (sum_val & 0xFFFF) + (sum_val >> 16); |
|
8460 ipf->ipf_checksum = sum_val; |
|
8461 } else if (ipf->ipf_checksum_flags != 0) { |
|
8462 /* Forget checksum offload from now on */ |
|
8463 ipf->ipf_checksum_flags = 0; |
|
8349 } |
8464 } |
8350 |
8465 |
8351 /* |
8466 /* |
8352 * We have a new piece of a datagram which is already being |
8467 * We have a new piece of a datagram which is already being |
8353 * reassembled. Update the ECN info if all IP fragments |
8468 * reassembled. Update the ECN info if all IP fragments |
8441 * header |
8556 * header |
8442 */ |
8557 */ |
8443 nexthdr = ipf->ipf_protocol; |
8558 nexthdr = ipf->ipf_protocol; |
8444 *prev_nexthdr_offset = ipf->ipf_prev_nexthdr_offset; |
8559 *prev_nexthdr_offset = ipf->ipf_prev_nexthdr_offset; |
8445 ipfp = ipf->ipf_ptphn; |
8560 ipfp = ipf->ipf_ptphn; |
8561 |
|
8562 /* We need to supply these to caller */ |
|
8563 if ((sum_flags = ipf->ipf_checksum_flags) != 0) |
|
8564 sum_val = ipf->ipf_checksum; |
|
8565 else |
|
8566 sum_val = 0; |
|
8567 |
|
8446 mp1 = ipf->ipf_mp; |
8568 mp1 = ipf->ipf_mp; |
8447 count = ipf->ipf_count; |
8569 count = ipf->ipf_count; |
8448 ipf = ipf->ipf_hash_next; |
8570 ipf = ipf->ipf_hash_next; |
8449 if (ipf) |
8571 if (ipf) |
8450 ipf->ipf_ptphn = ipfp; |
8572 ipf->ipf_ptphn = ipfp; |
8505 /* Restore original IP length in header. */ |
8627 /* Restore original IP length in header. */ |
8506 ip6h->ip6_plen = htons((uint16_t)(msgdsize(mp) - IPV6_HDR_LEN)); |
8628 ip6h->ip6_plen = htons((uint16_t)(msgdsize(mp) - IPV6_HDR_LEN)); |
8507 /* Record the ECN info. */ |
8629 /* Record the ECN info. */ |
8508 ip6h->ip6_vcf &= htonl(0xFFCFFFFF); |
8630 ip6h->ip6_vcf &= htonl(0xFFCFFFFF); |
8509 ip6h->ip6_vcf |= htonl(ecn_info << 20); |
8631 ip6h->ip6_vcf |= htonl(ecn_info << 20); |
8632 |
|
8633 /* Reassembly is successful; return checksum information if needed */ |
|
8634 if (cksum_val != NULL) |
|
8635 *cksum_val = sum_val; |
|
8636 if (cksum_flags != NULL) |
|
8637 *cksum_flags = sum_flags; |
|
8510 |
8638 |
8511 return (mp); |
8639 return (mp); |
8512 } |
8640 } |
8513 |
8641 |
8514 /* |
8642 /* |
9952 * switch when ratio exceeds e.g. 10:1 |
10080 * switch when ratio exceeds e.g. 10:1 |
9953 */ |
10081 */ |
9954 if (q->q_next == NULL) { |
10082 if (q->q_next == NULL) { |
9955 connp = Q_TO_CONN(q); |
10083 connp = Q_TO_CONN(q); |
9956 |
10084 |
9957 if (IS_TCP_CONN(connp)) { |
10085 if (IPCL_IS_TCP(connp)) { |
9958 /* change conn_send for the tcp_v4_connections */ |
10086 /* change conn_send for the tcp_v4_connections */ |
9959 connp->conn_send = ip_output; |
10087 connp->conn_send = ip_output; |
9960 } else if (connp->conn_ulp == IPPROTO_SCTP) { |
10088 } else if (connp->conn_ulp == IPPROTO_SCTP) { |
9961 /* The 'q' is the default SCTP queue */ |
10089 /* The 'q' is the default SCTP queue */ |
9962 connp = (conn_t *)arg; |
10090 connp = (conn_t *)arg; |
10424 |
10552 |
10425 if (ire->ire_stq != NULL) { |
10553 if (ire->ire_stq != NULL) { |
10426 uint32_t sum; |
10554 uint32_t sum; |
10427 uint_t ill_index = ((ill_t *)ire->ire_stq->q_ptr)-> |
10555 uint_t ill_index = ((ill_t *)ire->ire_stq->q_ptr)-> |
10428 ill_phyint->phyint_ifindex; |
10556 ill_phyint->phyint_ifindex; |
10557 queue_t *dev_q = ire->ire_stq->q_next; |
|
10429 |
10558 |
10430 /* |
10559 /* |
10431 * non-NULL send-to queue - packet is to be sent |
10560 * non-NULL send-to queue - packet is to be sent |
10432 * out an interface. |
10561 * out an interface. |
10433 */ |
10562 */ |
10563 |
|
10564 /* Driver is flow-controlling? */ |
|
10565 if (!IP_FLOW_CONTROLLED_ULP(nexthdr) && |
|
10566 ((dev_q->q_next || dev_q->q_first) && !canput(dev_q))) { |
|
10567 /* |
|
10568 * Queue packet if we have an conn to give back |
|
10569 * pressure. We can't queue packets intended for |
|
10570 * hardware acceleration since we've tossed that |
|
10571 * state already. If the packet is being fed back |
|
10572 * from ire_send_v6, we don't know the position in |
|
10573 * the queue to enqueue the packet and we discard |
|
10574 * the packet. |
|
10575 */ |
|
10576 ASSERT(mp == first_mp); |
|
10577 if (ip_output_queue && connp != NULL && |
|
10578 !mctl_present && caller != IRE_SEND) { |
|
10579 if (caller == IP_WSRV) { |
|
10580 connp->conn_did_putbq = 1; |
|
10581 (void) putbq(connp->conn_wq, mp); |
|
10582 conn_drain_insert(connp); |
|
10583 /* |
|
10584 * caller == IP_WSRV implies we are |
|
10585 * the service thread, and the |
|
10586 * queue is already noenabled. |
|
10587 * The check for canput and |
|
10588 * the putbq is not atomic. |
|
10589 * So we need to check again. |
|
10590 */ |
|
10591 if (canput(dev_q)) |
|
10592 connp->conn_did_putbq = 0; |
|
10593 } else { |
|
10594 (void) putq(connp->conn_wq, mp); |
|
10595 } |
|
10596 return; |
|
10597 } |
|
10598 BUMP_MIB(mibptr, ipv6OutDiscards); |
|
10599 freemsg(mp); |
|
10600 return; |
|
10601 } |
|
10434 |
10602 |
10435 /* |
10603 /* |
10436 * Look for reachability confirmations from the transport. |
10604 * Look for reachability confirmations from the transport. |
10437 */ |
10605 */ |
10438 if (ip6h->ip6_vcf & IP_FORWARD_PROG) { |
10606 if (ip6h->ip6_vcf & IP_FORWARD_PROG) { |
10488 up[4] + up[5] + up[6] + up[7] + |
10656 up[4] + up[5] + up[6] + up[7] + |
10489 up[8] + up[9] + up[10] + up[11] + |
10657 up[8] + up[9] + up[10] + up[11] + |
10490 up[12] + up[13] + up[14] + up[15]; |
10658 up[12] + up[13] + up[14] + up[15]; |
10491 sum = (sum & 0xffff) + (sum >> 16); |
10659 sum = (sum & 0xffff) + (sum >> 16); |
10492 *insp = IP_CSUM(mp, hdr_length, sum); |
10660 *insp = IP_CSUM(mp, hdr_length, sum); |
10661 if (*insp == 0) |
|
10662 *insp = 0xFFFF; |
|
10493 } else if (nexthdr == IPPROTO_TCP) { |
10663 } else if (nexthdr == IPPROTO_TCP) { |
10494 uint16_t *up; |
10664 uint16_t *up; |
10495 |
10665 |
10496 /* |
10666 /* |
10497 * Check for full IPv6 header + enough TCP header |
10667 * Check for full IPv6 header + enough TCP header |
10498 * to get at the checksum field. |
10668 * to get at the checksum field. |
10499 * XXX need hardware checksum support. |
|
10500 */ |
10669 */ |
10501 #define TCP_CSUM_OFFSET 16 |
|
10502 #define TCP_CSUM_SIZE 2 |
|
10503 if ((mp->b_wptr - mp->b_rptr) < |
10670 if ((mp->b_wptr - mp->b_rptr) < |
10504 (hdr_length + TCP_CSUM_OFFSET + TCP_CSUM_SIZE)) { |
10671 (hdr_length + TCP_CHECKSUM_OFFSET + |
10672 TCP_CHECKSUM_SIZE)) { |
|
10505 if (!pullupmsg(mp, hdr_length + |
10673 if (!pullupmsg(mp, hdr_length + |
10506 TCP_CSUM_OFFSET + TCP_CSUM_SIZE)) { |
10674 TCP_CHECKSUM_OFFSET + TCP_CHECKSUM_SIZE)) { |
10507 ip1dbg(("ip_wput_v6: TCP hdr pullupmsg" |
10675 ip1dbg(("ip_wput_v6: TCP hdr pullupmsg" |
10508 " failed\n")); |
10676 " failed\n")); |
10509 BUMP_MIB(mibptr, ipv6OutDiscards); |
10677 BUMP_MIB(mibptr, ipv6OutDiscards); |
10510 freemsg(first_mp); |
10678 freemsg(first_mp); |
10511 return; |
10679 return; |
10517 /* |
10685 /* |
10518 * Note: The TCP module has stored the length value |
10686 * Note: The TCP module has stored the length value |
10519 * into the tcp checksum field, so we don't |
10687 * into the tcp checksum field, so we don't |
10520 * need to explicitly sum it in here. |
10688 * need to explicitly sum it in here. |
10521 */ |
10689 */ |
10522 if (hdr_length == IPV6_HDR_LEN) { |
10690 sum = up[0] + up[1] + up[2] + up[3] + |
10523 /* src, dst, tcp consequtive */ |
10691 up[4] + up[5] + up[6] + up[7] + |
10524 up = (uint16_t *)(((uchar_t *)ip6h) + |
10692 up[8] + up[9] + up[10] + up[11] + |
10525 IPV6_HDR_LEN + TCP_CSUM_OFFSET); |
10693 up[12] + up[13] + up[14] + up[15]; |
10526 *up = IP_CSUM(mp, |
10694 |
10527 IPV6_HDR_LEN - 2 * sizeof (in6_addr_t), |
10695 /* Fold the initial sum */ |
10528 htons(IPPROTO_TCP)); |
10696 sum = (sum & 0xffff) + (sum >> 16); |
10529 } else { |
10697 |
10530 sum = htons(IPPROTO_TCP) + |
10698 up = (uint16_t *)(((uchar_t *)ip6h) + |
10531 up[0] + up[1] + up[2] + up[3] + |
10699 hdr_length + TCP_CHECKSUM_OFFSET); |
10532 up[4] + up[5] + up[6] + up[7] + |
10700 |
10533 up[8] + up[9] + up[10] + up[11] + |
10701 IP_CKSUM_XMIT(ill, ire, mp, ip6h, up, IPPROTO_TCP, |
10534 up[12] + up[13] + up[14] + up[15]; |
10702 hdr_length, ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN, |
10535 /* |
10703 ire->ire_max_frag, mctl_present, sum); |
10536 * Fold the initial sum. |
10704 |
10537 */ |
10705 /* Software checksum? */ |
10538 sum = (sum & 0xffff) + (sum >> 16); |
10706 if (DB_CKSUMFLAGS(mp) == 0) { |
10539 up = (uint16_t *)(((uchar_t *)ip6h) + |
10707 IP6_STAT(ip6_out_sw_cksum); |
10540 hdr_length + TCP_CSUM_OFFSET); |
10708 IP6_STAT_UPDATE(ip6_tcp_out_sw_cksum_bytes, |
10541 *up = IP_CSUM(mp, hdr_length, sum); |
10709 (ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN) - |
10542 } |
10710 hdr_length); |
10543 #undef TCP_CSUM_OFFSET |
10711 } |
10544 #undef TCP_CSUM_SIZE |
|
10545 |
|
10546 } else if (nexthdr == IPPROTO_UDP) { |
10712 } else if (nexthdr == IPPROTO_UDP) { |
10547 uint16_t *up; |
10713 uint16_t *up; |
10548 |
10714 |
10549 /* |
10715 /* |
10550 * check for full IPv6 header + enough UDP header |
10716 * check for full IPv6 header + enough UDP header |
10551 * to get at the UDP checksum field |
10717 * to get at the UDP checksum field |
10552 */ |
10718 */ |
10553 #define UDP_CSUM_OFFSET 6 |
|
10554 #define UDP_CSUM_SIZE 2 |
|
10555 if ((mp->b_wptr - mp->b_rptr) < (hdr_length + |
10719 if ((mp->b_wptr - mp->b_rptr) < (hdr_length + |
10556 UDP_CSUM_OFFSET + UDP_CSUM_SIZE)) { |
10720 UDP_CHECKSUM_OFFSET + UDP_CHECKSUM_SIZE)) { |
10557 if (!pullupmsg(mp, hdr_length + |
10721 if (!pullupmsg(mp, hdr_length + |
10558 UDP_CSUM_OFFSET + UDP_CSUM_SIZE)) { |
10722 UDP_CHECKSUM_OFFSET + UDP_CHECKSUM_SIZE)) { |
10559 ip1dbg(("ip_wput_v6: UDP hdr pullupmsg" |
10723 ip1dbg(("ip_wput_v6: UDP hdr pullupmsg" |
10560 " failed\n")); |
10724 " failed\n")); |
10561 BUMP_MIB(mibptr, ipv6OutDiscards); |
10725 BUMP_MIB(mibptr, ipv6OutDiscards); |
10562 freemsg(first_mp); |
10726 freemsg(first_mp); |
10563 return; |
10727 return; |
10568 /* |
10732 /* |
10569 * Note: The UDP module has stored the length value |
10733 * Note: The UDP module has stored the length value |
10570 * into the udp checksum field, so we don't |
10734 * into the udp checksum field, so we don't |
10571 * need to explicitly sum it in here. |
10735 * need to explicitly sum it in here. |
10572 */ |
10736 */ |
10573 if (hdr_length == IPV6_HDR_LEN) { |
10737 sum = up[0] + up[1] + up[2] + up[3] + |
10574 /* src, dst, udp consequtive */ |
10738 up[4] + up[5] + up[6] + up[7] + |
10575 up = (uint16_t *)(((uchar_t *)ip6h) + |
10739 up[8] + up[9] + up[10] + up[11] + |
10576 IPV6_HDR_LEN + UDP_CSUM_OFFSET); |
10740 up[12] + up[13] + up[14] + up[15]; |
10577 *up = IP_CSUM(mp, |
10741 |
10578 IPV6_HDR_LEN - 2 * sizeof (in6_addr_t), |
10742 /* Fold the initial sum */ |
10579 htons(IPPROTO_UDP)); |
10743 sum = (sum & 0xffff) + (sum >> 16); |
10580 } else { |
10744 |
10581 sum = htons(IPPROTO_UDP) + |
10745 up = (uint16_t *)(((uchar_t *)ip6h) + |
10582 up[0] + up[1] + up[2] + up[3] + |
10746 hdr_length + UDP_CHECKSUM_OFFSET); |
10583 up[4] + up[5] + up[6] + up[7] + |
10747 |
10584 up[8] + up[9] + up[10] + up[11] + |
10748 IP_CKSUM_XMIT(ill, ire, mp, ip6h, up, IPPROTO_UDP, |
10585 up[12] + up[13] + up[14] + up[15]; |
10749 hdr_length, ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN, |
10586 sum = (sum & 0xffff) + (sum >> 16); |
10750 ire->ire_max_frag, mctl_present, sum); |
10587 up = (uint16_t *)(((uchar_t *)ip6h) + |
10751 |
10588 hdr_length + UDP_CSUM_OFFSET); |
10752 /* Software checksum? */ |
10589 *up = IP_CSUM(mp, hdr_length, sum); |
10753 if (DB_CKSUMFLAGS(mp) == 0) { |
10590 } |
10754 IP6_STAT(ip6_out_sw_cksum); |
10591 |
10755 IP6_STAT_UPDATE(ip6_udp_out_sw_cksum_bytes, |
10592 /* |
10756 (ntohs(ip6h->ip6_plen) + IPV6_HDR_LEN) - |
10593 * According to RFC 2460, UDP in IPv6 shouldn't |
10757 hdr_length); |
10594 * appear with all zero checksum on the wire and |
10758 } |
10595 * should be changed to 0xffff. |
|
10596 */ |
|
10597 if (*up == 0) |
|
10598 *up = 0xffff; |
|
10599 #undef UDP_CSUM_OFFSET |
|
10600 #undef UDP_CSUM_SIZE |
|
10601 } else if (nexthdr == IPPROTO_ICMPV6) { |
10759 } else if (nexthdr == IPPROTO_ICMPV6) { |
10602 uint16_t *up; |
10760 uint16_t *up; |
10603 icmp6_t *icmp6; |
10761 icmp6_t *icmp6; |
10604 |
10762 |
10605 /* check for full IPv6+ICMPv6 header */ |
10763 /* check for full IPv6+ICMPv6 header */ |
10625 up[4] + up[5] + up[6] + up[7] + |
10783 up[4] + up[5] + up[6] + up[7] + |
10626 up[8] + up[9] + up[10] + up[11] + |
10784 up[8] + up[9] + up[10] + up[11] + |
10627 up[12] + up[13] + up[14] + up[15]; |
10785 up[12] + up[13] + up[14] + up[15]; |
10628 sum = (sum & 0xffff) + (sum >> 16); |
10786 sum = (sum & 0xffff) + (sum >> 16); |
10629 icmp6->icmp6_cksum = IP_CSUM(mp, hdr_length, sum); |
10787 icmp6->icmp6_cksum = IP_CSUM(mp, hdr_length, sum); |
10788 if (icmp6->icmp6_cksum == 0) |
|
10789 icmp6->icmp6_cksum = 0xFFFF; |
|
10790 |
|
10630 /* Update output mib stats */ |
10791 /* Update output mib stats */ |
10631 icmp_update_out_mib_v6(ill, icmp6); |
10792 icmp_update_out_mib_v6(ill, icmp6); |
10632 } else if (nexthdr == IPPROTO_SCTP) { |
10793 } else if (nexthdr == IPPROTO_SCTP) { |
10633 sctp_hdr_t *sctph; |
10794 sctp_hdr_t *sctph; |
10634 |
10795 |
10762 ip_wput_local_v6(RD(q), ill, ip6h, first_mp, ire, 0); |
10923 ip_wput_local_v6(RD(q), ill, ip6h, first_mp, ire, 0); |
10763 } |
10924 } |
10764 } |
10925 } |
10765 |
10926 |
10766 /* |
10927 /* |
10928 * Outbound IPv6 fragmentation routine using MDT. |
|
10929 */ |
|
10930 static void |
|
10931 ip_wput_frag_mdt_v6(mblk_t *mp, ire_t *ire, size_t max_chunk, |
|
10932 size_t unfragmentable_len, uint8_t nexthdr, uint_t prev_nexthdr_offset) |
|
10933 { |
|
10934 ip6_t *ip6h = (ip6_t *)mp->b_rptr; |
|
10935 uint_t pkts, wroff, hdr_chunk_len, pbuf_idx; |
|
10936 mblk_t *hdr_mp, *md_mp = NULL; |
|
10937 int i1; |
|
10938 multidata_t *mmd; |
|
10939 unsigned char *hdr_ptr, *pld_ptr; |
|
10940 ip_pdescinfo_t pdi; |
|
10941 uint32_t ident; |
|
10942 size_t len; |
|
10943 uint16_t offset; |
|
10944 queue_t *stq = ire->ire_stq; |
|
10945 ill_t *ill = (ill_t *)stq->q_ptr; |
|
10946 |
|
10947 ASSERT(DB_TYPE(mp) == M_DATA); |
|
10948 ASSERT(MBLKL(mp) > unfragmentable_len); |
|
10949 |
|
10950 /* |
|
10951 * Move read ptr past unfragmentable portion, we don't want this part |
|
10952 * of the data in our fragments. |
|
10953 */ |
|
10954 mp->b_rptr += unfragmentable_len; |
|
10955 |
|
10956 /* Calculate how many packets we will send out */ |
|
10957 i1 = (mp->b_cont == NULL) ? MBLKL(mp) : msgsize(mp); |
|
10958 pkts = (i1 + max_chunk - 1) / max_chunk; |
|
10959 ASSERT(pkts > 1); |
|
10960 |
|
10961 /* Allocate a message block which will hold all the IP Headers. */ |
|
10962 wroff = ip_wroff_extra; |
|
10963 hdr_chunk_len = wroff + unfragmentable_len + sizeof (ip6_frag_t); |
|
10964 |
|
10965 i1 = pkts * hdr_chunk_len; |
|
10966 /* |
|
10967 * Create the header buffer, Multidata and destination address |
|
10968 * and SAP attribute that should be associated with it. |
|
10969 */ |
|
10970 if ((hdr_mp = allocb(i1, BPRI_HI)) == NULL || |
|
10971 ((hdr_mp->b_wptr += i1), |
|
10972 (mmd = mmd_alloc(hdr_mp, &md_mp, KM_NOSLEEP)) == NULL) || |
|
10973 !ip_md_addr_attr(mmd, NULL, ire->ire_nce->nce_res_mp)) { |
|
10974 freemsg(mp); |
|
10975 if (md_mp == NULL) { |
|
10976 freemsg(hdr_mp); |
|
10977 } else { |
|
10978 free_mmd: IP6_STAT(ip6_frag_mdt_discarded); |
|
10979 freemsg(md_mp); |
|
10980 } |
|
10981 IP6_STAT(ip6_frag_mdt_allocfail); |
|
10982 BUMP_MIB(ill->ill_ip6_mib, ipv6OutFragFails); |
|
10983 UPDATE_MIB(ill->ill_ip6_mib, ipv6OutDiscards, pkts); |
|
10984 return; |
|
10985 } |
|
10986 IP6_STAT(ip6_frag_mdt_allocd); |
|
10987 |
|
10988 /* |
|
10989 * Add a payload buffer to the Multidata; this operation must not |
|
10990 * fail, or otherwise our logic in this routine is broken. There |
|
10991 * is no memory allocation done by the routine, so any returned |
|
10992 * failure simply tells us that we've done something wrong. |
|
10993 * |
|
10994 * A failure tells us that either we're adding the same payload |
|
10995 * buffer more than once, or we're trying to add more buffers than |
|
10996 * allowed. None of the above cases should happen, and we panic |
|
10997 * because either there's horrible heap corruption, and/or |
|
10998 * programming mistake. |
|
10999 */ |
|
11000 if ((pbuf_idx = mmd_addpldbuf(mmd, mp)) < 0) { |
|
11001 goto pbuf_panic; |
|
11002 } |
|
11003 |
|
11004 hdr_ptr = hdr_mp->b_rptr; |
|
11005 pld_ptr = mp->b_rptr; |
|
11006 |
|
11007 pdi.flags = PDESC_HBUF_REF | PDESC_PBUF_REF; |
|
11008 |
|
11009 ident = htonl(atomic_add_32_nv(&ire->ire_ident, 1)); |
|
11010 |
|
11011 /* |
|
11012 * len is the total length of the fragmentable data in this |
|
11013 * datagram. For each fragment sent, we will decrement len |
|
11014 * by the amount of fragmentable data sent in that fragment |
|
11015 * until len reaches zero. |
|
11016 */ |
|
11017 len = ntohs(ip6h->ip6_plen) - (unfragmentable_len - IPV6_HDR_LEN); |
|
11018 |
|
11019 offset = 0; |
|
11020 prev_nexthdr_offset += wroff; |
|
11021 |
|
11022 while (len != 0) { |
|
11023 size_t mlen; |
|
11024 ip6_t *fip6h; |
|
11025 ip6_frag_t *fraghdr; |
|
11026 int error; |
|
11027 |
|
11028 ASSERT((hdr_ptr + hdr_chunk_len) <= hdr_mp->b_wptr); |
|
11029 mlen = MIN(len, max_chunk); |
|
11030 len -= mlen; |
|
11031 |
|
11032 fip6h = (ip6_t *)(hdr_ptr + wroff); |
|
11033 ASSERT(OK_32PTR(fip6h)); |
|
11034 bcopy(ip6h, fip6h, unfragmentable_len); |
|
11035 hdr_ptr[prev_nexthdr_offset] = IPPROTO_FRAGMENT; |
|
11036 |
|
11037 fip6h->ip6_plen = htons((uint16_t)(mlen + |
|
11038 unfragmentable_len - IPV6_HDR_LEN + sizeof (ip6_frag_t))); |
|
11039 |
|
11040 fraghdr = (ip6_frag_t *)((unsigned char *)fip6h + |
|
11041 unfragmentable_len); |
|
11042 fraghdr->ip6f_nxt = nexthdr; |
|
11043 fraghdr->ip6f_reserved = 0; |
|
11044 fraghdr->ip6f_offlg = htons(offset) | |
|
11045 ((len != 0) ? IP6F_MORE_FRAG : 0); |
|
11046 fraghdr->ip6f_ident = ident; |
|
11047 |
|
11048 /* |
|
11049 * Record offset and size of header and data of the next packet |
|
11050 * in the multidata message. |
|
11051 */ |
|
11052 PDESC_HDR_ADD(&pdi, hdr_ptr, wroff, |
|
11053 unfragmentable_len + sizeof (ip6_frag_t), 0); |
|
11054 PDESC_PLD_INIT(&pdi); |
|
11055 i1 = MIN(mp->b_wptr - pld_ptr, mlen); |
|
11056 ASSERT(i1 > 0); |
|
11057 PDESC_PLD_SPAN_ADD(&pdi, pbuf_idx, pld_ptr, i1); |
|
11058 if (i1 == mlen) { |
|
11059 pld_ptr += mlen; |
|
11060 } else { |
|
11061 i1 = mlen - i1; |
|
11062 mp = mp->b_cont; |
|
11063 ASSERT(mp != NULL); |
|
11064 ASSERT(MBLKL(mp) >= i1); |
|
11065 /* |
|
11066 * Attach the next payload message block to the |
|
11067 * multidata message. |
|
11068 */ |
|
11069 if ((pbuf_idx = mmd_addpldbuf(mmd, mp)) < 0) |
|
11070 goto pbuf_panic; |
|
11071 PDESC_PLD_SPAN_ADD(&pdi, pbuf_idx, mp->b_rptr, i1); |
|
11072 pld_ptr = mp->b_rptr + i1; |
|
11073 } |
|
11074 |
|
11075 if ((mmd_addpdesc(mmd, (pdescinfo_t *)&pdi, &error, |
|
11076 KM_NOSLEEP)) == NULL) { |
|
11077 /* |
|
11078 * Any failure other than ENOMEM indicates that we |
|
11079 * have passed in invalid pdesc info or parameters |
|
11080 * to mmd_addpdesc, which must not happen. |
|
11081 * |
|
11082 * EINVAL is a result of failure on boundary checks |
|
11083 * against the pdesc info contents. It should not |
|
11084 * happen, and we panic because either there's |
|
11085 * horrible heap corruption, and/or programming |
|
11086 * mistake. |
|
11087 */ |
|
11088 if (error != ENOMEM) { |
|
11089 cmn_err(CE_PANIC, "ip_wput_frag_mdt_v6: " |
|
11090 "pdesc logic error detected for " |
|
11091 "mmd %p pinfo %p (%d)\n", |
|
11092 (void *)mmd, (void *)&pdi, error); |
|
11093 /* NOTREACHED */ |
|
11094 } |
|
11095 IP6_STAT(ip6_frag_mdt_addpdescfail); |
|
11096 /* Free unattached payload message blocks as well */ |
|
11097 md_mp->b_cont = mp->b_cont; |
|
11098 goto free_mmd; |
|
11099 } |
|
11100 |
|
11101 /* Advance fragment offset. */ |
|
11102 offset += mlen; |
|
11103 |
|
11104 /* Advance to location for next header in the buffer. */ |
|
11105 hdr_ptr += hdr_chunk_len; |
|
11106 |
|
11107 /* Did we reach the next payload message block? */ |
|
11108 if (pld_ptr == mp->b_wptr && mp->b_cont != NULL) { |
|
11109 mp = mp->b_cont; |
|
11110 /* |
|
11111 * Attach the next message block with payload |
|
11112 * data to the multidata message. |
|
11113 */ |
|
11114 if ((pbuf_idx = mmd_addpldbuf(mmd, mp)) < 0) |
|
11115 goto pbuf_panic; |
|
11116 pld_ptr = mp->b_rptr; |
|
11117 } |
|
11118 } |
|
11119 |
|
11120 ASSERT(hdr_mp->b_wptr == hdr_ptr); |
|
11121 ASSERT(mp->b_wptr == pld_ptr); |
|
11122 |
|
11123 /* Update IP statistics */ |
|
11124 UPDATE_MIB(ill->ill_ip6_mib, ipv6OutFragCreates, pkts); |
|
11125 BUMP_MIB(ill->ill_ip6_mib, ipv6OutFragOKs); |
|
11126 IP6_STAT_UPDATE(ip6_frag_mdt_pkt_out, pkts); |
|
11127 |
|
11128 ire->ire_ob_pkt_count += pkts; |
|
11129 if (ire->ire_ipif != NULL) |
|
11130 atomic_add_32(&ire->ire_ipif->ipif_ob_pkt_count, pkts); |
|
11131 |
|
11132 ire->ire_last_used_time = lbolt; |
|
11133 /* Send it down */ |
|
11134 putnext(stq, md_mp); |
|
11135 return; |
|
11136 |
|
11137 pbuf_panic: |
|
11138 cmn_err(CE_PANIC, "ip_wput_frag_mdt_v6: payload buffer logic " |
|
11139 "error for mmd %p pbuf %p (%d)", (void *)mmd, (void *)mp, |
|
11140 pbuf_idx); |
|
11141 /* NOTREACHED */ |
|
11142 } |
|
11143 |
|
11144 /* |
|
10767 * IPv6 fragmentation. Essentially the same as IPv4 fragmentation. |
11145 * IPv6 fragmentation. Essentially the same as IPv4 fragmentation. |
10768 * We have not optimized this in terms of number of mblks |
11146 * We have not optimized this in terms of number of mblks |
10769 * allocated. For instance, for each fragment sent we always allocate a |
11147 * allocated. For instance, for each fragment sent we always allocate a |
10770 * mblk to hold the IPv6 header and fragment header. |
11148 * mblk to hold the IPv6 header and fragment header. |
10771 * |
11149 * |
10777 * NOTE : This function does not ire_refrele the ire passed in as |
11155 * NOTE : This function does not ire_refrele the ire passed in as |
10778 * the argument. |
11156 * the argument. |
10779 */ |
11157 */ |
10780 void |
11158 void |
10781 ip_wput_frag_v6(mblk_t *mp, ire_t *ire, uint_t reachable, conn_t *connp, |
11159 ip_wput_frag_v6(mblk_t *mp, ire_t *ire, uint_t reachable, conn_t *connp, |
10782 boolean_t caller, int max_frag) |
11160 int caller, int max_frag) |
10783 { |
11161 { |
10784 ip6_t *ip6h = (ip6_t *)mp->b_rptr; |
11162 ip6_t *ip6h = (ip6_t *)mp->b_rptr; |
10785 ip6_t *fip6h; |
11163 ip6_t *fip6h; |
10786 mblk_t *hmp; |
11164 mblk_t *hmp; |
10787 mblk_t *hmp0; |
11165 mblk_t *hmp0; |
10847 hdr_len = 8 * (rthdr->ip6r_len + 1); |
11225 hdr_len = 8 * (rthdr->ip6r_len + 1); |
10848 ptr += hdr_len; |
11226 ptr += hdr_len; |
10849 } |
11227 } |
10850 unfragmentable_len = (uint_t)(ptr - (uint8_t *)ip6h); |
11228 unfragmentable_len = (uint_t)(ptr - (uint8_t *)ip6h); |
10851 |
11229 |
11230 max_chunk = (min(max_frag, ire->ire_max_frag) - unfragmentable_len - |
|
11231 sizeof (ip6_frag_t)) & ~7; |
|
11232 |
|
11233 /* Check if we can use MDT to send out the frags. */ |
|
11234 ASSERT(!IRE_IS_LOCAL(ire)); |
|
11235 if (ip_multidata_outbound && reachable == 0 && |
|
11236 !(ire->ire_flags & RTF_MULTIRT) && ILL_MDT_CAPABLE(ill) && |
|
11237 IP_CAN_FRAG_MDT(mp, unfragmentable_len, max_chunk)) { |
|
11238 ip_wput_frag_mdt_v6(mp, ire, max_chunk, unfragmentable_len, |
|
11239 nexthdr, prev_nexthdr_offset); |
|
11240 return; |
|
11241 } |
|
11242 |
|
10852 /* |
11243 /* |
10853 * Allocate an mblk with enough room for the link-layer |
11244 * Allocate an mblk with enough room for the link-layer |
10854 * header, the unfragmentable part of the datagram, and the |
11245 * header, the unfragmentable part of the datagram, and the |
10855 * fragment header. This (or a copy) will be used as the |
11246 * fragment header. This (or a copy) will be used as the |
10856 * first mblk for each fragment we send. |
11247 * first mblk for each fragment we send. |
10873 |
11264 |
10874 ident = atomic_add_32_nv(&ire->ire_ident, 1); |
11265 ident = atomic_add_32_nv(&ire->ire_ident, 1); |
10875 |
11266 |
10876 fraghdr->ip6f_nxt = nexthdr; |
11267 fraghdr->ip6f_nxt = nexthdr; |
10877 fraghdr->ip6f_reserved = 0; |
11268 fraghdr->ip6f_reserved = 0; |
10878 fraghdr->ip6f_offlg = htons(0); |
11269 fraghdr->ip6f_offlg = 0; |
10879 fraghdr->ip6f_ident = htonl(ident); |
11270 fraghdr->ip6f_ident = htonl(ident); |
10880 |
11271 |
10881 /* |
11272 /* |
10882 * len is the total length of the fragmentable data in this |
11273 * len is the total length of the fragmentable data in this |
10883 * datagram. For each fragment sent, we will decrement len |
11274 * datagram. For each fragment sent, we will decrement len |
10884 * by the amount of fragmentable data sent in that fragment |
11275 * by the amount of fragmentable data sent in that fragment |
10885 * until len reaches zero. |
11276 * until len reaches zero. |
10886 */ |
11277 */ |
10887 len = ntohs(ip6h->ip6_plen) - (unfragmentable_len - IPV6_HDR_LEN); |
11278 len = ntohs(ip6h->ip6_plen) - (unfragmentable_len - IPV6_HDR_LEN); |
10888 |
|
10889 max_chunk = (min(max_frag, ire->ire_max_frag) - unfragmentable_len - |
|
10890 sizeof (ip6_frag_t)) & ~7; |
|
10891 |
11279 |
10892 /* |
11280 /* |
10893 * Move read ptr past unfragmentable portion, we don't want this part |
11281 * Move read ptr past unfragmentable portion, we don't want this part |
10894 * of the data in our fragments. |
11282 * of the data in our fragments. |
10895 */ |
11283 */ |
11115 freemsg(mp); |
11503 freemsg(mp); |
11116 return; |
11504 return; |
11117 } |
11505 } |
11118 } |
11506 } |
11119 |
11507 |
11120 if (IP_FLOW_CONTROLLED_ULP(ip6h->ip6_nxt) || canput(stq->q_next)) { |
11508 /* Flow-control check has been done in ip_wput_ire_v6 */ |
11509 if (IP_FLOW_CONTROLLED_ULP(ip6h->ip6_nxt) || caller == IP_WPUT || |
|
11510 caller == IP_WSRV || canput(stq->q_next)) { |
|
11121 uint32_t ill_index; |
11511 uint32_t ill_index; |
11122 |
11512 |
11123 /* |
11513 /* |
11124 * In most cases, the emission loop below is entered only |
11514 * In most cases, the emission loop below is entered only |
11125 * once. Only in the case where the ire holds the |
11515 * once. Only in the case where the ire holds the |
11162 nce = ire->ire_nce; |
11552 nce = ire->ire_nce; |
11163 stq = ire->ire_stq; |
11553 stq = ire->ire_stq; |
11164 ill = ire_to_ill(ire); |
11554 ill = ire_to_ill(ire); |
11165 } |
11555 } |
11166 IRB_REFRELE(irb); |
11556 IRB_REFRELE(irb); |
11167 } else if (connp != NULL && IS_TCP_CONN(connp) && |
11557 } else if (connp != NULL && IPCL_IS_TCP(connp) && |
11168 connp->conn_mdt_ok && !connp->conn_tcp->tcp_mdt && |
11558 connp->conn_mdt_ok && !connp->conn_tcp->tcp_mdt && |
11169 ILL_MDT_USABLE(ill)) { |
11559 ILL_MDT_USABLE(ill)) { |
11170 /* |
11560 /* |
11171 * This tcp connection was marked as MDT-capable, but |
11561 * This tcp connection was marked as MDT-capable, but |
11172 * it has been turned off due changes in the interface. |
11562 * it has been turned off due changes in the interface. |
11581 if (caller == IP_WSRV) { |
11971 if (caller == IP_WSRV) { |
11582 connp->conn_did_putbq = 1; |
11972 connp->conn_did_putbq = 1; |
11583 (void) putbq(connp->conn_wq, mp); |
11973 (void) putbq(connp->conn_wq, mp); |
11584 conn_drain_insert(connp); |
11974 conn_drain_insert(connp); |
11585 /* |
11975 /* |
11586 * called_from_wsrv implies we are |
11976 * caller == IP_WSRV implies we are |
11587 * the service thread, and the |
11977 * the service thread, and the |
11588 * queue is already noenabled. |
11978 * queue is already noenabled. |
11589 * The check for canput and |
11979 * The check for canput and |
11590 * the putbq is not atomic. |
11980 * the putbq is not atomic. |
11591 * So we need to check again. |
11981 * So we need to check again. |