Yuchung Cheng | ffd177d | 2018-10-08 15:32:20 -0700 | [diff] [blame] | 1 | #ifndef _TCP_DCTCP_H |
| 2 | #define _TCP_DCTCP_H |
| 3 | |
| 4 | static inline void dctcp_ece_ack_cwr(struct sock *sk, u32 ce_state) |
| 5 | { |
| 6 | struct tcp_sock *tp = tcp_sk(sk); |
| 7 | |
| 8 | if (ce_state == 1) |
| 9 | tp->ecn_flags |= TCP_ECN_DEMAND_CWR; |
| 10 | else |
| 11 | tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR; |
| 12 | } |
| 13 | |
| 14 | /* Minimal DCTP CE state machine: |
| 15 | * |
| 16 | * S: 0 <- last pkt was non-CE |
| 17 | * 1 <- last pkt was CE |
| 18 | */ |
| 19 | static inline void dctcp_ece_ack_update(struct sock *sk, enum tcp_ca_event evt, |
| 20 | u32 *prior_rcv_nxt, u32 *ce_state) |
| 21 | { |
| 22 | u32 new_ce_state = (evt == CA_EVENT_ECN_IS_CE) ? 1 : 0; |
| 23 | |
| 24 | if (*ce_state != new_ce_state) { |
| 25 | /* CE state has changed, force an immediate ACK to |
| 26 | * reflect the new CE state. If an ACK was delayed, |
| 27 | * send that first to reflect the prior CE state. |
| 28 | */ |
| 29 | if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER) { |
| 30 | dctcp_ece_ack_cwr(sk, *ce_state); |
| 31 | __tcp_send_ack(sk, *prior_rcv_nxt); |
| 32 | } |
| 33 | inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW; |
| 34 | } |
| 35 | *prior_rcv_nxt = tcp_sk(sk)->rcv_nxt; |
| 36 | *ce_state = new_ce_state; |
| 37 | dctcp_ece_ack_cwr(sk, new_ce_state); |
| 38 | } |
| 39 | |
| 40 | #endif |