summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorsephe <sephe@FreeBSD.org>2016-02-18 04:58:34 +0000
committersephe <sephe@FreeBSD.org>2016-02-18 04:58:34 +0000
commit0354d2461f2d88b8f8617c27f322183d0730994d (patch)
treee659170447ca72f088cfb16af50b2dd2bc7aa3f5 /sys/netinet
parent96a8fa52de80131ac7fe64ec6fa9a3f7a10585ea (diff)
downloadFreeBSD-src-0354d2461f2d88b8f8617c27f322183d0730994d.zip
FreeBSD-src-0354d2461f2d88b8f8617c27f322183d0730994d.tar.gz
tcp/lro: Allow drivers to set the TCP ACK/data segment aggregation limit
ACK aggregation limit is append count based, while the TCP data segment aggregation limit is length based. Unless the network driver sets these two limits, it's an NO-OP. Reviewed by: adrian, gallatin (previous version), hselasky (previous version) Approved by: adrian (mentor) MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5185
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/tcp_lro.c15
-rw-r--r--sys/netinet/tcp_lro.h5
2 files changed, 18 insertions, 2 deletions
diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c
index 62d8595..7067abe 100644
--- a/sys/netinet/tcp_lro.c
+++ b/sys/netinet/tcp_lro.c
@@ -88,6 +88,8 @@ tcp_lro_init_args(struct lro_ctrl *lc, struct ifnet *ifp,
lc->lro_mbuf_count = 0;
lc->lro_mbuf_max = lro_mbufs;
lc->lro_cnt = lro_entries;
+ lc->lro_ackcnt_lim = TCP_LRO_ACKCNT_MAX;
+ lc->lro_length_lim = TCP_LRO_LENGTH_MAX;
lc->ifp = ifp;
SLIST_INIT(&lc->lro_free);
SLIST_INIT(&lc->lro_active);
@@ -610,7 +612,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
}
/* Flush now if appending will result in overflow. */
- if (le->p_len > (65535 - tcp_data_len)) {
+ if (le->p_len > (lc->lro_length_lim - tcp_data_len)) {
SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
tcp_lro_flush(lc, le);
break;
@@ -648,6 +650,15 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
if (tcp_data_len == 0) {
m_freem(m);
+ /*
+ * Flush this LRO entry, if this ACK should not
+ * be further delayed.
+ */
+ if (le->append_cnt >= lc->lro_ackcnt_lim) {
+ SLIST_REMOVE(&lc->lro_active, le, lro_entry,
+ next);
+ tcp_lro_flush(lc, le);
+ }
return (0);
}
@@ -668,7 +679,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
* If a possible next full length packet would cause an
* overflow, pro-actively flush now.
*/
- if (le->p_len > (65535 - lc->ifp->if_mtu)) {
+ if (le->p_len > (lc->lro_length_lim - lc->ifp->if_mtu)) {
SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
tcp_lro_flush(lc, le);
} else
diff --git a/sys/netinet/tcp_lro.h b/sys/netinet/tcp_lro.h
index 48c679d..3fc627c 100644
--- a/sys/netinet/tcp_lro.h
+++ b/sys/netinet/tcp_lro.h
@@ -91,11 +91,16 @@ struct lro_ctrl {
unsigned lro_cnt;
unsigned lro_mbuf_count;
unsigned lro_mbuf_max;
+ unsigned short lro_ackcnt_lim; /* max # of aggregated ACKs */
+ unsigned lro_length_lim; /* max len of aggregated data */
struct lro_head lro_active;
struct lro_head lro_free;
};
+#define TCP_LRO_LENGTH_MAX 65535
+#define TCP_LRO_ACKCNT_MAX 65535 /* unlimited */
+
int tcp_lro_init(struct lro_ctrl *);
int tcp_lro_init_args(struct lro_ctrl *, struct ifnet *, unsigned, unsigned);
void tcp_lro_free(struct lro_ctrl *);
OpenPOWER on IntegriCloud