diff options
author | Michael Tuexen <tuexen@FreeBSD.org> | 2023-11-09 10:37:27 +0000 |
---|---|---|
committer | Michael Tuexen <tuexen@FreeBSD.org> | 2024-01-12 16:55:40 +0000 |
commit | 002829ea6139fcbfc295790c97aed811535736fa (patch) | |
tree | 72a34e85ef0f5472853df7cb349b8bb54e7948ab | |
parent | e0f22f9e1867e9a4a2fc90327a13265eb233c7f3 (diff) | |
download | src-002829ea6139fcbfc295790c97aed811535736fa.tar.gz src-002829ea6139fcbfc295790c97aed811535736fa.zip |
if_tuntap: support receive checksum offloading for tap interfaces
When enabled, pretend that the IPv4 and transport layer checksum
is correct for packets injected via the character device.
This is a prerequisite for adding support for LRO, which will
be added next. Then packetdrill can be used to test the LRO
code in local mode.
Reviewed by: rscheff, zlei
Sponsored by: Netflix, Inc.
Differential Revision: https://reviews.freebsd.org/D42477
(cherry picked from commit ff69d13a50d1d07601de0885fd94f6a09a7ba383)
-rw-r--r-- | sys/net/if_tuntap.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/sys/net/if_tuntap.c b/sys/net/if_tuntap.c index f273e4993dfd..738e6b997ace 100644 --- a/sys/net/if_tuntap.c +++ b/sys/net/if_tuntap.c @@ -977,6 +977,8 @@ tuncreate(struct cdev *dev) ifp->if_flags = iflags; 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_capenable |= IFCAP_LINKSTATE; if ((tp->tun_flags & TUN_L2) != 0) { @@ -1784,9 +1786,35 @@ tunwrite_l2(struct tuntap_softc *tp, struct mbuf *m, return (0); } - if (vhdr != NULL && virtio_net_rx_csum(m, &vhdr->hdr)) { - m_freem(m); - return (0); + if (vhdr != NULL) { + if (virtio_net_rx_csum(m, &vhdr->hdr)) { + m_freem(m); + return (0); + } + } else { + switch (ntohs(eh->ether_type)) { +#ifdef INET + case ETHERTYPE_IP: + if (ifp->if_capenable & IFCAP_RXCSUM) { + m->m_pkthdr.csum_flags |= + CSUM_IP_CHECKED | CSUM_IP_VALID | + CSUM_DATA_VALID | CSUM_SCTP_VALID | + CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + break; +#endif +#ifdef INET6 + case ETHERTYPE_IPV6: + if (ifp->if_capenable & IFCAP_RXCSUM_IPV6) { + m->m_pkthdr.csum_flags |= + CSUM_DATA_VALID_IPV6 | CSUM_SCTP_VALID | + CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + break; +#endif + } } /* Pass packet up to parent. */ |