Print this page
DLPX-25998 TCP congestion control is inadequate
Reviewed at: http://reviews.delphix.com/r/34808/
DLPX-43064 include high-resolution round-trip times in connstat (EP-652)
DLPX-37540 TCP per-connection kernel statistics DLPX-37544 connstat command to display per-connection TCP statistics

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/tcp/tcp_output.c
          +++ new/usr/src/uts/common/inet/tcp/tcp_output.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  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      - * Copyright (c) 2014 by Delphix. All rights reserved.
       24 + * Copyright (c) 2014, 2017 by Delphix. All rights reserved.
  25   25   */
  26   26  
  27   27  /* This file contains all TCP output processing functions. */
  28   28  
  29   29  #include <sys/types.h>
  30   30  #include <sys/stream.h>
  31   31  #include <sys/strsun.h>
  32   32  #include <sys/strsubr.h>
  33   33  #include <sys/stropts.h>
  34   34  #include <sys/strlog.h>
↓ open down ↓ 21 lines elided ↑ open up ↑
  56   56  static void     tcp_wput_cmdblk(queue_t *, mblk_t *);
  57   57  static void     tcp_wput_flush(tcp_t *, mblk_t *);
  58   58  static void     tcp_wput_iocdata(tcp_t *tcp, mblk_t *mp);
  59   59  static int      tcp_xmit_end(tcp_t *);
  60   60  static int      tcp_send(tcp_t *, const int, const int, const int,
  61   61                      const int, int *, uint_t *, int *, mblk_t **, mblk_t *);
  62   62  static void     tcp_xmit_early_reset(char *, mblk_t *, uint32_t, uint32_t,
  63   63                      int, ip_recv_attr_t *, ip_stack_t *, conn_t *);
  64   64  static boolean_t        tcp_send_rst_chk(tcp_stack_t *);
  65   65  static void     tcp_process_shrunk_swnd(tcp_t *, uint32_t);
  66      -static void     tcp_fill_header(tcp_t *, uchar_t *, clock_t, int);
       66 +static void     tcp_fill_header(tcp_t *, uchar_t *, int);
  67   67  
  68   68  /*
  69   69   * Functions called directly via squeue having a prototype of edesc_t.
  70   70   */
  71   71  static void     tcp_wput_nondata(void *, mblk_t *, void *, ip_recv_attr_t *);
  72   72  static void     tcp_wput_ioctl(void *, mblk_t *, void *, ip_recv_attr_t *);
  73   73  static void     tcp_wput_proto(void *, mblk_t *, void *, ip_recv_attr_t *);
  74   74  
  75   75  /*
  76   76   * This controls how tiny a write must be before we try to copy it
  77   77   * into the mblk on the tail of the transmit queue.  Not much
  78   78   * speedup is observed for values larger than sixteen.  Zero will
  79   79   * disable the optimisation.
  80   80   */
  81   81  static int tcp_tx_pull_len = 16;
  82   82  
       83 +static void
       84 +cc_after_idle(tcp_t *tcp)
       85 +{
       86 +        uint32_t old_cwnd = tcp->tcp_cwnd;
       87 +
       88 +        if (CC_ALGO(tcp)->after_idle != NULL)
       89 +                CC_ALGO(tcp)->after_idle(&tcp->tcp_ccv);
       90 +
       91 +        DTRACE_PROBE3(cwnd__cc__after__idle, tcp_t *, tcp, uint32_t, old_cwnd,
       92 +            uint32_t, tcp->tcp_cwnd);
       93 +}
       94 +
  83   95  void
  84   96  tcp_wput(queue_t *q, mblk_t *mp)
  85   97  {
  86   98          conn_t  *connp = Q_TO_CONN(q);
  87   99          tcp_t   *tcp;
  88  100          void (*output_proc)();
  89  101          t_scalar_t type;
  90  102          uchar_t *rptr;
  91  103          struct iocblk   *iocp;
  92  104          size_t size;
↓ open down ↓ 117 lines elided ↑ open up ↑
 210  222          uint32_t        snxt;
 211  223          int             tail_unsent;
 212  224          int             tcpstate;
 213  225          int             usable = 0;
 214  226          mblk_t          *xmit_tail;
 215  227          int32_t         mss;
 216  228          int32_t         num_sack_blk = 0;
 217  229          int32_t         total_hdr_len;
 218  230          int32_t         tcp_hdr_len;
 219  231          int             rc;
 220      -        tcp_stack_t     *tcps = tcp->tcp_tcps;
 221  232          conn_t          *connp = tcp->tcp_connp;
 222  233          clock_t         now = LBOLT_FASTPATH;
 223  234  
 224  235          tcpstate = tcp->tcp_state;
 225  236          if (mp == NULL) {
 226  237                  /*
 227  238                   * tcp_wput_data() with NULL mp should only be called when
 228  239                   * there is unsent data.
 229  240                   */
 230  241                  ASSERT(tcp->tcp_unsent > 0);
↓ open down ↓ 134 lines elided ↑ open up ↑
 365  376                  total_hdr_len = connp->conn_ht_iphc_len + opt_len;
 366  377                  tcp_hdr_len = connp->conn_ht_ulp_len + opt_len;
 367  378          } else {
 368  379                  mss = tcp->tcp_mss;
 369  380                  total_hdr_len = connp->conn_ht_iphc_len;
 370  381                  tcp_hdr_len = connp->conn_ht_ulp_len;
 371  382          }
 372  383  
 373  384          if ((tcp->tcp_suna == snxt) && !tcp->tcp_localnet &&
 374  385              (TICK_TO_MSEC(now - tcp->tcp_last_recv_time) >= tcp->tcp_rto)) {
 375      -                TCP_SET_INIT_CWND(tcp, mss, tcps->tcps_slow_start_after_idle);
      386 +                cc_after_idle(tcp);
 376  387          }
 377  388          if (tcpstate == TCPS_SYN_RCVD) {
 378  389                  /*
 379  390                   * The three-way connection establishment handshake is not
 380  391                   * complete yet. We want to queue the data for transmission
 381  392                   * after entering ESTABLISHED state (RFC793). A jump to
 382  393                   * "done" label effectively leaves data on the queue.
 383  394                   */
 384  395                  goto done;
 385  396          } else {
↓ open down ↓ 60 lines elided ↑ open up ↑
 446  457  
 447  458                  /* usable = MAX(usable, {1 for urgent, 0 for data}) */
 448  459                  if (usable_r > 0) {
 449  460                          usable = usable_r;
 450  461                  } else {
 451  462                          /* Bypass all other unnecessary processing. */
 452  463                          goto done;
 453  464                  }
 454  465          }
 455  466  
      467 +#ifdef KERNEL_32
 456  468          local_time = (mblk_t *)now;
      469 +#else
      470 +        local_time = (mblk_t *)(intptr_t)gethrtime();
      471 +#endif
 457  472  
 458  473          /*
 459  474           * "Our" Nagle Algorithm.  This is not the same as in the old
 460  475           * BSD.  This is more in line with the true intent of Nagle.
 461  476           *
 462  477           * The conditions are:
 463  478           * 1. The amount of unsent data (or amount of data which can be
 464  479           *    sent, whichever is smaller) is less than Nagle limit.
 465  480           * 2. The last sent size is also less than Nagle limit.
 466  481           * 3. There is unack'ed data.
↓ open down ↓ 716 lines elided ↑ open up ↑
1183 1198           * Check to see if this connection has been idled for some
1184 1199           * time and no ACK is expected.  If it is, we need to slow
1185 1200           * start again to get back the connection's "self-clock" as
1186 1201           * described in VJ's paper.
1187 1202           *
1188 1203           * Reinitialize tcp_cwnd after idle.
1189 1204           */
1190 1205          now = LBOLT_FASTPATH;
1191 1206          if ((tcp->tcp_suna == snxt) && !tcp->tcp_localnet &&
1192 1207              (TICK_TO_MSEC(now - tcp->tcp_last_recv_time) >= tcp->tcp_rto)) {
1193      -                TCP_SET_INIT_CWND(tcp, mss, tcps->tcps_slow_start_after_idle);
     1208 +                cc_after_idle(tcp);
1194 1209          }
1195 1210  
1196 1211          usable = tcp->tcp_swnd;         /* tcp window size */
1197 1212          if (usable > tcp->tcp_cwnd)
1198 1213                  usable = tcp->tcp_cwnd; /* congestion window smaller */
1199 1214          usable -= snxt;         /* subtract stuff already sent */
1200 1215          suna = tcp->tcp_suna;
1201 1216          usable += suna;
1202 1217          /* usable can be < 0 if the congestion window is smaller */
1203 1218          if (len > usable) {
↓ open down ↓ 42 lines elided ↑ open up ↑
1246 1261          }
1247 1262  
1248 1263          /* we have always sent something */
1249 1264          tcp->tcp_rack_cnt = 0;
1250 1265  
1251 1266          tcp->tcp_snxt = snxt + len;
1252 1267          tcp->tcp_rack = tcp->tcp_rnxt;
1253 1268  
1254 1269          if ((mp1 = dupb(mp)) == 0)
1255 1270                  goto no_memory;
     1271 +#ifdef KERNEL_32
1256 1272          mp->b_prev = (mblk_t *)(uintptr_t)now;
     1273 +#else
     1274 +        mp->b_prev = (mblk_t *)(intptr_t)gethrtime();
     1275 +#endif
1257 1276          mp->b_next = (mblk_t *)(uintptr_t)snxt;
1258 1277  
1259 1278          /* adjust tcp header information */
1260 1279          tcpha = tcp->tcp_tcpha;
1261 1280          tcpha->tha_flags = (TH_ACK|TH_PUSH);
1262 1281  
1263 1282          sum = len + connp->conn_ht_ulp_len + connp->conn_sum;
1264 1283          sum = (sum >> 16) + (sum & 0xFFFF);
1265 1284          tcpha->tha_sum = htons(sum);
1266 1285  
1267 1286          tcpha->tha_seq = htonl(snxt);
1268 1287  
1269 1288          TCPS_BUMP_MIB(tcps, tcpOutDataSegs);
1270 1289          TCPS_UPDATE_MIB(tcps, tcpOutDataBytes, len);
1271      -        BUMP_LOCAL(tcp->tcp_obsegs);
     1290 +        TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
     1291 +        tcp->tcp_cs.tcp_out_data_segs++;
     1292 +        tcp->tcp_cs.tcp_out_data_bytes += len;
1272 1293  
1273 1294          /* Update the latest receive window size in TCP header. */
1274 1295          tcpha->tha_win = htons(tcp->tcp_rwnd >> tcp->tcp_rcv_ws);
1275 1296  
1276 1297          tcp->tcp_last_sent_len = (ushort_t)len;
1277 1298  
1278 1299          plen = len + connp->conn_ht_iphc_len;
1279 1300  
1280 1301          ixa = connp->conn_ixa;
1281 1302          ixa->ixa_pktlen = plen;
↓ open down ↓ 19 lines elided ↑ open up ↑
1301 1322                  mp->b_cont = mp1;
1302 1323                  mp1 = mp;
1303 1324                  /* Leave room for Link Level header */
1304 1325                  rptr = &mp1->b_rptr[tcps->tcps_wroff_xtra];
1305 1326                  mp1->b_wptr = &rptr[hdrlen];
1306 1327          }
1307 1328          mp1->b_rptr = rptr;
1308 1329  
1309 1330          /* Fill in the timestamp option. */
1310 1331          if (tcp->tcp_snd_ts_ok) {
1311      -                uint32_t llbolt = (uint32_t)LBOLT_FASTPATH;
1312      -
1313      -                U32_TO_BE32(llbolt,
1314      -                    (char *)tcpha + TCP_MIN_HEADER_LENGTH+4);
     1332 +                U32_TO_BE32(now,
     1333 +                    (char *)tcpha + TCP_MIN_HEADER_LENGTH + 4);
1315 1334                  U32_TO_BE32(tcp->tcp_ts_recent,
1316      -                    (char *)tcpha + TCP_MIN_HEADER_LENGTH+8);
     1335 +                    (char *)tcpha + TCP_MIN_HEADER_LENGTH + 8);
