日期:2014-05-16 浏览次数:21053 次
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)
};