Index: sys/netinet/tcp_stacks/rack.c =================================================================== --- sys/netinet/tcp_stacks/rack.c +++ sys/netinet/tcp_stacks/rack.c @@ -12508,6 +12508,7 @@ ip6, rack->r_ctl.fsb.th); } else #endif /* INET6 */ +#ifdef INET { rack->r_ctl.fsb.tcp_ip_hdr_len = sizeof(struct tcpiphdr); ip = (struct ip *)rack->r_ctl.fsb.tcp_ip_hdr; @@ -12527,9 +12528,38 @@ tp->t_port, ip, rack->r_ctl.fsb.th); } +#endif rack->r_fsb_inited = 1; } +static void +rack_update_fsb_codepoint(struct tcpcb *tp, struct tcp_rack *rack) +{ +#ifdef INET6 + struct ip6_hdr *ip6 = NULL; +#endif +#ifdef INET + struct ip *ip = NULL; +#endif + /* + * A socket option changed the outgoing TOS/TCLASS update + * the fast send block. + */ +#ifdef INET6 + if (rack->r_is_v6) { + ip6 = (struct ip6_hdr *)rack->r_ctl.fsb.tcp_ip_hdr; + ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) | + (rack->rc_inp->inp_flow & IPV6_FLOWINFO_MASK); + } +#endif +#ifdef INET + else { + ip = (struct ip *)rack->r_ctl.fsb.tcp_ip_hdr; + ip->ip_tos = rack->rc_inp->inp_ip_tos; + } +#endif +} + static int rack_init_fsb(struct tcpcb *tp, struct tcp_rack *rack) { @@ -16873,6 +16903,11 @@ } idle = 0; } + if (tp->t_flags2 & TF2_CODEPOINT_CHANGED) { + if (rack->r_fsb_inited) + rack_update_fsb_codepoint(tp, rack); + tp->t_flags2 &= ~TF2_CODEPOINT_CHANGED; + } if (rack_use_fsb && (rack->r_fsb_inited == 0) && (rack->r_state != TCPS_CLOSED)) rack_init_fsb_block(tp, rack); again: Index: sys/netinet/tcp_subr.c =================================================================== --- sys/netinet/tcp_subr.c +++ sys/netinet/tcp_subr.c @@ -4129,3 +4129,19 @@ } } } + +void +tcp_codepoint_changed(struct inpcb *inp) +{ + struct tcpcb *tp = intotcpcb(inp); + + /* + * This is used by IP stacks to announce a + * change in the IP DSCP codepoint. Stacks + * like rack can use the flag to realize their + * fastpath may need an update. + */ + INP_WLOCK(inp); + tp->t_flags2 |= TF2_CODEPOINT_CHANGED; + INP_WUNLOCK(inp); +} Index: sys/netinet/tcp_usrreq.c =================================================================== --- sys/netinet/tcp_usrreq.c +++ sys/netinet/tcp_usrreq.c @@ -1745,6 +1745,15 @@ #ifdef INET6 if (inp->inp_vflag & INP_IPV6PROTO) { error = ip6_ctloutput(so, sopt); + /* + * If the TCLASS changes we need to + * notify tcp stacks that care. + */ + if ((sopt->sopt_level == IPPROTO_IPV6) && + (sopt->sopt_name == IPV6_TCLASS) && + (error == 0)) { + tcp_codepoint_changed(inp); + } /* * In case of the IPV6_USE_MIN_MTU socket option, * the INC_IPV6MINMTU flag to announce a corresponding @@ -1788,7 +1797,17 @@ #endif #ifdef INET { + /* + * If the TOS changes we need to + * notify tcp stacks that care. + */ error = ip_ctloutput(so, sopt); + if ((sopt->sopt_level == IPPROTO_IP) && + (sopt->sopt_name == IP_TOS) && + (error == 0)) { + tcp_codepoint_changed(inp); + } + } #endif return (error); Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h +++ sys/netinet/tcp_var.h @@ -462,6 +462,7 @@ #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_CODEPOINT_CHANGED 0x00020000 /* An ip option changed the DSCP codepoint */ /* * Structure to hold TCP options that are only used during segment * processing (in tcp_input), but not held in the tcpcb. @@ -1124,6 +1125,7 @@ size_t seed_len); int tcp_can_enable_pacing(void); void tcp_decrement_paced_conn(void); +void tcp_codepoint_changed(struct inpcb *); struct mbuf * tcp_m_copym(struct mbuf *m, int32_t off0, int32_t *plen,