1317 1336          } else {
1318 1337                  ASSERT(connp->conn_ht_ulp_len == TCP_MIN_HEADER_LENGTH);
1319 1338          }
1320 1339  
1321 1340          /* copy header into outgoing packet */
1322 1341          dst = (ipaddr_t *)rptr;
1323 1342          src = (ipaddr_t *)connp->conn_ht_iphc;
1324 1343          dst[0] = src[0];
1325 1344          dst[1] = src[1];
1326 1345          dst[2] = src[2];
↓ open down ↓ 623 lines elided ↑ open up ↑
1950 1969                                  tcp->tcp_last_sent_len = (ushort_t)len;
1951 1970                          while (mp1->b_cont) {
1952 1971                                  *xmit_tail = (*xmit_tail)->b_cont;
1953 1972                                  (*xmit_tail)->b_prev = local_time;
1954 1973                                  (*xmit_tail)->b_next =
1955 1974                                      (mblk_t *)(uintptr_t)(*snxt);
1956 1975                                  mp1 = mp1->b_cont;
1957 1976                          }
1958 1977                          *snxt += len;
1959 1978                          *tail_unsent = (*xmit_tail)->b_wptr - mp1->b_wptr;
1960      -                        BUMP_LOCAL(tcp->tcp_obsegs);
     1979 +                        TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
