mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-19 15:33:56 +00:00
tcp: add conservative d.cep accounting algorithm
Accurate ECN asks to conservatively estimate, when the ACE counter may have wrapped due to a single ACK covering a larger number of segments. This is described in Annex A.2 of the accurate-ecn draft. Event: IETF 115 Hackathon Reviewed By: tuexen, #transport Sponsored by: NetApp, Inc. Differential Revision: https://reviews.freebsd.org/D37281
This commit is contained in:
parent
22c81cc516
commit
b1258b7643
@ -271,9 +271,9 @@ tcp_ecn_input_parallel_syn(struct tcpcb *tp, uint16_t thflags, int iptos)
|
||||
* TCP ECN processing.
|
||||
*/
|
||||
int
|
||||
tcp_ecn_input_segment(struct tcpcb *tp, uint16_t thflags, int iptos)
|
||||
tcp_ecn_input_segment(struct tcpcb *tp, uint16_t thflags, int tlen, int pkts, int iptos)
|
||||
{
|
||||
int delta_ace = 0;
|
||||
int delta_cep = 0;
|
||||
|
||||
if (tp->t_flags2 & (TF2_ECN_PERMIT | TF2_ACE_PERMIT)) {
|
||||
switch (iptos & IPTOS_ECN_MASK) {
|
||||
@ -292,9 +292,12 @@ tcp_ecn_input_segment(struct tcpcb *tp, uint16_t thflags, int iptos)
|
||||
if ((iptos & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
|
||||
tp->t_rcep += 1;
|
||||
if (tp->t_flags2 & TF2_ECN_PERMIT) {
|
||||
delta_ace = (tcp_ecn_get_ace(thflags) + 8 -
|
||||
(tp->t_scep & 0x07)) & 0x07;
|
||||
tp->t_scep += delta_ace;
|
||||
delta_cep = (tcp_ecn_get_ace(thflags) + 8 -
|
||||
(tp->t_scep & 7)) & 7;
|
||||
if (delta_cep < pkts)
|
||||
delta_cep = pkts -
|
||||
((pkts - delta_cep) & 7);
|
||||
tp->t_scep += delta_cep;
|
||||
} else {
|
||||
/*
|
||||
* process the final ACK of the 3WHS
|
||||
@ -326,7 +329,7 @@ tcp_ecn_input_segment(struct tcpcb *tp, uint16_t thflags, int iptos)
|
||||
} else {
|
||||
/* RFC3168 ECN handling */
|
||||
if ((thflags & (TH_SYN | TH_ECE)) == TH_ECE) {
|
||||
delta_ace = 1;
|
||||
delta_cep = 1;
|
||||
tp->t_scep++;
|
||||
}
|
||||
if (thflags & TH_CWR) {
|
||||
@ -341,7 +344,7 @@ tcp_ecn_input_segment(struct tcpcb *tp, uint16_t thflags, int iptos)
|
||||
cc_ecnpkt_handler_flags(tp, thflags, iptos);
|
||||
}
|
||||
|
||||
return delta_ace;
|
||||
return delta_cep;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
void tcp_ecn_input_syn_sent(struct tcpcb *, uint16_t, int);
|
||||
void tcp_ecn_input_parallel_syn(struct tcpcb *, uint16_t, int);
|
||||
int tcp_ecn_input_segment(struct tcpcb *, uint16_t, int);
|
||||
int tcp_ecn_input_segment(struct tcpcb *, uint16_t, int, int, int);
|
||||
uint16_t tcp_ecn_output_syn_sent(struct tcpcb *);
|
||||
int tcp_ecn_output_established(struct tcpcb *, uint16_t *, int, bool);
|
||||
void tcp_ecn_syncache_socket(struct tcpcb *, struct syncache *);
|
||||
|
@ -1627,7 +1627,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
|
||||
/*
|
||||
* TCP ECN processing.
|
||||
*/
|
||||
if (tcp_ecn_input_segment(tp, thflags, iptos))
|
||||
if (tcp_ecn_input_segment(tp, thflags, tlen,
|
||||
tcp_packets_this_ack(tp, th->th_ack),
|
||||
iptos))
|
||||
cc_cong_signal(tp, th, CC_ECN);
|
||||
|
||||
/*
|
||||
|
@ -13528,8 +13528,10 @@ rack_do_compressed_ack_processing(struct tcpcb *tp, struct socket *so, struct mb
|
||||
rack_cc_after_idle(rack, tp);
|
||||
}
|
||||
tp->t_rcvtime = ticks;
|
||||
/* Now what about ECN? */
|
||||
if (tcp_ecn_input_segment(tp, ae->flags, ae->codepoint))
|
||||
/* Now what about ECN of a chain of pure ACKs? */
|
||||
if (tcp_ecn_input_segment(tp, ae->flags, 0,
|
||||
tcp_packets_this_ack(tp, ae->ack),
|
||||
ae->codepoint))
|
||||
rack_cong_signal(tp, CC_ECN, ae->ack, __LINE__);
|
||||
#ifdef TCP_ACCOUNTING
|
||||
/* Count for the specific type of ack in */
|
||||
@ -14320,7 +14322,9 @@ rack_do_segment_nounlock(struct mbuf *m, struct tcphdr *th, struct socket *so,
|
||||
* TCP ECN processing. XXXJTL: If we ever use ECN, we need to move
|
||||
* this to occur after we've validated the segment.
|
||||
*/
|
||||
if (tcp_ecn_input_segment(tp, thflags, iptos))
|
||||
if (tcp_ecn_input_segment(tp, thflags, tlen,
|
||||
tcp_packets_this_ack(tp, th->th_ack),
|
||||
iptos))
|
||||
rack_cong_signal(tp, CC_ECN, th->th_ack, __LINE__);
|
||||
|
||||
/*
|
||||
|
@ -551,6 +551,12 @@ tcp_unlock_or_drop(struct tcpcb *tp, int tcp_output_retval)
|
||||
#endif
|
||||
|
||||
#define BYTES_THIS_ACK(tp, th) (th->th_ack - tp->snd_una)
|
||||
static int inline
|
||||
tcp_packets_this_ack(struct tcpcb *tp, tcp_seq ack)
|
||||
{
|
||||
return ((ack - tp->snd_una) / tp->t_maxseg +
|
||||
((((ack - tp->snd_una) % tp->t_maxseg) != 0) ? 1 : 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Flags for the t_oobflags field.
|
||||
|
Loading…
Reference in New Issue
Block a user