From: David Gwynne Subject: Re: vport/veb(4): use/fix checksum offload To: Jan Klemkow Cc: OpenBSD Tech Date: Sun, 29 Jun 2025 21:48:34 +1000 > On 28 Jun 2025, at 04:06, Jan Klemkow wrote: > > Hi, > > This diff enables checksum offload in vport(4) and fixes checksum > offload in veb(4) in some corner cases. If we get packages with > M_TCP_CSUM_OUT from an interface. > > When we bridge two vio(4) interfaces via veb(4), we will lost the > VIRTIO_NET_HDR_F_NEEDS_CSUM flags, which is encodes in our mbuf via > M_TCP_CSUM_OUT flag. > > In the case of bridging vio(4) with an physical interface (e.g. em(4), > we also have to M_TCP_CSUM_OUT flag. So, the hardware is able to > calculate the correct checksum. Or, when we bridge vio(4) with an > interface unable to calculate we have to do this here, before sending > the packet to the interface. > > ok? sure, ok. > > bye, > Jan > > Index: net/if_veb.c > =================================================================== > RCS file: /cvs/src/sys/net/if_veb.c,v > diff -u -p -r1.38 if_veb.c > --- net/if_veb.c 27 Jun 2025 09:25:57 -0000 1.38 > +++ net/if_veb.c 27 Jun 2025 17:33:10 -0000 > @@ -948,6 +948,9 @@ veb_ipsec_out(struct ifnet *ifp0, struct > static struct mbuf * > veb_offload(struct ifnet *ifp, struct ifnet *ifp0, struct mbuf *m) > { > + struct ether_extracted ext; > + int csum = 0; > + > #if NVLAN > 0 > if (ISSET(m->m_flags, M_VLANTAG) && > !ISSET(ifp0->if_capabilities, IFCAP_VLAN_HWTAGGING)) { > @@ -956,14 +959,56 @@ veb_offload(struct ifnet *ifp, struct if > * support, inject one in software. > */ > m = vlan_inject(m, ETHERTYPE_VLAN, m->m_pkthdr.ether_vtag); > - if (m == NULL) { > - counters_inc(ifp->if_counters, ifc_ierrors); > - return NULL; > - } > + if (m == NULL) > + goto drop; > } > #endif > > + if (ISSET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT) && > + !ISSET(ifp0->if_capabilities, IFCAP_CSUM_IPv4)) > + csum = 1; > + > + if (ISSET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT) && > + (!ISSET(ifp0->if_capabilities, IFCAP_CSUM_TCPv4) || > + !ISSET(ifp0->if_capabilities, IFCAP_CSUM_TCPv6))) > + csum = 1; > + > + if (ISSET(m->m_pkthdr.csum_flags, M_UDP_CSUM_OUT) && > + (!ISSET(ifp0->if_capabilities, IFCAP_CSUM_UDPv4) || > + !ISSET(ifp0->if_capabilities, IFCAP_CSUM_UDPv6))) > + csum = 1; > + > + if (csum) { > + int adjlen; > + > + ether_extract_headers(m, &ext); > + if (ext.eh) > + adjlen = sizeof *ext.eh; > + else if (ext.evh) > + adjlen = sizeof *ext.evh; > + else > + goto drop; > + > + m_adj(m, adjlen); > + > + if (ext.ip4) { > + in_hdr_cksum_out(m, ifp0); > + in_proto_cksum_out(m, ifp0); > +#ifdef INET6 > + } else if (ext.ip6) { > + in6_proto_cksum_out(m, ifp0); > +#endif > + } > + m = m_prepend(m, adjlen, 0); > + if (m == NULL) > + goto drop; > + } > + > return m; > + > + drop: > + counters_inc(ifp->if_counters, ifc_ierrors); > + return NULL; > } > > static void > @@ -2380,7 +2425,15 @@ vport_clone_create(struct if_clone *ifc, > ifp->if_qstart = vport_start; > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE; > - ifp->if_capabilities = IFCAP_VLAN_HWTAGGING; > + > + ifp->if_capabilities = 0; > +#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; > + > ether_fakeaddr(ifp); > > if_counters_alloc(ifp); >