162306a36Sopenharmony_ci#ifndef _TCP_DCTCP_H
262306a36Sopenharmony_ci#define _TCP_DCTCP_H
362306a36Sopenharmony_ci
462306a36Sopenharmony_cistatic inline void dctcp_ece_ack_cwr(struct sock *sk, u32 ce_state)
562306a36Sopenharmony_ci{
662306a36Sopenharmony_ci	struct tcp_sock *tp = tcp_sk(sk);
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci	if (ce_state == 1)
962306a36Sopenharmony_ci		tp->ecn_flags |= TCP_ECN_DEMAND_CWR;
1062306a36Sopenharmony_ci	else
1162306a36Sopenharmony_ci		tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR;
1262306a36Sopenharmony_ci}
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/* Minimal DCTP CE state machine:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * S:	0 <- last pkt was non-CE
1762306a36Sopenharmony_ci *	1 <- last pkt was CE
1862306a36Sopenharmony_ci */
1962306a36Sopenharmony_cistatic inline void dctcp_ece_ack_update(struct sock *sk, enum tcp_ca_event evt,
2062306a36Sopenharmony_ci					u32 *prior_rcv_nxt, u32 *ce_state)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	u32 new_ce_state = (evt == CA_EVENT_ECN_IS_CE) ? 1 : 0;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	if (*ce_state != new_ce_state) {
2562306a36Sopenharmony_ci		/* CE state has changed, force an immediate ACK to
2662306a36Sopenharmony_ci		 * reflect the new CE state. If an ACK was delayed,
2762306a36Sopenharmony_ci		 * send that first to reflect the prior CE state.
2862306a36Sopenharmony_ci		 */
2962306a36Sopenharmony_ci		if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER) {
3062306a36Sopenharmony_ci			dctcp_ece_ack_cwr(sk, *ce_state);
3162306a36Sopenharmony_ci			__tcp_send_ack(sk, *prior_rcv_nxt);
3262306a36Sopenharmony_ci		}
3362306a36Sopenharmony_ci		inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
3462306a36Sopenharmony_ci	}
3562306a36Sopenharmony_ci	*prior_rcv_nxt = tcp_sk(sk)->rcv_nxt;
3662306a36Sopenharmony_ci	*ce_state = new_ce_state;
3762306a36Sopenharmony_ci	dctcp_ece_ack_cwr(sk, new_ce_state);
3862306a36Sopenharmony_ci}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#endif
41