1961 1980                          TCPS_BUMP_MIB(tcps, tcpOutDataSegs);
1962 1981                          TCPS_UPDATE_MIB(tcps, tcpOutDataBytes, len);
     1982 +                        tcp->tcp_cs.tcp_out_data_segs++;
     1983 +                        tcp->tcp_cs.tcp_out_data_bytes += len;
1963 1984                          tcp_send_data(tcp, mp);
1964 1985                          continue;
1965 1986                  }
1966 1987  
1967 1988                  *snxt += len;   /* Adjust later if we don't send all of len */
     1989 +                TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
1968 1990                  TCPS_BUMP_MIB(tcps, tcpOutDataSegs);
1969 1991                  TCPS_UPDATE_MIB(tcps, tcpOutDataBytes, len);
     1992 +                tcp->tcp_cs.tcp_out_data_segs++;
     1993 +                tcp->tcp_cs.tcp_out_data_bytes += len;
1970 1994  
1971 1995                  if (*tail_unsent) {
1972 1996                          /* Are the bytes above us in flight? */
1973 1997                          rptr = (*xmit_tail)->b_wptr - *tail_unsent;
1974 1998                          if (rptr != (*xmit_tail)->b_rptr) {
1975 1999                                  *tail_unsent -= len;
1976 2000                                  if (len <= mss) /* LSO is unusable */
1977 2001                                          tcp->tcp_last_sent_len = (ushort_t)len;
1978 2002                                  len += total_hdr_len;
1979 2003                                  ixa->ixa_pktlen = len;
↓ open down ↓ 76 lines elided ↑ open up ↑
2056 2080                          /* Leave room for Link Level header */
2057 2081                          len = total_hdr_len;
2058 2082                          rptr = &mp->b_rptr[tcps->tcps_wroff_xtra];
2059 2083                          mp->b_wptr = &rptr[len];
2060 2084                  }
2061 2085  
2062 2086                  /*
2063 2087                   * Fill in the header using the template header, and add
2064 2088                   * options such as time-stamp, ECN and/or SACK, as needed.
2065 2089                   */
2066      -                tcp_fill_header(tcp, rptr, (clock_t)local_time, num_sack_blk);
     2090 +                tcp_fill_header(tcp, rptr, num_sack_blk);
2067 2091  
2068 2092                  mp->b_rptr = rptr;
2069 2093  
2070 2094                  if (*tail_unsent) {
2071 2095                          int spill = *tail_unsent;
2072 2096  
2073 2097                          mp1 = mp->b_cont;
2074 2098                          if (mp1 == NULL)
2075 2099                                  mp1 = mp;
2076 2100  
↓ open down ↓ 58 lines elided ↑ open up ↑
2135 2159                                  *tail_unsent = spill;
2136 2160                          } else {
2137 2161                                  /*
2138 2162                                   * We did not send everything we could in
2139 2163                                   * order to remain within the b_cont limit.
2140 2164                                   */
2141 2165                                  *usable -= spill;
2142 2166                                  *snxt += spill;
2143 2167                                  tcp->tcp_last_sent_len += spill;
2144 2168                                  TCPS_UPDATE_MIB(tcps, tcpOutDataBytes, spill);
     2169 +                                tcp->tcp_cs.tcp_out_data_bytes += spill;
2145 2170                                  /*
2146 2171                                   * Adjust the checksum
2147 2172                                   */
2148 2173                                  tcpha = (tcpha_t *)(rptr +
2149 2174                                      ixa->ixa_ip_hdr_length);
2150 2175                                  sum += spill;
2151 2176                                  sum = (sum >> 16) + (sum & 0xFFFF);
2152 2177                                  tcpha->tha_sum = htons(sum);
2153 2178                                  if (connp->conn_ipversion == IPV4_VERSION) {
2154 2179                                          sum = ntohs(
↓ open down ↓ 28 lines elided ↑ open up ↑
2183 2208                          DTRACE_PROBE2(tcp_send_lso, int, num_lso_seg,
2184 2209                              boolean_t, B_TRUE);
2185 2210  
2186 2211                          tcp_send_data(tcp, mp);
2187 2212  
2188 2213                          /*
2189 2214                           * Restore values of ixa_fragsize and ixa_extra_ident.
2190 2215                           */
2191 2216                          ixa->ixa_fragsize = ixa->ixa_pmtu;
2192 2217                          ixa->ixa_extra_ident = 0;
2193      -                        tcp->tcp_obsegs += num_lso_seg;
     2218 +                        TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
2194 2219                          TCP_STAT(tcps, tcp_lso_times);
2195 2220                          TCP_STAT_UPDATE(tcps, tcp_lso_pkt_out, num_lso_seg);
2196 2221                  } else {
2197 2222                          /*
2198 2223                           * Make sure to clean up LSO information. Wherever a
2199 2224                           * new mp uses the prepended header room after dupb(),
2200 2225                           * lso_info_cleanup() should be called.
2201 2226                           */
2202 2227                          lso_info_cleanup(mp);
2203 2228                          tcp_send_data(tcp, mp);
2204      -                        BUMP_LOCAL(tcp->tcp_obsegs);
     2229 +                        TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
2205 2230                  }
2206 2231          }
2207 2232  
2208 2233          return (0);
2209 2234  }
2210 2235  
2211 2236  /*
2212 2237   * Initiate closedown sequence on an active connection.  (May be called as
2213 2238   * writer.)  Return value zero for OK return, non-zero for error return.
2214 2239   */
↓ open down ↓ 59 lines elided ↑ open up ↑
2274 2299           */
2275 2300          if (tcps->tcps_rtt_updates == 0 ||
2276 2301              tcp->tcp_rtt_update < tcps->tcps_rtt_updates)
2277 2302                  return (0);
2278 2303  
2279 2304          /*
2280 2305           * We do not have a good algorithm to update ssthresh at this time.
2281 2306           * So don't do any update.
2282 2307           */
2283 2308          bzero(&uinfo, sizeof (uinfo));
2284      -        uinfo.iulp_rtt = tcp->tcp_rtt_sa;
2285      -        uinfo.iulp_rtt_sd = tcp->tcp_rtt_sd;
     2309 +        uinfo.iulp_rtt = NSEC2MSEC(tcp->tcp_rtt_sa);
     2310 +        uinfo.iulp_rtt_sd = NSEC2MSEC(tcp->tcp_rtt_sd);
2286 2311  
2287 2312          /*
2288 2313           * Note that uinfo is kept for conn_faddr in the DCE. Could update even
2289 2314           * if source routed but we don't.
2290 2315           */
2291 2316          if (connp->conn_ipversion == IPV4_VERSION) {
2292 2317                  if (connp->conn_faddr_v4 !=  tcp->tcp_ipha->ipha_dst) {
2293 2318                          return (0);
2294 2319                  }
2295 2320                  (void) dce_update_uinfo_v4(connp->conn_faddr_v4, &uinfo, ipst);
↓ open down ↓ 114 lines elided ↑ open up ↑
2410 2435                  }
2411 2436  
2412 2437                  /* Update the latest receive window size in TCP header. */
2413 2438                  tcpha->tha_win = htons(tcp->tcp_rwnd >> tcp->tcp_rcv_ws);
2414 2439                  /* Track what we sent to the peer */
2415 2440                  tcp->tcp_tcpha->tha_win = tcpha->tha_win;
2416 2441                  tcp->tcp_rack = ack;
2417 2442                  tcp->tcp_rack_cnt = 0;
2418 2443                  TCPS_BUMP_MIB(tcps, tcpOutAck);
2419 2444          }
2420      -        BUMP_LOCAL(tcp->tcp_obsegs);
     2445 +        TCPS_BUMP_MIB(tcps, tcpHCOutSegs);
