Print this page
*** NO COMMENTS ***

@@ -3475,10 +3475,12 @@
                  * and other stuffs.  Note that we don't check if the
                  * existing eager list meets the new tcp_conn_req_max
                  * requirement.
                  */
                 if (tcp->tcp_state != TCPS_LISTEN) {
+                        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                            tcp_t *, tcp, int32_t, TCPS_LISTEN);
                         tcp->tcp_state = TCPS_LISTEN;
                         /* Initialize the chain. Don't need the eager_lock */
                         tcp->tcp_eager_next_q0 = tcp->tcp_eager_prev_q0 = tcp;
                         tcp->tcp_eager_next_drop_q0 = tcp;
                         tcp->tcp_eager_prev_drop_q0 = tcp;

@@ -3771,10 +3773,12 @@
                         /*
                          * This port is ours. Insert in fanout and mark as
                          * bound to prevent others from getting the port
                          * number.
                          */
+                        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                            tcp_t *, tcp, int32_t, TCPS_BOUND);
                         tcp->tcp_state = TCPS_BOUND;
                         tcp->tcp_lport = htons(port);
                         *(uint16_t *)tcp->tcp_tcph->th_lport = tcp->tcp_lport;
 
                         ASSERT(&tcps->tcps_bind_fanout[TCP_BIND_HASH(

@@ -3902,10 +3906,13 @@
                          */
                         tcp_closei_local(tcp);
                         if (!tcp->tcp_tconnind_started) {
                                 CONN_DEC_REF(tcp->tcp_connp);
                         } else {
+                                DTRACE_TCP4(state__change, void, NULL,
+                                    conn_t *, NULL, tcp_t *, tcp, int32_t,
+                                    TCPS_BOUND);
                                 tcp->tcp_state = TCPS_BOUND;
                         }
                 } else {
                         tcp_close_detached(tcp);
                 }

@@ -4635,10 +4642,14 @@
 
         /* Need to cleanup any pending ioctls */
         ASSERT(tcp->tcp_time_wait_next == NULL);
         ASSERT(tcp->tcp_time_wait_prev == NULL);
         ASSERT(tcp->tcp_time_wait_expire == 0);
+        if (connp->conn_fully_bound) {
+                DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                    tcp_t *, tcp, int32_t, TCPS_CLOSED);
+        }
         tcp->tcp_state = TCPS_CLOSED;
 
         /* Release any SSL context */
         if (tcp->tcp_kssl_ent != NULL) {
                 kssl_release_ent(tcp->tcp_kssl_ent, NULL, KSSL_NO_PROXY);

@@ -5876,10 +5887,13 @@
         /*
          * No need to check for multicast destination since ip will only pass
          * up multicasts to those that have expressed interest
          * TODO: what about rejecting broadcasts?
          * Also check that source is not a multicast or broadcast address.
+         *
+         * DTrace tcp:::state-change is probed a little further down,
+         * where it is set for the second time.
          */
         eager->tcp_state = TCPS_SYN_RCVD;
 
 
         /*

@@ -5896,10 +5910,17 @@
                 /* Undo the bind_hash_insert */
                 tcp_bind_hash_remove(eager);
                 goto error3;
         }
 
+        /*
+         * DTrace the first SYN as a tcp:::receive. This is placed after
+         * tcp_adapt_ire() so that tcp->tcp_loopback has been set.
+         */
+        DTRACE_TCP5(receive, mblk_t *, NULL, conn_t *, NULL, void_ip_t *,
+            mp->b_rptr, tcp_t *, tcp, tcph_t *, tcph);
+
         /* Process all TCP options. */
         tcp_process_options(eager, tcph);
 
         /* Is the other end ECN capable? */
         if (tcps->tcps_ecn_permitted >= 1 &&

@@ -6012,10 +6033,12 @@
         eager->tcp_irs = seg_seq;
         eager->tcp_rack = seg_seq;
         eager->tcp_rnxt = seg_seq + 1;
         U32_TO_ABE32(eager->tcp_rnxt, eager->tcp_tcph->th_ack);
         BUMP_MIB(&tcps->tcps_mib, tcpPassiveOpens);
+        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL, tcp_t *, eager,
+            int32_t, TCPS_SYN_RCVD);
         eager->tcp_state = TCPS_SYN_RCVD;
         mp1 = tcp_xmit_mp(eager, eager->tcp_xmit_head, eager->tcp_mss,
             NULL, NULL, eager->tcp_iss, B_FALSE, NULL, B_FALSE);
         if (mp1 == NULL) {
                 /*

@@ -6121,10 +6144,27 @@
         }
         return;
 error3:
         CONN_DEC_REF(econnp);
 error2:
+        /*
+         * DTrace this tcp:::receive event, as we skipped the previous receive
+         * probe. For DTrace only, we find the IP header length so that the
+         * TCP header can be found.
+         */
+        ipvers = IPH_HDR_VERSION(mp->b_rptr);
+        if (OK_32PTR(mp->b_rptr) &&
+            (ipvers == IPV4_VERSION || ipvers == IPV6_VERSION)) {
+                if (ipvers == IPV4_VERSION)
+                        ip_hdr_len = IPH_HDR_LENGTH((ipha_t *)mp->b_rptr);
+                else
+                        ip_hdr_len = ip_hdr_length_v6(mp, (ip6_t *)mp->b_rptr);
+                DTRACE_TCP5(receive, mblk_t *, NULL, conn_t *, NULL,
+                    void_ip_t *, mp->b_rptr, tcp_t *, NULL, tcph_t *,
+                    &mp->b_rptr[ip_hdr_len]);
+        }
+
         freemsg(mp);
 }
 
 /*
  * In an ideal case of vertical partition in NUMA architecture, its

@@ -6619,10 +6659,12 @@
                 if (lport == 0) {
                         mp = mi_tpi_err_ack_alloc(mp, TNOADDR, 0);
                         goto failed;
                 }
         }
+        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL, tcp_t *, tcp,
+            int32_t, TCPS_SYN_SENT);
         tcp->tcp_state = TCPS_SYN_SENT;
 
         /*
          * TODO: allow data with connect requests
          * by unlinking M_DATA trailers here and

@@ -6631,10 +6673,12 @@
          * feed them to tcp_wput_data() rather than call
          * tcp_timer().
          */
         mp = mi_tpi_ok_ack_alloc(mp);
         if (!mp) {
+                DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                    tcp_t *, tcp, int32_t, oldstate);
                 tcp->tcp_state = oldstate;
                 goto failed;
         }
         if (tcp->tcp_family == AF_INET) {
                 mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ,

@@ -6671,10 +6715,12 @@
                 if (mp1 != NULL)
                         tcp_rput_other(tcp, mp1);
                 return;
         }
         /* Error case */
