Module Name:    src
Committed By:   jdolecek
Date:           Sun Mar 22 00:11:02 UTC 2020

Modified Files:
        src/sys/arch/xen/xen: if_xennet_xenbus.c xennet_checksum.c
            xennetback_xenbus.c

Log Message:
add support for skipping IPv6 checksum validation aka offloading -
for xennet(4) both Rx and Tx, for xvif(4) only Tx for now


To generate a diff of this commit:
cvs rdiff -u -r1.92 -r1.93 src/sys/arch/xen/xen/if_xennet_xenbus.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/xen/xen/xennet_checksum.c
cvs rdiff -u -r1.83 -r1.84 src/sys/arch/xen/xen/xennetback_xenbus.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/xen/xen/if_xennet_xenbus.c
diff -u src/sys/arch/xen/xen/if_xennet_xenbus.c:1.92 src/sys/arch/xen/xen/if_xennet_xenbus.c:1.93
--- src/sys/arch/xen/xen/if_xennet_xenbus.c:1.92	Thu Mar 19 10:53:43 2020
+++ src/sys/arch/xen/xen/if_xennet_xenbus.c	Sun Mar 22 00:11:02 2020
@@ -1,4 +1,4 @@
-/*      $NetBSD: if_xennet_xenbus.c,v 1.92 2020/03/19 10:53:43 jdolecek Exp $      */
+/*      $NetBSD: if_xennet_xenbus.c,v 1.93 2020/03/22 00:11:02 jdolecek Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -84,7 +84,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_xennet_xenbus.c,v 1.92 2020/03/19 10:53:43 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_xennet_xenbus.c,v 1.93 2020/03/22 00:11:02 jdolecek Exp $");
 
 #include "opt_xen.h"
 #include "opt_nfs_boot.h"
@@ -389,7 +389,14 @@ xennet_xenbus_attach(device_t parent, de
 	ifp->if_capabilities =
 		IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_IPv4_Tx
 		| IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_UDPv4_Tx
-		| IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx;
+		| IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx
+		| IFCAP_CSUM_UDPv6_Rx | IFCAP_CSUM_UDPv6_Tx
+		| IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_TCPv6_Tx;
+#define XN_M_CSUM_SUPPORTED (					\
+		M_CSUM_TCPv4 | M_CSUM_UDPv4 | M_CSUM_IPv4	\
+		| M_CSUM_TCPv6 | M_CSUM_UDPv6			\
+	)
+
 	IFQ_SET_READY(&ifp->if_snd);
 	if_attach(ifp);
 	ether_ifattach(ifp, sc->sc_enaddr);
@@ -1229,8 +1236,7 @@ xennet_softstart(void *arg)
 			break;
 		}
 
-		if ((m->m_pkthdr.csum_flags &
-		    (M_CSUM_TCPv4 | M_CSUM_UDPv4 | M_CSUM_IPv4)) != 0) {
+		if ((m->m_pkthdr.csum_flags & XN_M_CSUM_SUPPORTED) != 0) {
 			txflags = NETTXF_csum_blank;
 		} else {
 			txflags = NETTXF_data_validated;

Index: src/sys/arch/xen/xen/xennet_checksum.c
diff -u src/sys/arch/xen/xen/xennet_checksum.c:1.8 src/sys/arch/xen/xen/xennet_checksum.c:1.9
--- src/sys/arch/xen/xen/xennet_checksum.c:1.8	Thu Mar 19 10:53:43 2020
+++ src/sys/arch/xen/xen/xennet_checksum.c	Sun Mar 22 00:11:02 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: xennet_checksum.c,v 1.8 2020/03/19 10:53:43 jdolecek Exp $	*/
+/*	$NetBSD: xennet_checksum.c,v 1.9 2020/03/22 00:11:02 jdolecek Exp $	*/
 
 /*-
  * Copyright (c)2006 YAMAMOTO Takashi,
@@ -27,7 +27,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xennet_checksum.c,v 1.8 2020/03/19 10:53:43 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xennet_checksum.c,v 1.9 2020/03/22 00:11:02 jdolecek Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_inet.h"
+#endif
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -43,6 +47,8 @@ __KERNEL_RCSID(0, "$NetBSD: xennet_check
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
+#include <netinet/ip6.h>
+#include <netinet6/in6_offload.h>
 
 #include <xen/xennet_checksum.h>
 
@@ -57,16 +63,15 @@ EVCNT_ATTACH_STATIC(xn_cksum_defer);
 EVCNT_ATTACH_STATIC(xn_cksum_undefer);
 EVCNT_ATTACH_STATIC(xn_cksum_valid);
 
+#ifdef XENNET_DEBUG
 /* ratecheck(9) for checksum validation failures */
 static const struct timeval xn_cksum_errintvl = { 600, 0 };  /* 10 min, each */
