aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2018-01-05 18:30:47 -0500
committerAlexei Starovoitov <ast@kernel.org>2018-01-05 18:31:20 -0500
commit11d16edb04f113348b0c1d0c26cb666e9baaa7d3 (patch)
tree3e3d4ae57b0ebd5158afd33be318775883e943fa /drivers/net/virtio_net.c
parent5f103c5d4dbadec0f2cacd39b6429e1b8a8cf983 (diff)
parent0fca931a6f21c11f675363b92b5a4fe86da59f30 (diff)
Merge branch 'xdp_rxq_info'
Jesper Dangaard Brouer says: ==================== V4: * Added reviewers/acks to patches * Fix patch desc in i40e that got out-of-sync with code * Add SPDX license headers for the two new files added in patch 14 V3: * Fixed bug in virtio_net driver * Removed export of xdp_rxq_info_init() V2: * Changed API exposed to drivers - Removed invocation of "init" in drivers, and only call "reg" (Suggested by Saeed) - Allow "reg" to fail and handle this in drivers (Suggested by David Ahern) * Removed the SINKQ qtype, instead allow to register as "unused" * Also fixed some drivers during testing on actual HW (noted in patches) There is a need for XDP to know more about the RX-queue a given XDP frames have arrived on. For both the XDP bpf-prog and kernel side. Instead of extending struct xdp_buff each time new info is needed, this patchset takes a different approach. Struct xdp_buff is only extended with a pointer to a struct xdp_rxq_info (allowing for easier extending this later). This xdp_rxq_info contains information related to how the driver have setup the individual RX-queue's. This is read-mostly information, and all xdp_buff frames (in drivers napi_poll) point to the same xdp_rxq_info (per RX-queue). We stress this data/cache-line is for read-mostly info. This is NOT for dynamic per packet info, use the data_meta for such use-cases. This patchset start out small, and only expose ingress_ifindex and the RX-queue index to the XDP/BPF program. Access to tangible info like the ingress ifindex and RX queue index, is fairly easy to comprehent. The other future use-cases could allow XDP frames to be recycled back to the originating device driver, by providing info on RX device and queue number. As XDP doesn't have driver feature flags, and eBPF code due to bpf-tail-calls cannot determine that XDP driver invoke it, this patchset have to update every driver that support XDP. For driver developers (review individual driver patches!): The xdp_rxq_info is tied to the drivers RX-ring(s). Whenever a RX-ring modification require (temporary) stopping RX frames, then the xdp_rxq_info should (likely) also be unregistred and re-registered, especially if reallocating the pages in the ring. Make sure ethtool set_channels does the right thing. When replacing XDP prog, if and only if RX-ring need to be changed, then also re-register the xdp_rxq_info. I'm Cc'ing the individual driver patches to the registered maintainers. Testing: I've only tested the NIC drivers I have hardware for. The general test procedure is to (DUT = Device Under Test): (1) run pktgen script pktgen_sample04_many_flows.sh (against DUT) (2) run samples/bpf program xdp_rxq_info --dev $DEV (on DUT) (3) runtime modify number of NIC queues via ethtool -L (on DUT) (4) runtime modify number of NIC ring-size via ethtool -G (on DUT) Patch based on git tree bpf-next (at commit fb982666e380c1632a): https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/ ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 6fb7b658a6cc..ed8299343728 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -31,6 +31,7 @@
31#include <linux/average.h> 31#include <linux/average.h>
32#include <linux/filter.h> 32#include <linux/filter.h>
33#include <net/route.h> 33#include <net/route.h>
34#include <net/xdp.h>
34 35
35static int napi_weight = NAPI_POLL_WEIGHT; 36static int napi_weight = NAPI_POLL_WEIGHT;
36module_param(napi_weight, int, 0444); 37module_param(napi_weight, int, 0444);
@@ -115,6 +116,8 @@ struct receive_queue {
115 116
116 /* Name of this receive queue: input.$index */ 117 /* Name of this receive queue: input.$index */
117 char name[40]; 118 char name[40];
119
120 struct xdp_rxq_info xdp_rxq;
118}; 121};
119 122
120struct virtnet_info { 123struct virtnet_info {
@@ -559,6 +562,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
559 xdp.data = xdp.data_hard_start + xdp_headroom; 562 xdp.data = xdp.data_hard_start + xdp_headroom;
560 xdp_set_data_meta_invalid(&xdp); 563 xdp_set_data_meta_invalid(&xdp);
561 xdp.data_end = xdp.data + len; 564 xdp.data_end = xdp.data + len;
565 xdp.rxq = &rq->xdp_rxq;
562 orig_data = xdp.data; 566 orig_data = xdp.data;
563 act = bpf_prog_run_xdp(xdp_prog, &xdp); 567 act = bpf_prog_run_xdp(xdp_prog, &xdp);
564 568
@@ -692,6 +696,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
692 xdp.data = data + vi->hdr_len; 696 xdp.data = data + vi->hdr_len;
693 xdp_set_data_meta_invalid(&xdp); 697 xdp_set_data_meta_invalid(&xdp);
694 xdp.data_end = xdp.data + (len - vi->hdr_len); 698 xdp.data_end = xdp.data + (len - vi->hdr_len);
699 xdp.rxq = &rq->xdp_rxq;
700
695 act = bpf_prog_run_xdp(xdp_prog, &xdp); 701 act = bpf_prog_run_xdp(xdp_prog, &xdp);
696 702
697 if (act != XDP_PASS) 703 if (act != XDP_PASS)
@@ -1225,13 +1231,18 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
1225static int virtnet_open(struct net_device *dev) 1231static int virtnet_open(struct net_device *dev)
1226{ 1232{
1227 struct virtnet_info *vi = netdev_priv(dev); 1233 struct virtnet_info *vi = netdev_priv(dev);
1228 int i; 1234 int i, err;
1229 1235
1230 for (i = 0; i < vi->max_queue_pairs; i++) { 1236 for (i = 0; i < vi->max_queue_pairs; i++) {
1231 if (i < vi->curr_queue_pairs) 1237 if (i < vi->curr_queue_pairs)
1232 /* Make sure we have some buffers: if oom use wq. */ 1238 /* Make sure we have some buffers: if oom use wq. */
1233 if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL)) 1239 if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
1234 schedule_delayed_work(&vi->refill, 0); 1240 schedule_delayed_work(&vi->refill, 0);
1241
1242 err = xdp_rxq_info_reg(&vi->rq[i].xdp_rxq, dev, i);
1243 if (err < 0)
1244 return err;
1245
1235 virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi); 1246 virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
1236 virtnet_napi_tx_enable(vi, vi->sq[i].vq, &vi->sq[i].napi); 1247 virtnet_napi_tx_enable(vi, vi->sq[i].vq, &vi->sq[i].napi);
1237 } 1248 }
@@ -1560,6 +1571,7 @@ static int virtnet_close(struct net_device *dev)
1560 cancel_delayed_work_sync(&vi->refill); 1571 cancel_delayed_work_sync(&vi->refill);
1561 1572
1562 for (i = 0; i < vi->max_queue_pairs; i++) { 1573 for (i = 0; i < vi->max_queue_pairs; i++) {
1574 xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
1563 napi_disable(&vi->rq[i].napi); 1575 napi_disable(&vi->rq[i].napi);
1564 virtnet_napi_tx_disable(&vi->sq[i].napi); 1576 virtnet_napi_tx_disable(&vi->sq[i].napi);
1565 } 1577 }