Sat Dec 15 07:29:44 2018 UTC ()
Replace panic with rate-limited LOG_ERR message when we encounter
invalid ether frame with non-zero csum flags.

Requested by thorpej.


(rin)
diff -r1.4 -r1.5 src/sys/net/ether_sw_offload.c

cvs diff -r1.4 -r1.5 src/sys/net/ether_sw_offload.c (expand / switch to unified diff)

--- src/sys/net/ether_sw_offload.c 2018/12/13 20:54:50 1.4
+++ src/sys/net/ether_sw_offload.c 2018/12/15 07:29:44 1.5
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: ether_sw_offload.c,v 1.4 2018/12/13 20:54:50 rin Exp $ */ 1/* $NetBSD: ether_sw_offload.c,v 1.5 2018/12/15 07:29:44 rin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2018 The NetBSD Foundation, Inc. 4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Rin Okuyama. 8 * by Rin Okuyama.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -24,92 +24,108 @@ @@ -24,92 +24,108 @@
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#ifdef _KERNEL_OPT 32#ifdef _KERNEL_OPT
33#include "opt_inet.h" 33#include "opt_inet.h"
34#endif 34#endif
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: ether_sw_offload.c,v 1.4 2018/12/13 20:54:50 rin Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: ether_sw_offload.c,v 1.5 2018/12/15 07:29:44 rin Exp $");
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/types.h> 40#include <sys/types.h>
41#include <sys/mbuf.h> 41#include <sys/mbuf.h>
 42#include <sys/syslog.h>
 43#include <sys/time.h>
42 44
43#include <net/if.h> 45#include <net/if.h>
44#include <net/if_ether.h> 46#include <net/if_ether.h>
45#include <net/ether_sw_offload.h> 47#include <net/ether_sw_offload.h>
46 48
47#include <netinet/in.h> 49#include <netinet/in.h>
48#include <netinet/in_offload.h> 50#include <netinet/in_offload.h>
49#include <netinet/ip.h> 51#include <netinet/ip.h>
50#include <netinet/tcp.h> 52#include <netinet/tcp.h>
51#include <netinet/udp.h> 53#include <netinet/udp.h>
52 54
53#ifdef INET6 55#ifdef INET6
54#include <netinet/ip6.h> 56#include <netinet/ip6.h>
55#include <netinet6/in6.h> 57#include <netinet6/in6.h>
56#include <netinet6/in6_offload.h> 58#include <netinet6/in6_offload.h>
57#endif 59#endif
58 60
59/* 61/*
 62 * Limit error messages at most once per 10 seconds.
 63 */
 64static const struct timeval eso_err_interval = {
 65 .tv_sec = 10,
 66 .tv_usec = 0,
 67};
 68static struct timeval eso_err_lasttime;
 69
 70/*
60 * Handle TX offload in software. For TSO, split the packet into 71 * Handle TX offload in software. For TSO, split the packet into
61 * chanks with payloads of size MSS. For chekcsum offload, update 72 * chanks with payloads of size MSS. For chekcsum offload, update
62 * required checksum fields. The results are more than one packet 73 * required checksum fields. The results are more than one packet
63 * in general. Return a mbuf chain consists of them. 74 * in general. Return a mbuf chain consists of them.
64 */ 75 */
65 76
66struct mbuf * 77struct mbuf *
67ether_sw_offload_tx(struct ifnet *ifp, struct mbuf *m) 78ether_sw_offload_tx(struct ifnet *ifp, struct mbuf *m)
68{ 79{
69 struct ether_header *ep; 80 struct ether_header *ep;
70 int flags, ehlen; 81 int flags, ehlen;
 82 uint16_t type;
71#ifdef INET6 83#ifdef INET6
72 bool v6; 84 bool v6;
73#else 85#else
74 bool v6 __diagused; 86 bool v6 __diagused;
75#endif 87#endif
76 88
77 KASSERT(m->m_flags & M_PKTHDR); 89 KASSERT(m->m_flags & M_PKTHDR);
78 flags = m->m_pkthdr.csum_flags; 90 flags = m->m_pkthdr.csum_flags;
79 if (flags == 0) 91 if (flags == 0)
80 goto done; 92 goto done;
81 93
82 /* Sanity check */ 94 /* Sanity check */
83 if (!TX_OFFLOAD_SUPPORTED(ifp->if_csum_flags_tx, flags)) 95 if (!TX_OFFLOAD_SUPPORTED(ifp->if_csum_flags_tx, flags))
84 goto quit; 96 goto quit;
85 97
86 KASSERT(m->m_pkthdr.len >= sizeof(*ep)); 98 KASSERT(m->m_pkthdr.len >= sizeof(*ep));
87 if (m->m_len < sizeof(*ep)) { 99 if (m->m_len < sizeof(*ep)) {
88 m = m_pullup(m, sizeof(*ep)); 100 m = m_pullup(m, sizeof(*ep));
89 if (m == NULL) 101 if (m == NULL)
90 return NULL; 102 return NULL;
91 } 103 }
92 ep = mtod(m, struct ether_header *); 104 ep = mtod(m, struct ether_header *);
93 switch (ntohs(ep->ether_type)) { 105 switch (type = ntohs(ep->ether_type)) {
94 case ETHERTYPE_IP: 106 case ETHERTYPE_IP:
95 case ETHERTYPE_IPV6: 107 case ETHERTYPE_IPV6:
96 ehlen = ETHER_HDR_LEN; 108 ehlen = ETHER_HDR_LEN;
97 break; 109 break;
98 case ETHERTYPE_VLAN: 110 case ETHERTYPE_VLAN:
99 ehlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; 111 ehlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
100 break; 112 break;
101 default: 113 default:
102 panic("%s: unexpected frame type", __func__); 114 if (ratecheck(&eso_err_lasttime, &eso_err_interval))
 115 log(LOG_ERR, "%s: %s: dropping invalid frame "
 116 "type 0x%04hx csum_flags 0x%08x\n",
 117 __func__, ifp->if_xname, type, flags);
 118 goto quit;
103 } 119 }
104 KASSERT(m->m_pkthdr.len >= ehlen); 120 KASSERT(m->m_pkthdr.len >= ehlen);
105 121
106 v6 = flags & (M_CSUM_TSOv6 | M_CSUM_TCPv6 | M_CSUM_UDPv6); 122 v6 = flags & (M_CSUM_TSOv6 | M_CSUM_TCPv6 | M_CSUM_UDPv6);
107#ifndef INET6 123#ifndef INET6
108 KASSERT(!v6); 124 KASSERT(!v6);
109#endif 125#endif
110 126
111 if (flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6)) { 127 if (flags & (M_CSUM_TSOv4 | M_CSUM_TSOv6)) {
112 /* 128 /*
113 * tcp[46]_segment() assume that size of payloads is 129 * tcp[46]_segment() assume that size of payloads is
114 * a multiple of MSS. Further, tcp6_segment() assumes 130 * a multiple of MSS. Further, tcp6_segment() assumes
115 * no extention headers. 131 * no extention headers.