Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/xen/xen add support for skipping IPv6 checksum vali...



details:   https://anonhg.NetBSD.org/src/rev/16eb5db79364
branches:  trunk
changeset: 746099:16eb5db79364
user:      jdolecek <jdolecek%NetBSD.org@localhost>
date:      Sun Mar 22 00:11:02 2020 +0000

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

diffstat:

 sys/arch/xen/xen/if_xennet_xenbus.c  |   16 +++-
 sys/arch/xen/xen/xennet_checksum.c   |  115 ++++++++++++++++++++++++++--------
 sys/arch/xen/xen/xennetback_xenbus.c |   16 +++-
 3 files changed, 108 insertions(+), 39 deletions(-)

diffs (300 lines):

diff -r c86cb73b8189 -r 16eb5db79364 sys/arch/xen/xen/if_xennet_xenbus.c
--- a/sys/arch/xen/xen/if_xennet_xenbus.c       Sun Mar 22 00:05:17 2020 +0000
+++ b/sys/arch/xen/xen/if_xennet_xenbus.c       Sun Mar 22 00:11:02 2020 +0000
@@ -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 @@
        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 @@
                        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;
diff -r c86cb73b8189 -r 16eb5db79364 sys/arch/xen/xen/xennet_checksum.c
--- a/sys/arch/xen/xen/xennet_checksum.c        Sun Mar 22 00:05:17 2020 +0000
+++ b/sys/arch/xen/xen/xennet_checksum.c        Sun Mar 22 00:11:02 2020 +0000
@@ -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 @@
 #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_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 @@
 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 @@
                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 @@
 
        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 @@
                 * 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 @@
                            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
diff -r c86cb73b8189 -r 16eb5db79364 sys/arch/xen/xen/xennetback_xenbus.c
--- a/sys/arch/xen/xen/xennetback_xenbus.c      Sun Mar 22 00:05:17 2020 +0000
+++ b/sys/arch/xen/xen/xennetback_xenbus.c      Sun Mar 22 00:11:02 2020 +0000
@@ -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 @@
        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 @@
                        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 @@
                        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;



Home | Main Index | Thread Index | Old Index