From: Alexander Bluhm Subject: Re: bridge(4): use checksum offloading To: Jan Klemkow Cc: tech@openbsd.org Date: Wed, 17 Sep 2025 00:08:08 +0200 On Tue, Sep 16, 2025 at 02:45:42PM +0200, Jan Klemkow wrote: > 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? tested and OK bluhm@ > 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,