+        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL, tcp_t *, tcp,
+            int32_t, oldstate);
         tcp->tcp_state = oldstate;
         mp = mi_tpi_err_ack_alloc(mp, TSYSERR, ENOMEM);
 
 failed:
         /* return error ack and blow away saved option results if any */

@@ -6827,10 +6873,12 @@
                 if (lport == 0) {
                         mp = mi_tpi_err_ack_alloc(mp, TNOADDR, 0);
                         goto failed;
                 }
         }
+        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL, tcp_t *, tcp,
+            int32_t, TCPS_SYN_SENT);
         tcp->tcp_state = TCPS_SYN_SENT;
         /*
          * TODO: allow data with connect requests
          * by unlinking M_DATA trailers here and
          * linking them in behind the T_OK_ACK mblk.

@@ -6838,10 +6886,12 @@
          * feed them to tcp_wput_data() rather than call
          * tcp_timer().
          */
         mp = mi_tpi_ok_ack_alloc(mp);
         if (!mp) {
+                DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                    tcp_t *, tcp, int32_t, oldstate);
                 tcp->tcp_state = oldstate;
                 goto failed;
         }
         mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ, sizeof (ipa6_conn_t));
         if (mp1) {

@@ -6864,10 +6914,12 @@
                 if (mp1 != NULL)
                         tcp_rput_other(tcp, mp1);
                 return;
         }
         /* Error case */
