diff options
author | Jonathan Matthew <jmatthew@cvs.openbsd.org> | 2020-06-02 08:17:16 +0000 |
---|---|---|
committer | Jonathan Matthew <jmatthew@cvs.openbsd.org> | 2020-06-02 08:17:16 +0000 |
commit | 336161a702d4770a5311111b53e973508dce1fc6 (patch) | |
tree | 45bc4f48f3003c58e2ef1ff28ab5472628bba4fa /sys/dev | |
parent | e903e923aac74939d38343efe370e519c277b7ed (diff) |
Add support for hardware vlan tagging. Tag insertion here is actually
done by the driver, as it places the full L2 packet header inside the
send queue entry, so it can insert the vlan tag there if required.
ok dlg@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/if_mcx.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/sys/dev/pci/if_mcx.c b/sys/dev/pci/if_mcx.c index a06028bafe2..b826c2cd45f 100644 --- a/sys/dev/pci/if_mcx.c +++ b/sys/dev/pci/if_mcx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mcx.c,v 1.48 2020/05/27 04:03:20 dlg Exp $ */ +/* $OpenBSD: if_mcx.c,v 1.49 2020/06/02 08:17:15 jmatthew Exp $ */ /* * Copyright (c) 2017 David Gwynne <dlg@openbsd.org> @@ -18,6 +18,7 @@ */ #include "bpfilter.h" +#include "vlan.h" #include <sys/param.h> #include <sys/systm.h> @@ -92,6 +93,7 @@ ((1 << MCX_LOG_FLOW_TABLE_SIZE) - MCX_NUM_STATIC_FLOWS) #define MCX_SQ_INLINE_SIZE 18 +CTASSERT(ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN == MCX_SQ_INLINE_SIZE); /* doorbell offsets */ #define MCX_CQ_DOORBELL_OFFSET 0 @@ -1258,6 +1260,8 @@ struct mcx_cq_entry { #define MCX_CQ_ENTRY_FLAGS_L4_OK (1 << 26) #define MCX_CQ_ENTRY_FLAGS_L3_OK (1 << 25) #define MCX_CQ_ENTRY_FLAGS_L2_OK (1 << 24) +#define MCX_CQ_ENTRY_FLAGS_CV (1 << 16) +#define MCX_CQ_ENTRY_FLAGS_VLAN_MASK (0xffff) uint32_t cq_lro_srqn; uint32_t __reserved__[2]; @@ -2363,6 +2367,9 @@ mcx_attach(struct device *parent, struct device *self, void *aux) ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_IPv4 | IFCAP_CSUM_UDPv4 | IFCAP_CSUM_UDPv6 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_TCPv6; +#if NVLAN > 0 + ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; +#endif IFQ_SET_MAXLEN(&ifp->if_snd, 1024); ifmedia_init(&sc->sc_media, IFM_IMASK, mcx_media_change, @@ -4013,6 +4020,7 @@ mcx_create_rq(struct mcx_softc *sc, int cqn) struct mcx_rq_ctx *mbin; int error; uint64_t *pas; + uint32_t rq_flags; uint8_t *doorbell; int insize, npages, paslen, token; @@ -4044,7 +4052,11 @@ mcx_create_rq(struct mcx_softc *sc, int cqn) goto free; } mbin = (struct mcx_rq_ctx *)(((char *)mcx_cq_mbox_data(mcx_cq_mbox(&mxm, 0))) + 0x10); - mbin->rq_flags = htobe32(MCX_RQ_CTX_RLKEY | MCX_RQ_CTX_VLAN_STRIP_DIS); + rq_flags = MCX_RQ_CTX_RLKEY; +#if NVLAN == 0 + rq_flags |= MCX_RQ_CTX_VLAN_STRIP_DIS; +#endif + mbin->rq_flags = htobe32(rq_flags); mbin->rq_cqn = htobe32(cqn); mbin->rq_wq.wq_type = MCX_WQ_CTX_TYPE_CYCLIC; mbin->rq_wq.wq_pd = htobe32(sc->sc_pd); @@ -5697,6 +5709,13 @@ mcx_process_rx(struct mcx_softc *sc, struct mcx_cq_entry *cqe, if (flags & MCX_CQ_ENTRY_FLAGS_L4_OK) m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK; +#if NVLAN > 0 + if (flags & MCX_CQ_ENTRY_FLAGS_CV) { + m->m_pkthdr.ether_vtag = (flags & + MCX_CQ_ENTRY_FLAGS_VLAN_MASK); + m->m_flags |= M_VLANTAG; + } +#endif if (c->c_tdiff) { uint64_t t = bemtoh64(&cqe->cq_timestamp) - c->c_timestamp; @@ -6369,9 +6388,26 @@ mcx_start(struct ifqueue *ifq) csum |= MCX_SQE_L4_CSUM; sqe->sqe_mss_csum = htobe32(csum); sqe->sqe_inline_header_size = htobe16(MCX_SQ_INLINE_SIZE); - m_copydata(m, 0, MCX_SQ_INLINE_SIZE, - (caddr_t)sqe->sqe_inline_headers); - m_adj(m, MCX_SQ_INLINE_SIZE); +#if NVLAN > 0 + if (m->m_flags & M_VLANTAG) { + struct ether_vlan_header *evh; + evh = (struct ether_vlan_header *) + &sqe->sqe_inline_headers; + + /* slightly cheaper vlan_inject() */ + m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)evh); + evh->evl_proto = evh->evl_encap_proto; + evh->evl_encap_proto = htons(ETHERTYPE_VLAN); + evh->evl_tag = htons(m->m_pkthdr.ether_vtag); + + m_adj(m, ETHER_HDR_LEN); + } else +#endif + { + m_copydata(m, 0, MCX_SQ_INLINE_SIZE, + (caddr_t)sqe->sqe_inline_headers); + m_adj(m, MCX_SQ_INLINE_SIZE); + } if (mcx_load_mbuf(sc, ms, m) != 0) { m_freem(m); |