Factor out tcp6_use_min_mtu() to handle IPV6_USE_MIN_MTU by TCP.
Pass control for IP/IP6 level options from generic tcp_ctloutput_set() down to per-stack ctloutput. Call tcp6_use_min_mtu() from tcp stack tcp_default_ctloutput(). Reviewed by: rrs Differential Revision: https://reviews.freebsd.org/D32655
This commit is contained in:
parent
de156263a5
commit
f581a26e46
@ -14253,6 +14253,12 @@ bbr_set_sockopt(struct socket *so, struct sockopt *sopt,
|
||||
struct epoch_tracker et;
|
||||
int32_t error = 0, optval;
|
||||
|
||||
switch (sopt->sopt_level) {
|
||||
case IPPROTO_IPV6:
|
||||
case IPPROTO_IP:
|
||||
return (tcp_default_ctloutput(so, sopt, inp, tp));
|
||||
}
|
||||
|
||||
switch (sopt->sopt_name) {
|
||||
case TCP_RACK_PACE_MAX_SEG:
|
||||
case TCP_RACK_MIN_TO:
|
||||
|
@ -20248,6 +20248,25 @@ rack_set_sockopt(struct socket *so, struct sockopt *sopt,
|
||||
uint64_t loptval;
|
||||
int32_t error = 0, optval;
|
||||
|
||||
switch (sopt->sopt_level) {
|
||||
#ifdef INET6
|
||||
case IPPROTO_IPV6:
|
||||
MPASS(inp->inp_vflag & INP_IPV6PROTO);
|
||||
switch (sopt->sopt_name) {
|
||||
case IPV6_USE_MIN_MTU:
|
||||
tcp6_use_min_mtu(tp);
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
INP_WUNLOCK(inp);
|
||||
return (0);
|
||||
#endif
|
||||
#ifdef INET
|
||||
case IPPROTO_IP:
|
||||
INP_WUNLOCK(inp);
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (sopt->sopt_name) {
|
||||
case TCP_RACK_TLP_REDUCE: /* URL:tlp_reduce */
|
||||
/* Pacing related ones */
|
||||
|
@ -3559,6 +3559,41 @@ tcp_maxmtu6(struct in_conninfo *inc, struct tcp_ifcap *cap)
|
||||
|
||||
return (maxmtu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle setsockopt(IPV6_USE_MIN_MTU) by a TCP stack.
|
||||
*
|
||||
* XXXGL: we are updating inpcb here with INC_IPV6MINMTU flag.
|
||||
* The right place to do that is ip6_setpktopt() that has just been
|
||||
* executed. By the way it just filled ip6po_minmtu for us.
|
||||
*/
|
||||
void
|
||||
tcp6_use_min_mtu(struct tcpcb *tp)
|
||||
{
|
||||
struct inpcb *inp = tp->t_inpcb;
|
||||
|
||||
INP_WLOCK_ASSERT(inp);
|
||||
/*
|
||||
* In case of the IPV6_USE_MIN_MTU socket
|
||||
* option, the INC_IPV6MINMTU flag to announce
|
||||
* a corresponding MSS during the initial
|
||||
* handshake. If the TCP connection is not in
|
||||
* the front states, just reduce the MSS being
|
||||
* used. This avoids the sending of TCP
|
||||
* segments which will be fragmented at the
|
||||
* IPv6 layer.
|
||||
*/
|
||||
inp->inp_inc.inc_flags |= INC_IPV6MINMTU;
|
||||
if ((tp->t_state >= TCPS_SYN_SENT) &&
|
||||
(inp->inp_inc.inc_flags & INC_ISIPV6)) {
|
||||
struct ip6_pktopts *opt;
|
||||
|
||||
opt = inp->in6p_outputopts;
|
||||
if (opt != NULL && opt->ip6po_minmtu == IP6PO_MINMTU_ALL &&
|
||||
tp->t_maxseg > TCP6_MSS)
|
||||
tp->t_maxseg = TCP6_MSS;
|
||||
}
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
/*
|
||||
|
@ -1763,43 +1763,8 @@ tcp_ctloutput_set(struct inpcb *inp, struct sockopt *sopt)
|
||||
/* Notify tcp stacks that care (e.g. RACK). */
|
||||
break;
|
||||
case IPV6_USE_MIN_MTU:
|
||||
/*
|
||||
* XXXGL: this handling should belong to
|
||||
* stack specific tfb_tcp_ctloutput, we
|
||||
* should just break here.
|
||||
*
|
||||
* In case of the IPV6_USE_MIN_MTU socket
|
||||
* option, the INC_IPV6MINMTU flag to announce
|
||||
* a corresponding MSS during the initial
|
||||
* handshake. If the TCP connection is not in
|
||||
* the front states, just reduce the MSS being
|
||||
* used. This avoids the sending of TCP
|
||||
* segments which will be fragmented at the
|
||||
* IPv6 layer.
|
||||
*/
|
||||
INP_WLOCK(inp);
|
||||
if ((inp->inp_flags &
|
||||
(INP_TIMEWAIT | INP_DROPPED))) {
|
||||
INP_WUNLOCK(inp);
|
||||
return (ECONNRESET);
|
||||
}
|
||||
inp->inp_inc.inc_flags |= INC_IPV6MINMTU;
|
||||
tp = intotcpcb(inp);
|
||||
if ((tp->t_state >= TCPS_SYN_SENT) &&
|
||||
(inp->inp_inc.inc_flags & INC_ISIPV6)) {
|
||||
struct ip6_pktopts *opt;
|
||||
|
||||
opt = inp->in6p_outputopts;
|
||||
if ((opt != NULL) &&
|
||||
(opt->ip6po_minmtu ==
|
||||
IP6PO_MINMTU_ALL)) {
|
||||
if (tp->t_maxseg > TCP6_MSS) {
|
||||
tp->t_maxseg = TCP6_MSS;
|
||||
}
|
||||
}
|
||||
}
|
||||
INP_WUNLOCK(inp);
|
||||
/* FALLTHROUGH */
|
||||
/* Update t_maxseg accordingly. */
|
||||
break;
|
||||
default:
|
||||
return (error);
|
||||
}
|
||||
@ -2058,6 +2023,27 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp
|
||||
#endif
|
||||
size_t len;
|
||||
|
||||
INP_WLOCK_ASSERT(inp);
|
||||
|
||||
switch (sopt->sopt_level) {
|
||||
#ifdef INET6
|
||||
case IPPROTO_IPV6:
|
||||
MPASS(inp->inp_vflag & INP_IPV6PROTO);
|
||||
switch (sopt->sopt_name) {
|
||||
case IPV6_USE_MIN_MTU:
|
||||
tcp6_use_min_mtu(tp);
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
INP_WUNLOCK(inp);
|
||||
return (0);
|
||||
#endif
|
||||
#ifdef INET
|
||||
case IPPROTO_IP:
|
||||
INP_WUNLOCK(inp);
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* For TCP_CCALGOOPT forward the control to CC module, for both
|
||||
* SOPT_SET and SOPT_GET.
|
||||
|
@ -1053,6 +1053,7 @@ extern uint32_t tcp_ack_war_cnt;
|
||||
|
||||
uint32_t tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *);
|
||||
uint32_t tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *);
|
||||
void tcp6_use_min_mtu(struct tcpcb *);
|
||||
u_int tcp_maxseg(const struct tcpcb *);
|
||||
u_int tcp_fixed_maxseg(const struct tcpcb *);
|
||||
void tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *,
|
||||
|
Loading…
Reference in New Issue
Block a user