From: Jan Klemkow Subject: bridge(4): use checksum offloading To: tech@openbsd.org Date: Tue, 16 Sep 2025 14:45:42 +0200 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,