Page MenuHomeFreeBSD

D56564.id.diff
No OneTemporary

D56564.id.diff

diff --git a/sys/conf/files b/sys/conf/files
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -4239,6 +4239,7 @@
net/if_media.c standard
net/if_mib.c standard
net/if_ovpn.c optional ovpn inet | ovpn inet6
+net/if_offload.c optional inet | inet6
net/if_stf.c optional stf inet inet6
net/if_tuntap.c optional tuntap
net/if_vlan.c optional vlan
diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -91,6 +91,7 @@
#include <net/vnet.h>
#if defined(INET) || defined(INET6)
+#include <net/if_offload.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
@@ -2083,6 +2084,9 @@
ifp->if_flags |= IFF_UP;
getmicrotime(&ifp->if_lastchange);
+#if defined(INET) || defined(INET6)
+ if_offload_caps_changed(ifp);
+#endif /* defined(INET) || defined(INET6) */
if (ifp->if_carp)
(*carp_linkstate_p)(ifp);
rt_ifmsg(ifp, IFF_UP);
@@ -2529,6 +2533,9 @@
error = (*ifp->if_ioctl)(ifp, cmd, data);
if (error == 0)
getmicrotime(&ifp->if_lastchange);
+#if defined(INET) || defined(INET6)
+ if_offload_caps_changed(ifp);
+#endif /* defined(INET) || defined(INET6) */
break;
case SIOCSIFCAPNV:
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -4365,7 +4365,7 @@
ip = mtod(m, struct ip *);
m->m_pkthdr.csum_flags |= CSUM_IP;
- error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist);
+ error = ip_fragment(ip, &m, ifp->if_mtu);
if (error)
goto dropit;
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -369,6 +369,7 @@
eh = mtod(m, struct ether_header *);
memcpy(eh, phdr, hlen);
}
+ m->m_pkthdr.offload_l3_hdr_offset = hlen;
/*
* If a simplex interface, and the packet is being sent to our
diff --git a/sys/net/if_infiniband.c b/sys/net/if_infiniband.c
--- a/sys/net/if_infiniband.c
+++ b/sys/net/if_infiniband.c
@@ -438,6 +438,7 @@
error = ENOBUFS;
goto bad;
}
+ m->m_pkthdr.offload_l3_hdr_offset = hlen;
if ((pflags & RT_HAS_HEADER) == 0) {
ih = mtod(m, struct infiniband_header *);
memcpy(ih, phdr, hlen);
diff --git a/sys/net/if_offload.h b/sys/net/if_offload.h
new file mode 100644
--- /dev/null
+++ b/sys/net/if_offload.h
@@ -0,0 +1,48 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026, by Timo Voelker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NET_IF_OFFLOAD_H_
+#define _NET_IF_OFFLOAD_H_
+
+#include "opt_sctp.h"
+
+struct ifnet;
+struct mbuf;
+
+#if defined(SCTP) || defined(SCTP_SUPPORT)
+#define IF_OFFLOAD_EXPECTED4 (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP | CSUM_IP_SCTP)
+#define IF_OFFLOAD_EXPECTED6 (CSUM_IP6_UDP | CSUM_IP6_TCP | CSUM_IP6_SCTP)
+#else
+#define IF_OFFLOAD_EXPECTED4 (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP)
+#define IF_OFFLOAD_EXPECTED6 (CSUM_IP6_UDP | CSUM_IP6_TCP)
+#endif /* defined(SCTP) || defined(SCTP_SUPPORT) */
+#define IF_OFFLOAD_EXPECTED (IF_OFFLOAD_EXPECTED4 | IF_OFFLOAD_EXPECTED6)
+
+void if_offload_caps_changed(struct ifnet *);
+
+#endif /* !_NET_IF_OFFLOAD_H_ */
diff --git a/sys/net/if_offload.c b/sys/net/if_offload.c
new file mode 100644
--- /dev/null
+++ b/sys/net/if_offload.c
@@ -0,0 +1,305 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026, by Timo Voelker. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_inet6.h"
+#include "opt_inet.h"
+
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/sbuf.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_offload.h>
+#include <net/if_private.h>
+#include <net/ethernet.h>
+
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/ip_carp.h>
+#include <netinet/sctp_crc32.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+#ifdef INET
+#include <net/debugnet.h>
+#include <netinet/if_ether.h>
+#include <machine/in_cksum.h>
+#include <netinet/ip_var.h>
+#endif /* INET */
+#ifdef INET6
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
+#include <netinet/ip6.h>
+#endif /* INET6 */
+
+#define IF_OFFLOAD_DEBUG 0
+
+#if IF_OFFLOAD_DEBUG
+#define IF_OFFLOAD_LOG(a, ...) printf("%s:%d: " a "\n", __func__, __LINE__, \
+ ##__VA_ARGS__)
+#else
+#define IF_OFFLOAD_LOG(a, ...)
+#endif /* IF_OFFLOAD_DEBUG */
+
+SYSCTL_NODE(_net, OID_AUTO, offload, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
+ "Network interface offload capabilities");
+
+#ifdef INET
+/*
+ * Computes and inserts the IPv4 header checksum in the mbuf m.
+ * offset is the mbuf offset to the IPv4 header.
+ */
+static struct mbuf *
+if_offload_csum_ipv4(struct mbuf *m, uint16_t offset)
+{
+ struct ip *ip;
+ uint16_t ip_hdr_length;
+
+ if (__predict_false(m->m_len < (offset +
+ m->m_pkthdr.offload_l4_hdr_offset))) {
+ /* pullup the IP header. */
+ m = m_pullup(m, offset + m->m_pkthdr.offload_l4_hdr_offset);
+ if (m == NULL)
+ return (NULL);
+ }
+
+ ip = (struct ip *)mtodo(m, m->m_pkthdr.offload_l3_hdr_offset);
+ ip_hdr_length = (ip->ip_hl << 2);
+ IF_OFFLOAD_LOG(
+ "Compute IPv4 header checksum with offset=%d, ip_hdr_length=%d",
+ offset, ip_hdr_length);
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum_skip(m, offset + ip_hdr_length, offset);
+ m->m_pkthdr.csum_flags &= ~CSUM_IP;
+ return (m);
+}
+#endif /* INET */
+
+/*
+ * Computes and inserts the TCP/UDP checksum in the mbuf m.
+ * offset is the mbuf offset to the TCP/UDP header.
+ * l4csum_field_offset is the offset to the checksum field relative to the
+ * start of the TCP/UDP header.
+ * udp is true for UDP and false for TCP.
+ */
+static void
+if_offload_csum_tcpudp(struct mbuf *m, uint16_t offset,
+ uint16_t l4csum_field_offset, bool udp)
+{
+ uint16_t csum, field_total_offset, cklen;
+
+ IF_OFFLOAD_LOG(
+ "Compute TCP/UDP checksum with offset=%d, l4csum_field_offset=%d, udp=%d",
+ offset, l4csum_field_offset, udp);
+ cklen = m->m_pkthdr.len - offset;
+ csum = in_cksum_skip(m, offset + cklen, offset);
+ if (udp && csum == 0)
+ csum = 0xffff;
+
+ field_total_offset = offset + l4csum_field_offset;
+ if (m->m_len < (field_total_offset + sizeof(csum)))
+ m_copyback(m, field_total_offset, sizeof(csum), (caddr_t)&csum);
+ else
+ *(u_short *)mtodo(m, field_total_offset) = csum;
+ m->m_pkthdr.csum_flags &= ~(CSUM_IP_UDP | CSUM_IP_TCP | CSUM_IP6_UDP |
+ CSUM_IP6_TCP);
+}
+
+#if defined(SCTP) || defined(SCTP_SUPPORT)
+/*
+ * Computes and inserts the SCTP checksum in the mbuf m.
+ * offset is the mbuf offset to the SCTP header.
+ */
+static void
+if_offload_csum_sctp(struct mbuf *m, uint16_t offset)
+{
+ IF_OFFLOAD_LOG("Compute SCTP checksum with offset=%d", offset);
+ sctp_delayed_cksum(m, offset);
+ m->m_pkthdr.csum_flags &= ~(CSUM_IP_SCTP | CSUM_IP6_SCTP);
+}
+#endif /* defined(SCTP) || defined(SCTP_SUPPORT) */
+
+/*
+ * Performs the offload capabilities given by offload_req (e.g., compute and
+ * insert checksums) for the packet given by the mbuf m.
+ */
+static int
+if_offload_perform(struct mbuf *m, uint32_t offload_req)
+{
+ uint16_t offset, l4csum_field_offset;
+
+ IF_OFFLOAD_LOG("csum_flags=%b, offload_req=%b", m->m_pkthdr.csum_flags,
+ CSUM_BITS, offload_req, CSUM_BITS);
+
+ /* Check IP first. Compute and insert IPv4 header checksum. */
+#ifdef INET
+ if ((offload_req & CSUM_IP) != 0) {
+ offset = m->m_pkthdr.offload_l3_hdr_offset;
+ m = if_offload_csum_ipv4(m, offset);
+ if (m == NULL)
+ return (ENOMEM);
+ }
+#endif /* INET */
+
+ /* Compute and insert transport header checksum. */
+ offset = m->m_pkthdr.offload_l3_hdr_offset +
+ m->m_pkthdr.offload_l4_hdr_offset;
+ if ((offload_req & (CSUM_IP_TCP | CSUM_IP6_TCP)) != 0) {
+ l4csum_field_offset = offsetof(struct tcphdr, th_sum);
+ if_offload_csum_tcpudp(m, offset, l4csum_field_offset,
+ false);
+ } else if ((offload_req & (CSUM_IP_UDP | CSUM_IP6_UDP)) != 0) {
+ l4csum_field_offset = offsetof(struct udphdr, uh_sum);
+ if_offload_csum_tcpudp(m, offset, l4csum_field_offset,
+ true);
+ }
+#if defined(SCTP) || defined(SCTP_SUPPORT)
+ else if ((offload_req & (CSUM_IP_SCTP | CSUM_IP6_SCTP)) != 0)
+ if_offload_csum_sctp(m, offset);
+#endif /* defined(SCTP) || defined(SCTP_SUPPORT) */
+
+ return 0;
+}
+
+/*
+ * Checks if offload capabilities requested by the mbuf m need to be performed
+ * in software due to the lack of support from the interface (driver) ifp.
+ */
+static inline int
+if_offload_transmit(struct ifnet *ifp, struct mbuf *m)
+{
+ uint32_t offload_req;
+ int error;
+
+ IF_OFFLOAD_LOG("Enter if_offload_transmit for %s", ifp->if_xname);
+ KASSERT((m->m_flags & M_PKTHDR) != 0,
+ ("Cannot transmit packet without an mbuf packet header"));
+
+ /* determine the offload capabilities required to be performed here */
+ offload_req = m->m_pkthdr.csum_flags & IF_OFFLOAD_EXPECTED
+ & ~ifp->if_hwassist;
+ if (offload_req == 0)
+ return ((ifp->if_transmit_orig)(ifp, m));
+
+ error = if_offload_perform(m, offload_req);
+ if (error != 0)
+ return (error);
+ return ((ifp->if_transmit_orig)(ifp, m));
+}
+
+/*
+ * Called when interface capabilities may have changed. It checks if the
+ * interface ifp supports all the expected offload capabilities. If not, it sets
+ * ifp->if_transmit to if_offload_transmit.
+ */
+void
+if_offload_caps_changed(struct ifnet *ifp)
+{
+ uint32_t mask;
+
+ IF_OFFLOAD_LOG("Enter if_offload_caps_changed for %s", ifp->if_xname);
+ mask = (ifp->if_hwassist & IF_OFFLOAD_EXPECTED) ^ IF_OFFLOAD_EXPECTED;
+ if (mask == 0) {
+ IF_OFFLOAD_LOG(
+ "Interface does support all expected offload capabilities.");
+ if (if_gettransmitfn(ifp) == if_offload_transmit) {
+ IF_OFFLOAD_LOG(
+ "Change if_transmit back to original if_transmit.");
+ if_settransmitfn(ifp, ifp->if_transmit_orig);
+ }
+ } else {
+ IF_OFFLOAD_LOG(
+ "Interface doesn't support all expected offload capabilities. It misses: %b",
+ (uint32_t)mask, CSUM_BITS);
+ if (if_gettransmitfn(ifp) != if_offload_transmit) {
+ IF_OFFLOAD_LOG(
+ "Change if_transmit to if_offload_transmit.");
+ ifp->if_transmit_orig = if_gettransmitfn(ifp);
+ if_settransmitfn(ifp, if_offload_transmit);
+ }
+ }
+}
+
+static int
+if_offload_sysctl_expected_capabilities(SYSCTL_HANDLER_ARGS)
+{
+ struct sbuf sb;
+ int error;
+
+ sbuf_new_for_sysctl(&sb, NULL, 0, req);
+ sbuf_printf(&sb, "%b", IF_OFFLOAD_EXPECTED, CSUM_BITS);
+ error = sbuf_finish(&sb);
+ sbuf_delete(&sb);
+ return (error);
+}
+
+SYSCTL_PROC(_net_offload, OID_AUTO, expected_capabilities,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ if_offload_sysctl_expected_capabilities, "A",
+ "Expected offload capabilities");
+
+static int
+if_offload_sysctl_interfaces(SYSCTL_HANDLER_ARGS)
+{
+ struct ifnet *ifp;
+ struct sbuf sb;
+ int error;
+
+ sbuf_new_for_sysctl(&sb, NULL, 0, req);
+ sbuf_printf(&sb, "\n%-16s%-16s%s\n", "Interface", "Software", "Which");
+
+ IFNET_RLOCK();
+ CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
+ /* only active interfaces */
+ if ((ifp->if_flags & IFF_UP) &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ uint32_t mask;
+
+ mask = (ifp->if_hwassist & IF_OFFLOAD_EXPECTED) ^
+ IF_OFFLOAD_EXPECTED;
+ sbuf_printf(&sb, "%-16.15s%-16s%b\n", ifp->if_xname,
+ (if_gettransmitfn(ifp) == if_offload_transmit ?
+ "yes" : "no"),
+ mask, CSUM_BITS);
+ }
+ }
+ IFNET_RUNLOCK();
+
+ error = sbuf_finish(&sb);
+ sbuf_delete(&sb);
+ return (error);
+}
+
+SYSCTL_PROC(_net_offload, OID_AUTO, interfaces,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ if_offload_sysctl_interfaces, "A",
+ "List of active interfaces, indicating whether offload capabilities are performed in software and which");
diff --git a/sys/net/if_private.h b/sys/net/if_private.h
--- a/sys/net/if_private.h
+++ b/sys/net/if_private.h
@@ -132,6 +132,7 @@
(struct ifnet *, struct sockaddr **, struct sockaddr *);
if_qflush_fn_t if_qflush; /* flush any queue */
if_transmit_fn_t if_transmit; /* initiate output routine */
+ if_transmit_fn_t if_transmit_orig; /* original output routine */
if_reassign_fn_t if_reassign; /* reassign to vnet routine */
if_get_counter_t if_get_counter; /* get counter values */
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -469,32 +469,6 @@
} else
gw = (const struct sockaddr *)dst;
- /*
- * If the IP/SCTP/TCP/UDP header still needs a valid checksum and the
- * interface will not calculate it for us, do it here.
- * Note that if we defer checksum calculation, we might send an ICMP
- * message later that reflects this packet, which still has an
- * invalid checksum.
- */
- if (__predict_false(m->m_pkthdr.csum_flags & CSUM_IP &
- ~nh->nh_ifp->if_hwassist)) {
- ip->ip_sum = 0;
- ip->ip_sum = in_cksum(m, (ip->ip_hl << 2));
- m->m_pkthdr.csum_flags &= ~CSUM_IP;
- }
- if (__predict_false(m->m_pkthdr.csum_flags & CSUM_DELAY_DATA &
- ~nh->nh_ifp->if_hwassist)) {
- in_delayed_cksum(m);
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
- }
-#if defined(SCTP) || defined(SCTP_SUPPORT)
- if (__predict_false(m->m_pkthdr.csum_flags & CSUM_IP_SCTP &
- ~nh->nh_ifp->if_hwassist)) {
- sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2));
- m->m_pkthdr.csum_flags &= ~CSUM_IP_SCTP;
- }
-#endif
-
/* Handle redirect case. */
redest.s_addr = 0;
if (V_ipsendredirects && osrc.s_addr == ip->ip_src.s_addr &&
@@ -528,8 +502,7 @@
* We have to fragment the packet
*/
m->m_pkthdr.csum_flags |= CSUM_IP;
- if (ip_fragment(ip, &m, nh->nh_mtu,
- nh->nh_ifp->if_hwassist) != 0)
+ if (ip_fragment(ip, &m, nh->nh_mtu) != 0)
goto drop;
KASSERT(m != NULL, ("null mbuf and no error"));
/*
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -2422,7 +2422,7 @@
} else {
/* Fragment the packet */
mb_copy->m_pkthdr.csum_flags |= CSUM_IP;
- if (ip_fragment(ip, &mb_copy, mtu, 0) != 0) {
+ if (ip_fragment(ip, &mb_copy, mtu) != 0) {
m_freem(mb_copy);
return NULL;
}
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -758,17 +758,8 @@
}
}
+ m->m_pkthdr.offload_l4_hdr_offset = hlen;
m->m_pkthdr.csum_flags |= CSUM_IP;
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA & ~ifp->if_hwassist) {
- in_delayed_cksum(m);
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
- }
-#if defined(SCTP) || defined(SCTP_SUPPORT)
- if (m->m_pkthdr.csum_flags & CSUM_SCTP & ~ifp->if_hwassist) {
- sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2));
- m->m_pkthdr.csum_flags &= ~CSUM_SCTP;
- }
-#endif
/*
* If small enough for interface, or the interface will take
@@ -781,11 +772,6 @@
(m->m_pkthdr.csum_flags & ifp->if_hwassist &
(CSUM_TSO | CSUM_INNER_TSO)) != 0) {
ip->ip_sum = 0;
- if (m->m_pkthdr.csum_flags & CSUM_IP & ~ifp->if_hwassist) {
- ip->ip_sum = in_cksum(m, hlen);
- m->m_pkthdr.csum_flags &= ~CSUM_IP;
- }
-
/*
* Record statistics for this interface address.
* With CSUM_TSO the byte/packet count will be slightly
@@ -829,7 +815,7 @@
* Too large for interface; fragment if possible. If successful,
* on return, m will point to a list of packets to be sent.
*/
- error = ip_fragment(ip, &m, mtu, ifp->if_hwassist);
+ error = ip_fragment(ip, &m, mtu);
if (error)
goto bad;
for (; m; m = m0) {
@@ -870,12 +856,9 @@
* mbuf to be fragmented; on return it points to the chain with the fragments.
* Return 0 if no error. If error, m_frag may contain a partially built
* chain of fragments that should be freed by the caller.
- *
- * if_hwassist_flags is the hw offload capabilities (see if_data.ifi_hwassist)
*/
int
-ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
- u_long if_hwassist_flags)
+ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu)
{
int error = 0;
int hlen = ip->ip_hl << 2;
@@ -1016,10 +999,6 @@
#endif
mhip->ip_off = htons(mhip->ip_off);
mhip->ip_sum = 0;
- if (m->m_pkthdr.csum_flags & CSUM_IP & ~if_hwassist_flags) {
- mhip->ip_sum = in_cksum(m, mhlen);
- m->m_pkthdr.csum_flags &= ~CSUM_IP;
- }
*mnext = m;
mnext = &m->m_nextpkt;
}
@@ -1034,10 +1013,6 @@
ip->ip_len = htons((u_short)m0->m_pkthdr.len);
ip->ip_off = htons(ip_off | IP_MF);
ip->ip_sum = 0;
- if (m0->m_pkthdr.csum_flags & CSUM_IP & ~if_hwassist_flags) {
- ip->ip_sum = in_cksum(m0, hlen);
- m0->m_pkthdr.csum_flags &= ~CSUM_IP;
- }
done:
*m_frag = m0;
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -220,8 +220,7 @@
int inp_setmoptions(struct inpcb *, struct sockopt *);
int ip_ctloutput(struct socket *, struct sockopt *sopt);
-int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
- u_long if_hwassist_flags);
+int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu);
void ip_forward(struct mbuf *m, int srcrt);
int ip_output(struct mbuf *,
struct mbuf *, struct route *, int, struct ip_moptions *,
diff --git a/sys/netinet6/ip6_fastfwd.c b/sys/netinet6/ip6_fastfwd.c
--- a/sys/netinet6/ip6_fastfwd.c
+++ b/sys/netinet6/ip6_fastfwd.c
@@ -281,29 +281,6 @@
ip6->ip6_hlim -= IPV6_HLIMDEC;
}
- /*
- * If TCP/UDP header still needs a valid checksum and interface will not
- * calculate it for us, do it here.
- */
- if (__predict_false(m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6 &
- ~nh->nh_ifp->if_hwassist)) {
- int offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, NULL);
-
- if (offset < sizeof(struct ip6_hdr) || offset > m->m_pkthdr.len)
- goto drop;
- in6_delayed_cksum(m, m->m_pkthdr.len - offset, offset);
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
- }
-#if defined(SCTP) || defined(SCTP_SUPPORT)
- if (__predict_false(m->m_pkthdr.csum_flags & CSUM_IP6_SCTP &
- ~nh->nh_ifp->if_hwassist)) {
- int offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, NULL);
-
- sctp_delayed_cksum(m, offset);
- m->m_pkthdr.csum_flags &= ~CSUM_IP6_SCTP;
- }
-#endif
-
m_clrprotoflags(m); /* Avoid confusing lower layers. */
IP_PROBE(send, NULL, NULL, ip6, nh->nh_ifp, NULL, ip6);
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -392,29 +392,6 @@
goto bad;
}
- /*
- * If TCP/UDP header still needs a valid checksum and interface will not
- * calculate it for us, do it here.
- */
- if (__predict_false(m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6 &
- ~nh->nh_ifp->if_hwassist)) {
- int offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, NULL);
-
- if (offset < sizeof(struct ip6_hdr) || offset > m->m_pkthdr.len)
- goto bad;
- in6_delayed_cksum(m, m->m_pkthdr.len - offset, offset);
- m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
- }
-#if defined(SCTP) || defined(SCTP_SUPPORT)
- if (__predict_false(m->m_pkthdr.csum_flags & CSUM_IP6_SCTP &
- ~nh->nh_ifp->if_hwassist)) {
- int offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, NULL);
-
- sctp_delayed_cksum(m, offset);
- m->m_pkthdr.csum_flags &= ~CSUM_IP6_SCTP;
- }
-#endif
-
/* Currently LLE layer stores embedded IPv6 addresses */
if (IN6_IS_SCOPE_LINKLOCAL(&dst.sin6_addr)) {
in6_set_unicast_scopeid(&dst.sin6_addr, dst.sin6_scope_id);
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -540,6 +540,7 @@
/* Adjust mbuf packet header length. */
m->m_pkthdr.len += optlen;
plen = m->m_pkthdr.len - sizeof(*ip6);
+ m->m_pkthdr.offload_l4_hdr_offset = sizeof(*ip6) + optlen;
if (plen > IPV6_MAXPACKET) {
error = EMSGSIZE;
@@ -1121,12 +1122,10 @@
} else
tso = 0;
/*
- * If we added extension headers, we will not do TSO and calculate the
- * checksums ourselves for now.
+ * If we added extension headers, we will not do TSO for now.
* XXX-BZ Need a framework to know when the NIC can handle it, even
* with ext. hdrs.
*/
- ip6_output_delayed_csum(m, ifp, sw_csum, plen, optlen);
/* XXX-BZ m->m_pkthdr.csum_flags &= ~ifp->if_hwassist; */
tlen = m->m_pkthdr.len;
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -10011,7 +10011,7 @@
goto bad;
}
- error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist);
+ error = ip_fragment(ip, &m0, ifp->if_mtu);
if (error) {
SDT_PROBE1(pf, ip, route_to, drop, __LINE__);
action = PF_DROP;
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -217,7 +217,9 @@
#define vt_nrecs PH_per.sixteen[0] /* mld and v6-ND */
#define tso_segsz PH_per.sixteen[1] /* inbound after LRO */
#define lro_nsegs tso_segsz /* inbound after LRO */
-#define csum_data PH_per.thirtytwo[1] /* inbound from hardware up */
+#define offload_l3_hdr_offset PH_per.eight[4] /* outbound: IP header offset */
+#define offload_l4_hdr_offset PH_per.eight[5] /* outbound: layer 4 header offset relative to start of IP header */
+#define csum_data PH_per.sixteen[3] /* inbound from hardware up */
#define lro_tcp_d_len PH_loc.sixteen[0] /* inbound during LRO (no reassembly) */
#define lro_tcp_d_csum PH_loc.sixteen[1] /* inbound during LRO (no reassembly) */
#define lro_tcp_h_off PH_loc.sixteen[2] /* inbound during LRO (no reassembly) */

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 29, 8:28 PM (17 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32268991
Default Alt Text
D56564.id.diff (23 KB)

Event Timeline