diff options
author | Michael Tuexen <tuexen@FreeBSD.org> | 2023-11-09 10:37:27 +0000 |
---|---|---|
committer | Michael Tuexen <tuexen@FreeBSD.org> | 2024-01-12 17:53:19 +0000 |
commit | 41988a137d556b0e4bd6259bc7af0c63f6975596 (patch) | |
tree | 046dff550c662f417b77df7fcae4e2000ecd1333 | |
parent | f6aae554b0764dcf9fcb9fe886bdf722f3856e0d (diff) | |
download | src-41988a137d556b0e4bd6259bc7af0c63f6975596.tar.gz src-41988a137d556b0e4bd6259bc7af0c63f6975596.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 29e9c05e52bc..9cadd971eb37 100644 --- a/sys/net/if_tuntap.c +++ b/sys/net/if_tuntap.c @@ -970,6 +970,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) { @@ -1777,9 +1779,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. */ |