2421 2446          tcpha->tha_seq = htonl(seq);
2422 2447          tcpha->tha_ack = htonl(ack);
2423 2448          /*
2424 2449           * Include the adjustment for a source route if any.
2425 2450           */
2426 2451          sum = (sum >> 16) + (sum & 0xFFFF);
2427 2452          tcpha->tha_sum = htons(sum);
2428 2453          tcp_send_data(tcp, mp);
2429 2454  }
2430 2455  
↓ open down ↓ 948 lines elided ↑ open up ↑
3379 3404  
3380 3405                  usable_swnd -= seg_len;
3381 3406                  tcp->tcp_pipe += seg_len;
3382 3407                  tcp->tcp_sack_snxt = begin + seg_len;
3383 3408  
3384 3409                  tcp_send_data(tcp, xmit_mp);
3385 3410  
3386 3411                  /*
3387 3412                   * Update the send timestamp to avoid false retransmission.
3388 3413                   */
     3414 +#ifdef KERNEL_32
3389 3415                  snxt_mp->b_prev = (mblk_t *)ddi_get_lbolt();
     3416 +#else
     3417 +                snxt_mp->b_prev = (mblk_t *)(intptr_t)gethrtime();
     3418 +#endif
3390 3419  
3391 3420                  TCPS_BUMP_MIB(tcps, tcpRetransSegs);
3392 3421                  TCPS_UPDATE_MIB(tcps, tcpRetransBytes, seg_len);
3393 3422                  TCPS_BUMP_MIB(tcps, tcpOutSackRetransSegs);
     3423 +                tcp->tcp_cs.tcp_out_retrans_segs++;
     3424 +                tcp->tcp_cs.tcp_out_retrans_bytes += seg_len;
