* If a keepalive goes off, we had no other timers * happening. We always return 1 here since this * routine either drops the connection or sends * out a segment with respond. */
| 5433 | * out a segment with respond. |
| 5434 | */ |
| 5435 | static int |
| 5436 | rack_timeout_keepalive(struct tcpcb *tp, struct tcp_rack *rack, uint32_t cts) |
| 5437 | { |
| 5438 | struct tcptemp *t_template; |
| 5439 | struct inpcb *inp; |
| 5440 | |
| 5441 | if (tp->t_timers->tt_flags & TT_STOPPED) { |
| 5442 | return (1); |
| 5443 | } |
| 5444 | rack->r_ctl.rc_hpts_flags &= ~PACE_TMR_KEEP; |
| 5445 | inp = tp->t_inpcb; |
| 5446 | rack_log_to_event(rack, RACK_TO_FRM_KEEP, NULL); |
| 5447 | /* |
| 5448 | * Keep-alive timer went off; send something or drop connection if |
| 5449 | * idle for too long. |
| 5450 | */ |
| 5451 | KMOD_TCPSTAT_INC(tcps_keeptimeo); |
| 5452 | if (tp->t_state < TCPS_ESTABLISHED) |
| 5453 | goto dropit; |
| 5454 | if ((V_tcp_always_keepalive || inp->inp_socket->so_options & SO_KEEPALIVE) && |
| 5455 | tp->t_state <= TCPS_CLOSING) { |
| 5456 | if (ticks - tp->t_rcvtime >= TP_KEEPIDLE(tp) + TP_MAXIDLE(tp)) |
| 5457 | goto dropit; |
| 5458 | /* |
| 5459 | * Send a packet designed to force a response if the peer is |
| 5460 | * up and reachable: either an ACK if the connection is |
| 5461 | * still alive, or an RST if the peer has closed the |
| 5462 | * connection due to timeout or reboot. Using sequence |
| 5463 | * number tp->snd_una-1 causes the transmitted zero-length |
| 5464 | * segment to lie outside the receive window; by the |
| 5465 | * protocol spec, this requires the correspondent TCP to |
| 5466 | * respond. |
| 5467 | */ |
| 5468 | KMOD_TCPSTAT_INC(tcps_keepprobe); |
| 5469 | t_template = tcpip_maketemplate(inp); |
| 5470 | if (t_template) { |
| 5471 | if (rack->forced_ack == 0) { |
| 5472 | rack->forced_ack = 1; |
| 5473 | rack->r_ctl.forced_ack_ts = tcp_get_usecs(NULL); |
| 5474 | } |
| 5475 | tcp_respond(tp, t_template->tt_ipgen, |
| 5476 | &t_template->tt_t, (struct mbuf *)NULL, |
| 5477 | tp->rcv_nxt, tp->snd_una - 1, 0); |
| 5478 | free(t_template, M_TEMP); |
| 5479 | } |
| 5480 | } |
| 5481 | rack_start_hpts_timer(rack, tp, cts, 0, 0, 0); |
| 5482 | return (1); |
| 5483 | dropit: |
| 5484 | KMOD_TCPSTAT_INC(tcps_keepdrops); |
| 5485 | tcp_log_end_status(tp, TCP_EI_STATUS_KEEP_MAX); |
| 5486 | tcp_set_inp_to_drop(rack->rc_inp, ETIMEDOUT); |
| 5487 | return (1); |
| 5488 | } |
| 5489 | |
| 5490 | /* |
| 5491 | * Retransmit helper function, clear up all the ack |
no test coverage detected