日期:2014-05-16 浏览次数:20919 次
if (likely((tcb->flags & TCPCB_FLAG_SYN) == 0)) TCP_ECN_send(sk, skb, tcp_header_size);
//支持 #define INET_ECN_xmit(sk) do { inet_sk(sk)->tos |= INET_ECN_ECT_0; } while (0) //不支持 #define INET_ECN_dontxmit(sk) \ do { inet_sk(sk)->tos &= ~INET_ECN_MASK; } while (0)
enum { //发送端不支持ecn INET_ECN_NOT_ECT = 0, //下面这个貌似没有用到,不知道有什么意义。 INET_ECN_ECT_1 = 1, //发送端支持ecn INET_ECN_ECT_0 = 2, //发生了拥塞 INET_ECN_CE = 3, //掩码 INET_ECN_MASK = 3, };
static inline int IP_ECN_set_ce(struct iphdr *iph) { u32 check = (__force u32)iph->check; u32 ecn = (iph->tos + 1) & INET_ECN_MASK; /* * After the last operation we have (in binary): * INET_ECN_NOT_ECT => 01 * INET_ECN_ECT_1 => 10 * INET_ECN_ECT_0 => 11 * INET_ECN_CE => 00 */ //可以看到如果没有发生拥塞或者说不支持ecn的话直接返回。 if (!(ecn & 2)) return !ecn; /* * The following gives us: * INET_ECN_ECT_1 => check += htons(0xFFFD) * INET_ECN_ECT_0 => check += htons(0xFFFE) */ ///然后开始计算对应的域。 check += (__force u16)htons(0xFFFB) + (__force u16)htons(ecn); iph->check = (__force __sum16)(check + (check>=0xFFFF)); //设置tos为 INET_ECN_CE从而通知对端。 iph->tos |= INET_ECN_CE; return 1; }
static inline void TCP_ECN_check_ce(struct tcp_sock *tp, struct sk_buff *skb) { if (tp->ecn_flags & TCP_ECN_OK) { //如果发生了拥塞,则设置flags。 if (INET_ECN_is_ce(TCP_SKB_CB(skb)->flags)) tp->ecn_flags |= TCP_ECN_DEMAND_CWR; /* Funny extension: if ECT is not set on a segment, * it is surely retransmit. It is not in ECN RFC, * but Linux follows this rule. */ else if (INET_ECN_is_not_ect((TCP_SKB_CB(skb)->flags))) tcp_enter_quickack_mode((struct sock *)tp); } }
enum tcp_ca_state { TCP_CA_Open = 0, #define TCPF_CA_Open (1<<TCP_CA_Open) TCP_CA_Disorder = 1, #define TCPF_CA_Disorder (1<<TCP_CA_Disorder) TCP_CA_CWR = 2, #define TCPF_CA_CWR (1<<TCP_CA_CWR) TCP_CA_Recovery = 3, #define TCPF_CA_Recovery (1<<TCP_CA_Recovery) TCP_CA_Loss = 4 #define TCPF_CA_Loss (1<<TCP_CA_Loss) };