3394 3425                  /*
3395 3426                   * Update tcp_rexmit_max to extend this SACK recovery phase.
3396 3427                   * This happens when new data sent during fast recovery is
3397 3428                   * also lost.  If TCP retransmits those new data, it needs
3398 3429                   * to extend SACK recover phase to avoid starting another
3399 3430                   * fast retransmit/recovery unnecessarily.
3400 3431                   */
3401 3432                  if (SEQ_GT(tcp->tcp_sack_snxt, tcp->tcp_rexmit_max)) {
3402 3433                          tcp->tcp_rexmit_max = tcp->tcp_sack_snxt;
3403 3434                  }
↓ open down ↓ 47 lines elided ↑ open up ↑
3451 3482                                  return;
3452 3483  
3453 3484                          tcp_send_data(tcp, xmit_mp);
3454 3485  
3455 3486                          snxt += cnt;
3456 3487                          win -= cnt;
3457 3488                          /*
3458 3489                           * Update the send timestamp to avoid false
3459 3490                           * retransmission.
3460 3491                           */
     3492 +#ifdef KERNEL_32
3461 3493                          old_snxt_mp->b_prev = (mblk_t *)ddi_get_lbolt();
     3494 +#else
     3495 +                        old_snxt_mp->b_prev = (mblk_t *)(intptr_t)gethrtime();
     3496 +#endif
