Page MenuHomeFreeBSD

D51686.id159602.diff
No OneTemporary

D51686.id159602.diff

diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c
--- a/sys/dev/virtio/network/if_vtnet.c
+++ b/sys/dev/virtio/network/if_vtnet.c
@@ -28,6 +28,9 @@
/* Driver for VirtIO network devices. */
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
#include <sys/param.h>
#include <sys/eventhandler.h>
#include <sys/systm.h>
@@ -82,9 +85,6 @@
#include <dev/virtio/network/if_vtnetvar.h>
#include "virtio_if.h"
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
#if defined(INET) || defined(INET6)
#include <machine/in_cksum.h>
#endif
@@ -1770,24 +1770,16 @@
sc = rxq->vtnrx_sc;
/*
- * NEEDS_CSUM corresponds to Linux's CHECKSUM_PARTIAL, but FreeBSD does
- * not have an analogous CSUM flag. The checksum has been validated,
- * but is incomplete (TCP/UDP pseudo header).
- *
- * The packet is likely from another VM on the same host that itself
- * performed checksum offloading so Tx/Rx is basically a memcpy and
- * the checksum has little value.
- *
- * Default to receiving the packet as-is for performance reasons, but
- * this can cause issues if the packet is to be forwarded because it
- * does not contain a valid checksum. This patch may be helpful:
- * https://reviews.freebsd.org/D6611. In the meantime, have the driver
- * compute the checksum if requested.
+ * The packet is likely from another VM on the same host or from the
+ * host that itself performed checksum offloading so Tx/Rx is basically
+ * a memcpy and the checksum has little value so far.
*
- * BMV: Need to add an CSUM_PARTIAL flag?
+ * If the user don't want us to fix it up here by computing the
+ * checksum, just forward the order to compute the checksum by setting
+ * the corresponding mbuf flag (e.g., CSUM_TCP).
*/
if ((sc->vtnet_flags & VTNET_FLAG_FIXUP_NEEDS_CSUM) == 0) {
- error = vtnet_rxq_csum_data_valid(rxq, m, etype, hoff, hdr);
+ error = virtio_net_rx_csum_by_offset(m, etype, hoff, hdr);
return (error);
}
@@ -2497,6 +2489,10 @@
hdr->csum_start = vtnet_gtoh16(sc, csum_start);
hdr->csum_offset = vtnet_gtoh16(sc, m->m_pkthdr.csum_data);
txq->vtntx_stats.vtxs_csum++;
+ } else if ((flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) &&
+ (proto == IPPROTO_TCP || proto == IPPROTO_UDP) &&
+ (m->m_pkthdr.csum_data == 0xFFFF)) {
+ hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
}
if (flags & (CSUM_IP_TSO | CSUM_IP6_TSO)) {
@@ -2609,7 +2605,8 @@
m->m_flags &= ~M_VLANTAG;
}
- if (m->m_pkthdr.csum_flags & VTNET_CSUM_ALL_OFFLOAD) {
+ if (m->m_pkthdr.csum_flags &
+ (VTNET_CSUM_ALL_OFFLOAD | CSUM_DATA_VALID)) {
m = vtnet_txq_offload(txq, m, hdr);
if ((*m_head = m) == NULL) {
error = ENOBUFS;
diff --git a/sys/dev/virtio/network/virtio_net.h b/sys/dev/virtio/network/virtio_net.h
--- a/sys/dev/virtio/network/virtio_net.h
+++ b/sys/dev/virtio/network/virtio_net.h
@@ -261,19 +261,21 @@
struct virtio_net_hdr *hdr)
{
#if defined(INET) || defined(INET6)
+ bool isipv6;
int offset = hdr->csum_start + hdr->csum_offset;
-#endif
- /* Only do a basic sanity check on the offset. */
+ /* Get IP version and do a basic sanity check on the offset. */
switch (eth_type) {
#if defined(INET)
case ETHERTYPE_IP:
+ isipv6 = false;
if (__predict_false(offset < ip_start + sizeof(struct ip)))
return (1);
break;
#endif
#if defined(INET6)
case ETHERTYPE_IPV6:
+ isipv6 = true;
if (__predict_false(offset < ip_start + sizeof(struct ip6_hdr)))
return (1);
break;
@@ -284,6 +286,9 @@
}
/*
+ * Forward the order to calculate the checksum in case this packet
+ * will leave the host over a real interface with checksum offloading.
+ *
* Use the offset to determine the appropriate CSUM_* flags. This is
* a bit dirty, but we can get by with it since the checksum offsets
* happen to be different. We assume the host host does not do IPv4
@@ -291,15 +296,18 @@
*/
switch (hdr->csum_offset) {
case offsetof(struct udphdr, uh_sum):
+ m->m_pkthdr.csum_flags |= (isipv6 ? CSUM_UDP_IPV6 : CSUM_UDP);
+ break;
case offsetof(struct tcphdr, th_sum):
- m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- m->m_pkthdr.csum_data = 0xFFFF;
+ m->m_pkthdr.csum_flags |= (isipv6 ? CSUM_TCP_IPV6 : CSUM_TCP);
break;
default:
/* Here we should increment the rx_csum_bad_offset counter. */
return (1);
}
+ m->m_pkthdr.csum_data = hdr->csum_offset;
+#endif /* defined(INET) || defined(INET6) */
return (0);
}
@@ -526,6 +534,12 @@
/* Here we should increment the tx_csum counter. */
}
+ if ((flags & (CSUM_DATA_VALID | CSUM_PSEUDO_HDR)) &&
+ (proto == IPPROTO_TCP || proto == IPPROTO_UDP) &&
+ (m->m_pkthdr.csum_data == 0xFFFF)) {
+ hdr->flags |= VIRTIO_NET_HDR_F_DATA_VALID;
+ }
+
if (flags & CSUM_TSO) {
if (__predict_false(proto != IPPROTO_TCP)) {
/* Likely failed to correctly parse the mbuf.
diff --git a/sys/net/if_tuntap.c b/sys/net/if_tuntap.c
--- a/sys/net/if_tuntap.c
+++ b/sys/net/if_tuntap.c
@@ -1757,7 +1757,8 @@
struct virtio_net_hdr_mrg_rxbuf vhdr;
bzero(&vhdr, sizeof(vhdr));
- if (m->m_pkthdr.csum_flags & TAP_ALL_OFFLOAD) {
+ if (m->m_pkthdr.csum_flags &
+ (TAP_ALL_OFFLOAD | CSUM_DATA_VALID)) {
m = virtio_net_tx_offload(ifp, m, false, &vhdr.hdr);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 1, 3:03 PM (6 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28394819
Default Alt Text
D51686.id159602.diff (5 KB)

Event Timeline