git: 99c79cab4227 - main - if_tuntap: add LRO support to tap devices
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 19 Nov 2023 21:33:31 UTC
The branch main has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=99c79cab422705f92f05a2924a29bdf823372ebf commit 99c79cab422705f92f05a2924a29bdf823372ebf Author: Michael Tuexen <tuexen@FreeBSD.org> AuthorDate: 2023-11-19 14:57:53 +0000 Commit: Michael Tuexen <tuexen@FreeBSD.org> CommitDate: 2023-11-19 14:57:53 +0000 if_tuntap: add LRO support to tap devices This allows testing the LRO code with packetdrill in local mode. Reviewed by: rscheff MFC after: 1 week Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D42548 --- sys/net/if_tuntap.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/sys/net/if_tuntap.c b/sys/net/if_tuntap.c index 8881bbaec070..5a4231604f5a 100644 --- a/sys/net/if_tuntap.c +++ b/sys/net/if_tuntap.c @@ -97,6 +97,7 @@ #endif #include <netinet/udp.h> #include <netinet/tcp.h> +#include <netinet/tcp_lro.h> #include <net/bpf.h> #include <net/if_tap.h> #include <net/if_tun.h> @@ -144,6 +145,8 @@ struct tuntap_softc { struct ether_addr tun_ether; /* remote address */ int tun_busy; /* busy count */ int tun_vhdrlen; /* virtio-net header length */ + struct lro_ctrl tun_lro; /* for TCP LRO */ + bool tun_lro_ready; /* TCP LRO initialized */ }; #define TUN2IFP(sc) ((sc)->tun_ifp) @@ -978,7 +981,8 @@ tuncreate(struct cdev *dev) IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_capabilities |= IFCAP_LINKSTATE; if ((tp->tun_flags & TUN_L2) != 0) - ifp->if_capabilities |= IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6; + ifp->if_capabilities |= + IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6 | IFCAP_LRO; ifp->if_capenable |= IFCAP_LINKSTATE; if ((tp->tun_flags & TUN_L2) != 0) { @@ -1175,6 +1179,12 @@ tundtor(void *data) (l2tun && (ifp->if_flags & IFF_LINK0) != 0)) goto out; + if (l2tun && tp->tun_lro_ready) { + TUNDEBUG (ifp, "LRO disabled\n"); + tcp_lro_free(&tp->tun_lro); + tp->tun_lro_ready = false; + } + if (ifp->if_flags & IFF_UP) { TUN_UNLOCK(tp); if_down(ifp); @@ -1219,6 +1229,14 @@ tuninit(struct ifnet *ifp) getmicrotime(&ifp->if_lastchange); TUN_UNLOCK(tp); } else { + if (tcp_lro_init(&tp->tun_lro) == 0) { + TUNDEBUG(ifp, "LRO enabled\n"); + tp->tun_lro.ifp = ifp; + tp->tun_lro_ready = true; + } else { + TUNDEBUG(ifp, "Could not enable LRO\n"); + tp->tun_lro_ready = false; + } ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; TUN_UNLOCK(tp); /* attempt to start output */ @@ -1765,6 +1783,7 @@ tunwrite_l2(struct tuntap_softc *tp, struct mbuf *m, struct epoch_tracker et; struct ether_header *eh; struct ifnet *ifp; + int result; ifp = TUN2IFP(tp); @@ -1820,7 +1839,15 @@ tunwrite_l2(struct tuntap_softc *tp, struct mbuf *m, /* Pass packet up to parent. */ CURVNET_SET(ifp->if_vnet); NET_EPOCH_ENTER(et); - (*ifp->if_input)(ifp, m); + if (tp->tun_lro_ready && ifp->if_capenable & IFCAP_LRO) { + result = tcp_lro_rx(&tp->tun_lro, m, 0); + TUNDEBUG(ifp, "tcp_lro_rx() returned %d\n", result); + } else + result = TCP_LRO_CANNOT; + if (result == 0) + tcp_lro_flush_all(&tp->tun_lro); + else + (*ifp->if_input)(ifp, m); NET_EPOCH_EXIT(et); CURVNET_RESTORE(); /* ibytes are counted in parent */