Print this page
917 Make TCP's iss_incr a tunable


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 /*
  27  * This file contains functions related to TCP time wait processing.  Also
  28  * refer to the time wait handling comments in tcp_impl.h.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/strsun.h>
  33 #include <sys/squeue_impl.h>
  34 #include <sys/squeue.h>
  35 #include <sys/callo.h>
  36 
  37 #include <inet/common.h>
  38 #include <inet/ip.h>
  39 #include <inet/tcp.h>
  40 #include <inet/tcp_impl.h>
  41 #include <inet/tcp_cluster.h>
  42 
  43 static void     tcp_timewait_close(void *, mblk_t *, void *, ip_recv_attr_t *);


 493                                         ASSERT(tcp != NULL);
 494                                         TCP_TIMER_RESTART(tcp,
 495                                             tcps->tcps_time_wait_interval);
 496                                 }
 497                                 tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
 498                                     tcp->tcp_rnxt, TH_ACK);
 499                                 goto done;
 500                         }
 501                         flags |=  TH_ACK_NEEDED;
 502                         seg_len = 0;
 503                         goto process_ack;
 504                 }
 505 
 506                 /* Fix seg_seq, and chew the gap off the front. */
 507                 seg_seq = tcp->tcp_rnxt;
 508         }
 509 
 510         if ((flags & TH_SYN) && gap > 0 && rgap < 0) {
 511                 /*
 512                  * Make sure that when we accept the connection, pick
 513                  * an ISS greater than (tcp_snxt + ISS_INCR/2) for the
 514                  * old connection.
 515                  *
 516                  * The next ISS generated is equal to tcp_iss_incr_extra
 517                  * + ISS_INCR/2 + other components depending on the
 518                  * value of tcp_strong_iss.  We pre-calculate the new
 519                  * ISS here and compare with tcp_snxt to determine if
 520                  * we need to make adjustment to tcp_iss_incr_extra.
 521                  *
 522                  * The above calculation is ugly and is a
 523                  * waste of CPU cycles...
 524                  */
 525                 uint32_t new_iss = tcps->tcps_iss_incr_extra;
 526                 int32_t adj;
 527                 ip_stack_t *ipst = tcps->tcps_netstack->netstack_ip;
 528 
 529                 switch (tcps->tcps_strong_iss) {
 530                 case 2: {
 531                         /* Add time and MD5 components. */
 532                         uint32_t answer[4];
 533                         struct {
 534                                 uint32_t ports;
 535                                 in6_addr_t src;
 536                                 in6_addr_t dst;
 537                         } arg;


 540                         mutex_enter(&tcps->tcps_iss_key_lock);
 541                         context = tcps->tcps_iss_key;
 542                         mutex_exit(&tcps->tcps_iss_key_lock);
 543                         arg.ports = connp->conn_ports;
 544                         /* We use MAPPED addresses in tcp_iss_init */
 545                         arg.src = connp->conn_laddr_v6;
 546                         arg.dst = connp->conn_faddr_v6;
 547                         MD5Update(&context, (uchar_t *)&arg,
 548                             sizeof (arg));
 549                         MD5Final((uchar_t *)answer, &context);
 550                         answer[0] ^= answer[1] ^ answer[2] ^ answer[3];
 551                         new_iss += (gethrtime() >> ISS_NSEC_SHT) + answer[0];
 552                         break;
 553                 }
 554                 case 1:
 555                         /* Add time component and min random (i.e. 1). */
 556                         new_iss += (gethrtime() >> ISS_NSEC_SHT) + 1;
 557                         break;
 558                 default:
 559                         /* Add only time component. */
 560                         new_iss += (uint32_t)gethrestime_sec() * ISS_INCR;

 561                         break;
 562                 }
 563                 if ((adj = (int32_t)(tcp->tcp_snxt - new_iss)) > 0) {
 564                         /*
 565                          * New ISS not guaranteed to be ISS_INCR/2
 566                          * ahead of the current tcp_snxt, so add the
 567                          * difference to tcp_iss_incr_extra.
 568                          */
 569                         tcps->tcps_iss_incr_extra += adj;
 570                 }
 571                 /*
 572                  * If tcp_clean_death() can not perform the task now,
 573                  * drop the SYN packet and let the other side re-xmit.
 574                  * Otherwise pass the SYN packet back in, since the
 575                  * old tcp state has been cleaned up or freed.
 576                  */
 577                 if (tcp_clean_death(tcp, 0) == -1)
 578                         goto done;
 579                 nconnp = ipcl_classify(mp, ira, ipst);
 580                 if (nconnp != NULL) {
 581                         TCP_STAT(tcps, tcp_time_wait_syn_success);
 582                         /* Drops ref on nconnp */
 583                         tcp_reinput(nconnp, mp, ira, ipst);
 584                         return;
 585                 }




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, Joyent Inc. All rights reserved.
  25  */
  26 
  27 /*
  28  * This file contains functions related to TCP time wait processing.  Also
  29  * refer to the time wait handling comments in tcp_impl.h.
  30  */
  31 
  32 #include <sys/types.h>
  33 #include <sys/strsun.h>
  34 #include <sys/squeue_impl.h>
  35 #include <sys/squeue.h>
  36 #include <sys/callo.h>
  37 
  38 #include <inet/common.h>
  39 #include <inet/ip.h>
  40 #include <inet/tcp.h>
  41 #include <inet/tcp_impl.h>
  42 #include <inet/tcp_cluster.h>
  43 
  44 static void     tcp_timewait_close(void *, mblk_t *, void *, ip_recv_attr_t *);


 494                                         ASSERT(tcp != NULL);
 495                                         TCP_TIMER_RESTART(tcp,
 496                                             tcps->tcps_time_wait_interval);
 497                                 }
 498                                 tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
 499                                     tcp->tcp_rnxt, TH_ACK);
 500                                 goto done;
 501                         }
 502                         flags |=  TH_ACK_NEEDED;
 503                         seg_len = 0;
 504                         goto process_ack;
 505                 }
 506 
 507                 /* Fix seg_seq, and chew the gap off the front. */
 508                 seg_seq = tcp->tcp_rnxt;
 509         }
 510 
 511         if ((flags & TH_SYN) && gap > 0 && rgap < 0) {
 512                 /*
 513                  * Make sure that when we accept the connection, pick
 514                  * an ISS greater than (tcp_snxt + tcp_iss_incr/2) for the
 515                  * old connection.
 516                  *
 517                  * The next ISS generated is equal to tcp_iss_incr_extra
 518                  * + tcp_iss_incr/2 + other components depending on the
 519                  * value of tcp_strong_iss.  We pre-calculate the new
 520                  * ISS here and compare with tcp_snxt to determine if
 521                  * we need to make adjustment to tcp_iss_incr_extra.
 522                  *
 523                  * The above calculation is ugly and is a
 524                  * waste of CPU cycles...
 525                  */
 526                 uint32_t new_iss = tcps->tcps_iss_incr_extra;
 527                 int32_t adj;
 528                 ip_stack_t *ipst = tcps->tcps_netstack->netstack_ip;
 529 
 530                 switch (tcps->tcps_strong_iss) {
 531                 case 2: {
 532                         /* Add time and MD5 components. */
 533                         uint32_t answer[4];
 534                         struct {
 535                                 uint32_t ports;
 536                                 in6_addr_t src;
 537                                 in6_addr_t dst;
 538                         } arg;


 541                         mutex_enter(&tcps->tcps_iss_key_lock);
 542                         context = tcps->tcps_iss_key;
 543                         mutex_exit(&tcps->tcps_iss_key_lock);
 544                         arg.ports = connp->conn_ports;
 545                         /* We use MAPPED addresses in tcp_iss_init */
 546                         arg.src = connp->conn_laddr_v6;
 547                         arg.dst = connp->conn_faddr_v6;
 548                         MD5Update(&context, (uchar_t *)&arg,
 549                             sizeof (arg));
 550                         MD5Final((uchar_t *)answer, &context);
 551                         answer[0] ^= answer[1] ^ answer[2] ^ answer[3];
 552                         new_iss += (gethrtime() >> ISS_NSEC_SHT) + answer[0];
 553                         break;
 554                 }
 555                 case 1:
 556                         /* Add time component and min random (i.e. 1). */
 557                         new_iss += (gethrtime() >> ISS_NSEC_SHT) + 1;
 558                         break;
 559                 default:
 560                         /* Add only time component. */
 561                         new_iss += (uint32_t)gethrestime_sec() *
 562                             tcps->tcps_iss_incr;
 563                         break;
 564                 }
 565                 if ((adj = (int32_t)(tcp->tcp_snxt - new_iss)) > 0) {
 566                         /*
 567                          * New ISS not guaranteed to be tcp_iss_incr/2
 568                          * ahead of the current tcp_snxt, so add the
 569                          * difference to tcp_iss_incr_extra.
 570                          */
 571                         tcps->tcps_iss_incr_extra += adj;
 572                 }
 573                 /*
 574                  * If tcp_clean_death() can not perform the task now,
 575                  * drop the SYN packet and let the other side re-xmit.
 576                  * Otherwise pass the SYN packet back in, since the
 577                  * old tcp state has been cleaned up or freed.
 578                  */
 579                 if (tcp_clean_death(tcp, 0) == -1)
 580                         goto done;
 581                 nconnp = ipcl_classify(mp, ira, ipst);
 582                 if (nconnp != NULL) {
 583                         TCP_STAT(tcps, tcp_time_wait_syn_success);
 584                         /* Drops ref on nconnp */
 585                         tcp_reinput(nconnp, mp, ira, ipst);
 586                         return;
 587                 }