Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_ecn.c
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Process incoming SYN,ACK packet | * Process incoming SYN,ACK packet | ||||
*/ | */ | ||||
void | void | ||||
tcp_ecn_input_syn_sent(struct tcpcb *tp, uint16_t thflags, int iptos) | tcp_ecn_input_syn_sent(struct tcpcb *tp, uint16_t thflags, int iptos) | ||||
{ | { | ||||
thflags &= (TH_CWR|TH_ECE); | thflags &= (TH_CWR|TH_ECE); | ||||
if (((thflags & (TH_CWR | TH_ECE)) == TH_ECE) && | if ((thflags == TH_ECE) && | ||||
V_tcp_do_ecn) { | V_tcp_do_ecn) { | ||||
tp->t_flags2 |= TF2_ECN_PERMIT; | tp->t_flags2 |= TF2_ECN_PERMIT; | ||||
if (V_tcp_ecn_generalized) | |||||
tp->t_flags2 |= TF2_ECN_PLUSPLUS; | |||||
TCPSTAT_INC(tcps_ecn_shs); | TCPSTAT_INC(tcps_ecn_shs); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Handle parallel SYN for ECN | * Handle parallel SYN for ECN | ||||
*/ | */ | ||||
void | void | ||||
tcp_ecn_input_parallel_syn(struct tcpcb *tp, uint16_t thflags, int iptos) | tcp_ecn_input_parallel_syn(struct tcpcb *tp, uint16_t thflags, int iptos) | ||||
{ | { | ||||
if (thflags & TH_ACK) | if (thflags & TH_ACK) | ||||
return; | return; | ||||
if (V_tcp_do_ecn == 0) | if (V_tcp_do_ecn == 0) | ||||
return; | return; | ||||
if ((V_tcp_do_ecn == 1) || (V_tcp_do_ecn == 2)) { | if ((V_tcp_do_ecn == 1) || (V_tcp_do_ecn == 2)) { | ||||
/* RFC3168 ECN handling */ | /* RFC3168 ECN handling */ | ||||
if ((thflags & (TH_CWR | TH_ECE)) == (TH_CWR | TH_ECE)) { | if ((thflags & (TH_CWR | TH_ECE)) == (TH_CWR | TH_ECE)) { | ||||
tp->t_flags2 |= TF2_ECN_PERMIT; | tp->t_flags2 |= TF2_ECN_PERMIT; | ||||
tp->t_flags2 |= TF2_ECN_SND_ECE; | tp->t_flags2 |= TF2_ECN_SND_ECE; | ||||
if (V_tcp_ecn_generalized) | |||||
tp->t_flags2 |= TF2_ECN_PLUSPLUS; | |||||
TCPSTAT_INC(tcps_ecn_shs); | TCPSTAT_INC(tcps_ecn_shs); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* TCP ECN processing. | * TCP ECN processing. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | tcp_ecn_output_established(struct tcpcb *tp, uint16_t *thflags, int len) | ||||
/* | /* | ||||
* If the peer has ECN, mark data packets with | * If the peer has ECN, mark data packets with | ||||
* ECN capable transmission (ECT). | * ECN capable transmission (ECT). | ||||
* Ignore pure control packets, retransmissions | * Ignore pure control packets, retransmissions | ||||
* and window probes. | * and window probes. | ||||
*/ | */ | ||||
newdata = (len > 0 && SEQ_GEQ(tp->snd_nxt, tp->snd_max) && | newdata = (len > 0 && SEQ_GEQ(tp->snd_nxt, tp->snd_max) && | ||||
!((tp->t_flags & TF_FORCEDATA) && len == 1)); | !((tp->t_flags & TF_FORCEDATA) && len == 1)); | ||||
if (newdata) { | if (newdata || | ||||
/* | |||||
* Send ECN SYN segments as ECN-capable transport | |||||
* when ecn.generalized is set. This can not be | |||||
* futher simplified, as a fall-back to non-ECN | |||||
* may occur. | |||||
*/ | |||||
((tp->t_flags2 & TF2_ECN_PLUSPLUS) && | |||||
(((*thflags & (TH_SYN|TH_ACK|TH_ECE|TH_CWR)) == | |||||
(TH_SYN| TH_ECE|TH_CWR)) || | |||||
((*thflags & (TH_SYN|TH_ACK|TH_ECE|TH_CWR)) == | |||||
(TH_SYN|TH_ACK| TH_CWR)) || | |||||
((*thflags & (TH_SYN|TH_ACK|TH_ECE|TH_CWR)) == | |||||
(TH_SYN|TH_ACK|TH_ECE ))))) { | |||||
ipecn = IPTOS_ECN_ECT0; | ipecn = IPTOS_ECN_ECT0; | ||||
TCPSTAT_INC(tcps_ecn_ect0); | TCPSTAT_INC(tcps_ecn_ect0); | ||||
} | } | ||||
/* | /* | ||||
* Reply with proper ECN notifications. | * Reply with proper ECN notifications. | ||||
*/ | */ | ||||
if (newdata && | if (newdata && | ||||
(tp->t_flags2 & TF2_ECN_SND_CWR)) { | (tp->t_flags2 & TF2_ECN_SND_CWR)) { | ||||
Show All 12 Lines | |||||
*/ | */ | ||||
void | void | ||||
tcp_ecn_syncache_socket(struct tcpcb *tp, struct syncache *sc) | tcp_ecn_syncache_socket(struct tcpcb *tp, struct syncache *sc) | ||||
{ | { | ||||
if (sc->sc_flags & SCF_ECN_MASK) { | if (sc->sc_flags & SCF_ECN_MASK) { | ||||
switch (sc->sc_flags & SCF_ECN_MASK) { | switch (sc->sc_flags & SCF_ECN_MASK) { | ||||
case SCF_ECN: | case SCF_ECN: | ||||
tp->t_flags2 |= TF2_ECN_PERMIT; | tp->t_flags2 |= TF2_ECN_PERMIT; | ||||
if (V_tcp_ecn_generalized) | |||||
tp->t_flags2 |= TF2_ECN_PLUSPLUS; | |||||
break; | break; | ||||
/* undefined SCF codepoint */ | /* undefined SCF codepoint */ | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
Show All 19 Lines | tcp_ecn_syncache_add(uint16_t thflags, int iptos) | ||||
} | } | ||||
return scflags; | return scflags; | ||||
} | } | ||||
/* | /* | ||||
* Set up the ECN information for the <SYN,ACK> from | * Set up the ECN information for the <SYN,ACK> from | ||||
* syncache information. | * syncache information. | ||||
*/ | */ | ||||
uint16_t | int | ||||
tcp_ecn_syncache_respond(uint16_t thflags, struct syncache *sc) | tcp_ecn_syncache_respond(uint16_t *thflags, struct syncache *sc) | ||||
{ | { | ||||
if ((thflags & TH_SYN) && | int ipecn = IPTOS_ECN_NOTECT; | ||||
if ((*thflags & TH_SYN) && | |||||
(sc->sc_flags & SCF_ECN_MASK)) { | (sc->sc_flags & SCF_ECN_MASK)) { | ||||
switch (sc->sc_flags & SCF_ECN_MASK) { | switch (sc->sc_flags & SCF_ECN_MASK) { | ||||
case SCF_ECN: | case SCF_ECN: | ||||
thflags |= (0 | TH_ECE); | *thflags |= (0 | TH_ECE); | ||||
TCPSTAT_INC(tcps_ecn_shs); | TCPSTAT_INC(tcps_ecn_shs); | ||||
if ((V_tcp_ecn_generalized && | |||||
(*thflags & TH_ACK))) | |||||
ipecn = IPTOS_ECN_ECT0; | |||||
break; | break; | ||||
/* undefined SCF codepoint */ | /* undefined SCF codepoint */ | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return thflags; | return ipecn; | ||||
} | } |