+#endif
 
 static void *
 m_extract(struct mbuf *m, int off, int len)
 {
-	KASSERT(m->m_pkthdr.len >= off + len);
-	KASSERT(m->m_len >= off + len);
-
-	if (m->m_pkthdr.len >= off + len)
+	if (m->m_len >= off + len)
 		return mtod(m, char *) + off;
 	else
 		return NULL;
@@ -80,7 +85,10 @@ int
 xennet_checksum_fill(struct ifnet *ifp, struct mbuf *m, bool data_validated)
 {
 	const struct ether_header *eh;
-	struct ip *iph;
+	struct ip *iph = NULL;
+#ifdef INET6
+	struct ip6_hdr *ip6h = NULL;
+#endif
 	int ehlen;
 	int iphlen;
 	int iplen;
@@ -98,27 +106,49 @@ xennet_checksum_fill(struct ifnet *ifp, 
 		return EINVAL;
 	}
 	etype = eh->ether_type;
-	if (etype == htobe16(ETHERTYPE_VLAN)) {
-		ehlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
-	} else if (etype == htobe16(ETHERTYPE_IP)) {
-		ehlen = ETHER_HDR_LEN;
-	} else {
-		static struct timeval lasttime;
-		if (ratecheck(&lasttime, &xn_cksum_errintvl))
-			printf("%s: unknown etype %#x passed%s\n",
-			    ifp->if_xname, ntohs(etype),
-			    data_validated ? "" : " no checksum");
-		return EINVAL;
+	ehlen = ETHER_HDR_LEN;
+	if (__predict_false(etype == htons(ETHERTYPE_VLAN))) {
+		struct ether_vlan_header *evl = m_extract(m, 0, sizeof(*evl));
+		if (evl == NULL) {
+			/* Too short, packet will be dropped by upper layer */
+			return EINVAL;
+		}
+		ehlen += ETHER_VLAN_ENCAP_LEN;
+		etype = ntohs(evl->evl_proto);
 	}
 
-	iph = m_extract(m, ehlen, sizeof(*iph));
-	if (iph == NULL) {
-		/* Too short, packet will be dropped by upper layer */
-		return EINVAL;
+	switch (etype) {
+	case htons(ETHERTYPE_IP):
+		iph = m_extract(m, ehlen, sizeof(*iph));
+		if (iph == NULL) {
+			/* Too short, packet will be dropped by upper layer */
+			return EINVAL;
+		}
+		nxt = iph->ip_p;
+		iphlen = iph->ip_hl << 2;
+		iplen = ntohs(iph->ip_len);
+		break;
+#ifdef INET6
+	case htons(ETHERTYPE_IPV6):
+		ip6h = m_extract(m, ehlen, sizeof(*ip6h));
+		if (ip6h == NULL) {
+			/* Too short, packet will be dropped by upper layer */
+			return EINVAL;
+		}
+		if ((ip6h->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+			/* Bad version */
+			return EINVAL;
+		}
+		nxt = ip6h->ip6_nxt;
+		iphlen = sizeof(*ip6h);
+		iplen = ntohs(ip6h->ip6_plen);
+		break;
+#endif
+	default:
+		/* Not supported ethernet type */
+		return EOPNOTSUPP;
 	}
-	nxt = iph->ip_p;
-	iphlen = iph->ip_hl << 2;
-	iplen = ntohs(iph->ip_len);
+
 	if (ehlen + iplen > m->m_pkthdr.len) {
 		/* Too short, packet will be dropped by upper layer */
 		return EINVAL;
@@ -126,27 +156,47 @@ xennet_checksum_fill(struct ifnet *ifp, 
 
 	switch (nxt) {
 	case IPPROTO_UDP:
-		m->m_pkthdr.csum_flags = M_CSUM_UDPv4 | M_CSUM_IPv4;
+		if (iph)
+			m->m_pkthdr.csum_flags = M_CSUM_UDPv4 | M_CSUM_IPv4;
+#ifdef INET6
+		else
+			m->m_pkthdr.csum_flags = M_CSUM_UDPv6;
+#endif
 		m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
 		m->m_pkthdr.csum_data |= iphlen << 16;
 		break;
 	case IPPROTO_TCP:
-		m->m_pkthdr.csum_flags = M_CSUM_TCPv4 | M_CSUM_IPv4;
+		if (iph)
+			m->m_pkthdr.csum_flags = M_CSUM_TCPv4 | M_CSUM_IPv4;
+#ifdef INET6
+		else
+			m->m_pkthdr.csum_flags = M_CSUM_TCPv6;
+#endif
 		m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
 		m->m_pkthdr.csum_data |= iphlen << 16;
 		break;
 	case IPPROTO_ICMP:
 	case IPPROTO_IGMP:
-		m->m_pkthdr.csum_flags = M_CSUM_IPv4;
+		if (iph)
+			m->m_pkthdr.csum_flags = M_CSUM_IPv4;
 		m->m_pkthdr.csum_data = iphlen << 16;
 		break;
+	case IPPROTO_HOPOPTS:
+	case IPPROTO_ICMPV6:
+	case IPPROTO_FRAGMENT:
+		/* nothing to do */
+		error = 0;
+		goto out;
+		/* NOTREACHED */
 	default:
 	    {
+#ifdef XENNET_DEBUG
 		static struct timeval lasttime;
 		if (ratecheck(&lasttime, &xn_cksum_errintvl))
 			printf("%s: unknown proto %d passed%s\n",
 			    ifp->if_xname, nxt,
 			    data_validated ? "" : " no checksum");
+#endif /* XENNET_DEBUG */
 		error = EINVAL;
 		goto out;
 	    }
@@ -163,7 +213,7 @@ xennet_checksum_fill(struct ifnet *ifp, 
 		 * checksumming requires this. in_undefer_cksum()
 		 * also needs it to be zero.
 		 */
-		if (m->m_pkthdr.csum_flags & M_CSUM_IPv4)
+		if (iph != NULL && (m->m_pkthdr.csum_flags & M_CSUM_IPv4))
 			iph->ip_sum = 0;
 
 		if (sw_csum & (M_CSUM_IPv4|M_CSUM_UDPv4|M_CSUM_TCPv4)) {
@@ -171,6 +221,13 @@ xennet_checksum_fill(struct ifnet *ifp, 
 			    sw_csum & (M_CSUM_IPv4|M_CSUM_UDPv4|M_CSUM_TCPv4));
 		}
 
+#ifdef INET6
+		if (sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6)) {
+			in6_undefer_cksum(m, ehlen,
+			    sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6));
+		}
+#endif
+
 		if (m->m_pkthdr.csum_flags != 0) {
 			xn_cksum_defer.ev_count++;
 #ifdef M_CSUM_BLANK

Index: src/sys/arch/xen/xen/xennetback_xenbus.c
diff -u src/sys/arch/xen/xen/xennetback_xenbus.c:1.83 src/sys/arch/xen/xen/xennetback_xenbus.c:1.84
--- src/sys/arch/xen/xen/xennetback_xenbus.c:1.83	Sat Mar 21 23:25:53 2020
+++ src/sys/arch/xen/xen/xennetback_xenbus.c	Sun Mar 22 00:11:02 2020
@@ -1,4 +1,4 @@
-/*      $NetBSD: xennetback_xenbus.c,v 1.83 2020/03/21 23:25:53 jdolecek Exp $      */
+/*      $NetBSD: xennetback_xenbus.c,v 1.84 2020/03/22 00:11:02 jdolecek Exp $      */
 
 /*
  * Copyright (c) 2006 Manuel Bouyer.
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.83 2020/03/21 23:25:53 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.84 2020/03/22 00:11:02 jdolecek Exp $");
 
 #include "opt_xen.h"
 
@@ -306,7 +306,13 @@ xennetback_xenbus_create(struct xenbus_d
 	ifp->if_capabilities =
 		IFCAP_CSUM_IPv4_Tx
 		| IFCAP_CSUM_UDPv4_Tx
-		| IFCAP_CSUM_TCPv4_Tx;
+		| IFCAP_CSUM_TCPv4_Tx
+		| IFCAP_CSUM_UDPv6_Tx
+		| IFCAP_CSUM_TCPv6_Tx;
+#define XN_M_CSUM_SUPPORTED	(				\
+		M_CSUM_TCPv4 | M_CSUM_UDPv4 | M_CSUM_IPv4	\
+		| M_CSUM_TCPv6 | M_CSUM_UDPv6			\
+	)
 	ifp->if_ioctl = xennetback_ifioctl;
 	ifp->if_start = xennetback_ifstart;
 	ifp->if_watchdog = xennetback_ifwatchdog;
@@ -1050,7 +1056,7 @@ xennetback_ifsoftstart_transfer(void *ar
 			rxresp->offset = offset;
 			rxresp->status = m->m_pkthdr.len;
 			if ((m->m_pkthdr.csum_flags &
-			    (M_CSUM_TCPv4 | M_CSUM_UDPv4 | M_CSUM_IPv4)) != 0) {
+			    XN_M_CSUM_SUPPORTED) != 0) {
 				rxresp->flags = NETRXF_csum_blank;
 			} else {
 				rxresp->flags = NETRXF_data_validated;
@@ -1366,7 +1372,7 @@ xennetback_ifsoftstart_copy(void *arg)
 			rxresp->offset = 0;
 			rxresp->status = m->m_pkthdr.len;
 			if ((m->m_pkthdr.csum_flags &
-			    (M_CSUM_TCPv4 | M_CSUM_UDPv4 | M_CSUM_IPv4)) != 0) {
+			    XN_M_CSUM_SUPPORTED) != 0) {
 				rxresp->flags = NETRXF_csum_blank;
 			} else {
 				rxresp->flags = NETRXF_data_validated;

Reply via email to