diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4 --- a/share/man/man4/tcp.4 +++ b/share/man/man4/tcp.4 @@ -34,7 +34,7 @@ .\" From: @(#)tcp.4 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd October 7, 2022 +.Dd November 7, 2022 .Dt TCP 4 .Os .Sh NAME @@ -520,6 +520,9 @@ specific connection. This is needed to help with connection establishment when a broken firewall is in the network path. +.It Va ecn.option +Reflect back the number of received bytes with a particular ECN marking +by using the Accurate ECN TCP option on each outgoing packet. .It Va fast_finwait2_recycle Recycle .Tn TCP diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h --- a/sys/netinet/tcp.h +++ b/sys/netinet/tcp.h @@ -104,6 +104,10 @@ #define TCPOLEN_SIGNATURE 18 #define TCPOPT_FAST_OPEN 34 #define TCPOLEN_FAST_OPEN_EMPTY 2 +#define TCPOPT_ACCECN0 0xAC +#define TCPOPT_ACCECN1 0XAE +#define TCPOLEN_ACCECN_EMPTY 2 +#define TCPOLEN_ACCECN_COUNTER 3 #define MAX_TCPOPTLEN 40 /* Absolute maximum TCP options len */ @@ -392,12 +396,12 @@ /* Accurate ECN counters. */ u_int32_t tcpi_delivered_ce; u_int32_t tcpi_received_ce; /* # of CE marks received */ - u_int32_t __tcpi_delivered_e1_bytes; - u_int32_t __tcpi_delivered_e0_bytes; - u_int32_t __tcpi_delivered_ce_bytes; - u_int32_t __tcpi_received_e1_bytes; - u_int32_t __tcpi_received_e0_bytes; - u_int32_t __tcpi_received_ce_bytes; + u_int32_t tcpi_delivered_e1_bytes; + u_int32_t tcpi_delivered_e0_bytes; + u_int32_t tcpi_delivered_ce_bytes; + u_int32_t tcpi_received_e1_bytes; + u_int32_t tcpi_received_e0_bytes; + u_int32_t tcpi_received_ce_bytes; /* Padding to grow without breaking ABI. */ u_int32_t __tcpi_pad[19]; /* Padding. */ diff --git a/sys/netinet/tcp_ecn.c b/sys/netinet/tcp_ecn.c --- a/sys/netinet/tcp_ecn.c +++ b/sys/netinet/tcp_ecn.c @@ -115,13 +115,17 @@ CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_ecn_maxretries), 0, "Max retries before giving up on ECN"); +VNET_DEFINE(int, tcp_ecn_option) = 0; +SYSCTL_INT(_net_inet_tcp_ecn, OID_AUTO, option, + CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_ecn_option), 0, + "Use AccECN TCP option"); + /* * Process incoming SYN,ACK packet */ void tcp_ecn_input_syn_sent(struct tcpcb *tp, uint16_t thflags, int iptos) { - if (V_tcp_do_ecn == 0) return; if ((V_tcp_do_ecn == 1) || @@ -291,19 +295,24 @@ if (tp->t_flags2 & (TF2_ECN_PERMIT | TF2_ACE_PERMIT)) { switch (iptos & IPTOS_ECN_MASK) { case IPTOS_ECN_CE: + tp->t_flags2 |= TF2_ACO_CE; + tp->t_ae.rceb += tlen; TCPSTAT_INC(tcps_ecn_ce); + tp->t_rcep++; break; case IPTOS_ECN_ECT0: + tp->t_flags2 |= TF2_ACO_E0; + tp->t_ae.re0b += tlen; TCPSTAT_INC(tcps_ecn_ect0); break; case IPTOS_ECN_ECT1: + tp->t_flags2 |= TF2_ACO_E1; + tp->t_ae.re1b += tlen; TCPSTAT_INC(tcps_ecn_ect1); break; } if (tp->t_flags2 & TF2_ACE_PERMIT) { - if ((iptos & IPTOS_ECN_MASK) == IPTOS_ECN_CE) - tp->t_rcep += 1; if (tp->t_flags2 & TF2_ECN_PERMIT) { delta_cep = (tcp_ecn_get_ace(thflags) + 8 - (tp->t_scep & 7)) & 7; @@ -446,7 +455,6 @@ if (tp->t_flags2 & TF2_ECN_SND_ECE) *thflags |= TH_ECE; } - return ipecn; } diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -986,6 +986,8 @@ } tp = intotcpcb(inp); + to.to_ae = &tp->t_ae; + switch (tp->t_state) { case TCPS_TIME_WAIT: /* @@ -1550,6 +1552,7 @@ inc = &tp->t_inpcb->inp_inc; tp->sackhint.last_sack_ack = 0; sack_changed = 0; + to.to_ae = &tp->t_ae; nsegs = max(1, m->m_pkthdr.lro_nsegs); NET_EPOCH_ASSERT(); @@ -3556,6 +3559,64 @@ to->to_tfo_len = optlen - 2; to->to_tfo_cookie = to->to_tfo_len ? cp + 2 : NULL; break; + case TCPOPT_ACCECN0: + if (optlen >= (TCPOLEN_ACCECN_EMPTY + + 1 * TCPOLEN_ACCECN_COUNTER)) { + opt = (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 0)) << 16; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 1)) << 8; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 2)) << 0; + opt -= (to->to_ae->se0b & 0xFFFFFF); + if (opt > 0) + to->to_ae->se0b += opt; + } + if (optlen >= (TCPOLEN_ACCECN_EMPTY + + 2 * TCPOLEN_ACCECN_COUNTER)) { + opt = (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 3)) << 16; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 4)) << 8; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 5)) << 0; + opt -= (to->to_ae->sceb & 0xFFFFFF); + if (opt > 0) + to->to_ae->sceb += opt; + } + if (optlen >= (TCPOLEN_ACCECN_EMPTY + + 3 * TCPOLEN_ACCECN_COUNTER)) { + opt = (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 6)) << 16; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 7)) << 8; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 8)) << 0; + opt -= (to->to_ae->se1b & 0xFFFFFF); + if (opt > 0) + to->to_ae->se1b += opt; + } + break; + case TCPOPT_ACCECN1: + if (optlen >= (TCPOLEN_ACCECN_EMPTY + + 1 * TCPOLEN_ACCECN_COUNTER)) { + opt = (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 0)) << 16; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 1)) << 8; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 2)) << 0; + opt -= (to->to_ae->se1b & 0xFFFFFF); + if (opt > 0) + to->to_ae->se1b += opt; + } + if (optlen >= (TCPOLEN_ACCECN_EMPTY + + 2 * TCPOLEN_ACCECN_COUNTER)) { + opt = (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 3)) << 16; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 4)) << 8; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 5)) << 0; + opt -= (to->to_ae->sceb & 0xFFFFFF); + if (opt > 0) + to->to_ae->sceb += opt; + } + if (optlen >= (TCPOLEN_ACCECN_EMPTY + + 3 * TCPOLEN_ACCECN_COUNTER)) { + opt = (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 6)) << 16; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 7)) << 8; + opt |= (uint32_t)(*(uint8_t *)(cp + TCPOLEN_ACCECN_EMPTY + 8)) << 0; + opt -= (to->to_ae->se0b & 0xFFFFFF); + if (opt > 0) + to->to_ae->se0b += opt; + } + break; default: continue; } diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -888,9 +888,35 @@ if (tp->t_flags & TF_SIGNATURE) to.to_flags |= TOF_SIGNATURE; #endif /* TCP_SIGNATURE */ - + /* + * AccECN option + * Don't send on , only on or + * when doing an AccECN session + */ + if (V_tcp_ecn_option && + ((V_tcp_do_ecn == 3) || (V_tcp_do_ecn == 4)) && + ((tp->t_flags2 & TF2_ACE_PERMIT) || + ((flags & TH_SYN) && (flags & TH_ACK)))) { + to.to_flags |= TOF_ACCECNOPT; + to.to_ae = &tp->t_ae; + to.to_flags |= ((tp->t_flags2 & TF2_ACO_E0) ? TOF_ACCE_E0 : 0) | + ((tp->t_flags2 & TF2_ACO_E1) ? TOF_ACCE_E1 : 0) | + ((tp->t_flags2 & TF2_ACO_CE) ? TOF_ACCE_CE : 0); + if (flags & TH_SYN) + to.to_flags |= TOF_ACCE_SYN; + if (tp->t_flags & TF_ACKNOW) + to.to_flags |= TOF_ACCE_ACKNOW; + } /* Processing the options. */ hdrlen += optlen = tcp_addoptions(&to, opt); + if (to.to_flags & TOF_ACCECNOPT) { + if ((to.to_flags & TOF_ACCE_E0) == 0) + tp->t_flags2 &= ~TF2_ACO_E0; + if ((to.to_flags & TOF_ACCE_E1) == 0) + tp->t_flags2 &= ~TF2_ACO_E1; + if ((to.to_flags & TOF_ACCE_CE) == 0) + tp->t_flags2 &= ~TF2_ACO_CE; + } /* * If we wanted a TFO option to be added, but it was unable * to fit, ensure no data is sent. @@ -1953,6 +1979,128 @@ optlen += total_len; break; } + case TOF_ACCECNOPT: + { + int max_len = TCP_MAXOLEN - optlen; + if (max_len < TCPOLEN_ACCECN_EMPTY) { + to->to_flags &= ~TOF_ACCECNOPT; + continue; + } + if (max_len < (TCPOLEN_ACCECN_EMPTY + + 1 * TCPOLEN_ACCECN_COUNTER)) { + if (to->to_flags & TOF_ACCE_SYN) { + *optp++ = TCPOPT_ACCECN0; + optlen += TCPOLEN_ACCECN_EMPTY; + *optp++ = TCPOLEN_ACCECN_EMPTY; + continue; + } else { + to->to_flags &= ~TOF_ACCECNOPT; + continue; + } + } + if (max_len < (TCPOLEN_ACCECN_EMPTY + + 2 * TCPOLEN_ACCECN_COUNTER)) { + if (to->to_flags & TOF_ACCE_E1) { + *optp++ = TCPOPT_ACCECN1; + *optp++ = TCPOLEN_ACCECN_EMPTY + + TCPOLEN_ACCECN_COUNTER; + optlen += TCPOLEN_ACCECN_EMPTY + + TCPOLEN_ACCECN_COUNTER; + *optp++ = (char)(to->to_ae->re1b >> 16); + *optp++ = (char)(to->to_ae->re1b >> 8); + *optp++ = (char)(to->to_ae->re1b); + to->to_flags &= ~TOF_ACCE_E1; + continue; + } + *optp++ = TCPOPT_ACCECN0; + *optp++ = TCPOLEN_ACCECN_EMPTY + + TCPOLEN_ACCECN_COUNTER; + optlen += TCPOLEN_ACCECN_EMPTY + + TCPOLEN_ACCECN_COUNTER; + *optp++ = (char)(to->to_ae->re0b >> 16); + *optp++ = (char)(to->to_ae->re0b >> 8); + *optp++ = (char)(to->to_ae->re0b); + to->to_flags &= ~TOF_ACCE_E0; + continue; + } + if (max_len < (TCPOLEN_ACCECN_EMPTY + + 3 * TCPOLEN_ACCECN_COUNTER)) { + if (to->to_flags & TOF_ACCE_E1) { + *optp++ = TCPOPT_ACCECN1; + *optp++ = TCPOLEN_ACCECN_EMPTY + + 2 * TCPOLEN_ACCECN_COUNTER; + optlen += TCPOLEN_ACCECN_EMPTY + + 2 * TCPOLEN_ACCECN_COUNTER; + *optp++ = (char)(to->to_ae->re1b >> 16); + *optp++ = (char)(to->to_ae->re1b >> 8); + *optp++ = (char)(to->to_ae->re1b); + to->to_flags &= ~TOF_ACCE_E1; + *optp++ = (char)(to->to_ae->rceb >> 16); + *optp++ = (char)(to->to_ae->rceb >> 8); + *optp++ = (char)(to->to_ae->rceb); + to->to_flags &= ~TOF_ACCE_CE; + continue; + } + *optp++ = TCPOPT_ACCECN0; + *optp++ = TCPOLEN_ACCECN_EMPTY + + 2 * TCPOLEN_ACCECN_COUNTER; + optlen += TCPOLEN_ACCECN_EMPTY + + 2 * TCPOLEN_ACCECN_COUNTER; + *optp++ = (char)(to->to_ae->re0b >> 16); + *optp++ = (char)(to->to_ae->re0b >> 8); + *optp++ = (char)(to->to_ae->re0b); + to->to_flags &= ~TOF_ACCE_E0; + *optp++ = (char)(to->to_ae->rceb >> 16); + *optp++ = (char)(to->to_ae->rceb >> 8); + *optp++ = (char)(to->to_ae->rceb); + to->to_flags &= ~TOF_ACCE_CE; + continue; + } + /* + * TCP option sufficient to hold full AccECN option + * but only send changed counters normally, + * full counters on ACKNOW + */ + if (to->to_flags & TOF_ACCE_E1) { + *optp++ = TCPOPT_ACCECN1; + *optp++ = TCPOLEN_ACCECN_EMPTY + + 3 * TCPOLEN_ACCECN_COUNTER; + optlen += TCPOLEN_ACCECN_EMPTY + + 3 * TCPOLEN_ACCECN_COUNTER; + *optp++ = (char)(to->to_ae->re1b >> 16); + *optp++ = (char)(to->to_ae->re1b >> 8); + *optp++ = (char)(to->to_ae->re1b); + to->to_flags &= ~TOF_ACCE_E1; + *optp++ = (char)(to->to_ae->rceb >> 16); + *optp++ = (char)(to->to_ae->rceb >> 8); + *optp++ = (char)(to->to_ae->rceb); + to->to_flags &= ~TOF_ACCE_CE; + *optp++ = (char)(to->to_ae->re0b >> 16); + *optp++ = (char)(to->to_ae->re0b >> 8); + *optp++ = (char)(to->to_ae->re0b); + to->to_flags &= ~TOF_ACCE_E0; + continue; + } else { + *optp++ = TCPOPT_ACCECN0; + *optp++ = TCPOLEN_ACCECN_EMPTY + + 3 * TCPOLEN_ACCECN_COUNTER; + optlen += TCPOLEN_ACCECN_EMPTY + + 3 * TCPOLEN_ACCECN_COUNTER; + *optp++ = (char)(to->to_ae->re0b >> 16); + *optp++ = (char)(to->to_ae->re0b >> 8); + *optp++ = (char)(to->to_ae->re0b); + to->to_flags &= ~TOF_ACCE_E0; + *optp++ = (char)(to->to_ae->rceb >> 16); + *optp++ = (char)(to->to_ae->rceb >> 8); + *optp++ = (char)(to->to_ae->rceb); + to->to_flags &= ~TOF_ACCE_CE; + *optp++ = (char)(to->to_ae->re1b >> 16); + *optp++ = (char)(to->to_ae->re1b >> 8); + *optp++ = (char)(to->to_ae->re1b); + to->to_flags &= ~TOF_ACCE_E1; + continue; + } + } default: panic("%s: unknown TCP option type", __func__); break; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1801,7 +1801,6 @@ #ifdef INVARIANTS int thflags = tcp_get_flags(th); #endif - KASSERT(tp != NULL || m != NULL, ("tcp_respond: tp and m both NULL")); NET_EPOCH_ASSERT(); @@ -2008,9 +2007,26 @@ if (tp->t_flags & TF_SIGNATURE) to.to_flags |= TOF_SIGNATURE; #endif + /* AccECN option */ + if (V_tcp_ecn_option && + ((V_tcp_do_ecn == 3) || (V_tcp_do_ecn == 4)) && + (tp->t_flags2 & TF2_ACE_PERMIT)) { + to.to_flags |= TOF_ACCECNOPT; + to.to_ae = &tp->t_ae; + to.to_flags |= ((tp->t_flags2 & TF2_ACO_E0) ? TOF_ACCE_E0 : 0) | + ((tp->t_flags2 & TF2_ACO_E1) ? TOF_ACCE_E1 : 0) | + ((tp->t_flags2 & TF2_ACO_CE) ? TOF_ACCE_CE : 0); + } /* Add the options. */ tlen += optlen = tcp_addoptions(&to, optp); - + if (to.to_flags & TOF_ACCECNOPT) { + if ((to.to_flags & TOF_ACCE_E0) == 0) + tp->t_flags2 &= ~TF2_ACO_E0; + if ((to.to_flags & TOF_ACCE_E1) == 0) + tp->t_flags2 &= ~TF2_ACO_E1; + if ((to.to_flags & TOF_ACCE_CE) == 0) + tp->t_flags2 &= ~TF2_ACO_CE; + } /* Update m_len in the correct mbuf. */ optm->m_len += optlen; } else @@ -2331,6 +2347,14 @@ tcp_log_tcpcbinit(tp); #endif tp->t_pacing_rate = -1; + if (V_tcp_do_lrd) + tp->t_flags |= TF_LRD; + tp->t_ae.re0b = 1; + tp->t_ae.re1b = 1; + tp->t_ae.rceb = 0; + tp->t_ae.se0b = 1; + tp->t_ae.se1b = 1; + tp->t_ae.sceb = 0; if (tp->t_fb->tfb_tcp_fb_init) { if ((*tp->t_fb->tfb_tcp_fb_init)(tp)) { refcount_release(&tp->t_fb->tfb_refcnt); diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -1817,6 +1817,7 @@ #ifdef INET6 struct ip6_hdr *ip6 = NULL; #endif + struct accecn ae; NET_EPOCH_ASSERT(); @@ -1956,6 +1957,20 @@ /* don't send cookie again when retransmitting response */ sc->sc_tfo_cookie = NULL; } + if (V_tcp_ecn_option) + to.to_flags |= TOF_ACCE_SYN; + } + if (V_tcp_ecn_option && + (sc->sc_flags & SCF_ECN_MASK) && + ((sc->sc_flags & SCF_ECN_MASK) != SCF_ECN)) { + to.to_flags |= TOF_ACCECNOPT; + to.to_flags |= TOF_ACCE_E0 | + TOF_ACCE_E1 | + TOF_ACCE_CE; + ae.re0b = 1; + ae.re1b = 1; + ae.rceb = 0; + to.to_ae = &ae; } if (sc->sc_flags & SCF_TIMESTAMP) { to.to_tsval = sc->sc_tsoff + tcp_ts_getticks(); diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1644,15 +1644,23 @@ * AccECN related counters. */ if ((tp->t_flags2 & (TF2_ECN_PERMIT | TF2_ACE_PERMIT)) == - (TF2_ECN_PERMIT | TF2_ACE_PERMIT)) + (TF2_ECN_PERMIT | TF2_ACE_PERMIT)) { /* * Internal counter starts at 5 for AccECN * but 0 for RFC3168 ECN. */ ti->tcpi_delivered_ce = tp->t_scep - 5; - else + ti->tcpi_received_ce = tp->t_rcep - 5; + } else { ti->tcpi_delivered_ce = tp->t_scep; - ti->tcpi_received_ce = tp->t_rcep; + ti->tcpi_received_ce = tp->t_rcep; + } + ti->tcpi_received_e0_bytes = tp->t_ae.re0b - 1; + ti->tcpi_received_e1_bytes = tp->t_ae.re1b - 1; + ti->tcpi_received_ce_bytes = tp->t_ae.rceb; + ti->tcpi_delivered_e0_bytes = tp->t_ae.se0b - 1; + ti->tcpi_delivered_e1_bytes = tp->t_ae.se1b - 1; + ti->tcpi_delivered_ce_bytes = tp->t_ae.sceb; } /* diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -120,6 +120,15 @@ uint32_t prr_out; /* Bytes sent during IN_RECOVERY */ }; +struct accecn { + uint32_t re0b; /* Number of ECT0 marked data bytes */ + uint32_t re1b; /* Number of ECT1 marked data bytes */ + uint32_t rceb; /* Number of CE marked data bytes */ + uint32_t se0b; /* Synced number of delivered ECT0 bytes */ + uint32_t se1b; /* Synced number of delivered ECT1 bytes */ + uint32_t sceb; /* Synced number of delivered CE bytes */ +}; + #define SEGQ_EMPTY(tp) TAILQ_EMPTY(&(tp)->t_segq) STAILQ_HEAD(tcp_log_stailq, tcp_log_mem); @@ -251,6 +260,7 @@ int t_loglimit; /* Maximum number of log entries */ uint32_t t_rcep; /* Number of received CE marked pkts */ uint32_t t_scep; /* Synced number of delivered CE pkts */ + struct accecn t_ae; /* AccECN related byte counters */ int64_t t_pacing_rate; /* bytes / sec, -1 => unlimited */ struct tcp_log_stailq t_logs; /* Log buffer */ struct tcp_log_id_node *t_lin; @@ -577,7 +587,10 @@ #define TF2_ECN_SND_CWR 0x00000040 /* ECN CWR in queue */ #define TF2_ECN_SND_ECE 0x00000080 /* ECN ECE in queue */ #define TF2_ACE_PERMIT 0x00000100 /* Accurate ECN mode */ -#define TF2_FBYTES_COMPLETE 0x00000400 /* We have first bytes in and out */ +#define TF2_ACO_E0 0x00000200 /* EE0 counter changed */ +#define TF2_ACO_E1 0x00000400 /* EE1 counter changed */ +#define TF2_ACO_CE 0x00000800 /* ECE counter changed */ +#define TF2_FBYTES_COMPLETE 0x00001000 /* We have first bytes in and out */ /* * Structure to hold TCP options that are only used during segment * processing (in tcp_input), but not held in the tcpcb. @@ -588,14 +601,21 @@ */ struct tcpopt { u_int32_t to_flags; /* which options are present */ -#define TOF_MSS 0x0001 /* maximum segment size */ -#define TOF_SCALE 0x0002 /* window scaling */ -#define TOF_SACKPERM 0x0004 /* SACK permitted */ -#define TOF_TS 0x0010 /* timestamp */ -#define TOF_SIGNATURE 0x0040 /* TCP-MD5 signature option (RFC2385) */ -#define TOF_SACK 0x0080 /* Peer sent SACK option */ -#define TOF_FASTOPEN 0x0100 /* TCP Fast Open (TFO) cookie */ -#define TOF_MAXOPT 0x0200 +#define TOF_MSS 0x00000001 /* maximum segment size */ +#define TOF_SCALE 0x00000002 /* window scaling */ +#define TOF_SACKPERM 0x00000004 /* SACK permitted */ +#define TOF_TS 0x00000010 /* timestamp */ +#define TOF_SIGNATURE 0x00000040 /* TCP-MD5 signature option (RFC2385) */ +#define TOF_SACK 0x00000080 /* Peer sent SACK option */ +#define TOF_FASTOPEN 0x00000100 /* TCP Fast Open (TFO) cookie */ +#define TOF_ACCECNOPT 0x00000200 /* AccECN Option */ +#define TOF_MAXOPT 0x00000400 + /* Keep internal flags above TOF_MAXOPT */ +#define TOF_ACCE_SYN 0x80000000 /* send empty option */ +#define TOF_ACCE_CE 0x40000000 /* CE counter changed */ +#define TOF_ACCE_E0 0x20000000 /* E0 counter changed */ +#define TOF_ACCE_E1 0x10000000 /* E1 counter changed */ +#define TOF_ACCE_ACKNOW 0x08000000 /* send full option */ u_int32_t to_tsval; /* new timestamp */ u_int32_t to_tsecr; /* reflected timestamp */ u_char *to_sacks; /* pointer to the first SACK blocks */ @@ -605,7 +625,8 @@ u_int8_t to_wscale; /* window scaling */ u_int8_t to_nsacks; /* number of SACK blocks */ u_int8_t to_tfo_len; /* TFO cookie length */ - u_int32_t to_spare; /* UTO */ + struct accecn *to_ae; /* pointer to AccECN byte counters */ + u_int32_t to_spare; /* UTO */ }; /* @@ -996,6 +1017,7 @@ VNET_DECLARE(int, tcp_do_sack); VNET_DECLARE(int, tcp_do_tso); VNET_DECLARE(int, tcp_ecn_maxretries); +VNET_DECLARE(int, tcp_ecn_option); VNET_DECLARE(int, tcp_initcwnd_segments); VNET_DECLARE(int, tcp_insecure_rst); VNET_DECLARE(int, tcp_insecure_syn); @@ -1042,6 +1064,7 @@ #define V_tcp_do_sack VNET(tcp_do_sack) #define V_tcp_do_tso VNET(tcp_do_tso) #define V_tcp_ecn_maxretries VNET(tcp_ecn_maxretries) +#define V_tcp_ecn_option VNET(tcp_ecn_option) #define V_tcp_initcwnd_segments VNET(tcp_initcwnd_segments) #define V_tcp_insecure_rst VNET(tcp_insecure_rst) #define V_tcp_insecure_syn VNET(tcp_insecure_syn)