3462 3497                          TCPS_BUMP_MIB(tcps, tcpRetransSegs);
3463 3498                          TCPS_UPDATE_MIB(tcps, tcpRetransBytes, cnt);
     3499 +                        tcp->tcp_cs.tcp_out_retrans_segs++;
     3500 +                        tcp->tcp_cs.tcp_out_retrans_bytes += cnt;
3464 3501  
3465 3502                          tcp->tcp_rexmit_nxt = snxt;
3466 3503                  }
3467 3504                  /*
3468 3505                   * If we have transmitted all we have at the time
3469 3506                   * we started the retranmission, we can leave
3470 3507                   * the rest of the job to tcp_wput_data().  But we
3471 3508                   * need to check the send window first.  If the
3472 3509                   * win is not 0, go on with tcp_wput_data().
3473 3510                   */
↓ open down ↓ 137 lines elided ↑ open up ↑
3611 3648                   */
3612 3649                  TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
3613 3650  }
3614 3651  
3615 3652  /*
3616 3653   * tcp_fill_header is called by tcp_send() to fill the outgoing TCP header
3617 3654   * with the template header, as well as other options such as time-stamp,
3618 3655   * ECN and/or SACK.
3619 3656   */
3620 3657  static void
3621      -tcp_fill_header(tcp_t *tcp, uchar_t *rptr, clock_t now, int num_sack_blk)
     3658 +tcp_fill_header(tcp_t *tcp, uchar_t *rptr, int num_sack_blk)