+        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL, tcp_t *, tcp,
+            int32_t, oldstate);
         tcp->tcp_state = oldstate;
         mp = mi_tpi_err_ack_alloc(mp, TSYSERR, ENOMEM);
 
 failed:
         /* return error ack and blow away saved option results if any */

@@ -7012,13 +7064,17 @@
                             tcp->tcp_connp->conn_zoneid, ipst);
                         if (connp != NULL)
                                 ltcp = connp->conn_tcp;
                 }
                 if (tcp->tcp_conn_req_max && ltcp == NULL) {
+                        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                            tcp_t *, tcp, int32_t, TCPS_LISTEN);
                         tcp->tcp_state = TCPS_LISTEN;
                 } else if (old_state > TCPS_BOUND) {
                         tcp->tcp_conn_req_max = 0;
+                        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                            tcp_t *, tcp, int32_t, TCPS_BOUND);
                         tcp->tcp_state = TCPS_BOUND;
                 }
                 if (ltcp != NULL)
                         CONN_DEC_REF(ltcp->tcp_connp);
                 if (old_state == TCPS_SYN_SENT || old_state == TCPS_SYN_RCVD) {

@@ -7915,10 +7971,12 @@
                  * the global queue, TCP will do a tcp_lookup_listener()
                  * to find this stream.  This works because this stream
                  * is only removed from connected hash.
                  *
                  */
+                DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                    tcp_t *, tcp, int32_t, TCPS_LISTEN);
                 tcp->tcp_state = TCPS_LISTEN;
                 tcp->tcp_eager_next_q0 = tcp->tcp_eager_prev_q0 = tcp;
                 tcp->tcp_eager_next_drop_q0 = tcp;
                 tcp->tcp_eager_prev_drop_q0 = tcp;
                 tcp->tcp_connp->conn_recv = tcp_conn_request;

@@ -7930,10 +7988,12 @@
                         ASSERT(!tcp->tcp_connp->conn_af_isv6);
                         (void) ipcl_bind_insert(tcp->tcp_connp, IPPROTO_TCP,
                             tcp->tcp_ipha->ipha_src, tcp->tcp_lport);
                 }
         } else {
+                DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                    tcp_t *, tcp, int32_t, TCPS_BOUND);
                 tcp->tcp_state = TCPS_BOUND;
         }
 
         /*
          * Initialize to default values

@@ -8291,10 +8351,11 @@
 {
         int     err;
 
         tcp->tcp_rq = q;
         tcp->tcp_wq = WR(q);
+        /* DTrace ignores this - it isn't a tcp:::state-change */
         tcp->tcp_state = TCPS_IDLE;
         if ((err = tcp_init_values(tcp)) != 0)
                 tcp_timers_stop(tcp);
         return (err);
 }

@@ -13292,10 +13353,17 @@
                         mp->b_wptr = (uchar_t *)tcph + TCP_HDR_LENGTH(tcph);
                         seg_len = 0;
                 }
         }
 
