summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmatthew <jmatthew@openbsd.org>2020-06-02 08:17:15 +0000
committerjmatthew <jmatthew@openbsd.org>2020-06-02 08:17:15 +0000
commita3eb38c42c6a533ba94c969aa47ded08c81530e4 (patch)
tree0109c3f909185791940971d20d84514dc0123643
parentdistracting whitespace (diff)
downloadwireguard-openbsd-a3eb38c42c6a533ba94c969aa47ded08c81530e4.tar.xz
wireguard-openbsd-a3eb38c42c6a533ba94c969aa47ded08c81530e4.zip
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@
-rw-r--r--sys/dev/pci/if_mcx.c46
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);