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