+        DTRACE_TCP5(receive, mblk_t *, NULL, conn_t *, NULL, void_ip_t *,
+            iphdr, tcp_t *, tcp, tcph_t *, tcph);
+        if (tcp->tcp_state == TCPS_SYN_RCVD && (flags & TH_ACK)) {
+                DTRACE_TCP5(accept__established, mblk_t *, NULL, conn_t *,
+                    NULL, void_ip_t *, iphdr, tcp_t *, tcp, tcph_t *, tcph);
+        }
+
         switch (tcp->tcp_state) {
         case TCPS_SYN_SENT:
                 if (flags & TH_ACK) {
                         /*
                          * Note that our stack cannot send data before a

@@ -13313,10 +13381,14 @@
                                 return;
                         }
                         ASSERT(tcp->tcp_suna + 1 == seg_ack);
                 }
                 if (flags & TH_RST) {
+                        DTRACE_TCP5(connect__refused, mblk_t *, NULL,
+                            conn_t *, NULL, void_ip_t *, iphdr, tcp_t *, NULL,
+                            tcph_t *, tcph);
+
                         freemsg(mp);
                         if (flags & TH_ACK)
                                 (void) tcp_clean_death(tcp,
                                     ECONNREFUSED, 13);
                         return;

@@ -13387,13 +13459,22 @@
                                 tcp->tcp_ip_forward_progress = B_TRUE;
 
                         /* One for the SYN */
                         tcp->tcp_suna = tcp->tcp_iss + 1;
                         tcp->tcp_valid_bits &= ~TCP_ISS_VALID;
+                        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                            tcp_t *, tcp, int32_t, TCPS_ESTABLISHED);
                         tcp->tcp_state = TCPS_ESTABLISHED;
 
                         /*
+                         * For DTrace observability, remember that we just
+                         * established a connection and are about to send
+                         * the final ACK.
+                         */
+                        tcp->tcp_dtrace_connect_established = B_TRUE;
+
+                        /*
                          * If SYN was retransmitted, need to reset all
                          * retransmission info.  This is because this
                          * segment will be treated as a dup ACK.
                          */
                         if (tcp->tcp_rexmit) {

@@ -13496,10 +13577,12 @@
 
                         flags &= ~TH_SYN;
                         seg_seq++;
                         break;
                 }
+                DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                    tcp_t *, tcp, int32_t, TCPS_SYN_RCVD);
                 tcp->tcp_state = TCPS_SYN_RCVD;
                 mp1 = tcp_xmit_mp(tcp, tcp->tcp_xmit_head, tcp->tcp_mss,
                     NULL, NULL, tcp->tcp_iss, B_FALSE, NULL, B_FALSE);
                 if (mp1) {
                         DB_CPID(mp1) = tcp->tcp_cpid;

@@ -14415,10 +14498,12 @@
 
                 if (new_swnd > tcp->tcp_max_swnd)
                         tcp->tcp_max_swnd = new_swnd;
                 tcp->tcp_swl1 = seg_seq;
                 tcp->tcp_swl2 = seg_ack;
+                DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL,
+                    tcp_t *, tcp, int32_t, TCPS_ESTABLISHED);
                 tcp->tcp_state = TCPS_ESTABLISHED;
                 tcp->tcp_valid_bits &= ~TCP_ISS_VALID;
 
                 /* Fuse when both sides are in ESTABLISHED state */
                 if (tcp->tcp_loopback && do_tcp_fusion)

