Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/740352/?format=api
{ "id": 740352, "url": "http://patchwork.ozlabs.org/api/patches/740352/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20170317151643.8653.78437.stgit@john-Precision-Tower-5810/", "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": "<20170317151643.8653.78437.stgit@john-Precision-Tower-5810>", "list_archive_url": null, "date": "2017-03-17T15:16:43", "name": "[net-next,v6,1/2] ixgbe: add XDP support for pass and drop actions", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "56063a2d3b3807606b9b4b401afe68b5603a6497", "submitter": { "id": 20028, "url": "http://patchwork.ozlabs.org/api/people/20028/?format=api", "name": "John Fastabend", "email": "john.fastabend@gmail.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/20170317151643.8653.78437.stgit@john-Precision-Tower-5810/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/740352/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/740352/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@lists.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" ], "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 3vl88H2nBhz9s1h\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 18 Mar 2017 02:17:03 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 89E3C8800A;\n\tFri, 17 Mar 2017 15:17:01 +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 LSkK9xjYVJYk; Fri, 17 Mar 2017 15:17:00 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 7DDEF88008;\n\tFri, 17 Mar 2017 15:17:00 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 1D3001C03B0\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 17 Mar 2017 15:16:59 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 1830489064\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 17 Mar 2017 15:16:59 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id BJfQZt57xKrT for <intel-wired-lan@lists.osuosl.org>;\n\tFri, 17 Mar 2017 15:16:58 +0000 (UTC)", "from mail-pg0-f67.google.com (mail-pg0-f67.google.com\n\t[74.125.83.67])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id E634688B85\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 17 Mar 2017 15:16:57 +0000 (UTC)", "by mail-pg0-f67.google.com with SMTP id 81so2176592pgh.3\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 17 Mar 2017 08:16:57 -0700 (PDT)", "from [127.0.1.1] ([72.168.145.12])\n\tby smtp.gmail.com with ESMTPSA id\n\ti3sm17516678pfg.117.2017.03.17.08.16.50\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tFri, 17 Mar 2017 08:16:56 -0700 (PDT)" ], "Authentication-Results": "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"f9KEWCai\"; dkim-atps=neutral", "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=from:subject:to:cc:date:message-id:user-agent:mime-version\n\t:content-transfer-encoding;\n\tbh=0XMSD76UFofqM+aOca1a/9QAHACeF8R2dnZninqs3Qw=;\n\tb=f9KEWCail+OKQ68FdU3UJ9rEiH+RCtSMUrkwHyB5YZafhFXMj5o/maIBooPEj884ns\n\t0AC3U3o+5KSLEXJPTm/HY/51rHi/fHQN3hxnkFAoMtzhQ6UyfMJLHMETCwwB2abWCP5/\n\tukyL+C59UYcDqzilx0plT/oxda625PKY2c7BEzbve0sPgf5Ml3oaEmJd56C2BAE++RTG\n\tdvWC4W3IyqeZxtTIiPkiZtv1x2uW27BcPhi2b5zEG/gWZeHfpKRWp6ByR6igy0pDgyZj\n\tcu5c2jxVMioKo7Q23sIJeXd+T5VjOzKjidFVJyYFSY2mm9paiRTrSuDDgI8i2AS/Kzdz\n\tZmDQ==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:subject:to:cc:date:message-id:user-agent\n\t:mime-version:content-transfer-encoding;\n\tbh=0XMSD76UFofqM+aOca1a/9QAHACeF8R2dnZninqs3Qw=;\n\tb=uaZ2LVmUFlDlrdl70LjPU+KQW/bfN0tT5x630FVBykybPCAMpxIPbdvYIRvIxWcYvr\n\tONxFz8m7W+8waV/6ByrYQynf2FH+/UF/6oWPY6XljKrNUv9BBhoxkQcJW7WyBz/8SCtG\n\tfe0piO/OUldO46dZJgINLf/FxuEaYfwITmYVwCEvC/JhI1Ht39BRnmMnCaWX+y8wsFg6\n\tzI8NSfIYUCTmA4Wac+tVmYmKxOVKxsn1UExi/Nzs08XRrYPVnws0Kv6JMtL6yOrP7Nwa\n\tiiiPRlN/zYYFxNSBQxsionJeiQ6oYd5Kss0fDLsOnqPTPTr3itpi631WHiN7Zqb7VXTQ\n\tRM4A==", "X-Gm-Message-State": "AFeK/H2t7hRKUqHnnzeMTyN2GksSDnX2V41mQQRqqvj32M0g9UU8wTktLRpX6bQ3PA6XIg==", "X-Received": "by 10.98.80.209 with SMTP id g78mr17267253pfj.163.1489763817454; \n\tFri, 17 Mar 2017 08:16:57 -0700 (PDT)", "From": "John Fastabend <john.fastabend@gmail.com>", "X-Google-Original-From": "John Fastabend <john.r.fastabend@intel.com>", "To": "john.fastabend@gmail.com, alexander.duyck@gmail.com", "Date": "Fri, 17 Mar 2017 08:16:43 -0700", "Message-ID": "<20170317151643.8653.78437.stgit@john-Precision-Tower-5810>", "User-Agent": "StGit/0.17.1-dirty", "MIME-Version": "1.0", "Cc": "intel-wired-lan@lists.osuosl.org, alexei.starovoitov@gmail.com,\n\tdaniel@iogearbox.net, u9012063@gmail.com", "Subject": "[Intel-wired-lan] [net-next PATCH v6 1/2] ixgbe: add XDP support\n\tfor pass and drop actions", "X-BeenThere": "intel-wired-lan@lists.osuosl.org", "X-Mailman-Version": "2.1.18-1", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.lists.osuosl.org>", "List-Unsubscribe": "<http://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@lists.osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@lists.osuosl.org?subject=help>", "List-Subscribe": "<http://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@lists.osuosl.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@lists.osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@lists.osuosl.org>" }, "content": "Basic XDP drop support for ixgbe. Uses READ_ONCE/xchg semantics on XDP\nprograms instead of rcu primitives as suggested by Daniel Borkmann and\nAlex Duyck.\n\nSigned-off-by: John Fastabend <john.r.fastabend@intel.com>\nAcked-by: Alexander Duyck <alexander.h.duyck@intel.com>\n---\n drivers/net/ethernet/intel/ixgbe/ixgbe.h | 4 -\n drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 4 -\n drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 163 +++++++++++++++++++---\n 3 files changed, 144 insertions(+), 27 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h\nindex 656ca8f..cb14813 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h\n@@ -318,6 +318,7 @@ struct ixgbe_ring {\n \tstruct ixgbe_ring *next;\t/* pointer to next ring in q_vector */\n \tstruct ixgbe_q_vector *q_vector; /* backpointer to host q_vector */\n \tstruct net_device *netdev;\t/* netdev ring belongs to */\n+\tstruct bpf_prog *xdp_prog;\n \tstruct device *dev;\t\t/* device for DMA mapping */\n \tstruct ixgbe_fwd_adapter *l2_accel_priv;\n \tvoid *desc;\t\t\t/* descriptor ring memory */\n@@ -555,6 +556,7 @@ struct ixgbe_adapter {\n \tunsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];\n \t/* OS defined structs */\n \tstruct net_device *netdev;\n+\tstruct bpf_prog *xdp_prog;\n \tstruct pci_dev *pdev;\n \n \tunsigned long state;\n@@ -835,7 +837,7 @@ enum ixgbe_boards {\n void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);\n void ixgbe_reset(struct ixgbe_adapter *adapter);\n void ixgbe_set_ethtool_ops(struct net_device *netdev);\n-int ixgbe_setup_rx_resources(struct ixgbe_ring *);\n+int ixgbe_setup_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);\n int ixgbe_setup_tx_resources(struct ixgbe_ring *);\n void ixgbe_free_rx_resources(struct ixgbe_ring *);\n void ixgbe_free_tx_resources(struct ixgbe_ring *);\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c\nindex 59730ed..79a126d 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c\n@@ -1128,7 +1128,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,\n \t\t\t sizeof(struct ixgbe_ring));\n \n \t\t\ttemp_ring[i].count = new_rx_count;\n-\t\t\terr = ixgbe_setup_rx_resources(&temp_ring[i]);\n+\t\t\terr = ixgbe_setup_rx_resources(adapter, &temp_ring[i]);\n \t\t\tif (err) {\n \t\t\t\twhile (i) {\n \t\t\t\t\ti--;\n@@ -1761,7 +1761,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)\n \trx_ring->netdev = adapter->netdev;\n \trx_ring->reg_idx = adapter->rx_ring[0]->reg_idx;\n \n-\terr = ixgbe_setup_rx_resources(rx_ring);\n+\terr = ixgbe_setup_rx_resources(adapter, rx_ring);\n \tif (err) {\n \t\tret_val = 4;\n \t\tgoto err_nomem;\ndiff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\nindex 91c1cda..ac1a99f 100644\n--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\n+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c\n@@ -49,6 +49,9 @@\n #include <linux/if_macvlan.h>\n #include <linux/if_bridge.h>\n #include <linux/prefetch.h>\n+#include <linux/bpf.h>\n+#include <linux/bpf_trace.h>\n+#include <linux/atomic.h>\n #include <scsi/fc/fc_fcoe.h>\n #include <net/udp_tunnel.h>\n #include <net/pkt_cls.h>\n@@ -1858,6 +1861,10 @@ static void ixgbe_dma_sync_frag(struct ixgbe_ring *rx_ring,\n * @rx_desc: pointer to the EOP Rx descriptor\n * @skb: pointer to current skb being fixed\n *\n+ * Check if the skb is valid in the XDP case it will be an error pointer.\n+ * Return true in this case to abort processing and advance to next\n+ * descriptor.\n+ *\n * Check for corrupted packet headers caused by senders on the local L2\n * embedded NIC switch not setting up their Tx Descriptors right. These\n * should be very rare.\n@@ -1876,6 +1883,10 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,\n {\n \tstruct net_device *netdev = rx_ring->netdev;\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(ixgbe_test_staterr(rx_desc,\n \t\t\t\t\tIXGBE_RXDADV_ERR_FRAME_ERR_MASK) &&\n@@ -2051,7 +2062,7 @@ static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring,\n \t\t/* hand second half of page back to the ring */\n \t\tixgbe_reuse_rx_page(rx_ring, rx_buffer);\n \t} else {\n-\t\tif (IXGBE_CB(skb)->dma == rx_buffer->dma) {\n+\t\tif (!IS_ERR(skb) && IXGBE_CB(skb)->dma == rx_buffer->dma) {\n \t\t\t/* the page has been released from the ring */\n \t\t\tIXGBE_CB(skb)->page_released = true;\n \t\t} else {\n@@ -2072,10 +2083,10 @@ static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring,\n \n static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,\n \t\t\t\t\t struct ixgbe_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+\tunsigned int size = xdp->data_end - xdp->data;\n #if (PAGE_SIZE < 8192)\n \tunsigned int truesize = ixgbe_rx_pg_size(rx_ring) / 2;\n #else\n@@ -2084,9 +2095,9 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,\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@@ -2099,7 +2110,7 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,\n \t\t\tIXGBE_CB(skb)->dma = rx_buffer->dma;\n \n \t\tskb_add_rx_frag(skb, 0, rx_buffer->page,\n-\t\t\t\trx_buffer->page_offset,\n+\t\t\t\txdp->data - page_address(rx_buffer->page),\n \t\t\t\tsize, truesize);\n #if (PAGE_SIZE < 8192)\n \t\trx_buffer->page_offset ^= truesize;\n@@ -2107,7 +2118,8 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,\n \t\trx_buffer->page_offset += truesize;\n #endif\n \t} else {\n-\t\tmemcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));\n+\t\tmemcpy(__skb_put(skb, size),\n+\t\t xdp->data, ALIGN(size, sizeof(long)));\n \t\trx_buffer->pagecnt_bias++;\n \t}\n \n@@ -2116,10 +2128,9 @@ static struct sk_buff *ixgbe_construct_skb(struct ixgbe_ring *rx_ring,\n \n static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring,\n \t\t\t\t struct ixgbe_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 #if (PAGE_SIZE < 8192)\n \tunsigned int truesize = ixgbe_rx_pg_size(rx_ring) / 2;\n #else\n@@ -2129,19 +2140,19 @@ static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring,\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 around the page buffer */\n-\tskb = build_skb(va - IXGBE_SKB_PAD, truesize);\n+\t/* build an skb to 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, IXGBE_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/* record DMA address if this is the start of a chain of buffers */\n \tif (!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_EOP))\n@@ -2157,6 +2168,41 @@ static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring,\n \treturn skb;\n }\n \n+#define IXGBE_XDP_PASS 0\n+#define IXGBE_XDP_CONSUMED 1\n+\n+static struct sk_buff *ixgbe_run_xdp(struct ixgbe_ring *rx_ring,\n+\t\t\t\t struct xdp_buff *xdp)\n+{\n+\tint result = IXGBE_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+\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 = IXGBE_XDP_CONSUMED;\n+\t\tbreak;\n+\t}\n+xdp_out:\n+\trcu_read_unlock();\n+\treturn ERR_PTR(-result);\n+}\n+\n /**\n * ixgbe_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf\n * @q_vector: structure containing interrupt and ring information\n@@ -2186,6 +2232,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,\n \t\tunion ixgbe_adv_rx_desc *rx_desc;\n \t\tstruct ixgbe_rx_buffer *rx_buffer;\n \t\tstruct sk_buff *skb;\n+\t\tstruct xdp_buff xdp;\n \t\tunsigned int size;\n \n \t\t/* return some buffers to hardware, one at a time is too slow */\n@@ -2208,14 +2255,29 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,\n \t\trx_buffer = ixgbe_get_rx_buffer(rx_ring, rx_desc, &skb, 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\t\trx_buffer->page_offset;\n+\t\t\txdp.data_hard_start = xdp.data -\n+\t\t\t\t\t\tixgbe_rx_offset(rx_ring);\n+\t\t\txdp.data_end = xdp.data + size;\n+\n+\t\t\tskb = ixgbe_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\tixgbe_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 = ixgbe_build_skb(rx_ring, rx_buffer,\n-\t\t\t\t\t rx_desc, size);\n-\t\telse\n+\t\t\t\t\t &xdp, rx_desc);\n+\t\t} else {\n \t\t\tskb = ixgbe_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@@ -6074,7 +6136,8 @@ static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter)\n *\n * Returns 0 on success, negative on failure\n **/\n-int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring)\n+int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter,\n+\t\t\t struct ixgbe_ring *rx_ring)\n {\n \tstruct device *dev = rx_ring->dev;\n \tint orig_node = dev_to_node(dev);\n@@ -6111,6 +6174,8 @@ int ixgbe_setup_rx_resources(struct ixgbe_ring *rx_ring)\n \trx_ring->next_to_clean = 0;\n \trx_ring->next_to_use = 0;\n \n+\trx_ring->xdp_prog = adapter->xdp_prog;\n+\n \treturn 0;\n err:\n \tvfree(rx_ring->rx_buffer_info);\n@@ -6134,7 +6199,7 @@ static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter)\n \tint i, err = 0;\n \n \tfor (i = 0; i < adapter->num_rx_queues; i++) {\n-\t\terr = ixgbe_setup_rx_resources(adapter->rx_ring[i]);\n+\t\terr = ixgbe_setup_rx_resources(adapter, adapter->rx_ring[i]);\n \t\tif (!err)\n \t\t\tcontinue;\n \n@@ -6202,6 +6267,7 @@ void ixgbe_free_rx_resources(struct ixgbe_ring *rx_ring)\n {\n \tixgbe_clean_rx_ring(rx_ring);\n \n+\trx_ring->xdp_prog = NULL;\n \tvfree(rx_ring->rx_buffer_info);\n \trx_ring->rx_buffer_info = NULL;\n \n@@ -9470,6 +9536,54 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)\n \treturn features;\n }\n \n+static int ixgbe_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 ixgbe_adapter *adapter = netdev_priv(dev);\n+\tstruct bpf_prog *old_prog;\n+\n+\tif (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)\n+\t\treturn -EINVAL;\n+\n+\tif (adapter->flags & IXGBE_FLAG_DCB_ENABLED)\n+\t\treturn -EINVAL;\n+\n+\t/* verify ixgbe ring attributes are sufficient for XDP */\n+\tfor (i = 0; i < adapter->num_rx_queues; i++) {\n+\t\tstruct ixgbe_ring *ring = adapter->rx_ring[i];\n+\n+\t\tif (ring_is_rsc_enabled(ring))\n+\t\t\treturn -EINVAL;\n+\n+\t\tif (frame_size > ixgbe_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 ixgbe_xdp(struct net_device *dev, struct netdev_xdp *xdp)\n+{\n+\tstruct ixgbe_adapter *adapter = netdev_priv(dev);\n+\n+\tswitch (xdp->command) {\n+\tcase XDP_SETUP_PROG:\n+\t\treturn ixgbe_xdp_setup(dev, xdp->prog);\n+\tcase XDP_QUERY_PROG:\n+\t\txdp->prog_attached = !!(adapter->rx_ring[0]->xdp_prog);\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+}\n+\n static const struct net_device_ops ixgbe_netdev_ops = {\n \t.ndo_open\t\t= ixgbe_open,\n \t.ndo_stop\t\t= ixgbe_close,\n@@ -9515,6 +9629,7 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)\n \t.ndo_udp_tunnel_add\t= ixgbe_add_udp_tunnel_port,\n \t.ndo_udp_tunnel_del\t= ixgbe_del_udp_tunnel_port,\n \t.ndo_features_check\t= ixgbe_features_check,\n+\t.ndo_xdp\t\t= ixgbe_xdp,\n };\n \n /**\n", "prefixes": [ "net-next", "v6", "1/2" ] }