Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | #ifndef _NET_TCP_ECN_H_ |
2 | #define _NET_TCP_ECN_H_ 1 | |
3 | ||
4 | #include <net/inet_ecn.h> | |
5 | ||
6 | #define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH)) | |
7 | ||
8 | #define TCP_ECN_OK 1 | |
9 | #define TCP_ECN_QUEUE_CWR 2 | |
10 | #define TCP_ECN_DEMAND_CWR 4 | |
11 | ||
12 | static inline void TCP_ECN_queue_cwr(struct tcp_sock *tp) | |
13 | { | |
14 | if (tp->ecn_flags&TCP_ECN_OK) | |
15 | tp->ecn_flags |= TCP_ECN_QUEUE_CWR; | |
16 | } | |
17 | ||
18 | ||
19 | /* Output functions */ | |
20 | ||
21 | static inline void TCP_ECN_send_synack(struct tcp_sock *tp, | |
22 | struct sk_buff *skb) | |
23 | { | |
24 | TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_CWR; | |
25 | if (!(tp->ecn_flags&TCP_ECN_OK)) | |
26 | TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_ECE; | |
27 | } | |
28 | ||
29 | static inline void TCP_ECN_send_syn(struct sock *sk, struct tcp_sock *tp, | |
30 | struct sk_buff *skb) | |
31 | { | |
32 | tp->ecn_flags = 0; | |
33 | if (sysctl_tcp_ecn && !(sk->sk_route_caps & NETIF_F_TSO)) { | |
34 | TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE|TCPCB_FLAG_CWR; | |
35 | tp->ecn_flags = TCP_ECN_OK; | |
36 | sock_set_flag(sk, SOCK_NO_LARGESEND); | |
37 | } | |
38 | } | |
39 | ||
40 | static __inline__ void | |
41 | TCP_ECN_make_synack(struct open_request *req, struct tcphdr *th) | |
42 | { | |
43 | if (req->ecn_ok) | |
44 | th->ece = 1; | |
45 | } | |
46 | ||
47 | static inline void TCP_ECN_send(struct sock *sk, struct tcp_sock *tp, | |
48 | struct sk_buff *skb, int tcp_header_len) | |
49 | { | |
50 | if (tp->ecn_flags & TCP_ECN_OK) { | |
51 | /* Not-retransmitted data segment: set ECT and inject CWR. */ | |
52 | if (skb->len != tcp_header_len && | |
53 | !before(TCP_SKB_CB(skb)->seq, tp->snd_nxt)) { | |
54 | INET_ECN_xmit(sk); | |
55 | if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) { | |
56 | tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; | |
57 | skb->h.th->cwr = 1; | |
58 | } | |
59 | } else { | |
60 | /* ACK or retransmitted segment: clear ECT|CE */ | |
61 | INET_ECN_dontxmit(sk); | |
62 | } | |
63 | if (tp->ecn_flags & TCP_ECN_DEMAND_CWR) | |
64 | skb->h.th->ece = 1; | |
65 | } | |
66 | } | |
67 | ||
68 | /* Input functions */ | |
69 | ||
70 | static inline void TCP_ECN_accept_cwr(struct tcp_sock *tp, struct sk_buff *skb) | |
71 | { | |
72 | if (skb->h.th->cwr) | |
73 | tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR; | |
74 | } | |
75 | ||
76 | static inline void TCP_ECN_withdraw_cwr(struct tcp_sock *tp) | |
77 | { | |
78 | tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR; | |
79 | } | |
80 | ||
81 | static inline void TCP_ECN_check_ce(struct tcp_sock *tp, struct sk_buff *skb) | |
82 | { | |
83 | if (tp->ecn_flags&TCP_ECN_OK) { | |
84 | if (INET_ECN_is_ce(TCP_SKB_CB(skb)->flags)) | |
85 | tp->ecn_flags |= TCP_ECN_DEMAND_CWR; | |
86 | /* Funny extension: if ECT is not set on a segment, | |
87 | * it is surely retransmit. It is not in ECN RFC, | |
88 | * but Linux follows this rule. */ | |
89 | else if (INET_ECN_is_not_ect((TCP_SKB_CB(skb)->flags))) | |
90 | tcp_enter_quickack_mode(tp); | |
91 | } | |
92 | } | |
93 | ||
94 | static inline void TCP_ECN_rcv_synack(struct tcp_sock *tp, struct tcphdr *th) | |
95 | { | |
96 | if ((tp->ecn_flags&TCP_ECN_OK) && (!th->ece || th->cwr)) | |
97 | tp->ecn_flags &= ~TCP_ECN_OK; | |
98 | } | |
99 | ||
100 | static inline void TCP_ECN_rcv_syn(struct tcp_sock *tp, struct tcphdr *th) | |
101 | { | |
102 | if ((tp->ecn_flags&TCP_ECN_OK) && (!th->ece || !th->cwr)) | |
103 | tp->ecn_flags &= ~TCP_ECN_OK; | |
104 | } | |
105 | ||
106 | static inline int TCP_ECN_rcv_ecn_echo(struct tcp_sock *tp, struct tcphdr *th) | |
107 | { | |
108 | if (th->ece && !th->syn && (tp->ecn_flags&TCP_ECN_OK)) | |
109 | return 1; | |
110 | return 0; | |
111 | } | |
112 | ||
113 | static inline void TCP_ECN_openreq_child(struct tcp_sock *tp, | |
114 | struct open_request *req) | |
115 | { | |
116 | tp->ecn_flags = req->ecn_ok ? TCP_ECN_OK : 0; | |
117 | } | |
118 | ||
119 | static __inline__ void | |
120 | TCP_ECN_create_request(struct open_request *req, struct tcphdr *th) | |
121 | { | |
122 | if (sysctl_tcp_ecn && th->ece && th->cwr) | |
123 | req->ecn_ok = 1; | |
124 | } | |
125 | ||
126 | #endif |