@@ -15051,10 +15136,13 @@
         if (tcp->tcp_state > TCPS_ESTABLISHED) {
 
                 switch (tcp->tcp_state) {
                 case TCPS_FIN_WAIT_1:
                         if (tcp->tcp_fin_acked) {
+                                DTRACE_TCP4(state__change, void, NULL,
+                                    conn_t *, NULL, tcp_t *, tcp, int32_t,
+                                    TCPS_FIN_WAIT_2);
                                 tcp->tcp_state = TCPS_FIN_WAIT_2;
                                 /*
                                  * We implement the non-standard BSD/SunOS
                                  * FIN_WAIT_2 flushing algorithm.
                                  * If there is no user attached to this

@@ -15083,10 +15171,13 @@
                                 return;
                         }
                         goto xmit_check;
                 case TCPS_CLOSING:
                         if (tcp->tcp_fin_acked) {
+                                DTRACE_TCP4(state__change, void, NULL,
+                                    conn_t *, NULL, tcp_t *, tcp, int32_t,
+                                    TCPS_TIME_WAIT);
                                 tcp->tcp_state = TCPS_TIME_WAIT;
                                 /*
                                  * Unconditionally clear the exclusive binding
                                  * bit so this TIME-WAIT connection won't
                                  * interfere with new ones.

@@ -15128,20 +15219,29 @@
                             !TCP_IS_DETACHED(tcp) && (!tcp->tcp_hard_binding))
                                 flags |= TH_ORDREL_NEEDED;
                         switch (tcp->tcp_state) {
                         case TCPS_SYN_RCVD:
                         case TCPS_ESTABLISHED:
+                                DTRACE_TCP4(state__change, void, NULL,
+                                    conn_t *, NULL, tcp_t *, tcp, int32_t,
+                                    TCPS_CLOSE_WAIT);
                                 tcp->tcp_state = TCPS_CLOSE_WAIT;
                                 /* Keepalive? */
                                 break;
                         case TCPS_FIN_WAIT_1:
                                 if (!tcp->tcp_fin_acked) {
+                                        DTRACE_TCP4(state__change, void, NULL,
+                                            conn_t *, NULL, tcp_t *, tcp,
+                                            int32_t, TCPS_CLOSING);
                                         tcp->tcp_state = TCPS_CLOSING;
                                         break;
                                 }
                                 /* FALLTHRU */
                         case TCPS_FIN_WAIT_2:
+                                DTRACE_TCP4(state__change, void, NULL,
+                                    conn_t *, NULL, tcp_t *, tcp, int32_t,
+                                    TCPS_TIME_WAIT);
                                 tcp->tcp_state = TCPS_TIME_WAIT;
                                 /*
                                  * Unconditionally clear the exclusive binding
                                  * bit so this TIME-WAIT connection won't
                                  * interfere with new ones.

@@ -15998,10 +16098,12 @@
         default:
                 panic("tcp_bind_failed: unexpected TPI type");
                 /*NOTREACHED*/
         }
 
+        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL, tcp_t *, tcp,
+            int32_t, TCPS_IDLE);
         tcp->tcp_state = TCPS_IDLE;
         if (tcp->tcp_ipversion == IPV4_VERSION)
                 tcp->tcp_ipha->ipha_src = 0;
         else
                 V6_SET_ZERO(tcp->tcp_ip6h->ip6_src);

@@ -16040,10 +16142,11 @@
         mblk_t *mdti;
         mblk_t *lsoi;
         int     retval;
         mblk_t *ire_mp;
         tcp_stack_t     *tcps = tcp->tcp_tcps;
+        uint_t  ip_hdr_len;
 
         switch (mp->b_datap->db_type) {
         case M_PROTO:
         case M_PCPROTO:
                 ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);

@@ -16224,10 +16327,28 @@
 
                                 TCP_RECORD_TRACE(tcp, syn_mp,
                                     TCP_TRACE_SEND_PKT);
                                 mblk_setcred(syn_mp, cr);
                                 DB_CPID(syn_mp) = pid;
+
+                                /*
+                                 * DTrace sending the first SYN as a
+                                 * tcp:::connect-request event. For DTrace
+                                 * only, the IP header length is found
+                                 * so that the TCP header can be retrieved.
+                                 */
+                                if (tcp->tcp_ipversion == IPV4_VERSION)
+                                        ip_hdr_len = IPH_HDR_LENGTH(
+                                            (ipha_t *)syn_mp->b_rptr);
+                                else
+                                        ip_hdr_len = ip_hdr_length_v6(mp,
+                                            (ip6_t *)syn_mp->b_rptr);
+                                DTRACE_TCP5(connect__request, mblk_t *, NULL,
+                                    conn_t *, NULL, void_ip_t *,
+                                    syn_mp->b_rptr, tcp_t *, tcp, tcph_t *,
+                                    &syn_mp->b_rptr[ip_hdr_len]);
+
                                 tcp_send_data(tcp, tcp->tcp_wq, syn_mp);
                         }
                 after_syn_sent:
                         /*
                          * A trailer mblk indicates a waiting client upstream.

@@ -17843,10 +17964,12 @@
                 V6_SET_ZERO(tcp->tcp_ip6h->ip6_src);
         }
         V6_SET_ZERO(tcp->tcp_ip_src_v6);
         bzero(tcp->tcp_tcph->th_lport, sizeof (tcp->tcp_tcph->th_lport));
         tcp_bind_hash_remove(tcp);
+        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL, tcp_t *, tcp,
+            int32_t, TCPS_IDLE);
         tcp->tcp_state = TCPS_IDLE;
         tcp->tcp_mdt = B_FALSE;
         /* Send M_FLUSH according to TPI */
         (void) putnextctl1(tcp->tcp_rq, M_FLUSH, FLUSHRW);
         connp = tcp->tcp_connp;

