Download raw body.
bridge(4): use checksum offloading
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,
bridge(4): use checksum offloading