Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
Re: bridge(4): use checksum offloading
To:
Jan Klemkow <jan@openbsd.org>
Cc:
tech@openbsd.org
Date:
Wed, 17 Sep 2025 00:08:08 +0200

Download raw body.

Thread
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,