Download raw body.
bridge(4): use checksum offloading
Hi,
Similar to veb(4) this diff adds checksum offloading to bridge(4) and
vether(4). This diff is the last requirement for my vmd+offloading
diff[1]. Otherwise, vmd+bridge would break.
ok?
bye,
Jan
[1]: https://marc.info/?t=174779131200001&r=1&w=2
Index: net/if_bridge.c
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.c,v
diff -u -p -r1.377 if_bridge.c
--- net/if_bridge.c 16 Sep 2025 09:07:00 -0000 1.377
+++ net/if_bridge.c 16 Sep 2025 11:36:09 -0000
@@ -799,8 +799,11 @@ bridge_stop(struct bridge_softc *sc)
}
struct mbuf *
-bridge_offload(struct ifnet *ifp, struct mbuf *m)
+bridge_offload(struct ifnet *brifp, struct ifnet *ifp, struct mbuf *m)
{
+ struct ether_extracted ext;
+ int csum = 0;
+
#if NVLAN > 0
/*
* If the underlying interface has no VLAN hardware tagging support,
@@ -813,7 +816,63 @@ bridge_offload(struct ifnet *ifp, struct
return NULL;
}
#endif
+
+ if (ISSET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT) &&
+ !ISSET(ifp->if_capabilities, IFCAP_CSUM_IPv4))
+ csum = 1;
+
+ if (ISSET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT) &&
+ (!ISSET(ifp->if_capabilities, IFCAP_CSUM_TCPv4) ||
+ !ISSET(ifp->if_capabilities, IFCAP_CSUM_TCPv6)))
+ csum = 1;
+
+ if (ISSET(m->m_pkthdr.csum_flags, M_UDP_CSUM_OUT) &&
+ (!ISSET(ifp->if_capabilities, IFCAP_CSUM_UDPv4) ||
+ !ISSET(ifp->if_capabilities, IFCAP_CSUM_UDPv6)))
+ csum = 1;
+
+ if (csum) {
+ int ethlen;
+ int hlen;
+
+ ether_extract_headers(m, &ext);
+
+ ethlen = sizeof *ext.eh;
+ if (ext.evh)
+ ethlen = sizeof *ext.evh;
+
+ hlen = m->m_pkthdr.len - ext.paylen;
+
+ if (m->m_len < hlen) {
+ m = m_pullup(m, hlen);
+ if (m == NULL)
+ goto err;
+ }
+
+ /* hide ethernet header */
+ m->m_data += ethlen;
+ m->m_len -= ethlen;
+ m->m_pkthdr.len -= ethlen;
+
+ if (ext.ip4) {
+ in_hdr_cksum_out(m, ifp);
+ in_proto_cksum_out(m, ifp);
+#ifdef INET6
+ } else if (ext.ip6) {
+ in6_proto_cksum_out(m, ifp);
+#endif
+ }
+
+ /* show ethernet header again */
+ m->m_data -= ethlen;
+ m->m_len += ethlen;
+ m->m_pkthdr.len += ethlen;
+ }
+
return m;
+err:
+ counters_inc(brifp->if_counters, ifc_ierrors);
+ return NULL;
}
/*
@@ -1921,7 +1980,7 @@ bridge_ifenqueue(struct ifnet *brifp, st
{
int error, len;
- if ((m = bridge_offload(ifp, m)) == NULL) {
+ if ((m = bridge_offload(brifp, ifp, m)) == NULL) {
error = ENOBUFS;
goto err;
}
Index: net/if_vether.c
===================================================================
RCS file: /cvs/src/sys/net/if_vether.c,v
diff -u -p -r1.38 if_vether.c
--- net/if_vether.c 16 Sep 2025 09:07:00 -0000 1.38
+++ net/if_vether.c 16 Sep 2025 11:38:14 -0000
@@ -89,6 +89,9 @@ vether_clone_create(struct if_clone *ifc
#if NVLAN > 0
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
#endif
+ ifp->if_capabilities |= IFCAP_CSUM_IPv4;
+ ifp->if_capabilities |= IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
+ ifp->if_capabilities |= IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE;
ifmedia_init(&sc->sc_media, 0, vether_media_change,
bridge(4): use checksum offloading