1 /* 2 * Copyright (c) 2003, 2004 Jeffrey M. Hsu. All rights reserved. 3 * Copyright (c) 2003, 2004 The DragonFly Project. All rights reserved. 4 * 5 * This code is derived from software contributed to The DragonFly Project 6 * by Jeffrey M. Hsu. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of The DragonFly Project nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific, prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 2003, 2004 Jeffrey M. Hsu. All rights reserved. 36 * 37 * License terms: all terms for the DragonFly license above plus the following: 38 * 39 * 4. All advertising materials mentioning features or use of this software 40 * must display the following acknowledgement: 41 * 42 * This product includes software developed by Jeffrey M. Hsu 43 * for the DragonFly Project. 44 * 45 * This requirement may be waived with permission from Jeffrey Hsu. 46 * This requirement will sunset and may be removed on July 8 2005, 47 * after which the standard DragonFly license (as shown above) will 48 * apply. 49 */ 50 51 /* 52 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 53 * The Regents of the University of California. All rights reserved. 54 * 55 * Redistribution and use in source and binary forms, with or without 56 * modification, are permitted provided that the following conditions 57 * are met: 58 * 1. Redistributions of source code must retain the above copyright 59 * notice, this list of conditions and the following disclaimer. 60 * 2. Redistributions in binary form must reproduce the above copyright 61 * notice, this list of conditions and the following disclaimer in the 62 * documentation and/or other materials provided with the distribution. 63 * 3. All advertising materials mentioning features or use of this software 64 * must display the following acknowledgement: 65 * This product includes software developed by the University of 66 * California, Berkeley and its contributors. 67 * 4. Neither the name of the University nor the names of its contributors 68 * may be used to endorse or promote products derived from this software 69 * without specific prior written permission. 70 * 71 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 72 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 73 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 74 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 75 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 76 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 77 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 78 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 79 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 80 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 81 * SUCH DAMAGE. 82 * 83 * @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95 84 * $FreeBSD: src/sys/netinet/tcp_timer.c,v 1.34.2.14 2003/02/03 02:33:41 hsu Exp $ 85 * $DragonFly: src/sys/netinet/tcp_timer.c,v 1.15 2005/06/02 23:52:42 dillon Exp $ 86 */ 87 88 #include "opt_compat.h" 89 #include "opt_inet6.h" 90 #include "opt_tcpdebug.h" 91 92 #include <sys/param.h> 93 #include <sys/systm.h> 94 #include <sys/kernel.h> 95 #include <sys/mbuf.h> 96 #include <sys/sysctl.h> 97 #include <sys/socket.h> 98 #include <sys/socketvar.h> 99 #include <sys/protosw.h> 100 #include <sys/thread.h> 101 #include <sys/globaldata.h> 102 #include <sys/thread2.h> 103 104 #include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */ 105 106 #include <net/route.h> 107 108 #include <netinet/in.h> 109 #include <netinet/in_systm.h> 110 #include <netinet/in_pcb.h> 111 #ifdef INET6 112 #include <netinet6/in6_pcb.h> 113 #endif 114 #include <netinet/ip_var.h> 115 #include <netinet/tcp.h> 116 #include <netinet/tcp_fsm.h> 117 #include <netinet/tcp_seq.h> 118 #include <netinet/tcp_timer.h> 119 #include <netinet/tcp_var.h> 120 #include <netinet/tcpip.h> 121 #ifdef TCPDEBUG 122 #include <netinet/tcp_debug.h> 123 #endif 124 125 static int 126 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS) 127 { 128 int error, s, tt; 129 130 tt = *(int *)oidp->oid_arg1; 131 s = (int)((int64_t)tt * 1000 / hz); 132 133 error = sysctl_handle_int(oidp, &s, 0, req); 134 if (error || !req->newptr) 135 return (error); 136 137 tt = (int)((int64_t)s * hz / 1000); 138 if (tt < 1) 139 return (EINVAL); 140 141 *(int *)oidp->oid_arg1 = tt; 142 return (0); 143 } 144 145 int tcp_keepinit; 146 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINIT, keepinit, CTLTYPE_INT|CTLFLAG_RW, 147 &tcp_keepinit, 0, sysctl_msec_to_ticks, "I", ""); 148 149 int tcp_keepidle; 150 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPIDLE, keepidle, CTLTYPE_INT|CTLFLAG_RW, 151 &tcp_keepidle, 0, sysctl_msec_to_ticks, "I", ""); 152 153 int tcp_keepintvl; 154 SYSCTL_PROC(_net_inet_tcp, TCPCTL_KEEPINTVL, keepintvl, CTLTYPE_INT|CTLFLAG_RW, 155 &tcp_keepintvl, 0, sysctl_msec_to_ticks, "I", ""); 156 157 int tcp_delacktime; 158 SYSCTL_PROC(_net_inet_tcp, TCPCTL_DELACKTIME, delacktime, 159 CTLTYPE_INT|CTLFLAG_RW, &tcp_delacktime, 0, sysctl_msec_to_ticks, "I", 160 "Time before a delayed ACK is sent"); 161 162 int tcp_msl; 163 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl, CTLTYPE_INT|CTLFLAG_RW, 164 &tcp_msl, 0, sysctl_msec_to_ticks, "I", "Maximum segment lifetime"); 165 166 int tcp_rexmit_min; 167 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min, CTLTYPE_INT|CTLFLAG_RW, 168 &tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I", "Minimum Retransmission Timeout"); 169 170 int tcp_rexmit_slop; 171 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_slop, CTLTYPE_INT|CTLFLAG_RW, 172 &tcp_rexmit_slop, 0, sysctl_msec_to_ticks, "I", 173 "Retransmission Timer Slop"); 174 175 static int always_keepalive = 0; 176 SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive, CTLFLAG_RW, 177 &always_keepalive , 0, "Assume SO_KEEPALIVE on all TCP connections"); 178 179 static int tcp_keepcnt = TCPTV_KEEPCNT; 180 /* max idle probes */ 181 int tcp_maxpersistidle; 182 /* max idle time in persist */ 183 int tcp_maxidle; 184 185 /* 186 * Tcp protocol timeout routine called every 500 ms. 187 * Updates timestamps used for TCP 188 * causes finite state machine actions if timers expire. 189 */ 190 void 191 tcp_slowtimo(void) 192 { 193 crit_enter(); 194 tcp_maxidle = tcp_keepcnt * tcp_keepintvl; 195 crit_exit(); 196 } 197 198 /* 199 * Cancel all timers for TCP tp. 200 */ 201 void 202 tcp_canceltimers(struct tcpcb *tp) 203 { 204 callout_stop(tp->tt_2msl); 205 callout_stop(tp->tt_persist); 206 callout_stop(tp->tt_keep); 207 callout_stop(tp->tt_rexmt); 208 } 209 210 int tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] = 211 { 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 64, 64 }; 212 213 int tcp_backoff[TCP_MAXRXTSHIFT + 1] = 214 { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; 215 216 static int tcp_totbackoff = 511; /* sum of tcp_backoff[] */ 217 218 /* 219 * TCP timer processing. 220 */ 221 void 222 tcp_timer_delack(void *xtp) 223 { 224 struct tcpcb *tp = xtp; 225 226 crit_enter(); 227 if (callout_pending(tp->tt_delack) || !callout_active(tp->tt_delack)) { 228 crit_exit(); 229 return; 230 } 231 callout_deactivate(tp->tt_delack); 232 233 tp->t_flags |= TF_ACKNOW; 234 tcpstat.tcps_delack++; 235 tcp_output(tp); 236 crit_exit(); 237 } 238 239 void 240 tcp_timer_2msl(void *xtp) 241 { 242 struct tcpcb *tp = xtp; 243 #ifdef TCPDEBUG 244 int ostate; 245 246 ostate = tp->t_state; 247 #endif 248 crit_enter(); 249 if (callout_pending(tp->tt_2msl) || !callout_active(tp->tt_2msl)) { 250 crit_exit(); 251 return; 252 } 253 callout_deactivate(tp->tt_2msl); 254 /* 255 * 2 MSL timeout in shutdown went off. If we're closed but 256 * still waiting for peer to close and connection has been idle 257 * too long, or if 2MSL time is up from TIME_WAIT, delete connection 258 * control block. Otherwise, check again in a bit. 259 */ 260 if (tp->t_state != TCPS_TIME_WAIT && 261 (ticks - tp->t_rcvtime) <= tcp_maxidle) 262 callout_reset(tp->tt_2msl, tcp_keepintvl, 263 tcp_timer_2msl, tp); 264 else 265 tp = tcp_close(tp); 266 267 #ifdef TCPDEBUG 268 if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) 269 tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); 270 #endif 271 crit_exit(); 272 } 273 274 void 275 tcp_timer_keep(void *xtp) 276 { 277 struct tcpcb *tp = xtp; 278 struct tcptemp *t_template; 279 #ifdef TCPDEBUG 280 int ostate; 281 282 ostate = tp->t_state; 283 #endif 284 crit_enter(); 285 if (callout_pending(tp->tt_keep) || !callout_active(tp->tt_keep)) { 286 crit_exit(); 287 return; 288 } 289 callout_deactivate(tp->tt_keep); 290 /* 291 * Keep-alive timer went off; send something 292 * or drop connection if idle for too long. 293 */ 294 tcpstat.tcps_keeptimeo++; 295 if (tp->t_state < TCPS_ESTABLISHED) 296 goto dropit; 297 if ((always_keepalive || 298 tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) && 299 tp->t_state <= TCPS_CLOSING) { 300 if ((ticks - tp->t_rcvtime) >= tcp_keepidle + tcp_maxidle) 301 goto dropit; 302 /* 303 * Send a packet designed to force a response 304 * if the peer is up and reachable: 305 * either an ACK if the connection is still alive, 306 * or an RST if the peer has closed the connection 307 * due to timeout or reboot. 308 * Using sequence number tp->snd_una-1 309 * causes the transmitted zero-length segment 310 * to lie outside the receive window; 311 * by the protocol spec, this requires the 312 * correspondent TCP to respond. 313 */ 314 tcpstat.tcps_keepprobe++; 315 t_template = tcp_maketemplate(tp); 316 if (t_template) { 317 tcp_respond(tp, t_template->tt_ipgen, 318 &t_template->tt_t, (struct mbuf *)NULL, 319 tp->rcv_nxt, tp->snd_una - 1, 0); 320 tcp_freetemplate(t_template); 321 } 322 callout_reset(tp->tt_keep, tcp_keepintvl, tcp_timer_keep, tp); 323 } else 324 callout_reset(tp->tt_keep, tcp_keepidle, tcp_timer_keep, tp); 325 326 #ifdef TCPDEBUG 327 if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) 328 tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); 329 #endif 330 crit_exit(); 331 return; 332 333 dropit: 334 tcpstat.tcps_keepdrops++; 335 tp = tcp_drop(tp, ETIMEDOUT); 336 337 #ifdef TCPDEBUG 338 if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) 339 tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); 340 #endif 341 crit_exit(); 342 } 343 344 void 345 tcp_timer_persist(void *xtp) 346 { 347 struct tcpcb *tp = xtp; 348 #ifdef TCPDEBUG 349 int ostate; 350 351 ostate = tp->t_state; 352 #endif 353 crit_enter(); 354 if (callout_pending(tp->tt_persist) || !callout_active(tp->tt_persist)){ 355 crit_exit(); 356 return; 357 } 358 callout_deactivate(tp->tt_persist); 359 /* 360 * Persistance timer into zero window. 361 * Force a byte to be output, if possible. 362 */ 363 tcpstat.tcps_persisttimeo++; 364 /* 365 * Hack: if the peer is dead/unreachable, we do not 366 * time out if the window is closed. After a full 367 * backoff, drop the connection if the idle time 368 * (no responses to probes) reaches the maximum 369 * backoff that we would use if retransmitting. 370 */ 371 if (tp->t_rxtshift == TCP_MAXRXTSHIFT && 372 ((ticks - tp->t_rcvtime) >= tcp_maxpersistidle || 373 (ticks - tp->t_rcvtime) >= TCP_REXMTVAL(tp) * tcp_totbackoff)) { 374 tcpstat.tcps_persistdrop++; 375 tp = tcp_drop(tp, ETIMEDOUT); 376 goto out; 377 } 378 tcp_setpersist(tp); 379 tp->t_flags |= TF_FORCE; 380 tcp_output(tp); 381 tp->t_flags &= ~TF_FORCE; 382 383 out: 384 #ifdef TCPDEBUG 385 if (tp && tp->t_inpcb->inp_socket->so_options & SO_DEBUG) 386 tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); 387 #endif 388 crit_exit(); 389 } 390 391 void 392 tcp_save_congestion_state(struct tcpcb *tp) 393 { 394 tp->snd_cwnd_prev = tp->snd_cwnd; 395 tp->snd_wacked_prev = tp->snd_wacked; 396 tp->snd_ssthresh_prev = tp->snd_ssthresh; 397 tp->snd_recover_prev = tp->snd_recover; 398 if (IN_FASTRECOVERY(tp)) 399 tp->t_flags |= TF_WASFRECOVERY; 400 else 401 tp->t_flags &= ~TF_WASFRECOVERY; 402 if (tp->t_flags & TF_RCVD_TSTMP) { 403 tp->t_rexmtTS = ticks; 404 tp->t_flags |= TF_FIRSTACCACK; 405 } 406 #ifdef later 407 tcp_sack_save_scoreboard(&tp->scb); 408 #endif 409 } 410 411 void 412 tcp_revert_congestion_state(struct tcpcb *tp) 413 { 414 tp->snd_cwnd = tp->snd_cwnd_prev; 415 tp->snd_wacked = tp->snd_wacked_prev; 416 tp->snd_ssthresh = tp->snd_ssthresh_prev; 417 tp->snd_recover = tp->snd_recover_prev; 418 if (tp->t_flags & TF_WASFRECOVERY) 419 ENTER_FASTRECOVERY(tp); 420 if (tp->t_flags & TF_FASTREXMT) { 421 ++tcpstat.tcps_sndfastrexmitbad; 422 if (tp->t_flags & TF_EARLYREXMT) 423 ++tcpstat.tcps_sndearlyrexmitbad; 424 } else 425 ++tcpstat.tcps_sndrtobad; 426 tp->t_badrxtwin = 0; 427 tp->t_rxtshift = 0; 428 tp->snd_nxt = tp->snd_max; 429 #ifdef later 430 tcp_sack_revert_scoreboard(&tp->scb, tp->snd_una); 431 #endif 432 } 433 434 void 435 tcp_timer_rexmt(void *xtp) 436 { 437 struct tcpcb *tp = xtp; 438 int rexmt; 439 #ifdef TCPDEBUG 440 int ostate; 441 442 ostate = tp->t_state; 443 #endif 444 crit_enter(); 445 if (callout_pending(tp->tt_rexmt) || !callout_active(tp->tt_rexmt)) { 446 crit_exit(); 447 return; 448 } 449 callout_deactivate(tp->tt_rexmt); 450 /* 451 * Retransmission timer went off. Message has not 452 * been acked within retransmit interval. Back off 453 * to a longer retransmit interval and retransmit one segment. 454 */ 455 if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { 456 tp->t_rxtshift = TCP_MAXRXTSHIFT; 457 tcpstat.tcps_timeoutdrop++; 458 tp = tcp_drop(tp, tp->t_softerror ? 459 tp->t_softerror : ETIMEDOUT); 460 goto out; 461 } 462 if (tp->t_rxtshift == 1) { 463 /* 464 * first retransmit; record ssthresh and cwnd so they can 465 * be recovered if this turns out to be a "bad" retransmit. 466 * A retransmit is considered "bad" if an ACK for this 467 * segment is received within RTT/2 interval; the assumption 468 * here is that the ACK was already in flight. See 469 * "On Estimating End-to-End Network Path Properties" by 470 * Allman and Paxson for more details. 471 */ 472 tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1)); 473 tcp_save_congestion_state(tp); 474 tp->t_flags &= ~(TF_FASTREXMT | TF_EARLYREXMT); 475 } 476 /* Throw away SACK blocks on a RTO, as specified by RFC2018. */ 477 tcp_sack_cleanup(&tp->scb); 478 tcpstat.tcps_rexmttimeo++; 479 if (tp->t_state == TCPS_SYN_SENT) 480 rexmt = TCP_REXMTVAL(tp) * tcp_syn_backoff[tp->t_rxtshift]; 481 else 482 rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; 483 TCPT_RANGESET(tp->t_rxtcur, rexmt, 484 tp->t_rttmin, TCPTV_REXMTMAX); 485 /* 486 * Disable rfc1323 and rfc1644 if we havn't got any response to 487 * our third SYN to work-around some broken terminal servers 488 * (most of which have hopefully been retired) that have bad VJ 489 * header compression code which trashes TCP segments containing 490 * unknown-to-them TCP options. 491 */ 492 if ((tp->t_state == TCPS_SYN_SENT) && (tp->t_rxtshift == 3)) 493 tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_REQ_CC); 494 /* 495 * If losing, let the lower level know and try for 496 * a better route. Also, if we backed off this far, 497 * our srtt estimate is probably bogus. Clobber it 498 * so we'll take the next rtt measurement as our srtt; 499 * move the current srtt into rttvar to keep the current 500 * retransmit times until then. 501 */ 502 if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { 503 #ifdef INET6 504 if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) 505 in6_losing(tp->t_inpcb); 506 else 507 #endif 508 in_losing(tp->t_inpcb); 509 tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); 510 tp->t_srtt = 0; 511 } 512 tp->snd_nxt = tp->snd_una; 513 tp->rexmt_high = tp->snd_una; 514 tp->snd_recover = tp->snd_max; 515 /* 516 * Force a segment to be sent. 517 */ 518 tp->t_flags |= TF_ACKNOW; 519 /* 520 * If timing a segment in this window, stop the timer. 521 */ 522 tp->t_rtttime = 0; 523 /* 524 * Close the congestion window down to one segment 525 * (we'll open it by one segment for each ack we get). 526 * Since we probably have a window's worth of unacked 527 * data accumulated, this "slow start" keeps us from 528 * dumping all that data as back-to-back packets (which 529 * might overwhelm an intermediate gateway). 530 * 531 * There are two phases to the opening: Initially we 532 * open by one mss on each ack. This makes the window 533 * size increase exponentially with time. If the 534 * window is larger than the path can handle, this 535 * exponential growth results in dropped packet(s) 536 * almost immediately. To get more time between 537 * drops but still "push" the network to take advantage 538 * of improving conditions, we switch from exponential 539 * to linear window opening at some threshhold size. 540 * For a threshhold, we use half the current window 541 * size, truncated to a multiple of the mss. 542 * 543 * (the minimum cwnd that will give us exponential 544 * growth is 2 mss. We don't allow the threshhold 545 * to go below this.) 546 */ 547 { 548 u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; 549 550 if (win < 2) 551 win = 2; 552 tp->snd_cwnd = tp->t_maxseg; 553 tp->snd_wacked = 0; 554 tp->snd_ssthresh = win * tp->t_maxseg; 555 tp->t_dupacks = 0; 556 } 557 EXIT_FASTRECOVERY(tp); 558 tcp_output(tp); 559 560 out: 561 #ifdef TCPDEBUG 562 if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) 563 tcp_trace(TA_USER, ostate, tp, NULL, NULL, PRU_SLOWTIMO); 564 #endif 565 crit_exit(); 566 } 567