Changeset View
Standalone View
sys/netinet/tcp_subr.c
Show First 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, sack_to_ack_thresh, | ||||
CTLFLAG_RW, | CTLFLAG_RW, | ||||
&tcp_sack_to_ack_thresh, 700, | &tcp_sack_to_ack_thresh, 700, | ||||
"Percentage of sacks to acks we must see above (10.1 percent is 101)?"); | "Percentage of sacks to acks we must see above (10.1 percent is 101)?"); | ||||
int32_t tcp_sack_to_move_thresh = 600; /* 60 % */ | int32_t tcp_sack_to_move_thresh = 600; /* 60 % */ | ||||
SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, move_thresh, | SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, move_thresh, | ||||
CTLFLAG_RW, | CTLFLAG_RW, | ||||
&tcp_sack_to_move_thresh, 600, | &tcp_sack_to_move_thresh, 600, | ||||
"Percentage of sack moves we must see above (10.1 percent is 101)"); | "Percentage of sack moves we must see above (10.1 percent is 101)"); | ||||
int32_t tcp_restoral_thresh = 650; /* 65 % (sack:2:ack -5%) */ | int32_t tcp_restoral_thresh = 450; /* 45 % (sack:2:ack -25%) (mv:ratio -15%) **/ | ||||
SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, restore_thresh, | SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, restore_thresh, | ||||
CTLFLAG_RW, | CTLFLAG_RW, | ||||
&tcp_restoral_thresh, 550, | &tcp_restoral_thresh, 450, | ||||
"Percentage of sack to ack percentage we must see below to restore(10.1 percent is 101)"); | "Percentage of sack to ack percentage we must see below to restore(10.1 percent is 101)"); | ||||
int32_t tcp_sad_decay_val = 800; | int32_t tcp_sad_decay_val = 800; | ||||
SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, decay_per, | SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, decay_per, | ||||
CTLFLAG_RW, | CTLFLAG_RW, | ||||
&tcp_sad_decay_val, 800, | &tcp_sad_decay_val, 800, | ||||
"The decay percentage (10.1 percent equals 101 )"); | "The decay percentage (10.1 percent equals 101 )"); | ||||
int32_t tcp_map_minimum = 500; | int32_t tcp_map_minimum = 500; | ||||
SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, nummaps, | SYSCTL_INT(_net_inet_tcp_sack_attack, OID_AUTO, nummaps, | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | |||||
VNET_DEFINE(int, tcp_ts_offset_per_conn) = 1; | VNET_DEFINE(int, tcp_ts_offset_per_conn) = 1; | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, ts_offset_per_conn, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, ts_offset_per_conn, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(tcp_ts_offset_per_conn), 0, | &VNET_NAME(tcp_ts_offset_per_conn), 0, | ||||
"Initialize TCP timestamps per connection instead of per host pair"); | "Initialize TCP timestamps per connection instead of per host pair"); | ||||
/* How many connections are pacing */ | /* How many connections are pacing */ | ||||
static volatile uint32_t number_of_tcp_connections_pacing = 0; | static volatile uint32_t number_of_tcp_connections_pacing = 0; | ||||
static uint32_t shadow_num_connections = 0; | static uint32_t shadow_num_connections = 0; | ||||
static counter_u64_t tcp_pacing_failures; | |||||
static int tcp_pacing_limit = 10000; | static int tcp_pacing_limit = 10000; | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, pacing_limit, CTLFLAG_RW, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, pacing_limit, CTLFLAG_RW, | ||||
&tcp_pacing_limit, 1000, | &tcp_pacing_limit, 1000, | ||||
"If the TCP stack does pacing, is there a limit (-1 = no, 0 = no pacing N = number of connections)"); | "If the TCP stack does pacing, is there a limit (-1 = no, 0 = no pacing N = number of connections)"); | ||||
SYSCTL_UINT(_net_inet_tcp, OID_AUTO, pacing_count, CTLFLAG_RD, | SYSCTL_UINT(_net_inet_tcp, OID_AUTO, pacing_count, CTLFLAG_RD, | ||||
&shadow_num_connections, 0, "Number of TCP connections being paced"); | &shadow_num_connections, 0, "Number of TCP connections being paced"); | ||||
SYSCTL_COUNTER_U64(_net_inet_tcp, OID_AUTO, pacing_failures, CTLFLAG_RD, | |||||
&tcp_pacing_failures, "Number of times we failed to enable pacing to avoid exceeding the limit"); | |||||
static int tcp_log_debug = 0; | static int tcp_log_debug = 0; | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_debug, CTLFLAG_RW, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_debug, CTLFLAG_RW, | ||||
&tcp_log_debug, 0, "Log errors caused by incoming TCP segments"); | &tcp_log_debug, 0, "Log errors caused by incoming TCP segments"); | ||||
static int tcp_tcbhashsize; | static int tcp_tcbhashsize; | ||||
SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcbhashsize, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, | SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcbhashsize, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, | ||||
&tcp_tcbhashsize, 0, "Size of TCP control-block hashtable"); | &tcp_tcbhashsize, 0, "Size of TCP control-block hashtable"); | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
static void tcp_default_fb_fini(struct tcpcb *tp, int tcb_is_purged); | static void tcp_default_fb_fini(struct tcpcb *tp, int tcb_is_purged); | ||||
static int tcp_default_handoff_ok(struct tcpcb *tp); | static int tcp_default_handoff_ok(struct tcpcb *tp); | ||||
static struct inpcb *tcp_notify(struct inpcb *, int); | static struct inpcb *tcp_notify(struct inpcb *, int); | ||||
static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int); | static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int); | ||||
static struct inpcb *tcp_mtudisc(struct inpcb *, int); | static struct inpcb *tcp_mtudisc(struct inpcb *, int); | ||||
static struct inpcb *tcp_drop_syn_sent(struct inpcb *, int); | static struct inpcb *tcp_drop_syn_sent(struct inpcb *, int); | ||||
static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th, | static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th, | ||||
const void *ip4hdr, const void *ip6hdr); | const void *ip4hdr, const void *ip6hdr); | ||||
static void tcp_default_switch_failed(struct tcpcb *tp); | |||||
static ipproto_ctlinput_t tcp_ctlinput; | static ipproto_ctlinput_t tcp_ctlinput; | ||||
static udp_tun_icmp_t tcp_ctlinput_viaudp; | static udp_tun_icmp_t tcp_ctlinput_viaudp; | ||||
static struct tcp_function_block tcp_def_funcblk = { | static struct tcp_function_block tcp_def_funcblk = { | ||||
.tfb_tcp_block_name = "freebsd", | .tfb_tcp_block_name = "freebsd", | ||||
.tfb_tcp_output = tcp_default_output, | .tfb_tcp_output = tcp_default_output, | ||||
.tfb_tcp_do_segment = tcp_do_segment, | .tfb_tcp_do_segment = tcp_do_segment, | ||||
.tfb_tcp_ctloutput = tcp_default_ctloutput, | .tfb_tcp_ctloutput = tcp_default_ctloutput, | ||||
.tfb_tcp_handoff_ok = tcp_default_handoff_ok, | .tfb_tcp_handoff_ok = tcp_default_handoff_ok, | ||||
.tfb_tcp_fb_init = tcp_default_fb_init, | .tfb_tcp_fb_init = tcp_default_fb_init, | ||||
.tfb_tcp_fb_fini = tcp_default_fb_fini, | .tfb_tcp_fb_fini = tcp_default_fb_fini, | ||||
.tfb_switch_failed = tcp_default_switch_failed, | |||||
}; | }; | ||||
static int tcp_fb_cnt = 0; | static int tcp_fb_cnt = 0; | ||||
struct tcp_funchead t_functions; | struct tcp_funchead t_functions; | ||||
VNET_DEFINE_STATIC(struct tcp_function_block *, tcp_func_set_ptr) = &tcp_def_funcblk; | VNET_DEFINE_STATIC(struct tcp_function_block *, tcp_func_set_ptr) = &tcp_def_funcblk; | ||||
#define V_tcp_func_set_ptr VNET(tcp_func_set_ptr) | #define V_tcp_func_set_ptr VNET(tcp_func_set_ptr) | ||||
void | void | ||||
▲ Show 20 Lines • Show All 702 Lines • ▼ Show 20 Lines | if ((!TCPS_HAVEESTABLISHED(tp->t_state) || sbavail(&so->so_snd) || | ||||
* be in the persist state, set the persist timer. Otherwise, | * be in the persist state, set the persist timer. Otherwise, | ||||
* set the retransmit timer. | * set the retransmit timer. | ||||
*/ | */ | ||||
if (TCPS_HAVEESTABLISHED(tp->t_state) && tp->snd_wnd == 0 && | if (TCPS_HAVEESTABLISHED(tp->t_state) && tp->snd_wnd == 0 && | ||||
(int32_t)(tp->snd_nxt - tp->snd_una) < | (int32_t)(tp->snd_nxt - tp->snd_una) < | ||||
(int32_t)sbavail(&so->so_snd)) | (int32_t)sbavail(&so->so_snd)) | ||||
tcp_setpersist(tp); | tcp_setpersist(tp); | ||||
else | else | ||||
tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); | tcp_timer_activate(tp, TT_REXMT, TP_RXTCUR(tp)); | ||||
} | } | ||||
/* All non-embryonic sessions get a keepalive timer. */ | /* All non-embryonic sessions get a keepalive timer. */ | ||||
if (!tcp_timer_active(tp, TT_KEEP)) | if (!tcp_timer_active(tp, TT_KEEP)) | ||||
tcp_timer_activate(tp, TT_KEEP, | tcp_timer_activate(tp, TT_KEEP, | ||||
TCPS_HAVEESTABLISHED(tp->t_state) ? TP_KEEPIDLE(tp) : | TCPS_HAVEESTABLISHED(tp->t_state) ? TP_KEEPIDLE(tp) : | ||||
TP_KEEPINIT(tp)); | TP_KEEPINIT(tp)); | ||||
Show All 16 Lines | |||||
* This changes state as necessary (or prudent) to prepare for another stack | * This changes state as necessary (or prudent) to prepare for another stack | ||||
* to assume responsibility for the connection. | * to assume responsibility for the connection. | ||||
*/ | */ | ||||
static void | static void | ||||
tcp_default_fb_fini(struct tcpcb *tp, int tcb_is_purged) | tcp_default_fb_fini(struct tcpcb *tp, int tcb_is_purged) | ||||
{ | { | ||||
INP_WLOCK_ASSERT(tptoinpcb(tp)); | INP_WLOCK_ASSERT(tptoinpcb(tp)); | ||||
#ifdef TCP_BLACKBOX | |||||
tcp_log_flowend(tp); | |||||
#endif | |||||
tp->t_acktime = 0; | |||||
return; | |||||
} | } | ||||
/* | /* | ||||
* Target size of TCP PCB hash tables. Must be a power of two. | * Target size of TCP PCB hash tables. Must be a power of two. | ||||
* | * | ||||
* Note that this can be overridden by the kernel environment | * Note that this can be overridden by the kernel environment | ||||
* variable net.inet.tcp.tcbhashsize | * variable net.inet.tcp.tcbhashsize | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 405 Lines • ▼ Show 20 Lines | #endif /* INET6 */ | ||||
tcp_inp_lro_wokeup_queue = counter_u64_alloc(M_WAITOK); | tcp_inp_lro_wokeup_queue = counter_u64_alloc(M_WAITOK); | ||||
tcp_inp_lro_compressed = counter_u64_alloc(M_WAITOK); | tcp_inp_lro_compressed = counter_u64_alloc(M_WAITOK); | ||||
tcp_inp_lro_locks_taken = counter_u64_alloc(M_WAITOK); | tcp_inp_lro_locks_taken = counter_u64_alloc(M_WAITOK); | ||||
tcp_extra_mbuf = counter_u64_alloc(M_WAITOK); | tcp_extra_mbuf = counter_u64_alloc(M_WAITOK); | ||||
tcp_would_have_but = counter_u64_alloc(M_WAITOK); | tcp_would_have_but = counter_u64_alloc(M_WAITOK); | ||||
tcp_comp_total = counter_u64_alloc(M_WAITOK); | tcp_comp_total = counter_u64_alloc(M_WAITOK); | ||||
tcp_uncomp_total = counter_u64_alloc(M_WAITOK); | tcp_uncomp_total = counter_u64_alloc(M_WAITOK); | ||||
tcp_bad_csums = counter_u64_alloc(M_WAITOK); | tcp_bad_csums = counter_u64_alloc(M_WAITOK); | ||||
tcp_pacing_failures = counter_u64_alloc(M_WAITOK); | |||||
#ifdef TCPPCAP | #ifdef TCPPCAP | ||||
tcp_pcap_init(); | tcp_pcap_init(); | ||||
#endif | #endif | ||||
hashsize = TCBHASHSIZE; | hashsize = TCBHASHSIZE; | ||||
tcbhash_tuneable = "net.inet.tcp.tcbhashsize"; | tcbhash_tuneable = "net.inet.tcp.tcbhashsize"; | ||||
TUNABLE_INT_FETCH(tcbhash_tuneable, &hashsize); | TUNABLE_INT_FETCH(tcbhash_tuneable, &hashsize); | ||||
if (hashsize == 0) { | if (hashsize == 0) { | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | | ||||
(inp->inp_flow & IPV6_FLOWINFO_MASK); | (inp->inp_flow & IPV6_FLOWINFO_MASK); | ||||
ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) | | ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) | | ||||
(IPV6_VERSION & IPV6_VERSION_MASK); | (IPV6_VERSION & IPV6_VERSION_MASK); | ||||
if (port == 0) | if (port == 0) | ||||
ip6->ip6_nxt = IPPROTO_TCP; | ip6->ip6_nxt = IPPROTO_TCP; | ||||
else | else | ||||
ip6->ip6_nxt = IPPROTO_UDP; | ip6->ip6_nxt = IPPROTO_UDP; | ||||
ip6->ip6_plen = htons(sizeof(struct tcphdr)); | ip6->ip6_plen = htons(sizeof(struct tcphdr)); | ||||
ip6->ip6_src = inp->in6p_laddr; | ip6->ip6_src = inp->in6p_laddr; | ||||
rscheff: this appears to be the inverse of IPV6_DCSP - suggest to maybe extract only the DSCP above… | |||||
Done Inline ActionsThis particular change was actually done by Drew Gallatin IIRR. Basically at NF we use a specific label when And to Michael, well if ip6_output() set it, it was *not* setting it for V6 when we went through the respond function. I can rrs: This particular change was actually done by Drew Gallatin IIRR. Basically at NF we use a… | |||||
Not Done Inline ActionsThe code looks OK to me. It clears the flowlabel and the DSCP and then sets the DSCP. tuexen: The code looks OK to me. It clears the flowlabel and the DSCP and then sets the DSCP.
It looks… | |||||
Done Inline ActionsLet me go change it to that..I don't see why that won't work and like you say makes sure As I poke in the code the ip6->ip6_flow = (....) line you have at the beginning rrs: Let me go change it to that..I don't see why that won't work and like you say makes sure
we… | |||||
Done Inline ActionsOk Richard your suggested fix is broken in a couple of ways: a) IPV6_DSCP() only works on an ip6_flow pointer htonl(dscp << (20 + 2)) which I believe will be broken since you did not slide it down 22 but only 20. So I have decided I will let the FreeBSD version continue to be like this. We will keep our rrs: Ok Richard your suggested fix is broken in a couple of ways:
a) IPV6_DSCP() only works on an… | |||||
Not Done Inline ActionsSo, the IPV6_DSCP macro is extracting the tclass masked to the dscp... Sorry for not catching that. Still, the following seems to be cleaner to me (and probably fewer ops): + int32_t tclass = 0; ip6 = (struct ip6_hdr *)ip_ptr; - ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | - (inp->inp_flow & IPV6_FLOWINFO_MASK); + ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | + (inp->inp_flow & IPV6_FLOWLABEL_MASK); ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) | (IPV6_VERSION & IPV6_VERSION_MASK); if (inp->in6p_outputopts != NULL) - tclass = inp->in6p_outputopts->ip6po_tclass; + tclass = (inp->in6p_outputopts->ip6po_tclass & ~IPTOS_ECN_MASK); - else - tclass = 0; - ip6->ip6_flow &= htonl((~0xfc) << 20); - ip6->ip6_flow |= htonl((tclass & 0xfc) << 20); + ip6->ip6_flow |= htonl(tclass << IPV6_FLOWLABEL_LEN); rscheff: So, the IPV6_DSCP macro is extracting the tclass masked to the dscp... Sorry for not catching… | |||||
Done Inline ActionsIsn't the traffic class set in ip6_output()? tuexen: Isn't the traffic class set in `ip6_output()`? | |||||
ip6->ip6_dst = inp->in6p_faddr; | ip6->ip6_dst = inp->in6p_faddr; | ||||
} | } | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
#if defined(INET6) && defined(INET) | #if defined(INET6) && defined(INET) | ||||
else | else | ||||
#endif | #endif | ||||
#ifdef INET | #ifdef INET | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 212 Lines • ▼ Show 20 Lines | #endif /* INET6 */ | ||||
} else { | } else { | ||||
/* | /* | ||||
* reuse the mbuf. | * reuse the mbuf. | ||||
* XXX MRT We inherit the FIB, which is lucky. | * XXX MRT We inherit the FIB, which is lucky. | ||||
*/ | */ | ||||
m_freem(m->m_next); | m_freem(m->m_next); | ||||
m->m_next = NULL; | m->m_next = NULL; | ||||
m->m_data = (caddr_t)ipgen; | m->m_data = (caddr_t)ipgen; | ||||
/* clear any receive flags for proper bpf timestamping */ | |||||
m->m_flags &= ~(M_TSTMP | M_TSTMP_LRO); | |||||
/* m_len is set later */ | /* m_len is set later */ | ||||
#ifdef INET6 | #ifdef INET6 | ||||
if (isipv6) { | if (isipv6) { | ||||
xchg(ip6->ip6_dst, ip6->ip6_src, struct in6_addr); | xchg(ip6->ip6_dst, ip6->ip6_src, struct in6_addr); | ||||
nth = (struct tcphdr *)(ip6 + 1); | nth = (struct tcphdr *)(ip6 + 1); | ||||
} else | } else | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | if (inp != NULL) { | ||||
*/ | */ | ||||
mac_netinet_tcp_reply(m); | mac_netinet_tcp_reply(m); | ||||
} | } | ||||
#endif | #endif | ||||
nth->th_seq = htonl(seq); | nth->th_seq = htonl(seq); | ||||
nth->th_ack = htonl(ack); | nth->th_ack = htonl(ack); | ||||
nth->th_off = (sizeof (struct tcphdr) + optlen) >> 2; | nth->th_off = (sizeof (struct tcphdr) + optlen) >> 2; | ||||
tcp_set_flags(nth, flags); | tcp_set_flags(nth, flags); | ||||
if (tp && (flags & TH_RST)) { | |||||
/* Log the reset */ | |||||
tcp_log_end_status(tp, TCP_EI_STATUS_SERVER_RST); | |||||
} | |||||
if (tp != NULL) | if (tp != NULL) | ||||
nth->th_win = htons((u_short) (win >> tp->rcv_scale)); | nth->th_win = htons((u_short) (win >> tp->rcv_scale)); | ||||
else | else | ||||
nth->th_win = htons((u_short)win); | nth->th_win = htons((u_short)win); | ||||
nth->th_urp = 0; | nth->th_urp = 0; | ||||
#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) | #if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE) | ||||
if (to.to_flags & TOF_SIGNATURE) { | if (to.to_flags & TOF_SIGNATURE) { | ||||
▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | #endif | ||||
TAILQ_INIT(&tp->t_segq); | TAILQ_INIT(&tp->t_segq); | ||||
tp->t_maxseg = | tp->t_maxseg = | ||||
#ifdef INET6 | #ifdef INET6 | ||||
isipv6 ? V_tcp_v6mssdflt : | isipv6 ? V_tcp_v6mssdflt : | ||||
#endif /* INET6 */ | #endif /* INET6 */ | ||||
V_tcp_mssdflt; | V_tcp_mssdflt; | ||||
/* All mbuf queue/ack compress flags should be off */ | |||||
tcp_lro_features_off(tptoinpcb(tp)); | |||||
callout_init_rw(&tp->t_callout, &inp->inp_lock, CALLOUT_RETURNUNLOCKED); | callout_init_rw(&tp->t_callout, &inp->inp_lock, CALLOUT_RETURNUNLOCKED); | ||||
for (int i = 0; i < TT_N; i++) | for (int i = 0; i < TT_N; i++) | ||||
tp->t_timers[i] = SBT_MAX; | tp->t_timers[i] = SBT_MAX; | ||||
switch (V_tcp_do_rfc1323) { | switch (V_tcp_do_rfc1323) { | ||||
case 0: | case 0: | ||||
break; | break; | ||||
default: | default: | ||||
▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | #ifdef STATS | ||||
stats_blob_destroy(tp->t_stats); | stats_blob_destroy(tp->t_stats); | ||||
#endif | #endif | ||||
CC_ALGO(tp) = NULL; | CC_ALGO(tp) = NULL; | ||||
#ifdef TCP_BLACKBOX | #ifdef TCP_BLACKBOX | ||||
tcp_log_tcpcbfini(tp); | tcp_log_tcpcbfini(tp); | ||||
#endif | #endif | ||||
if (tp->t_in_pkt) { | |||||
struct mbuf *m, *n; | |||||
m = tp->t_in_pkt; | |||||
tp->t_in_pkt = tp->t_tail_pkt = NULL; | |||||
while (m) { | |||||
n = m->m_nextpkt; | |||||
m_freem(m); | |||||
m = n; | |||||
} | |||||
} | |||||
TCPSTATES_DEC(tp->t_state); | TCPSTATES_DEC(tp->t_state); | ||||
if (tp->t_fb->tfb_tcp_fb_fini) | if (tp->t_fb->tfb_tcp_fb_fini) | ||||
(*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); | (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1); | ||||
/* | /* | ||||
* If we got enough samples through the srtt filter, | * If we got enough samples through the srtt filter, | ||||
* save the rtt and rttvar in the routing entry. | * save the rtt and rttvar in the routing entry. | ||||
* 'Enough' is arbitrarily defined as 4 rtt samples. | * 'Enough' is arbitrarily defined as 4 rtt samples. | ||||
▲ Show 20 Lines • Show All 1,565 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
if ((tcp_pacing_limit == -1) || | if ((tcp_pacing_limit == -1) || | ||||
(tcp_pacing_limit > number_of_tcp_connections_pacing)) { | (tcp_pacing_limit > number_of_tcp_connections_pacing)) { | ||||
atomic_fetchadd_int(&number_of_tcp_connections_pacing, 1); | atomic_fetchadd_int(&number_of_tcp_connections_pacing, 1); | ||||
shadow_num_connections = number_of_tcp_connections_pacing; | shadow_num_connections = number_of_tcp_connections_pacing; | ||||
return (1); | return (1); | ||||
} else { | } else { | ||||
counter_u64_add(tcp_pacing_failures, 1); | |||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
static uint8_t tcp_pacing_warning = 0; | static uint8_t tcp_pacing_warning = 0; | ||||
void | void | ||||
tcp_decrement_paced_conn(void) | tcp_decrement_paced_conn(void) | ||||
{ | { | ||||
uint32_t ret; | uint32_t ret; | ||||
ret = atomic_fetchadd_int(&number_of_tcp_connections_pacing, -1); | ret = atomic_fetchadd_int(&number_of_tcp_connections_pacing, -1); | ||||
shadow_num_connections = number_of_tcp_connections_pacing; | shadow_num_connections = number_of_tcp_connections_pacing; | ||||
KASSERT(ret != 0, ("tcp_paced_connection_exits -1 would cause wrap?")); | KASSERT(ret != 0, ("tcp_paced_connection_exits -1 would cause wrap?")); | ||||
if (ret == 0) { | if (ret == 0) { | ||||
if (tcp_pacing_limit != -1) { | if (tcp_pacing_limit != -1) { | ||||
printf("Warning all pacing is now disabled, count decrements invalidly!\n"); | printf("Warning all pacing is now disabled, count decrements invalidly!\n"); | ||||
tcp_pacing_limit = 0; | tcp_pacing_limit = 0; | ||||
} else if (tcp_pacing_warning == 0) { | } else if (tcp_pacing_warning == 0) { | ||||
printf("Warning pacing count is invalid, invalid decrement\n"); | printf("Warning pacing count is invalid, invalid decrement\n"); | ||||
tcp_pacing_warning = 1; | tcp_pacing_warning = 1; | ||||
} | } | ||||
} | } | ||||
} | |||||
static void | |||||
tcp_default_switch_failed(struct tcpcb *tp) | |||||
{ | |||||
/* | |||||
* If a switch fails we only need to | |||||
* care about two things: | |||||
* a) The inp_flags2 | |||||
* and | |||||
* b) The timer granularity. | |||||
* Timeouts, at least for now, don't use the | |||||
* old callout system in the other stacks so | |||||
* those are hopefully safe. | |||||
*/ | |||||
tcp_lro_features_off(tptoinpcb(tp)); | |||||
tcp_change_time_units(tp, TCP_TMR_GRANULARITY_TICKS); | |||||
} | } | ||||
#ifdef TCP_ACCOUNTING | #ifdef TCP_ACCOUNTING | ||||
int | int | ||||
tcp_do_ack_accounting(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to, uint32_t tiwin, int mss) | tcp_do_ack_accounting(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to, uint32_t tiwin, int mss) | ||||
{ | { | ||||
if (SEQ_LT(th->th_ack, tp->snd_una)) { | if (SEQ_LT(th->th_ack, tp->snd_una)) { | ||||
/* Do we have a SACK? */ | /* Do we have a SACK? */ | ||||
▲ Show 20 Lines • Show All 589 Lines • Show Last 20 Lines |
this appears to be the inverse of IPV6_DCSP - suggest to maybe extract only the DSCP above (using the IPV6_DSCP macro, and storing this in a "dscp" var instead of a tclass var.
And then setting this like what ip_carp is doing:
ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | (inp->inp_flow & IPV6_FLOWLABEL_MASK);
:
if (inp->in6p_outputopts != NULL)
ip6->ip6_flow |= htonl(dscp << (IPV6_FLOWLABEL_LEN + IPTOS_DSCP_OFFSET));