标签:
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