3622 3659  {
3623 3660          tcpha_t *tcp_tmpl, *tcpha;
3624 3661          uint32_t *dst, *src;
3625 3662          int hdrlen;
3626 3663          conn_t *connp = tcp->tcp_connp;
3627 3664  
3628 3665          ASSERT(OK_32PTR(rptr));
3629 3666  
3630 3667          /* Template header */
3631 3668          tcp_tmpl = tcp->tcp_tcpha;
↓ open down ↓ 1 lines elided ↑ open up ↑
3633 3670          /* Header of outgoing packet */
3634 3671          tcpha = (tcpha_t *)(rptr + connp->conn_ixa->ixa_ip_hdr_length);
3635 3672  
3636 3673          /* dst and src are opaque 32-bit fields, used for copying */
3637 3674          dst = (uint32_t *)rptr;
3638 3675          src = (uint32_t *)connp->conn_ht_iphc;
3639 3676          hdrlen = connp->conn_ht_iphc_len;
3640 3677  
3641 3678          /* Fill time-stamp option if needed */
3642 3679          if (tcp->tcp_snd_ts_ok) {
3643      -                U32_TO_BE32((uint32_t)now,
     3680 +                U32_TO_BE32(LBOLT_FASTPATH,
3644 3681                      (char *)tcp_tmpl + TCP_MIN_HEADER_LENGTH + 4);
3645 3682                  U32_TO_BE32(tcp->tcp_ts_recent,
3646 3683                      (char *)tcp_tmpl + TCP_MIN_HEADER_LENGTH + 8);
3647 3684          } else {
3648 3685                  ASSERT(connp->conn_ht_ulp_len == TCP_MIN_HEADER_LENGTH);
3649 3686          }
3650 3687  
3651 3688          /*
3652 3689           * Copy the template header; is this really more efficient than
3653 3690           * calling bcopy()?  For simple IPv4/TCP, it may be the case,
↓ open down ↓ 61 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX