From: Jan Klemkow Subject: vport(4): Use VLAN HW Tagging To: tech@openbsd.org Date: Mon, 23 Jun 2025 17:35:48 +0200 Hi, the following diff introduces VLAN offload to vport(4). veb(4) just calls vlan_inject() if the underlying send interface it not capable of hw tagging. So, we don't call it in most cases and avoid an mget() for every packet. ok? bye, Jan Index: net/if_veb.c =================================================================== RCS file: /cvs/src/sys/net/if_veb.c,v diff -u -p -r1.37 if_veb.c --- net/if_veb.c 2 Mar 2025 21:28:32 -0000 1.37 +++ net/if_veb.c 23 Jun 2025 15:06:54 -0000 @@ -927,6 +927,27 @@ veb_ipsec_out(struct ifnet *ifp0, struct } #endif /* IPSEC */ +static struct mbuf * +veb_offload(struct ifnet *ifp, struct mbuf *m) +{ +#if NVLAN > 0 + if (ISSET(m->m_flags, M_VLANTAG) && + !ISSET(ifp->if_capabilities, IFCAP_VLAN_HWTAGGING)) { + /* + * If the underlying interface has no VLAN hardware tagging + * 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; + } + } +#endif + + return m; +} + static void veb_broadcast(struct veb_softc *sc, struct veb_port *rp, struct mbuf *m0, uint64_t src, uint64_t dst, struct netstack *ns) @@ -996,6 +1017,9 @@ veb_broadcast(struct veb_softc *sc, stru if (veb_rule_filter(tp, VEB_RULE_LIST_OUT, m0, src, dst)) continue; + if ((m0 = veb_offload(ifp0, m0)) == NULL) + goto done; + m = m_dup_pkt(m0, max_linkhdr + ETHER_ALIGN, M_NOWAIT); if (m == NULL) { /* XXX count error? */ @@ -1048,6 +1072,9 @@ veb_transmit(struct veb_softc *sc, struc counters_pkt(ifp->if_counters, ifc_opackets, ifc_obytes, m->m_pkthdr.len); + if ((m = veb_offload(ifp0, m)) == NULL) + goto drop; + (*tp->p_enqueue)(ifp0, m); /* XXX count error */ return (NULL); @@ -1105,20 +1132,6 @@ veb_port_input(struct ifnet *ifp0, struc } } -#if NVLAN > 0 - /* - * If the underlying interface removed the VLAN header itself, - * add it back. - */ - if (ISSET(m->m_flags, M_VLANTAG)) { - m = vlan_inject(m, ETHERTYPE_VLAN, m->m_pkthdr.ether_vtag); - if (m == NULL) { - counters_inc(ifp->if_counters, ifc_ierrors); - goto drop; - } - } -#endif - counters_pkt(ifp->if_counters, ifc_ipackets, ifc_ibytes, m->m_pkthdr.len); @@ -2349,6 +2362,7 @@ 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; ether_fakeaddr(ifp); if_counters_alloc(ifp);