[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20181219171656.19376-1-domagoj.pintaric@sartura.hr>
Date: Wed, 19 Dec 2018 18:16:56 +0100
From: Domagoj Pintaric <domagoj.pintaric@...tura.hr>
To: netdev@...r.kernel.org
Cc: Domagoj Pintaric <domagoj.pintaric@...tura.hr>,
Luka Perkov <luka.perkov@...tura.hr>,
Thomas Petazzoni <thomas.petazzoni@...tlin.com>,
"David S . Miller" <davem@...emloft.net>
Subject: [PATCH] net: mvneta: add basic XDP_DROP support
Add initial mvneta XDP support for hardware buffer management enabled
devices only.
Signed-off-by: Domagoj Pintaric <domagoj.pintaric@...tura.hr>
CC: Luka Perkov <luka.perkov@...tura.hr>
CC: Thomas Petazzoni <thomas.petazzoni@...tlin.com>
CC: David S. Miller <davem@...emloft.net>
---
drivers/net/ethernet/marvell/mvneta.c | 70 +++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index e5397c8197b9..8b42b7d7a0f3 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -31,6 +31,7 @@
#include <linux/phylink.h>
#include <linux/platform_device.h>
#include <linux/skbuff.h>
+#include <linux/bpf.h>
#include <net/hwbm.h>
#include "mvneta_bm.h"
#include <net/ip.h>
@@ -455,6 +456,8 @@ struct mvneta_port {
bool neta_armada3700;
u16 rx_offset_correction;
const struct mbus_dram_target_info *dram_target_info;
+
+ struct bpf_prog *xdp_prog;
};
/* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -627,6 +630,8 @@ struct mvneta_rx_queue {
/* error counters */
u32 skb_alloc_err;
u32 refill_err;
+
+ struct bpf_prog *xdp_prog;
};
static enum cpuhp_state online_hpstate;
@@ -2100,6 +2105,7 @@ static int mvneta_rx_hwbm(struct napi_struct *napi,
int rx_done;
u32 rcvd_pkts = 0;
u32 rcvd_bytes = 0;
+ struct bpf_prog *xdp_prog;
/* Get number of received packets */
rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
@@ -2141,6 +2147,28 @@ static int mvneta_rx_hwbm(struct napi_struct *napi,
continue;
}
+ xdp_prog = READ_ONCE(rxq->xdp_prog);
+ if (xdp_prog) {
+ struct xdp_buff xdp;
+ enum xdp_action act;
+
+ xdp.data = data + MVNETA_MH_SIZE + NET_SKB_PAD;
+ xdp.data_end = xdp.data + rx_bytes;
+
+ act = bpf_prog_run_xdp(xdp_prog, &xdp);
+ switch (act) {
+ case XDP_PASS:
+ break;
+ default:
+ bpf_warn_invalid_xdp_action(act);
+ case XDP_DROP:
+ /* Return the buffer to the pool */
+ mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
+ rx_desc->buf_phys_addr);
+ continue;
+ }
+ }
+
if (rx_bytes <= rx_copybreak) {
/* better copy a small frame and not unmap the DMA region */
skb = netdev_alloc_skb_ip_align(dev, rx_bytes);
@@ -2934,6 +2962,8 @@ static int mvneta_rxq_init(struct mvneta_port *pp,
mvneta_rxq_hw_init(pp, rxq);
+ rxq->xdp_prog = pp->xdp_prog;
+
return 0;
}
@@ -2960,6 +2990,7 @@ static void mvneta_rxq_deinit(struct mvneta_port *pp,
rxq->refill_num = 0;
rxq->skb = NULL;
rxq->left_size = 0;
+ rxq->xdp_prog = NULL;
}
static int mvneta_txq_sw_init(struct mvneta_port *pp,
@@ -3868,6 +3899,9 @@ static int mvneta_stop(struct net_device *dev)
mvneta_cleanup_rxqs(pp);
mvneta_cleanup_txqs(pp);
+ if (pp->xdp_prog)
+ bpf_prog_put(pp->xdp_prog);
+
return 0;
}
@@ -3878,6 +3912,41 @@ static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return phylink_mii_ioctl(pp->phylink, ifr, cmd);
}
+static int mvneta_xdp_set(struct net_device *dev, struct bpf_prog *xdp_prog)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+ struct bpf_prog *xdp_prog_old;
+ int queue;
+
+ xdp_prog_old = xchg(&pp->xdp_prog, xdp_prog);
+
+ for (queue = 0; queue < rxq_number; queue++) {
+ struct mvneta_rx_queue *rxq = &pp->rxqs[queue];
+
+ xchg(&rxq->xdp_prog, pp->xdp_prog);
+ }
+
+ if (xdp_prog_old)
+ bpf_prog_put(xdp_prog_old);
+
+ return 0;
+}
+
+static int mvneta_bpf(struct net_device *dev, struct netdev_bpf *bpf)
+{
+ struct mvneta_port *pp = netdev_priv(dev);
+
+ switch (bpf->command) {
+ case XDP_SETUP_PROG:
+ return mvneta_xdp_set(dev, bpf->prog);
+ case XDP_QUERY_PROG:
+ bpf->prog_id = pp->xdp_prog ? pp->xdp_prog->aux->id : 0;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
/* Ethtool methods */
/* Set link ksettings (phy address, speed) for ethtools */
@@ -4275,6 +4344,7 @@ static const struct net_device_ops mvneta_netdev_ops = {
.ndo_fix_features = mvneta_fix_features,
.ndo_get_stats64 = mvneta_get_stats64,
.ndo_do_ioctl = mvneta_ioctl,
+ .ndo_bpf = mvneta_bpf,
};
static const struct ethtool_ops mvneta_eth_tool_ops = {
--
2.20.0
Powered by blists - more mailing lists