1.tcp_init_xmit_timers()
void tcp_init_xmit_timers(struct sock *sk)
{
inet_csk_init_xmit_timers(sk, &tcp_write_timer, &tcp_delack_timer,
&tcp_keepalive_timer);
}
2.tcp_write_timer()
static void tcp_write_timer(unsigned long data)
{
if (!sock_owned_by_user(sk)) {
tcp_write_timer_handler(sk);
}
}
3.tcp_write_timer_handler()
void tcp_write_timer_handler(struct sock *sk)
{
switch (event) {
case ICSK_TIME_LOSS_PROBE:
tcp_send_loss_probe(sk);
break;
case ICSK_TIME_RETRANS:
icsk->icsk_pending = 0;
tcp_retransmit_timer(sk);
break;
}
}
4.tcp_retransmit_timer()
/*
* The TCP retransmit timer.
*/
void tcp_retransmit_timer(struct sock *sk)
{
tcp_enter_loss(sk, 0);
tcp_retransmit_skb(sk, tcp_write_queue_head(sk));
}
5.tcp_enter_loss()
/* Enter Loss state. If "how" is not zero, forget all SACK information
* and reset tags completely, otherwise preserve SACKs. If receiver
* dropped its ofo queue, we will know this due to reneging detection.
*/
void tcp_enter_loss(struct sock *sk, int how)
{
tcp_set_ca_state(sk, TCP_CA_Loss);
}
6.tcp_ack()
/* This routine deals with incoming acks, but not outgoing ones. */
static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
{
tcp_fastretrans_alert(sk, acked, prior_unsacked,is_dupack, flag);
}
7.tcp_fastretrans_alert()
/* Process an event, which can update packets-in-flight not trivially.
* Main goal of this function is to calculate new estimate for left_out,
* taking into account both packets sitting in receiver's buffer and
* packets lost by network.
*
* Besides that it does CWND reduction, when packet loss is detected
* and changes state of machine.
*
* It does _not_ decide what to send, it is made in function
* tcp_xmit_retransmit_queue().
*/
static void tcp_fastretrans_alert(struct sock *sk, const int acked,const int prior_unsacked,
bool is_dupack, int flag)
{
case TCP_CA_Loss:
tcp_process_loss(sk, flag, is_dupack);
if (icsk->icsk_ca_state != TCP_CA_Open)
return;
}
8.tcp_process_loss()
/* Process an ACK in CA_Loss state. Move to CA_Open if lost data are
* recovered or spurious. Otherwise retransmits more on partial ACKs.
*/
static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
{
tcp_xmit_retransmit_queue(sk);
}
9.tcp_xmit_retransmit_queue()
/* This gets called after a retransmit timeout, and the initially
* retransmitted data is acknowledged. It tries to continue
* resending the rest of the retransmit queue, until either
* we've sent it all or the congestion window limit is reached.
* If doing SACK, the first ACK which comes back for a timeout
* based retransmit packet might feed us FACK information again.
* If so, we use it to avoid unnecessarily retransmissions.
*/
void tcp_xmit_retransmit_queue(struct sock *sk)
{
tcp_for_write_queue_from(skb, sk) {
if (tcp_retransmit_skb(sk, skb))
return;
}
}
Note:
1.丢失一组数据,则调用tcp_retransmit_skb传输即可
2.丢失N组数据,则在调用tcp_retransmit_skb重传之后,在成功接收到ack后,又会再进一步传输丢失的数据
3.实验手法:在传输数据时,单纯的断掉客户端以到达超时的目的=-=
阅读(2406) | 评论(0) | 转发(0) |