Print this page
11547 Want connstat(1M) command to display per-connection TCP statistics
Portions contributed by: Cody Peter Mello <cody.mello@joyent.com>
Portions contributed by: Ahmed G <ahmedg@delphix.com>
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/tcp/tcp_stats.c
          +++ new/usr/src/uts/common/inet/tcp/tcp_stats.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright (c) 2011, Joyent Inc. All rights reserved.
       25 + * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
  25   26   */
  26   27  
  27   28  #include <sys/types.h>
  28   29  #include <sys/tihdr.h>
  29   30  #include <sys/policy.h>
  30   31  #include <sys/tsol/tnet.h>
  31   32  #include <sys/kstat.h>
  32   33  
  33   34  #include <inet/common.h>
  34   35  #include <inet/ip.h>
↓ open down ↓ 44 lines elided ↑ open up ↑
  79   80                  return (MIB2_TCP_lastAck);
  80   81          case TCPS_FIN_WAIT_2:
  81   82                  return (MIB2_TCP_finWait2);
  82   83          case TCPS_TIME_WAIT:
  83   84                  return (MIB2_TCP_timeWait);
  84   85          default:
  85   86                  return (0);
  86   87          }
  87   88  }
  88   89  
       90 +static void
       91 +tcp_set_conninfo(tcp_t *tcp, struct tcpConnEntryInfo_s *tcei, boolean_t ispriv)
       92 +{
       93 +        /* Don't want just anybody seeing these... */
       94 +        if (ispriv) {
       95 +                tcei->ce_snxt = tcp->tcp_snxt;
       96 +                tcei->ce_suna = tcp->tcp_suna;
       97 +                tcei->ce_rnxt = tcp->tcp_rnxt;
       98 +                tcei->ce_rack = tcp->tcp_rack;
       99 +        } else {
      100 +                /*
      101 +                 * Netstat, unfortunately, uses this to get send/receive queue
      102 +                 * sizes.  How to fix? Why not compute the difference only?
      103 +                 */
      104 +                tcei->ce_snxt = tcp->tcp_snxt - tcp->tcp_suna;
      105 +                tcei->ce_suna = 0;
      106 +                tcei->ce_rnxt = tcp->tcp_rnxt - tcp->tcp_rack;
      107 +                tcei->ce_rack = 0;
      108 +        }
      109 +
      110 +        tcei->ce_in_data_inorder_bytes = tcp->tcp_cs.tcp_in_data_inorder_bytes;
      111 +        tcei->ce_in_data_inorder_segs = tcp->tcp_cs.tcp_in_data_inorder_segs;
      112 +        tcei->ce_in_data_unorder_bytes = tcp->tcp_cs.tcp_in_data_unorder_bytes;
      113 +        tcei->ce_in_data_unorder_segs = tcp->tcp_cs.tcp_in_data_unorder_segs;
      114 +        tcei->ce_in_zwnd_probes = tcp->tcp_cs.tcp_in_zwnd_probes;
      115 +
      116 +        tcei->ce_out_data_bytes = tcp->tcp_cs.tcp_out_data_bytes;
      117 +        tcei->ce_out_data_segs = tcp->tcp_cs.tcp_out_data_segs;
      118 +        tcei->ce_out_retrans_bytes = tcp->tcp_cs.tcp_out_retrans_bytes;
      119 +        tcei->ce_out_retrans_segs = tcp->tcp_cs.tcp_out_retrans_segs;
      120 +        tcei->ce_out_zwnd_probes = tcp->tcp_cs.tcp_out_zwnd_probes;
      121 +
      122 +        tcei->ce_unsent = tcp->tcp_unsent;
      123 +        tcei->ce_swnd = tcp->tcp_swnd;
      124 +        tcei->ce_cwnd = tcp->tcp_cwnd;
      125 +        tcei->ce_rwnd = tcp->tcp_rwnd;
      126 +        tcei->ce_rto =  tcp->tcp_rto;
      127 +        tcei->ce_mss =  tcp->tcp_mss;
      128 +        tcei->ce_state = tcp->tcp_state;
      129 +        tcei->ce_rtt_sa = NSEC2USEC(tcp->tcp_rtt_sa >> 3);
      130 +        tcei->ce_rtt_sum = NSEC2USEC(tcp->tcp_rtt_sum);
      131 +        tcei->ce_rtt_cnt = tcp->tcp_rtt_cnt;
      132 +}
      133 +
  89  134  /*
  90  135   * Return SNMP stuff in buffer in mpdata.
  91  136   */
  92  137  mblk_t *
  93  138  tcp_snmp_get(queue_t *q, mblk_t *mpctl, boolean_t legacy_req)
  94  139  {
  95  140          mblk_t                  *mpdata;
  96  141          mblk_t                  *mp_conn_ctl = NULL;
  97  142          mblk_t                  *mp_conn_tail;
  98  143          mblk_t                  *mp_attr_ctl = NULL;
↓ open down ↓ 77 lines elided ↑ open up ↑
 176  221  
 177  222                  while ((connp =
 178  223                      ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
 179  224                          tcp_t *tcp;
 180  225                          boolean_t needattr;
 181  226  
 182  227                          if (connp->conn_zoneid != zoneid)
 183  228                                  continue;       /* not in this zone */
 184  229  
 185  230                          tcp = connp->conn_tcp;
 186      -                        TCPS_UPDATE_MIB(tcps, tcpHCInSegs, tcp->tcp_ibsegs);
 187      -                        tcp->tcp_ibsegs = 0;
 188      -                        TCPS_UPDATE_MIB(tcps, tcpHCOutSegs, tcp->tcp_obsegs);
 189      -                        tcp->tcp_obsegs = 0;
 190      -
 191  231                          tce6.tcp6ConnState = tce.tcpConnState =
 192  232                              tcp_snmp_state(tcp);
 193  233                          if (tce.tcpConnState == MIB2_TCP_established ||
 194  234                              tce.tcpConnState == MIB2_TCP_closeWait)
 195  235                                  BUMP_MIB(&tcp_mib, tcpCurrEstab);
 196  236  
 197  237                          needattr = B_FALSE;
 198  238                          bzero(&mlp, sizeof (mlp));
 199  239                          if (connp->conn_mlp_type != mlptSingle) {
 200  240                                  if (connp->conn_mlp_type == mlptShared ||
↓ open down ↓ 35 lines elided ↑ open up ↑
 236  276                          tce6.tcp6ConnLocalAddress = connp->conn_laddr_v6;
 237  277                          tce6.tcp6ConnRemAddress = connp->conn_faddr_v6;
 238  278                          tce6.tcp6ConnLocalPort = ntohs(connp->conn_lport);
 239  279                          tce6.tcp6ConnRemPort = ntohs(connp->conn_fport);
 240  280                          if (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET) {
 241  281                                  tce6.tcp6ConnIfIndex =
 242  282                                      connp->conn_ixa->ixa_scopeid;
 243  283                          } else {
 244  284                                  tce6.tcp6ConnIfIndex = connp->conn_bound_if;
 245  285                          }
 246      -                        /* Don't want just anybody seeing these... */
 247      -                        if (ispriv) {
 248      -                                tce6.tcp6ConnEntryInfo.ce_snxt =
 249      -                                    tcp->tcp_snxt;
 250      -                                tce6.tcp6ConnEntryInfo.ce_suna =
 251      -                                    tcp->tcp_suna;
 252      -                                tce6.tcp6ConnEntryInfo.ce_rnxt =
 253      -                                    tcp->tcp_rnxt;
 254      -                                tce6.tcp6ConnEntryInfo.ce_rack =
 255      -                                    tcp->tcp_rack;
 256      -                        } else {
 257      -                                /*
 258      -                                 * Netstat, unfortunately, uses this to
 259      -                                 * get send/receive queue sizes.  How to fix?
 260      -                                 * Why not compute the difference only?
 261      -                                 */
 262      -                                tce6.tcp6ConnEntryInfo.ce_snxt =
 263      -                                    tcp->tcp_snxt - tcp->tcp_suna;
 264      -                                tce6.tcp6ConnEntryInfo.ce_suna = 0;
 265      -                                tce6.tcp6ConnEntryInfo.ce_rnxt =
 266      -                                    tcp->tcp_rnxt - tcp->tcp_rack;
 267      -                                tce6.tcp6ConnEntryInfo.ce_rack = 0;
 268      -                        }
 269  286  
 270      -                        tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd;
 271      -                        tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
 272      -                        tce6.tcp6ConnEntryInfo.ce_rto =  tcp->tcp_rto;
 273      -                        tce6.tcp6ConnEntryInfo.ce_mss =  tcp->tcp_mss;
 274      -                        tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
      287 +                        tcp_set_conninfo(tcp, &tce6.tcp6ConnEntryInfo,
      288 +                            ispriv);
 275  289  
 276  290                          tce6.tcp6ConnCreationProcess =
 277  291                              (connp->conn_cpid < 0) ? MIB2_UNKNOWN_PROCESS :
 278  292                              connp->conn_cpid;
 279  293                          tce6.tcp6ConnCreationTime = connp->conn_open_time;
 280  294  
 281  295                          (void) snmp_append_data2(mp6_conn_ctl->b_cont,
 282  296                              &mp6_conn_tail, (char *)&tce6, tce6_size);
 283  297  
 284  298                          mlp.tme_connidx = v6_conn_idx++;
↓ open down ↓ 15 lines elided ↑ open up ↑
 300  314                                          tce.tcpConnRemAddress = INADDR_ANY;
 301  315                                          tce.tcpConnLocalAddress = INADDR_ANY;
 302  316                                  } else {
 303  317                                          tce.tcpConnRemAddress =
 304  318                                              connp->conn_faddr_v4;
 305  319                                          tce.tcpConnLocalAddress =
 306  320                                              connp->conn_laddr_v4;
 307  321                                  }
 308  322                                  tce.tcpConnLocalPort = ntohs(connp->conn_lport);
 309  323                                  tce.tcpConnRemPort = ntohs(connp->conn_fport);
 310      -                                /* Don't want just anybody seeing these... */
 311      -                                if (ispriv) {
 312      -                                        tce.tcpConnEntryInfo.ce_snxt =
 313      -                                            tcp->tcp_snxt;
 314      -                                        tce.tcpConnEntryInfo.ce_suna =
 315      -                                            tcp->tcp_suna;
 316      -                                        tce.tcpConnEntryInfo.ce_rnxt =
 317      -                                            tcp->tcp_rnxt;
 318      -                                        tce.tcpConnEntryInfo.ce_rack =
 319      -                                            tcp->tcp_rack;
 320      -                                } else {
 321      -                                        /*
 322      -                                         * Netstat, unfortunately, uses this to
 323      -                                         * get send/receive queue sizes.  How
 324      -                                         * to fix?
 325      -                                         * Why not compute the difference only?
 326      -                                         */
 327      -                                        tce.tcpConnEntryInfo.ce_snxt =
 328      -                                            tcp->tcp_snxt - tcp->tcp_suna;
 329      -                                        tce.tcpConnEntryInfo.ce_suna = 0;
 330      -                                        tce.tcpConnEntryInfo.ce_rnxt =
 331      -                                            tcp->tcp_rnxt - tcp->tcp_rack;
 332      -                                        tce.tcpConnEntryInfo.ce_rack = 0;
 333      -                                }
 334  324  
 335      -                                tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd;
 336      -                                tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
 337      -                                tce.tcpConnEntryInfo.ce_rto =  tcp->tcp_rto;
 338      -                                tce.tcpConnEntryInfo.ce_mss =  tcp->tcp_mss;
 339      -                                tce.tcpConnEntryInfo.ce_state =
 340      -                                    tcp->tcp_state;
      325 +                                tcp_set_conninfo(tcp, &tce.tcpConnEntryInfo,
      326 +                                    ispriv);
 341  327  
 342  328                                  tce.tcpConnCreationProcess =
 343  329                                      (connp->conn_cpid < 0) ?
 344  330                                      MIB2_UNKNOWN_PROCESS :
 345  331                                      connp->conn_cpid;
 346  332                                  tce.tcpConnCreationTime = connp->conn_open_time;
 347  333  
 348  334                                  (void) snmp_append_data2(mp_conn_ctl->b_cont,
 349  335                                      &mp_conn_tail, (char *)&tce, tce_size);
 350  336  
↓ open down ↓ 707 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX