summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/net/if.c19
-rw-r--r--sys/net/if_var.h5
-rw-r--r--sys/netinet/tcp_input.c17
-rw-r--r--sys/netinet/tcp_output.c9
-rw-r--r--sys/netinet/tcp_subr.c14
-rw-r--r--sys/netinet/tcp_var.h17
6 files changed, 55 insertions, 26 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index dc5681e..3fd6efb 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -74,18 +74,18 @@
#include <net/vnet.h>
#if defined(INET) || defined(INET6)
-/*XXX*/
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <netinet/ip.h>
#include <netinet/ip_carp.h>
+#ifdef INET
+#include <netinet/if_ether.h>
+#endif /* INET */
#ifdef INET6
#include <netinet6/in6_var.h>
#include <netinet6/in6_ifattach.h>
-#endif
-#endif
-#ifdef INET
-#include <netinet/if_ether.h>
-#endif
+#endif /* INET6 */
+#endif /* INET || INET6 */
#include <security/mac/mac_framework.h>
@@ -653,6 +653,13 @@ if_attach_internal(struct ifnet *ifp, int vmove)
TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
/* Reliably crash if used uninitialized. */
ifp->if_broadcastaddr = NULL;
+
+ /* Initialize to max value. */
+ if (ifp->if_hw_tsomax == 0)
+ ifp->if_hw_tsomax = IP_MAXPACKET;
+ KASSERT(ifp->if_hw_tsomax <= IP_MAXPACKET &&
+ ifp->if_hw_tsomax >= IP_MAXPACKET / 8,
+ ("%s: tsomax outside of range", __func__));
}
#ifdef VIMAGE
else {
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index ce8f06a..3babc22 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -204,6 +204,11 @@ struct ifnet {
u_int if_fib; /* interface FIB */
u_char if_alloctype; /* if_type at time of allocation */
+ u_int if_hw_tsomax; /* tso burst length limit, the minmum
+ * is (IP_MAXPACKET / 8).
+ * XXXAO: Have to find a better place
+ * for it eventually. */
+
/*
* Spare fields are added so that we can modify sensitive data
* structures without changing the kernel binary interface, and must
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index a3122a1..25b320e 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -3434,7 +3434,7 @@ tcp_xmit_timer(struct tcpcb *tp, int rtt)
*/
void
tcp_mss_update(struct tcpcb *tp, int offer, int mtuoffer,
- struct hc_metrics_lite *metricptr, int *mtuflags)
+ struct hc_metrics_lite *metricptr, struct tcp_ifcap *cap)
{
int mss = 0;
u_long maxmtu = 0;
@@ -3461,7 +3461,7 @@ tcp_mss_update(struct tcpcb *tp, int offer, int mtuoffer,
/* Initialize. */
#ifdef INET6
if (isipv6) {
- maxmtu = tcp_maxmtu6(&inp->inp_inc, mtuflags);
+ maxmtu = tcp_maxmtu6(&inp->inp_inc, cap);
tp->t_maxopd = tp->t_maxseg = V_tcp_v6mssdflt;
}
#endif
@@ -3470,7 +3470,7 @@ tcp_mss_update(struct tcpcb *tp, int offer, int mtuoffer,
#endif
#ifdef INET
{
- maxmtu = tcp_maxmtu(&inp->inp_inc, mtuflags);
+ maxmtu = tcp_maxmtu(&inp->inp_inc, cap);
tp->t_maxopd = tp->t_maxseg = V_tcp_mssdflt;
}
#endif
@@ -3605,11 +3605,12 @@ tcp_mss(struct tcpcb *tp, int offer)
struct inpcb *inp;
struct socket *so;
struct hc_metrics_lite metrics;
- int mtuflags = 0;
+ struct tcp_ifcap cap;
KASSERT(tp != NULL, ("%s: tp == NULL", __func__));
-
- tcp_mss_update(tp, offer, -1, &metrics, &mtuflags);
+
+ bzero(&cap, sizeof(cap));
+ tcp_mss_update(tp, offer, -1, &metrics, &cap);
mss = tp->t_maxseg;
inp = tp->t_inpcb;
@@ -3654,8 +3655,10 @@ tcp_mss(struct tcpcb *tp, int offer)
SOCKBUF_UNLOCK(&so->so_rcv);
/* Check the interface for TSO capabilities. */
- if (mtuflags & CSUM_TSO)
+ if (cap.ifcap & CSUM_TSO) {
tp->t_flags |= TF_TSO;
+ tp->t_tsomax = cap.tsomax;
+ }
}
/*
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 16038cb..b4342f3 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -769,12 +769,13 @@ send:
("%s: TSO can't do IP options", __func__));
/*
- * Limit a burst to IP_MAXPACKET minus IP,
+ * Limit a burst to t_tsomax minus IP,
* TCP and options length to keep ip->ip_len
- * from overflowing.
+ * from overflowing or exceeding the maximum
+ * length allowed by the network interface.
*/
- if (len > IP_MAXPACKET - hdrlen) {
- len = IP_MAXPACKET - hdrlen;
+ if (len > tp->t_tsomax - hdrlen) {
+ len = tp->t_tsomax - hdrlen;
sendalot = 1;
}
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 05030fd..c466bf4 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1770,7 +1770,7 @@ tcp_mtudisc(struct inpcb *inp, int mtuoffer)
* tcp_mss_update to get the peer/interface MTU.
*/
u_long
-tcp_maxmtu(struct in_conninfo *inc, int *flags)
+tcp_maxmtu(struct in_conninfo *inc, struct tcp_ifcap *cap)
{
struct route sro;
struct sockaddr_in *dst;
@@ -1795,10 +1795,11 @@ tcp_maxmtu(struct in_conninfo *inc, int *flags)
maxmtu = min(sro.ro_rt->rt_rmx.rmx_mtu, ifp->if_mtu);
/* Report additional interface capabilities. */
- if (flags != NULL) {
+ if (cap != NULL) {
if (ifp->if_capenable & IFCAP_TSO4 &&
ifp->if_hwassist & CSUM_TSO)
- *flags |= CSUM_TSO;
+ cap->ifcap |= CSUM_TSO;
+ cap->tsomax = ifp->if_hw_tsomax;
}
RTFREE(sro.ro_rt);
}
@@ -1808,7 +1809,7 @@ tcp_maxmtu(struct in_conninfo *inc, int *flags)
#ifdef INET6
u_long
-tcp_maxmtu6(struct in_conninfo *inc, int *flags)
+tcp_maxmtu6(struct in_conninfo *inc, struct tcp_ifcap *cap)
{
struct route_in6 sro6;
struct ifnet *ifp;
@@ -1832,10 +1833,11 @@ tcp_maxmtu6(struct in_conninfo *inc, int *flags)
IN6_LINKMTU(sro6.ro_rt->rt_ifp));
/* Report additional interface capabilities. */
- if (flags != NULL) {
+ if (cap != NULL) {
if (ifp->if_capenable & IFCAP_TSO6 &&
ifp->if_hwassist & CSUM_TSO)
- *flags |= CSUM_TSO;
+ cap->ifcap |= CSUM_TSO;
+ cap->tsomax = ifp->if_hw_tsomax;
}
RTFREE(sro6.ro_rt);
}
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index eddbd3c..0445d8c 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -208,6 +208,8 @@ struct tcpcb {
u_int t_keepintvl; /* interval between keepalives */
u_int t_keepcnt; /* number of keepalives before close */
+ u_int t_tsomax; /* tso burst length limit */
+
uint32_t t_ispare[8]; /* 5 UTO, 3 TBD */
void *t_pspare2[4]; /* 4 TBD */
uint64_t _pad[6]; /* 6 TBD (1-2 CC/RTT?) */
@@ -324,6 +326,15 @@ struct hc_metrics_lite { /* must stay in sync with hc_metrics */
u_long rmx_recvpipe; /* inbound delay-bandwidth product */
};
+/*
+ * Used by tcp_maxmtu() to communicate interface specific features
+ * and limits at the time of connection setup.
+ */
+struct tcp_ifcap {
+ int ifcap;
+ u_int tsomax;
+};
+
#ifndef _NETINET_IN_PCB_H_
struct in_conninfo;
#endif /* _NETINET_IN_PCB_H_ */
@@ -782,10 +793,10 @@ void tcp_reass_flush(struct tcpcb *);
void tcp_reass_destroy(void);
#endif
void tcp_input(struct mbuf *, int);
-u_long tcp_maxmtu(struct in_conninfo *, int *);
-u_long tcp_maxmtu6(struct in_conninfo *, int *);
+u_long tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *);
+u_long tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *);
void tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *,
- int *);
+ struct tcp_ifcap *);
void tcp_mss(struct tcpcb *, int);
int tcp_mssopt(struct in_conninfo *);
struct inpcb *
OpenPOWER on IntegriCloud