@@ -19521,10 +19644,11 @@
         uint32_t        hcksum_txflags = 0;
         mblk_t          *ire_fp_mp;
         uint_t          ire_fp_mp_len;
         tcp_stack_t     *tcps = tcp->tcp_tcps;
         ip_stack_t      *ipst = tcps->tcps_netstack->netstack_ip;
+        uint_t          ip_hdr_len;
 
         ASSERT(DB_TYPE(mp) == M_DATA);
 
         if (DB_CRED(mp) == NULL)
                 mblk_setcred(mp, CONN_CRED(connp));

@@ -19531,10 +19655,22 @@
 
         ipha = (ipha_t *)mp->b_rptr;
         src = ipha->ipha_src;
         dst = ipha->ipha_dst;
 
+        if (tcp->tcp_ipversion == IPV4_VERSION) {
+                DTRACE_TCP5(send, mblk_t *, NULL, conn_t *, NULL,
+                    void_ip_t *, ipha, tcp_t *, tcp, tcph_t *,
+                    &mp->b_rptr[IPH_HDR_LENGTH(mp->b_rptr)]);
+                if (tcp->tcp_dtrace_connect_established) {
+                        DTRACE_TCP5(connect__established, mblk_t *, NULL,
+                            conn_t *, NULL, void_ip_t *, ipha, tcp_t *, tcp,
+                            tcph_t *, &mp->b_rptr[IPH_HDR_LENGTH(mp->b_rptr)]);
+                        tcp->tcp_dtrace_connect_established = B_FALSE;
+                }
+        }
+
         /*
          * Drop off fast path for IPv6 and also if options are present or
          * we need to resolve a TS label.
          */
         if (tcp->tcp_ipversion != IPV4_VERSION ||

@@ -19546,10 +19682,25 @@
             ipha->ipha_version_and_hdr_length != IP_SIMPLE_HDR_VERSION ||
             IPP_ENABLED(IPP_LOCAL_OUT, ipst)) {
                 if (tcp->tcp_snd_zcopy_aware)
                         mp = tcp_zcopy_disable(tcp, mp);
                 TCP_STAT(tcps, tcp_ip_send);
+
+                if (tcp->tcp_ipversion == IPV6_VERSION) {
+                        ip_hdr_len = ip_hdr_length_v6(mp, (ip6_t *)mp->b_rptr);
+                        DTRACE_TCP5(send, mblk_t *, NULL, conn_t *, NULL,
+                            void_ip_t *, mp->b_rptr, tcp_t *, tcp, tcph_t *,
+                            &mp->b_rptr[ip_hdr_len]);
+                        if (tcp->tcp_dtrace_connect_established) {
+                                DTRACE_TCP5(connect__established, mblk_t *,
+                                    NULL, conn_t *, NULL, void_ip_t *,
+                                    mp->b_rptr, tcp_t *, tcp, tcph_t *,
+                                    &mp->b_rptr[ip_hdr_len]);
+                                tcp->tcp_dtrace_connect_established = B_FALSE;
+                        }
+                }
+
                 CALL_IP_WPUT(connp, q, mp);
                 return;
         }
 
         if (!tcp_send_find_ire_ill(tcp, mp, &ire, &ill)) {

@@ -20954,10 +21105,13 @@
                                         /*
                                          * tcp state must be ESTABLISHED
                                          * in order for us to get here in
                                          * the first place.
                                          */
+                                        DTRACE_TCP4(state__change, void, NULL,
+                                            conn_t *, NULL, tcp_t *, tcp,
+                                            int32_t, TCPS_FIN_WAIT_1);
                                         tcp->tcp_state = TCPS_FIN_WAIT_1;
 
                                         /*
                                          * Upon returning from this routine,
                                          * tcp_wput_data() will set tcp_snxt

@@ -21589,10 +21743,13 @@
         *up = 0;
 
         IP_CKSUM_XMIT_FAST(ire->ire_ipversion, hcksum_txflags, mp, ipha, up,
             IPPROTO_TCP, IP_SIMPLE_HDR_LENGTH, ntohs(ipha->ipha_length), cksum);
 
+        DTRACE_TCP5(send, mblk_t *, NULL, conn_t *, NULL, void_ip_t *, ipha,
+            tcp_t *, tcp, tcph_t *, &mp->b_rptr[IPH_HDR_LENGTH(mp->b_rptr)]);
+
         /*
          * Append LSO flag to DB_LSOFLAGS(mp) and set the mss to DB_LSOMSS(mp).
          */
         DB_LSOFLAGS(mp) |= HW_LSO;
         DB_LSOMSS(mp) = mss;

@@ -23234,10 +23391,17 @@
                 freemsg(ipsec_mp);
                 return;
         }
         ipsec_mp = nmp;
 
