// tcp_ack() 函数处理接收到的 ack 报文 // tcp_ack() 函数中调用 tcp_clean_rtx_queue() 来将已经 ack 的报文从重传队列中移除, // 同时对 tp->packets_out 做减法 // tcp_clean_rtx_queue() 中会判断是不是有新的报文被确认, // 如果是,则返回的 flag 中包含 FLAG_SET_XMIT_TIMER 标志 /...
A:tcp_clean_rtx_queue() is called to remove and free the acknowledged packets from the retransmit queue, and packets_out is decremented by the number of freed packets. /* Remove acknowledged frames from the retransmission queue. * If our packet is before the ack sequence we can discard it ...
在tcp_clean_rtx_queue()中,并非对每个ACK都进行时延采样。是否进行时延采样,跟这个ACK是否为 重复的ACK、这个ACK是否确认了重传包,以及是否使用时间戳选项都有关系。 本文主要内容:tcp_clean_rtx_queue()的一些细节,时延采样的条件。 内核版本:3.2.12 Author:zhangskd @ csdn 记分牌 TCP_SKB_CB(skb)->sacked...
icsk->icsk_accept_queue.rskq_defer_accept || icsk->icsk_ack.pingpong) //延迟确认... else{ tcp_send_ack(sk); } } tcp_ack()->tcp_clean_rtx_queue() //file: net/ipv4/tcp_input.c staticinttcp_clean_rtx_queue(struct sock *sk,intprior_...
埃里克的patch只优化了接收端,对于发送端处理ACK时的行为,也有一个耗时的kfree_skb,即tcp_clean_rtx_queue函数中清理重传队列后的free操作: staticinttcp_clean_rtx_queue(structsock*sk,u32prior_fack,u32prior_snd_una,structtcp_sacktag_state*sack){...for(skb=skb_rb_first(&sk->tcp_rtx_queue);skb...
reqsk_queue_alloc函数中计算了半连接队列的长度,因为有些复杂所以没有在前面展开,这里深入一下。 int reqsk_queue_alloc(struct request_sock_queue *queue, unsigend int nr_table_entries){// 计算半连接队列的长度nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog);nr_table_...
tcp_rcv_established->tcp_ack->tcp_clean_rtx_queue->tcp_ack_update_rtt->tcp_set_rto image.png 重传定时器初始化 重传定时器的值类型为ICSK_TIME_RETRANS icsk_retransmit_timer在inet_csk_init_xmit_timers函数中被初始化: /* * Using different timers for retransmit, delayed acks and probes ...
如果能正常接收到服务器响应的 synack,那么客户端的这个定时器会清除。这段逻辑在 tcp_rearm_rto 里。(tcp_rcv_state_process -> tcp_rcv_synsent_state_process -> tcp_ack -> tcp_clean_rtx_queue -> tcp_rearm_rto) 复制 //file:net/ipv4/tcp_input.cvoid tcp_rearm_rto(struct sock *sk){inet...
最后我们来看tcp_clean_rtx_queue函数,这个函数主要用于清理发送队列中已经被ack的数据段。函数比较大,我们来分段看。 这里有使用karn算法,也就是如果重传的段,则计算rto的话,不采样这次的值。 还有就是要判断是syn的ack回复,还是数据的ack回复。以及sack的判断。
tcp_ack()->tcp_clean_rtx_queue() 客户端修改自己的 socket 状态为 ESTABLISHED,接着打开 TCP 的保活计时器。 在tcp_send_ack 中构造 ack 包,并把它发送了出去。 客户端响应来自服务器端的 synack 时清除了 connect 时设置的重传定时器,把当前 socket 状态设置为 ESTABLISHED,开启保活计时器后发出...