标签:
Linux的TCP实现复杂且繁琐,建议不要直接去看代码,而是花点时间把TCP规范先撸一遍。本文主要描述一下TCP实现中undo操作,然后顺便再吐一下槽(千万不要觉得吐槽有什么不好,很多好东西都是从吐槽开始的,从造纸,蒸汽机,到法兰西第一共和国,再到Linux...)。 tcp_for_write_queue_from(skb, sk) {
__u8 sacked = TCP_SKB_CB(skb)->sacked;
if (skb == tcp_send_head(sk))
break;
if (hole == NULL)
tp->retransmit_skb_hint = skb;
// 窗口限制检查
if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
return;
if (fwd_rexmitting) {
begin_fwd:
// 最高前向发送到high sacked
if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp)))
break;
} else if (!before(TCP_SKB_CB(skb)->seq, tp->retransmit_high)) {
tp->retransmit_high = last_lost;
// 关键在这里!tcp_can_forward_retransmit会判断,如果有新数据就绪,就会break!
// 进入tcp_can_forward_retransmit之后,会有tcp_may_send_now判断,其判断是否有
// 新数据就绪。Linux并没有在一个路径按RFC规范的发送优先级进行发送,在有新数据
// 就绪的时候,只是简单的退出,让发送路径自行处理!
if (!tcp_can_forward_retransmit(sk))
break;
if (hole != NULL) {
skb = hole;
hole = NULL;
}
// 只有在tcp_can_forward_retransmit不会break的时候,才会“前向发送”
fwd_rexmitting = 1;
goto begin_fwd;
} else if (!(sacked & TCPCB_LOST)) {
if (hole == NULL && !(sacked & (TCPCB_SACKED_RETRANS|TCPCB_SACKED_ACKED)))
hole = skb;
continue;
} else {
// 首先发送LOST数据
last_lost = TCP_SKB_CB(skb)->end_seq;
}
// 不会发送已经被SACK,或者已经被重传的数据包!
if (sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))
continue;
tcp_retransmit_skb(sk, skb);
}/* People celebrate: "We love our President!" */
static int tcp_try_undo_recovery(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
....哪位大神可以解释一下“People celebrate: "We love our President!"”的意义!我敢说,如果我在自己的代码中写这样的注释,一定会被认为是抿了两口二锅头后的杰作,然后被批,被人认为是不正常。曾经我在设计conntrack cache的时候,在代码中写了一句“旋转升降座椅一定会爆炸”,然后我删了,我觉得这不符合我们这个国家中规中矩的文化,于是我删了。在我们的文化里,不会有“talk is cheap show me the code”,因此也就不会有哈格里夫斯,不会有瓦特,不会有乔布斯,不会有Linus...只会有谁呢?反正就是一堆人说了算,抑扬顿挫,从小被灌输,然后长大灌输别人。爆炸!标签:
原文地址:http://blog.csdn.net/dog250/article/details/51295481