Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154532022
D56564.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
23 KB
Referenced Files
None
Subscribers
None
D56564.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D56564: offload: Compute and insert checksums as late as possible
Attached
Detach File
Event Timeline
Log In to Comment