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,40 @@ tp->t_port, ip, rack->r_ctl.fsb.th); } +#endif rack->r_fsb_inited = 1; } +static void +rack_dscp_change(struct tcpcb *tp) +{ +#ifdef INET6 + struct ip6_hdr *ip6 = NULL; +#endif +#ifdef INET + struct ip *ip = NULL; +#endif + struct tcp_rack *rack; + /* + * A socket option changed the outgoing TOS/TCLASS update + * the fast send block. + */ + rack = (struct tcp_rack *)tp->t_fb_ptr; +#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) { @@ -20232,6 +20264,7 @@ .tfb_tcp_mtu_chg = rack_mtu_change, .tfb_pru_options = rack_pru_options, .tfb_hwtls_change = rack_hw_tls_change, + .tfb_dscp_change = rack_dscp_change, }; /* Index: sys/netinet/tcp_subr.c =================================================================== --- sys/netinet/tcp_subr.c +++ sys/netinet/tcp_subr.c @@ -4129,3 +4129,4 @@ } } } + Index: sys/netinet/tcp_usrreq.c =================================================================== --- sys/netinet/tcp_usrreq.c +++ sys/netinet/tcp_usrreq.c @@ -1745,6 +1745,29 @@ #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)) { + INP_WLOCK(inp); + if ((inp->inp_flags & + (INP_TIMEWAIT | INP_DROPPED))) { + INP_WUNLOCK(inp); + return (ECONNRESET); + } + tp = intotcpcb(inp); + if (tp->t_fb->tfb_dscp_change != NULL) { + /* + * This stack wants to know about DSCP codepoint + * changes. + */ + (tp->t_fb->tfb_dscp_change)(tp); + } + INP_WUNLOCK(inp); + } /* * In case of the IPV6_USE_MIN_MTU socket option, * the INC_IPV6MINMTU flag to announce a corresponding @@ -1788,7 +1811,30 @@ #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)) { + INP_WLOCK(inp); + if ((inp->inp_flags & + (INP_TIMEWAIT | INP_DROPPED))) { + INP_WUNLOCK(inp); + return (ECONNRESET); + } + tp = intotcpcb(inp); + if (tp->t_fb->tfb_dscp_change != NULL) { + /* + * This stack wants to know about DSCP codepoint + * changes. + */ + (tp->t_fb->tfb_dscp_change)(tp); + } + INP_WUNLOCK(inp); + } } #endif return (error); Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h +++ sys/netinet/tcp_var.h @@ -373,6 +373,7 @@ void (*tfb_tcp_mtu_chg)(struct tcpcb *); int (*tfb_pru_options)(struct tcpcb *, int); void (*tfb_hwtls_change)(struct tcpcb *, int); + void (*tfb_dscp_change)(struct tcpcb *); volatile uint32_t tfb_refcnt; uint32_t tfb_flags; uint8_t tfb_id;