+        DTRACE_TCP5(send, mblk_t *, NULL, conn_t *, NULL, void_ip_t *,
+            mp->b_rptr, tcp_t *, NULL, tcph_t *, tcph);
+        if (tcph->th_flags[0] == (TH_RST|TH_ACK)) {
+                DTRACE_TCP5(accept__refused, mblk_t *, NULL, conn_t *, NULL,
+                    void_ip_t *, mp->b_rptr, tcp_t *, NULL, tcph_t *, tcph);
+        }
+
         /*
          * NOTE:  one might consider tracing a TCP packet here, but
          * this function has no active TCP state and no tcp structure
          * that has a trace buffer.  If we traced here, we would have
          * to keep a local trace buffer in tcp_record_trace().

@@ -23454,10 +23618,17 @@
         tcph = (tcph_t *)&rptr[ip_hdr_len];
         seg_seq = BE32_TO_U32(tcph->th_seq);
         seg_ack = BE32_TO_U32(tcph->th_ack);
         flags = tcph->th_flags[0];
 
+        /*
+         * DTrace this "unknown" segment as a tcp:::receive, as we did
+         * just receive something that was TCP.
+         */
+        DTRACE_TCP5(receive, mblk_t *, NULL, conn_t *, NULL, void_ip_t *, rptr,
+            tcp_t *, NULL, tcph_t *, tcph);
+
         seg_len = msgdsize(mp) - (TCP_HDR_LENGTH(tcph) + ip_hdr_len);
         if (flags & TH_RST) {
                 freemsg(ipsec_mp);
         } else if (flags & TH_ACK) {
                 tcp_xmit_early_reset("no tcp, reset",

@@ -23791,13 +23962,19 @@
                         if (!tcp->tcp_fin_sent) {
                                 tcp->tcp_fin_sent = B_TRUE;
                                 switch (tcp->tcp_state) {
                                 case TCPS_SYN_RCVD:
                                 case TCPS_ESTABLISHED:
+                                        DTRACE_TCP4(state__change, void, NULL,
+                                            conn_t *, NULL, tcp_t *, tcp,
+                                            int32_t, TCPS_FIN_WAIT_1);
                                         tcp->tcp_state = TCPS_FIN_WAIT_1;
                                         break;
                                 case TCPS_CLOSE_WAIT:
+                                        DTRACE_TCP4(state__change, void, NULL,
+                                            conn_t *, NULL, tcp_t *, tcp,
+                                            int32_t, TCPS_LAST_ACK);
                                         tcp->tcp_state = TCPS_LAST_ACK;
                                         break;
                                 }
                                 if (tcp->tcp_suna == tcp->tcp_snxt)
                                         TCP_TIMER_RESTART(tcp, tcp->tcp_rto);

@@ -24143,10 +24320,12 @@
         /*
          * Only initialize the necessary info in those structures.  Note
          * that since INADDR_ANY is all 0, we do not need to set
          * tcp_bound_source to INADDR_ANY here.
          */
+        DTRACE_TCP4(state__change, void, NULL, conn_t *, NULL, tcp_t *, tcp,
+            int32_t, TCPS_BOUND);
         tcp->tcp_state = TCPS_BOUND;
         tcp->tcp_lport = port;
         tcp->tcp_exclbind = 1;
         tcp->tcp_reserved_port = 1;