diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-04-04 17:37:14 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-04-04 17:37:14 +0000 |
commit | 84636c8082b9aee9413dca55149c8d17a373523e (patch) | |
tree | 9c3ebe73bdec96177e962591eae4a4ee10c42c2c | |
parent | 4ac08e240a8b70d239bb2fed6f0d1a09f8da3038 (diff) | |
download | illumos-joyent-84636c8082b9aee9413dca55149c8d17a373523e.tar.gz |
OS-6812 implement RFD 118 interpretation of HCKSUM_INET_FULL_V4/6
-rw-r--r-- | usr/src/man/man9e/mac.9e | 26 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip6_output.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip_output.c | 8 | ||||
-rw-r--r-- | usr/src/uts/common/io/qede/qede_gld.c | 11 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dlpi.h | 7 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/viona/viona.c | 43 |
6 files changed, 84 insertions, 24 deletions
diff --git a/usr/src/man/man9e/mac.9e b/usr/src/man/man9e/mac.9e index 52984f9791..c22becc131 100644 --- a/usr/src/man/man9e/mac.9e +++ b/usr/src/man/man9e/mac.9e @@ -9,9 +9,9 @@ .\" http://www.illumos.org/license/CDDL. .\" .\" -.\" Copyright 2016 Joyent, Inc. +.\" Copyright 2018 Joyent, Inc. .\" -.Dd March 26, 2017 +.Dd March 23, 2018 .Dt MAC 9E .Os .Sh NAME @@ -550,24 +550,28 @@ The following set of flags may be combined through a bitwise inclusive OR: .Bl -tag -width Ds .It Sy HCKSUM_INET_PARTIAL This indicates that the hardware can calculate a partial checksum for -both IPv4 and IPv6; however, it requires the pseudo-header checksum be -calculated for it. +both IPv4 and IPv6 UDP and TCP packets; however, it requires the pseudo-header +checksum be calculated for it. The pseudo-header checksum will be available for the mblk_t when calling .Xr mac_hcksum_get 9F . -Note this does not imply that the hardware is capable of calculating the -IPv4 header checksum. +Note this does not imply that the hardware is capable of calculating +the partial checksum for other L4 protocols or the IPv4 header checksum. That should be indicated with the .Sy HCKSUM_IPHDRCKSUM flag. .It Sy HCKSUM_INET_FULL_V4 -This indicates that the hardware will fully calculate the L4 checksum -for outgoing IPv4 packets and does not require a pseudo-header checksum. +This indicates that the hardware will fully calculate the L4 checksum for +outgoing IPv4 UDP or TCP packets only, and does not require a pseudo-header +checksum. Note this does not imply that the hardware is capable of calculating the -IPv4 header checksum. +checksum for other L4 protocols or the IPv4 header checksum. That should be indicated with the .Sy HCKSUM_IPHDRCKSUM . .It Sy HCKSUM_INET_FULL_V6 -This indicates that the hardware will fully calculate the L4 checksum -for outgoing IPv6 packets and does not require a pseudo-header checksum. +This indicates that the hardware will fully calculate the L4 checksum for +outgoing IPv6 UDP or TCP packets only, and does not require a pseudo-header +checksum. +Note this does not imply that the hardware is capable of calculating the +checksum for any other L4 protocols. .It Sy HCKSUM_IPHDRCKSUM This indicates that the hardware supports calculating the checksum for the IPv4 header itself. diff --git a/usr/src/uts/common/inet/ip/ip6_output.c b/usr/src/uts/common/inet/ip/ip6_output.c index b023a2fe6a..dc074454e3 100644 --- a/usr/src/uts/common/inet/ip/ip6_output.c +++ b/usr/src/uts/common/inet/ip/ip6_output.c @@ -23,6 +23,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2017 OmniTI Computer Consulting, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. */ /* Copyright (c) 1990 Mentat Inc. */ @@ -866,8 +867,16 @@ ip_output_cksum_v6(iaflags_t ixaflags, mblk_t *mp, ip6_t *ip6h, ixa->ixa_raw_cksum_offset); cksum = htons(protocol); } else if (protocol == IPPROTO_ICMPV6) { - cksump = IPH_ICMPV6_CHECKSUMP(ip6h, ip_hdr_length); - cksum = IP_ICMPV6_CSUM_COMP; /* Pseudo-header cksum */ + /* + * Currently we assume no HW support for ICMP checksum calc. + * + * When HW support is advertised for ICMP, we'll want the + * following to be set: + * cksump = IPH_ICMPV6_CHECKSUMP(ip6h, ip_hdr_length); + * cksum = IP_ICMPV6_CSUM_COMP; Pseudo-header cksum + */ + + return (ip_output_sw_cksum_v6(mp, ip6h, ixa)); } else { ip_hdr_cksum: /* No IP header checksum for IPv6 */ diff --git a/usr/src/uts/common/inet/ip/ip_output.c b/usr/src/uts/common/inet/ip/ip_output.c index 5caa043a35..02a59e69c5 100644 --- a/usr/src/uts/common/inet/ip/ip_output.c +++ b/usr/src/uts/common/inet/ip/ip_output.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018 Joyent, Inc. */ /* Copyright (c) 1990 Mentat Inc. */ @@ -1737,6 +1738,13 @@ ip_output_cksum_v4(iaflags_t ixaflags, mblk_t *mp, ipha_t *ipha, #endif sctph->sh_chksum = sctp_cksum(mp, ip_hdr_length); goto ip_hdr_cksum; + } else if (protocol == IPPROTO_ICMP) { + /* + * Note that we always calculate a SW checksum for ICMP. In the + * future, if HW support for ICMP is advertised, we can change + * this. + */ + return (ip_output_sw_cksum_v4(mp, ipha, ixa)); } else { ip_hdr_cksum: /* Calculate IPv4 header checksum */ diff --git a/usr/src/uts/common/io/qede/qede_gld.c b/usr/src/uts/common/io/qede/qede_gld.c index 50a4013555..4098409c17 100644 --- a/usr/src/uts/common/io/qede/qede_gld.c +++ b/usr/src/uts/common/io/qede/qede_gld.c @@ -33,6 +33,9 @@ * limitations under the License. */ +/* + * Copyright 2018 Joyent, Inc. + */ #include "qede.h" @@ -2009,12 +2012,10 @@ qede_mac_get_capability(void *arg, } /* - * Hardware does not support ICMPv6 checksumming. Right now the - * GLDv3 doesn't provide us a way to specify that we don't - * support that. As such, we cannot indicate - * HCKSUM_INET_FULL_V6. + * Hardware does not support ICMPv6 checksumming, but + * HCKSUM_INET_FULL_V4/6 only applies for UDP and TCP. */ - *tx_flags = HCKSUM_INET_FULL_V4 | + *tx_flags = HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 | HCKSUM_IPHDRCKSUM; ret = B_TRUE; break; diff --git a/usr/src/uts/common/sys/dlpi.h b/usr/src/uts/common/sys/dlpi.h index 34f1c17236..d76daffeb7 100644 --- a/usr/src/uts/common/sys/dlpi.h +++ b/usr/src/uts/common/sys/dlpi.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -676,11 +677,11 @@ typedef struct { #define HCKSUM_ENABLE 0x01 /* Set to enable hardware checksum */ /* capability */ #define HCKSUM_INET_PARTIAL 0x02 /* Partial 1's complement checksum */ - /* ability */ + /* ability for TCP/UDP packets. */ #define HCKSUM_INET_FULL_V4 0x04 /* Full 1's complement checksum */ - /* ability for IPv4 packets. */ + /* ability for IPv4 TCP/UDP packets. */ #define HCKSUM_INET_FULL_V6 0x08 /* Full 1's complement checksum */ - /* ability for IPv6 packets. */ + /* ability for IPv6 TCP/UDP packets. */ #define HCKSUM_IPHDRCKSUM 0x10 /* IPv4 Header checksum offload */ /* capability */ #ifdef _KERNEL diff --git a/usr/src/uts/i86pc/io/viona/viona.c b/usr/src/uts/i86pc/io/viona/viona.c index 768a85f500..427a45cfad 100644 --- a/usr/src/uts/i86pc/io/viona/viona.c +++ b/usr/src/uts/i86pc/io/viona/viona.c @@ -56,6 +56,7 @@ #include <sys/mac_provider.h> #include <sys/mac_client_priv.h> #include <sys/vlan.h> +#include <inet/ip.h> #include <sys/vmm_drv.h> #include <sys/viona_io.h> @@ -1934,6 +1935,28 @@ viona_desb_release(viona_desb_t *dp) mutex_exit(&ring->vr_lock); } +static int +viona_mb_get_uint8(mblk_t *mp, off_t off, uint8_t *out) +{ + size_t mpsize; + uint8_t *bp; + + mpsize = msgsize(mp); + if (off + sizeof (uint8_t) > mpsize) + return (-1); + + mpsize = MBLKL(mp); + while (off >= mpsize) { + mp = mp->b_cont; + off -= mpsize; + mpsize = MBLKL(mp); + } + + bp = mp->b_rptr + off; + *out = *bp; + return (0); +} + static boolean_t viona_tx_csum(viona_vring_t *ring, const struct virtio_net_hdr *hdr, mblk_t *mp, uint32_t len) @@ -1942,6 +1965,7 @@ viona_tx_csum(viona_vring_t *ring, const struct virtio_net_hdr *hdr, const struct ether_header *eth; uint_t eth_len = sizeof (struct ether_header); ushort_t ftype; + uint8_t ipproto = IPPROTO_NONE; /* NONE is not exactly right, but ok */ eth = (const struct ether_header *)mp->b_rptr; if (MBLKL(mp) < sizeof (*eth)) { @@ -1959,11 +1983,22 @@ viona_tx_csum(viona_vring_t *ring, const struct virtio_net_hdr *hdr, ftype = ntohs(veth->ether_type); } + if (ftype == ETHERTYPE_IP) { + const size_t off = offsetof(ipha_t, ipha_protocol) + eth_len; + + (void) viona_mb_get_uint8(mp, off, &ipproto); + } else if (ftype == ETHERTYPE_IPV6) { + const size_t off = offsetof(ip6_t, ip6_nxt) + eth_len; + + (void) viona_mb_get_uint8(mp, off, &ipproto); + } + /* * Partial checksum support from the NIC is ideal, since it most * closely maps to the interface defined by virtio. */ - if ((link->l_cap_csum & HCKSUM_INET_PARTIAL) != 0) { + if ((link->l_cap_csum & HCKSUM_INET_PARTIAL) != 0 && + (ipproto == IPPROTO_TCP || ipproto == IPPROTO_UDP)) { uint_t start, stuff, end; /* @@ -1984,7 +2019,8 @@ viona_tx_csum(viona_vring_t *ring, const struct virtio_net_hdr *hdr, * checksum will need to calculated inline. */ if (ftype == ETHERTYPE_IP) { - if ((link->l_cap_csum & HCKSUM_INET_FULL_V4) != 0) { + if ((link->l_cap_csum & HCKSUM_INET_FULL_V4) != 0 && + (ipproto == IPPROTO_TCP || ipproto == IPPROTO_UDP)) { mac_hcksum_set(mp, 0, 0, 0, 0, HCK_FULLCKSUM); return (B_TRUE); } @@ -1994,7 +2030,8 @@ viona_tx_csum(viona_vring_t *ring, const struct virtio_net_hdr *hdr, VIONA_RING_STAT_INCR(ring, fail_hcksum); return (B_FALSE); } else if (ftype == ETHERTYPE_IPV6) { - if ((link->l_cap_csum & HCKSUM_INET_FULL_V6) != 0) { + if ((link->l_cap_csum & HCKSUM_INET_FULL_V6) != 0 && + (ipproto == IPPROTO_TCP || ipproto == IPPROTO_UDP)) { mac_hcksum_set(mp, 0, 0, 0, 0, HCK_FULLCKSUM); return (B_TRUE); } |