get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/887199/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 887199,
    "url": "http://patchwork.ozlabs.org/api/patches/887199/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20180316223406.7295-2-anthony.l.nguyen@intel.com/",
    "project": {
        "id": 46,
        "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api",
        "name": "Intel Wired Ethernet development",
        "link_name": "intel-wired-lan",
        "list_id": "intel-wired-lan.osuosl.org",
        "list_email": "intel-wired-lan@osuosl.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20180316223406.7295-2-anthony.l.nguyen@intel.com>",
    "list_archive_url": null,
    "date": "2018-03-16T22:34:02",
    "name": "[1/5] ixgbevf: Add XDP support for pass and drop actions",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "6ffb466a141b3e993ca51b4590202ba15debed2c",
    "submitter": {
        "id": 68875,
        "url": "http://patchwork.ozlabs.org/api/people/68875/?format=api",
        "name": "Tony Nguyen",
        "email": "anthony.l.nguyen@intel.com"
    },
    "delegate": {
        "id": 68,
        "url": "http://patchwork.ozlabs.org/api/users/68/?format=api",
        "username": "jtkirshe",
        "first_name": "Jeff",
        "last_name": "Kirsher",
        "email": "jeffrey.t.kirsher@intel.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20180316223406.7295-2-anthony.l.nguyen@intel.com/mbox/",
    "series": [
        {
            "id": 34301,
            "url": "http://patchwork.ozlabs.org/api/series/34301/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=34301",
            "date": "2018-03-16T22:34:04",
            "name": "Enable XDP for ixgbevf",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/34301/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/887199/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/887199/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<intel-wired-lan-bounces@osuosl.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@bilbo.ozlabs.org",
            "intel-wired-lan@lists.osuosl.org"
        ],
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.137; helo=fraxinus.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org;\n\tdmarc=none (p=none dis=none) header.from=intel.com"
        ],
        "Received": [
            "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 4030qT710yz9sSx\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 17 Mar 2018 09:43:33 +1100 (AEDT)",
            "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 84E4788A28;\n\tFri, 16 Mar 2018 22:43:32 +0000 (UTC)",
            "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 0o85UFeCImiU; Fri, 16 Mar 2018 22:43:30 +0000 (UTC)",
            "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id A4125889F7;\n\tFri, 16 Mar 2018 22:43:30 +0000 (UTC)",
            "from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\tby ash.osuosl.org (Postfix) with ESMTP id 880391C218D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 16 Mar 2018 22:43:27 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 84DDA86AFE\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 16 Mar 2018 22:43:27 +0000 (UTC)",
            "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id BZCvV72CN7U7 for <intel-wired-lan@lists.osuosl.org>;\n\tFri, 16 Mar 2018 22:43:26 +0000 (UTC)",
            "from mga07.intel.com (mga07.intel.com [134.134.136.100])\n\tby whitealder.osuosl.org (Postfix) with ESMTPS id 255258582C\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 16 Mar 2018 22:43:26 +0000 (UTC)",
            "from orsmga007.jf.intel.com ([10.7.209.58])\n\tby orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t16 Mar 2018 15:43:24 -0700",
            "from unknown (HELO anguy11-linux.jf.intel.com) ([10.166.244.153])\n\tby orsmga007.jf.intel.com with ESMTP; 16 Mar 2018 15:43:24 -0700"
        ],
        "X-Virus-Scanned": [
            "amavisd-new at osuosl.org",
            "amavisd-new at osuosl.org"
        ],
        "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6",
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.48,317,1517904000\"; d=\"scan'208\";a=\"25375060\"",
        "From": "Tony Nguyen <anthony.l.nguyen@intel.com>",
        "To": "intel-wired-lan@lists.osuosl.org",
        "Date": "Fri, 16 Mar 2018 15:34:02 -0700",
        "Message-Id": "<20180316223406.7295-2-anthony.l.nguyen@intel.com>",
        "X-Mailer": "git-send-email 2.13.6",
        "In-Reply-To": "<20180316223406.7295-1-anthony.l.nguyen@intel.com>",
        "References": "<20180316223406.7295-1-anthony.l.nguyen@intel.com>",
        "Subject": "[Intel-wired-lan] [PATCH 1/5] ixgbevf: Add XDP support for pass and\n\tdrop actions",
        "X-BeenThere": "intel-wired-lan@osuosl.org",
        "X-Mailman-Version": "2.1.24",
        "Precedence": "list",
        "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>",
        "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>",
        "List-Post": "<mailto:intel-wired-lan@osuosl.org>",
        "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>",
        "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>",
        "Cc": "netdev@vger.kernel.org",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "intel-wired-lan-bounces@osuosl.org",
        "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>"
    },
    "content": "Implement XDP_PASS and XDP_DROP based on the ixgbe implementation.\n\nBased largely on commit 924708081629 (\"ixgbe: add XDP support for pass and\ndrop actions\").\n\nSigned-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>\nAcked-by: John Fastabend <john.fastabend@gmail.com>\n---\n drivers/net/ethernet/intel/ixgbevf/ethtool.c      |   9 +-\n drivers/net/ethernet/intel/ixgbevf/ixgbevf.h      |  10 +-\n drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | 201 ++++++++++++++++++----\n 3 files changed, 178 insertions(+), 42 deletions(-)",
    "diff": "diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c\nindex e7623fed42da..4946a62c70a4 100644\n--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c\n+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c\n@@ -1,7 +1,7 @@\n /*******************************************************************************\n \n   Intel 82599 Virtual Function driver\n-  Copyright(c) 1999 - 2015 Intel Corporation.\n+  Copyright(c) 1999 - 2018 Intel Corporation.\n \n   This program is free software; you can redistribute it and/or modify it\n   under the terms and conditions of the GNU General Public License,\n@@ -336,8 +336,13 @@ static int ixgbevf_set_ringparam(struct net_device *netdev,\n \t\tfor (i = 0; i < adapter->num_rx_queues; i++) {\n \t\t\t/* clone ring and setup updated count */\n \t\t\trx_ring[i] = *adapter->rx_ring[i];\n+\n+\t\t\t/* Clear copied XDP RX-queue info */\n+\t\t\tmemset(&rx_ring[i].xdp_rxq, 0,\n+\t\t\t       sizeof(rx_ring[i].xdp_rxq));\n+\n \t\t\trx_ring[i].count = new_rx_count;\n-\t\t\terr = ixgbevf_setup_rx_resources(&rx_ring[i]);\n+\t\t\terr = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]);\n \t\t\tif (err) {\n \t\t\t\twhile (i) {\n \t\t\t\t\ti--;\ndiff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h\nindex 7778c30b6ca5..6f6b4a157dff 100644\n--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h\n+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h\n@@ -2,7 +2,7 @@\n /*******************************************************************************\n \n   Intel 82599 Virtual Function driver\n-  Copyright(c) 1999 - 2015 Intel Corporation.\n+  Copyright(c) 1999 - 2018 Intel Corporation.\n \n   This program is free software; you can redistribute it and/or modify it\n   under the terms and conditions of the GNU General Public License,\n@@ -35,6 +35,7 @@\n #include <linux/netdevice.h>\n #include <linux/if_vlan.h>\n #include <linux/u64_stats_sync.h>\n+#include <net/xdp.h>\n \n #include \"vf.h\"\n \n@@ -100,6 +101,7 @@ struct ixgbevf_ring {\n \tstruct ixgbevf_ring *next;\n \tstruct ixgbevf_q_vector *q_vector;\t/* backpointer to q_vector */\n \tstruct net_device *netdev;\n+\tstruct bpf_prog *xdp_prog;\n \tstruct device *dev;\n \tvoid *desc;\t\t\t/* descriptor ring memory */\n \tdma_addr_t dma;\t\t\t/* phys. address of descriptor ring */\n@@ -120,7 +122,7 @@ struct ixgbevf_ring {\n \t\tstruct ixgbevf_tx_queue_stats tx_stats;\n \t\tstruct ixgbevf_rx_queue_stats rx_stats;\n \t};\n-\n+\tstruct xdp_rxq_info xdp_rxq;\n \tu64 hw_csum_rx_error;\n \tu8 __iomem *tail;\n \tstruct sk_buff *skb;\n@@ -357,6 +359,7 @@ struct ixgbevf_adapter {\n \n \t/* OS defined structs */\n \tstruct net_device *netdev;\n+\tstruct bpf_prog *xdp_prog;\n \tstruct pci_dev *pdev;\n \n \t/* structs defined in ixgbe_vf.h */\n@@ -443,7 +446,8 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter);\n void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter);\n void ixgbevf_reset(struct ixgbevf_adapter *adapter);\n void ixgbevf_set_ethtool_ops(struct net_device *netdev);\n-int ixgbevf_setup_rx_resources(struct ixgbevf_ring *);\n+int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,\n+\t\t\t       struct ixgbevf_ring *rx_ring);\n int ixgbevf_setup_tx_resources(struct ixgbevf_ring *);\n void ixgbevf_free_rx_resources(struct ixgbevf_ring *);\n void ixgbevf_free_tx_resources(struct ixgbevf_ring *);\ndiff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c\nindex 4da449e0a4ba..2696b5a6806f 100644\n--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c\n+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c\n@@ -1,7 +1,7 @@\n /*******************************************************************************\n \n   Intel 82599 Virtual Function driver\n-  Copyright(c) 1999 - 2015 Intel Corporation.\n+  Copyright(c) 1999 - 2018 Intel Corporation.\n \n   This program is free software; you can redistribute it and/or modify it\n   under the terms and conditions of the GNU General Public License,\n@@ -50,6 +50,9 @@\n #include <linux/if_vlan.h>\n #include <linux/prefetch.h>\n #include <net/mpls.h>\n+#include <linux/bpf.h>\n+#include <linux/bpf_trace.h>\n+#include <linux/atomic.h>\n \n #include \"ixgbevf.h\"\n \n@@ -552,19 +555,21 @@ struct ixgbevf_rx_buffer *ixgbevf_get_rx_buffer(struct ixgbevf_ring *rx_ring,\n }\n \n static void ixgbevf_put_rx_buffer(struct ixgbevf_ring *rx_ring,\n-\t\t\t\t  struct ixgbevf_rx_buffer *rx_buffer)\n+\t\t\t\t  struct ixgbevf_rx_buffer *rx_buffer,\n+\t\t\t\t  struct sk_buff *skb)\n {\n \tif (ixgbevf_can_reuse_rx_page(rx_buffer)) {\n \t\t/* hand second half of page back to the ring */\n \t\tixgbevf_reuse_rx_page(rx_ring, rx_buffer);\n \t} else {\n-\t\t/* We are not reusing the buffer so unmap it and free\n-\t\t * any references we are holding to it\n-\t\t */\n-\t\tdma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,\n-\t\t\t\t     ixgbevf_rx_pg_size(rx_ring),\n-\t\t\t\t     DMA_FROM_DEVICE,\n-\t\t\t\t     IXGBEVF_RX_DMA_ATTR);\n+\t\tif (IS_ERR(skb))\n+\t\t\t/* We are not reusing the buffer so unmap it and free\n+\t\t\t * any references we are holding to it\n+\t\t\t */\n+\t\t\tdma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,\n+\t\t\t\t\t     ixgbevf_rx_pg_size(rx_ring),\n+\t\t\t\t\t     DMA_FROM_DEVICE,\n+\t\t\t\t\t     IXGBEVF_RX_DMA_ATTR);\n \t\t__page_frag_cache_drain(rx_buffer->page,\n \t\t\t\t\trx_buffer->pagecnt_bias);\n \t}\n@@ -737,6 +742,10 @@ static bool ixgbevf_cleanup_headers(struct ixgbevf_ring *rx_ring,\n \t\t\t\t    union ixgbe_adv_rx_desc *rx_desc,\n \t\t\t\t    struct sk_buff *skb)\n {\n+\t/* XDP packets use error pointer so abort at this point */\n+\tif (IS_ERR(skb))\n+\t\treturn true;\n+\n \t/* verify that the packet does not have any known errors */\n \tif (unlikely(ixgbevf_test_staterr(rx_desc,\n \t\t\t\t\t  IXGBE_RXDADV_ERR_FRAME_ERR_MASK))) {\n@@ -853,22 +862,23 @@ static void ixgbevf_add_rx_frag(struct ixgbevf_ring *rx_ring,\n static\n struct sk_buff *ixgbevf_construct_skb(struct ixgbevf_ring *rx_ring,\n \t\t\t\t      struct ixgbevf_rx_buffer *rx_buffer,\n-\t\t\t\t      union ixgbe_adv_rx_desc *rx_desc,\n-\t\t\t\t      unsigned int size)\n+\t\t\t\t      struct xdp_buff *xdp,\n+\t\t\t\t      union ixgbe_adv_rx_desc *rx_desc)\n {\n-\tvoid *va = page_address(rx_buffer->page) + rx_buffer->page_offset;\n+\tunsigned int size = xdp->data_end - xdp->data;\n #if (PAGE_SIZE < 8192)\n \tunsigned int truesize = ixgbevf_rx_pg_size(rx_ring) / 2;\n #else\n-\tunsigned int truesize = SKB_DATA_ALIGN(size);\n+\tunsigned int truesize = SKB_DATA_ALIGN(xdp->data_end -\n+\t\t\t\t\t       xdp->data_hard_start);\n #endif\n \tunsigned int headlen;\n \tstruct sk_buff *skb;\n \n \t/* prefetch first cache line of first page */\n-\tprefetch(va);\n+\tprefetch(xdp->data);\n #if L1_CACHE_BYTES < 128\n-\tprefetch(va + L1_CACHE_BYTES);\n+\tprefetch(xdp->data + L1_CACHE_BYTES);\n #endif\n \n \t/* allocate a skb to store the frags */\n@@ -879,16 +889,18 @@ struct sk_buff *ixgbevf_construct_skb(struct ixgbevf_ring *rx_ring,\n \t/* Determine available headroom for copy */\n \theadlen = size;\n \tif (headlen > IXGBEVF_RX_HDR_SIZE)\n-\t\theadlen = eth_get_headlen(va, IXGBEVF_RX_HDR_SIZE);\n+\t\theadlen = eth_get_headlen(xdp->data, IXGBEVF_RX_HDR_SIZE);\n \n \t/* align pull length to size of long to optimize memcpy performance */\n-\tmemcpy(__skb_put(skb, headlen), va, ALIGN(headlen, sizeof(long)));\n+\tmemcpy(__skb_put(skb, headlen), xdp->data,\n+\t       ALIGN(headlen, sizeof(long)));\n \n \t/* update all of the pointers */\n \tsize -= headlen;\n \tif (size) {\n \t\tskb_add_rx_frag(skb, 0, rx_buffer->page,\n-\t\t\t\t(va + headlen) - page_address(rx_buffer->page),\n+\t\t\t\t(xdp->data + headlen) -\n+\t\t\t\t\tpage_address(rx_buffer->page),\n \t\t\t\tsize, truesize);\n #if (PAGE_SIZE < 8192)\n \t\trx_buffer->page_offset ^= truesize;\n@@ -912,32 +924,32 @@ static inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter,\n \n static struct sk_buff *ixgbevf_build_skb(struct ixgbevf_ring *rx_ring,\n \t\t\t\t\t struct ixgbevf_rx_buffer *rx_buffer,\n-\t\t\t\t\t union ixgbe_adv_rx_desc *rx_desc,\n-\t\t\t\t\t unsigned int size)\n+\t\t\t\t\t struct xdp_buff *xdp,\n+\t\t\t\t\t union ixgbe_adv_rx_desc *rx_desc)\n {\n-\tvoid *va = page_address(rx_buffer->page) + rx_buffer->page_offset;\n #if (PAGE_SIZE < 8192)\n \tunsigned int truesize = ixgbevf_rx_pg_size(rx_ring) / 2;\n #else\n \tunsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +\n-\t\t\t\tSKB_DATA_ALIGN(IXGBEVF_SKB_PAD + size);\n+\t\t\t\tSKB_DATA_ALIGN(xdp->data_end -\n+\t\t\t\t\t       xdp->data_hard_start);\n #endif\n \tstruct sk_buff *skb;\n \n \t/* prefetch first cache line of first page */\n-\tprefetch(va);\n+\tprefetch(xdp->data);\n #if L1_CACHE_BYTES < 128\n-\tprefetch(va + L1_CACHE_BYTES);\n+\tprefetch(xdp->data + L1_CACHE_BYTES);\n #endif\n \n-\t/* build an skb to around the page buffer */\n-\tskb = build_skb(va - IXGBEVF_SKB_PAD, truesize);\n+\t/* build an skb around the page buffer */\n+\tskb = build_skb(xdp->data_hard_start, truesize);\n \tif (unlikely(!skb))\n \t\treturn NULL;\n \n \t/* update pointers within the skb to store the data */\n-\tskb_reserve(skb, IXGBEVF_SKB_PAD);\n-\t__skb_put(skb, size);\n+\tskb_reserve(skb, xdp->data - xdp->data_hard_start);\n+\t__skb_put(skb, xdp->data_end - xdp->data);\n \n \t/* update buffer offset */\n #if (PAGE_SIZE < 8192)\n@@ -948,6 +960,43 @@ static struct sk_buff *ixgbevf_build_skb(struct ixgbevf_ring *rx_ring,\n \n \treturn skb;\n }\n+\n+#define IXGBEVF_XDP_PASS 0\n+#define IXGBEVF_XDP_CONSUMED 1\n+\n+static struct sk_buff *ixgbevf_run_xdp(struct ixgbevf_ring  *rx_ring,\n+\t\t\t\t       struct xdp_buff *xdp)\n+{\n+\tint result = IXGBEVF_XDP_PASS;\n+\tstruct bpf_prog *xdp_prog;\n+\tu32 act;\n+\n+\trcu_read_lock();\n+\txdp_prog = READ_ONCE(rx_ring->xdp_prog);\n+\n+\tif (!xdp_prog)\n+\t\tgoto xdp_out;\n+\n+\tact = bpf_prog_run_xdp(xdp_prog, xdp);\n+\tswitch (act) {\n+\tcase XDP_PASS:\n+\t\tbreak;\n+\tdefault:\n+\t\tbpf_warn_invalid_xdp_action(act);\n+\t\t/* fallthrough */\n+\tcase XDP_TX:\n+\tcase XDP_ABORTED:\n+\t\ttrace_xdp_exception(rx_ring->netdev, xdp_prog, act);\n+\t\t/* fallthrough -- handle aborts by dropping packet */\n+\tcase XDP_DROP:\n+\t\tresult = IXGBEVF_XDP_CONSUMED;\n+\t\tbreak;\n+\t}\n+xdp_out:\n+\trcu_read_unlock();\n+\treturn ERR_PTR(-result);\n+}\n+\n static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,\n \t\t\t\tstruct ixgbevf_ring *rx_ring,\n \t\t\t\tint budget)\n@@ -955,10 +1004,13 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,\n \tunsigned int total_rx_bytes = 0, total_rx_packets = 0;\n \tu16 cleaned_count = ixgbevf_desc_unused(rx_ring);\n \tstruct sk_buff *skb = rx_ring->skb;\n+\tstruct xdp_buff xdp;\n+\n+\txdp.rxq = &rx_ring->xdp_rxq;\n \n \twhile (likely(total_rx_packets < budget)) {\n-\t\tunion ixgbe_adv_rx_desc *rx_desc;\n \t\tstruct ixgbevf_rx_buffer *rx_buffer;\n+\t\tunion ixgbe_adv_rx_desc *rx_desc;\n \t\tunsigned int size;\n \n \t\t/* return some buffers to hardware, one at a time is too slow */\n@@ -981,14 +1033,30 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,\n \t\trx_buffer = ixgbevf_get_rx_buffer(rx_ring, size);\n \n \t\t/* retrieve a buffer from the ring */\n-\t\tif (skb)\n+\t\tif (!skb) {\n+\t\t\txdp.data = page_address(rx_buffer->page) +\n+\t\t\t\t   rx_buffer->page_offset;\n+\t\t\txdp_set_data_meta_invalid(&xdp);\n+\t\t\txdp.data_hard_start = xdp.data -\n+\t\t\t\t\t      ixgbevf_rx_offset(rx_ring);\n+\t\t\txdp.data_end = xdp.data + size;\n+\n+\t\t\tskb = ixgbevf_run_xdp(rx_ring, &xdp);\n+\t\t}\n+\n+\t\tif (IS_ERR(skb)) {\n+\t\t\ttotal_rx_packets++;\n+\t\t\ttotal_rx_bytes += size;\n+\t\t\trx_buffer->pagecnt_bias++;\n+\t\t} else if (skb) {\n \t\t\tixgbevf_add_rx_frag(rx_ring, rx_buffer, skb, size);\n-\t\telse if (ring_uses_build_skb(rx_ring))\n+\t\t} else if (ring_uses_build_skb(rx_ring)) {\n \t\t\tskb = ixgbevf_build_skb(rx_ring, rx_buffer,\n-\t\t\t\t\t\trx_desc, size);\n-\t\telse\n+\t\t\t\t\t\t&xdp, rx_desc);\n+\t\t} else {\n \t\t\tskb = ixgbevf_construct_skb(rx_ring, rx_buffer,\n-\t\t\t\t\t\t    rx_desc, size);\n+\t\t\t\t\t\t    &xdp, rx_desc);\n+\t\t}\n \n \t\t/* exit if we failed to retrieve a buffer */\n \t\tif (!skb) {\n@@ -997,7 +1065,7 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,\n \t\t\tbreak;\n \t\t}\n \n-\t\tixgbevf_put_rx_buffer(rx_ring, rx_buffer);\n+\t\tixgbevf_put_rx_buffer(rx_ring, rx_buffer, skb);\n \t\tcleaned_count++;\n \n \t\t/* fetch next buffer in frame if non-eop */\n@@ -3159,11 +3227,13 @@ static int ixgbevf_setup_all_tx_resources(struct ixgbevf_adapter *adapter)\n \n /**\n  * ixgbevf_setup_rx_resources - allocate Rx resources (Descriptors)\n+ * @adapter: board private structure\n  * @rx_ring: Rx descriptor ring (for a specific queue) to setup\n  *\n  * Returns 0 on success, negative on failure\n  **/\n-int ixgbevf_setup_rx_resources(struct ixgbevf_ring *rx_ring)\n+int ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter,\n+\t\t\t       struct ixgbevf_ring *rx_ring)\n {\n \tint size;\n \n@@ -3184,6 +3254,13 @@ int ixgbevf_setup_rx_resources(struct ixgbevf_ring *rx_ring)\n \tif (!rx_ring->desc)\n \t\tgoto err;\n \n+\t/* XDP RX-queue info */\n+\tif (xdp_rxq_info_reg(&rx_ring->xdp_rxq, adapter->netdev,\n+\t\t\t     rx_ring->queue_index) < 0)\n+\t\tgoto err;\n+\n+\trx_ring->xdp_prog = adapter->xdp_prog;\n+\n \treturn 0;\n err:\n \tvfree(rx_ring->rx_buffer_info);\n@@ -3207,7 +3284,7 @@ static int ixgbevf_setup_all_rx_resources(struct ixgbevf_adapter *adapter)\n \tint i, err = 0;\n \n \tfor (i = 0; i < adapter->num_rx_queues; i++) {\n-\t\terr = ixgbevf_setup_rx_resources(adapter->rx_ring[i]);\n+\t\terr = ixgbevf_setup_rx_resources(adapter, adapter->rx_ring[i]);\n \t\tif (!err)\n \t\t\tcontinue;\n \t\thw_dbg(&adapter->hw, \"Allocation for Rx Queue %u failed\\n\", i);\n@@ -3232,6 +3309,8 @@ void ixgbevf_free_rx_resources(struct ixgbevf_ring *rx_ring)\n {\n \tixgbevf_clean_rx_ring(rx_ring);\n \n+\trx_ring->xdp_prog = NULL;\n+\txdp_rxq_info_unreg(&rx_ring->xdp_rxq);\n \tvfree(rx_ring->rx_buffer_info);\n \trx_ring->rx_buffer_info = NULL;\n \n@@ -3918,6 +3997,12 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)\n \tint max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;\n \tint ret;\n \n+\t/* prevent MTU being changed to a size unsupported by XDP */\n+\tif (adapter->xdp_prog) {\n+\t\tdev_warn(&adapter->pdev->dev, \"MTU cannot be changed while XDP program is loaded\\n\");\n+\t\treturn -EPERM;\n+\t}\n+\n \tspin_lock_bh(&adapter->mbx_lock);\n \t/* notify the PF of our intent to use this size of frame */\n \tret = hw->mac.ops.set_rlpml(hw, max_frame);\n@@ -4101,6 +4186,47 @@ ixgbevf_features_check(struct sk_buff *skb, struct net_device *dev,\n \treturn features;\n }\n \n+static int ixgbevf_xdp_setup(struct net_device *dev, struct bpf_prog *prog)\n+{\n+\tint i, frame_size = dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;\n+\tstruct ixgbevf_adapter *adapter = netdev_priv(dev);\n+\tstruct bpf_prog *old_prog;\n+\n+\t/* verify ixgbevf ring attributes are sufficient for XDP */\n+\tfor (i = 0; i < adapter->num_rx_queues; i++) {\n+\t\tstruct ixgbevf_ring *ring = adapter->rx_ring[i];\n+\n+\t\tif (frame_size > ixgbevf_rx_bufsz(ring))\n+\t\t\treturn -EINVAL;\n+\t}\n+\n+\told_prog = xchg(&adapter->xdp_prog, prog);\n+\tfor (i = 0; i < adapter->num_rx_queues; i++)\n+\t\txchg(&adapter->rx_ring[i]->xdp_prog, adapter->xdp_prog);\n+\n+\tif (old_prog)\n+\t\tbpf_prog_put(old_prog);\n+\n+\treturn 0;\n+}\n+\n+static int ixgbevf_xdp(struct net_device *dev, struct netdev_bpf *xdp)\n+{\n+\tstruct ixgbevf_adapter *adapter = netdev_priv(dev);\n+\n+\tswitch (xdp->command) {\n+\tcase XDP_SETUP_PROG:\n+\t\treturn ixgbevf_xdp_setup(dev, xdp->prog);\n+\tcase XDP_QUERY_PROG:\n+\t\txdp->prog_attached = !!(adapter->xdp_prog);\n+\t\txdp->prog_id = adapter->xdp_prog ?\n+\t\t\t       adapter->xdp_prog->aux->id : 0;\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n static const struct net_device_ops ixgbevf_netdev_ops = {\n \t.ndo_open\t\t= ixgbevf_open,\n \t.ndo_stop\t\t= ixgbevf_close,\n@@ -4117,6 +4243,7 @@ static const struct net_device_ops ixgbevf_netdev_ops = {\n \t.ndo_poll_controller\t= ixgbevf_netpoll,\n #endif\n \t.ndo_features_check\t= ixgbevf_features_check,\n+\t.ndo_bpf\t\t= ixgbevf_xdp,\n };\n \n static void ixgbevf_assign_netdev_ops(struct net_device *dev)\n",
    "prefixes": [
        "1/5"
    ]
}