summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/tcp_input.c19
-rw-r--r--sys/netinet/tcp_output.c2
-rw-r--r--sys/netinet/tcp_subr.c27
-rw-r--r--sys/netinet/tcp_var.h3
4 files changed, 32 insertions, 19 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 1a31c5e..7c8310f 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -3288,22 +3288,19 @@ tcp_xmit_timer(struct tcpcb *tp, int rtt)
* are present. Store the upper limit of the length of options plus
* data in maxopd.
*
- * In case of T/TCP, we call this routine during implicit connection
- * setup as well (offer = -1), to initialize maxseg from the cached
- * MSS of our peer.
- *
* NOTE that this routine is only called when we process an incoming
- * segment. Outgoing SYN/ACK MSS settings are handled in tcp_mssopt().
+ * segment, or an ICMP need fragmentation datagram. Outgoing SYN/ACK MSS
+ * settings are handled in tcp_mssopt().
*/
void
-tcp_mss_update(struct tcpcb *tp, int offer,
+tcp_mss_update(struct tcpcb *tp, int offer, int mtuoffer,
struct hc_metrics_lite *metricptr, int *mtuflags)
{
int mss = 0;
u_long maxmtu = 0;
struct inpcb *inp = tp->t_inpcb;
struct hc_metrics_lite metrics;
- int origoffer = offer;
+ int origoffer;
#ifdef INET6
int isipv6 = ((inp->inp_vflag & INP_IPV6) != 0) ? 1 : 0;
size_t min_protoh = isipv6 ?
@@ -3315,6 +3312,12 @@ tcp_mss_update(struct tcpcb *tp, int offer,
INP_WLOCK_ASSERT(tp->t_inpcb);
+ if (mtuoffer != -1) {
+ KASSERT(offer == -1, ("%s: conflict", __func__));
+ offer = mtuoffer - min_protoh;
+ }
+ origoffer = offer;
+
/* Initialize. */
#ifdef INET6
if (isipv6) {
@@ -3473,7 +3476,7 @@ tcp_mss(struct tcpcb *tp, int offer)
KASSERT(tp != NULL, ("%s: tp == NULL", __func__));
- tcp_mss_update(tp, offer, &metrics, &mtuflags);
+ tcp_mss_update(tp, offer, -1, &metrics, &mtuflags);
mss = tp->t_maxseg;
inp = tp->t_inpcb;
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 1965db1..645fb37 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1293,7 +1293,7 @@ out:
*/
if (tso)
tp->t_flags &= ~TF_TSO;
- tcp_mtudisc(tp->t_inpcb, 0);
+ tcp_mtudisc(tp->t_inpcb, -1);
return (0);
case EHOSTDOWN:
case EHOSTUNREACH:
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index a86d8f7..561749a 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -222,6 +222,7 @@ VNET_DEFINE(uma_zone_t, sack_hole_zone);
VNET_DEFINE(struct hhook_head *, tcp_hhh[HHOOK_TCP_LAST+1]);
static struct inpcb *tcp_notify(struct inpcb *, int);
+static struct inpcb *tcp_mtudisc_notify(struct inpcb *, int);
static char * tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th,
void *ip4hdr, const void *ip6hdr);
@@ -1337,7 +1338,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
return;
if (cmd == PRC_MSGSIZE)
- notify = tcp_mtudisc;
+ notify = tcp_mtudisc_notify;
else if (V_icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
notify = tcp_drop_syn_sent;
@@ -1410,9 +1411,10 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
*/
if (mtu <= tcp_maxmtu(&inc, NULL))
tcp_hc_updatemtu(&inc, mtu);
- }
-
- inp = (*notify)(inp, inetctlerrmap[cmd]);
+ tcp_mtudisc(inp, mtu);
+ } else
+ inp = (*notify)(inp,
+ inetctlerrmap[cmd]);
}
}
if (inp != NULL)
@@ -1452,7 +1454,7 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
return;
if (cmd == PRC_MSGSIZE)
- notify = tcp_mtudisc;
+ notify = tcp_mtudisc_notify;
else if (!PRC_IS_REDIRECT(cmd) &&
((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
return;
@@ -1653,12 +1655,19 @@ tcp_drop_syn_sent(struct inpcb *inp, int errno)
/*
* When `need fragmentation' ICMP is received, update our idea of the MSS
- * based on the new value in the route. Also nudge TCP to send something,
- * since we know the packet we just sent was dropped.
+ * based on the new value. Also nudge TCP to send something, since we
+ * know the packet we just sent was dropped.
* This duplicates some code in the tcp_mss() function in tcp_input.c.
*/
+static struct inpcb *
+tcp_mtudisc_notify(struct inpcb *inp, int error)
+{
+
+ return (tcp_mtudisc(inp, -1));
+}
+
struct inpcb *
-tcp_mtudisc(struct inpcb *inp, int errno)
+tcp_mtudisc(struct inpcb *inp, int mtuoffer)
{
struct tcpcb *tp;
struct socket *so;
@@ -1671,7 +1680,7 @@ tcp_mtudisc(struct inpcb *inp, int errno)
tp = intotcpcb(inp);
KASSERT(tp != NULL, ("tcp_mtudisc: tp == NULL"));
- tcp_mss_update(tp, -1, NULL, NULL);
+ tcp_mss_update(tp, -1, mtuoffer, NULL, NULL);
so = inp->inp_socket;
SOCKBUF_LOCK(&so->so_snd);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index b602c27..3b8bdf7 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -675,7 +675,8 @@ void tcp_reass_destroy(void);
void tcp_input(struct mbuf *, int);
u_long tcp_maxmtu(struct in_conninfo *, int *);
u_long tcp_maxmtu6(struct in_conninfo *, int *);
-void tcp_mss_update(struct tcpcb *, int, struct hc_metrics_lite *, int *);
+void tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *,
+ int *);
void tcp_mss(struct tcpcb *, int);
int tcp_mssopt(struct in_conninfo *);
struct inpcb *
OpenPOWER on IntegriCloud