summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/tcp_lro.c23
-rw-r--r--sys/netinet/tcp_lro.h4
2 files changed, 26 insertions, 1 deletions
diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c
index 032d47c..63a6bba 100644
--- a/sys/netinet/tcp_lro.c
+++ b/sys/netinet/tcp_lro.c
@@ -194,6 +194,25 @@ tcp_lro_rx_csum_fixup(struct lro_entry *le, void *l3hdr, struct tcphdr *th,
#endif
void
+tcp_lro_flush_inactive(struct lro_ctrl *lc, const struct timeval *timeout)
+{
+ struct lro_entry *le, *le_tmp;
+ struct timeval tv;
+
+ if (SLIST_EMPTY(&lc->lro_active))
+ return;
+
+ getmicrotime(&tv);
+ timevalsub(&tv, timeout);
+ SLIST_FOREACH_SAFE(le, &lc->lro_active, next, le_tmp) {
+ if (timevalcmp(&tv, &le->mtime, >=)) {
+ SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ tcp_lro_flush(lc, le);
+ }
+ }
+}
+
+void
tcp_lro_flush(struct lro_ctrl *lc, struct lro_entry *le)
{
@@ -543,7 +562,8 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
if (le->p_len > (65535 - lc->ifp->if_mtu)) {
SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
tcp_lro_flush(lc, le);
- }
+ } else
+ getmicrotime(&le->mtime);
return (0);
}
@@ -556,6 +576,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
le = SLIST_FIRST(&lc->lro_free);
SLIST_REMOVE_HEAD(&lc->lro_free, next);
SLIST_INSERT_HEAD(&lc->lro_active, le, next);
+ getmicrotime(&le->mtime);
/* Start filling in details. */
switch (eh_type) {
diff --git a/sys/netinet/tcp_lro.h b/sys/netinet/tcp_lro.h
index b3a5017..ab6d74a 100644
--- a/sys/netinet/tcp_lro.h
+++ b/sys/netinet/tcp_lro.h
@@ -30,6 +30,8 @@
#ifndef _TCP_LRO_H_
#define _TCP_LRO_H_
+#include <sys/time.h>
+
struct lro_entry
{
SLIST_ENTRY(lro_entry) next;
@@ -59,6 +61,7 @@ struct lro_entry
uint32_t tsecr;
uint16_t window;
uint16_t timestamp; /* flag, not a TCP hdr field. */
+ struct timeval mtime;
};
SLIST_HEAD(lro_head, lro_entry);
@@ -83,6 +86,7 @@ struct lro_ctrl {
int tcp_lro_init(struct lro_ctrl *);
void tcp_lro_free(struct lro_ctrl *);
+void tcp_lro_flush_inactive(struct lro_ctrl *, const struct timeval *);
void tcp_lro_flush(struct lro_ctrl *, struct lro_entry *);
int tcp_lro_rx(struct lro_ctrl *, struct mbuf *, uint32_t);
OpenPOWER on IntegriCloud