get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 818163,
    "url": "http://patchwork.ozlabs.org/api/patches/818163/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/1506335021-32024-7-git-send-email-simon.horman@netronome.com/",
    "project": {
        "id": 7,
        "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api",
        "name": "Linux network development",
        "link_name": "netdev",
        "list_id": "netdev.vger.kernel.org",
        "list_email": "netdev@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1506335021-32024-7-git-send-email-simon.horman@netronome.com>",
    "list_archive_url": null,
    "date": "2017-09-25T10:23:40",
    "name": "[net-next,6/7] nfp: flower vxlan neighbour offload",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "ad7cccc55bde2832816f006a27bf4a9554a31b49",
    "submitter": {
        "id": 64714,
        "url": "http://patchwork.ozlabs.org/api/people/64714/?format=api",
        "name": "Simon Horman",
        "email": "simon.horman@netronome.com"
    },
    "delegate": {
        "id": 34,
        "url": "http://patchwork.ozlabs.org/api/users/34/?format=api",
        "username": "davem",
        "first_name": "David",
        "last_name": "Miller",
        "email": "davem@davemloft.net"
    },
    "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/1506335021-32024-7-git-send-email-simon.horman@netronome.com/mbox/",
    "series": [
        {
            "id": 4932,
            "url": "http://patchwork.ozlabs.org/api/series/4932/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=4932",
            "date": "2017-09-25T10:23:34",
            "name": "nfp: flower vxlan tunnel offload",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/4932/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/818163/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/818163/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<netdev-owner@vger.kernel.org>",
        "X-Original-To": "patchwork-incoming@ozlabs.org",
        "Delivered-To": "patchwork-incoming@ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=netronome-com.20150623.gappssmtp.com\n\theader.i=@netronome-com.20150623.gappssmtp.com\n\theader.b=\"jdjydQDm\"; dkim-atps=neutral"
        ],
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3y10Yt1yhjz9tX3\n\tfor <patchwork-incoming@ozlabs.org>;\n\tMon, 25 Sep 2017 20:24:18 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S934479AbdIYKYQ (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tMon, 25 Sep 2017 06:24:16 -0400",
            "from mail-wr0-f170.google.com ([209.85.128.170]:51341 \"EHLO\n\tmail-wr0-f170.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S934332AbdIYKYI (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Mon, 25 Sep 2017 06:24:08 -0400",
            "by mail-wr0-f170.google.com with SMTP id z39so6877921wrb.8\n\tfor <netdev@vger.kernel.org>; Mon, 25 Sep 2017 03:24:08 -0700 (PDT)",
            "from penelope.horms.nl ([217.111.208.18])\n\tby smtp.gmail.com with ESMTPSA id\n\t10sm6816818wrt.59.2017.09.25.03.24.05\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tMon, 25 Sep 2017 03:24:06 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=netronome-com.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=flRmuO2Nau605HBZw0avBMyvdRzKMUo7CxNRquXI0j0=;\n\tb=jdjydQDmPBOpTadA7fchI8gGbPQbQC6MWiv6WpZaDxhTd8SjGK8vbjA8JPw1el2UNj\n\tZ+h1akkxyt3jcxAEy7PeS/vW19IfDhIm2PE2V77GVgGJEdisIlUYFdqEV6CR1ERjWwFl\n\tnbR5llQGaqp6cD9XoPpgrAyvm2+hLcFLG5IuMD4maK9KNXFdmu6jXwx3FZIfLPb9diYC\n\tNc7qxB10rj4NXn/Ci5UqEumE6BKnQEZMlJ7DLrbyggfsYNKtr5JmPTvkeRSltYWTAenJ\n\tdMP0qeMwEUecz2pNvL59wnyijb7tAC7TMt+PuHJhoV7lWyssti9x9Rsbat4CaP69LX6Q\n\tGghA==",
        "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:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=flRmuO2Nau605HBZw0avBMyvdRzKMUo7CxNRquXI0j0=;\n\tb=Eet8IzZA5zC2httIfVsMQME3/Q2oktibhghBjueCkmCI8SUh6/nrqfHp2flcy1pdig\n\tOhsf2yFJf+BRCjlt2/xlFS8Q4uXO4FZBMcFQSOAUc9xrumvQXs/A+Ef7Qm45xE0XMWfG\n\tIIzsNbsf0YEOuPcY6JiZg1Gorb/QU6cfrF/CgvqFd5qfHqaJ+EPKU2c1LHc2Yhq5ueZz\n\tst6Jrfq2eEWsaOgDsg8E5IXhiF2JmGVK5PCB0rdw3P+gzSfbl6LqiPWfSts9kBtDYQDp\n\tI3aG9TicZfaI4OT7RKHqEFSD4vAGz9wssIHjLWSLNsPN76IxWX8v2A5ag0MDjqSz1jt5\n\t7MPw==",
        "X-Gm-Message-State": "AHPjjUgWzKoN9Y/54YEYX+pZ0+Xv6oXunou/7eUEPXfKNOqfTQlNSdbx\n\tSSve2xJ2HpSzlQG0MSvypbhXiQ==",
        "X-Google-Smtp-Source": "AOwi7QDVwcfW2JTmWpHOT34XoJSDzIj43TCfoqztbWJaQOwes1cgCA4QyvVKTLm3px8eM0tp4hn69w==",
        "X-Received": "by 10.223.196.238 with SMTP id o43mr6183675wrf.276.1506335047095;\n\tMon, 25 Sep 2017 03:24:07 -0700 (PDT)",
        "From": "Simon Horman <simon.horman@netronome.com>",
        "To": "David Miller <davem@davemloft.net>,\n\tJakub Kicinski <jakub.kicinski@netronome.com>",
        "Cc": "netdev@vger.kernel.org, oss-drivers@netronome.com,\n\tJohn Hurley <john.hurley@netronome.com>,\n\tSimon Horman <simon.horman@netronome.com>",
        "Subject": "[PATCH net-next 6/7] nfp: flower vxlan neighbour offload",
        "Date": "Mon, 25 Sep 2017 12:23:40 +0200",
        "Message-Id": "<1506335021-32024-7-git-send-email-simon.horman@netronome.com>",
        "X-Mailer": "git-send-email 2.1.4",
        "In-Reply-To": "<1506335021-32024-1-git-send-email-simon.horman@netronome.com>",
        "References": "<1506335021-32024-1-git-send-email-simon.horman@netronome.com>",
        "Sender": "netdev-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<netdev.vger.kernel.org>",
        "X-Mailing-List": "netdev@vger.kernel.org"
    },
    "content": "From: John Hurley <john.hurley@netronome.com>\n\nReceive a request when the NFP does not know the next hop for a packet\nthat is to be encapsulated in a VXLAN tunnel. Do a route lookup, determine\nthe next hop entry and update neighbour table on NFP. Monitor the kernel\nneighbour table for link changes and update NFP with relevant information.\nOverwrite routes with zero values on the NFP when they expire.\n\nSigned-off-by: John Hurley <john.hurley@netronome.com>\nReviewed-by: Simon Horman <simon.horman@netronome.com>\nSigned-off-by: Simon Horman <simon.horman@netronome.com>\n---\n drivers/net/ethernet/netronome/nfp/flower/cmsg.c   |   6 +\n drivers/net/ethernet/netronome/nfp/flower/cmsg.h   |   2 +\n drivers/net/ethernet/netronome/nfp/flower/main.h   |   7 +\n .../ethernet/netronome/nfp/flower/tunnel_conf.c    | 253 +++++++++++++++++++++\n 4 files changed, 268 insertions(+)",
    "diff": "diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c\nindex b756006dba6f..862787daaa68 100644\n--- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c\n+++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c\n@@ -181,6 +181,12 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb)\n \tcase NFP_FLOWER_CMSG_TYPE_FLOW_STATS:\n \t\tnfp_flower_rx_flow_stats(app, skb);\n \t\tbreak;\n+\tcase NFP_FLOWER_CMSG_TYPE_NO_NEIGH:\n+\t\tnfp_tunnel_request_route(app, skb);\n+\t\tbreak;\n+\tcase NFP_FLOWER_CMSG_TYPE_TUN_NEIGH:\n+\t\t/* Acks from the NFP that the route is added - ignore. */\n+\t\tbreak;\n \tdefault:\n \t\tnfp_flower_cmsg_warn(app, \"Cannot handle invalid repr control type %u\\n\",\n \t\t\t\t     type);\ndiff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h\nindex 6540bb1ceefb..1dc72a1ed577 100644\n--- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h\n+++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h\n@@ -317,7 +317,9 @@ enum nfp_flower_cmsg_type_port {\n \tNFP_FLOWER_CMSG_TYPE_FLOW_DEL =\t\t2,\n \tNFP_FLOWER_CMSG_TYPE_MAC_REPR =\t\t7,\n \tNFP_FLOWER_CMSG_TYPE_PORT_MOD =\t\t8,\n+\tNFP_FLOWER_CMSG_TYPE_NO_NEIGH =\t\t10,\n \tNFP_FLOWER_CMSG_TYPE_TUN_MAC =\t\t11,\n+\tNFP_FLOWER_CMSG_TYPE_TUN_NEIGH =\t13,\n \tNFP_FLOWER_CMSG_TYPE_TUN_IPS =\t\t14,\n \tNFP_FLOWER_CMSG_TYPE_FLOW_STATS =\t15,\n \tNFP_FLOWER_CMSG_TYPE_PORT_ECHO =\t16,\ndiff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h\nindex 53306af6cfe8..93ad969c3653 100644\n--- a/drivers/net/ethernet/netronome/nfp/flower/main.h\n+++ b/drivers/net/ethernet/netronome/nfp/flower/main.h\n@@ -87,12 +87,15 @@ struct nfp_fl_stats_id {\n  * @nfp_mac_off_list:\tList of MAC addresses to offload\n  * @nfp_mac_index_list:\tList of unique 8-bit indexes for non NFP netdevs\n  * @nfp_ipv4_off_list:\tList of IPv4 addresses to offload\n+ * @nfp_neigh_off_list:\tList of neighbour offloads\n  * @nfp_mac_off_lock:\tLock for the MAC address list\n  * @nfp_mac_index_lock:\tLock for the MAC index list\n  * @nfp_ipv4_off_lock:\tLock for the IPv4 address list\n+ * @nfp_neigh_off_lock:\tLock for the neighbour address list\n  * @nfp_mac_off_ids:\tIDA to manage id assignment for offloaded macs\n  * @nfp_mac_off_count:\tNumber of MACs in address list\n  * @nfp_tun_mac_nb:\tNotifier to monitor link state\n+ * @nfp_tun_neigh_nb:\tNotifier to monitor neighbour state\n  */\n struct nfp_flower_priv {\n \tstruct nfp_app *app;\n@@ -108,12 +111,15 @@ struct nfp_flower_priv {\n \tstruct list_head nfp_mac_off_list;\n \tstruct list_head nfp_mac_index_list;\n \tstruct list_head nfp_ipv4_off_list;\n+\tstruct list_head nfp_neigh_off_list;\n \tstruct mutex nfp_mac_off_lock;\n \tstruct mutex nfp_mac_index_lock;\n \tstruct mutex nfp_ipv4_off_lock;\n+\tstruct mutex nfp_neigh_off_lock;\n \tstruct ida nfp_mac_off_ids;\n \tint nfp_mac_off_count;\n \tstruct notifier_block nfp_tun_mac_nb;\n+\tstruct notifier_block nfp_tun_neigh_nb;\n };\n \n struct nfp_fl_key_ls {\n@@ -189,5 +195,6 @@ void nfp_tunnel_config_stop(struct nfp_app *app);\n void nfp_tunnel_write_macs(struct nfp_app *app);\n void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4);\n void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4);\n+void nfp_tunnel_request_route(struct nfp_app *app, struct sk_buff *skb);\n \n #endif\ndiff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c\nindex 185505140f5e..8c6b88a1306b 100644\n--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c\n+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c\n@@ -33,6 +33,7 @@\n \n #include <linux/etherdevice.h>\n #include <linux/inetdevice.h>\n+#include <net/netevent.h>\n #include <linux/idr.h>\n #include <net/dst_metadata.h>\n \n@@ -41,6 +42,44 @@\n #include \"../nfp_net_repr.h\"\n #include \"../nfp_net.h\"\n \n+/**\n+ * struct nfp_tun_neigh - neighbour/route entry on the NFP\n+ * @dst_ipv4:\tdestination IPv4 address\n+ * @src_ipv4:\tsource IPv4 address\n+ * @dst_addr:\tdestination MAC address\n+ * @src_addr:\tsource MAC address\n+ * @port_id:\tNFP port to output packet on - associated with source IPv4\n+ */\n+struct nfp_tun_neigh {\n+\t__be32 dst_ipv4;\n+\t__be32 src_ipv4;\n+\tu8 dst_addr[ETH_ALEN];\n+\tu8 src_addr[ETH_ALEN];\n+\t__be32 port_id;\n+};\n+\n+/**\n+ * struct nfp_tun_req_route_ipv4 - NFP requests a route/neighbour lookup\n+ * @ingress_port:\tingress port of packet that signalled request\n+ * @ipv4_addr:\t\tdestination ipv4 address for route\n+ * @reserved:\t\treserved for future use\n+ */\n+struct nfp_tun_req_route_ipv4 {\n+\t__be32 ingress_port;\n+\t__be32 ipv4_addr;\n+\t__be32 reserved[2];\n+};\n+\n+/**\n+ * struct nfp_ipv4_route_entry - routes that are offloaded to the NFP\n+ * @ipv4_addr:\tdestination of route\n+ * @list:\tlist pointer\n+ */\n+struct nfp_ipv4_route_entry {\n+\t__be32 ipv4_addr;\n+\tstruct list_head list;\n+};\n+\n #define NFP_FL_IPV4_ADDRS_MAX        32\n \n /**\n@@ -137,6 +176,197 @@ nfp_flower_xmit_tun_conf(struct nfp_app *app, u8 mtype, u16 plen, void *pdata)\n \treturn 0;\n }\n \n+static bool nfp_tun_has_route(struct nfp_app *app, __be32 ipv4_addr)\n+{\n+\tstruct nfp_flower_priv *priv = app->priv;\n+\tstruct nfp_ipv4_route_entry *entry;\n+\tstruct list_head *ptr, *storage;\n+\n+\tmutex_lock(&priv->nfp_neigh_off_lock);\n+\tlist_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) {\n+\t\tentry = list_entry(ptr, struct nfp_ipv4_route_entry, list);\n+\t\tif (entry->ipv4_addr == ipv4_addr) {\n+\t\t\tmutex_unlock(&priv->nfp_neigh_off_lock);\n+\t\t\treturn true;\n+\t\t}\n+\t}\n+\tmutex_unlock(&priv->nfp_neigh_off_lock);\n+\treturn false;\n+}\n+\n+static void nfp_tun_add_route_to_cache(struct nfp_app *app, __be32 ipv4_addr)\n+{\n+\tstruct nfp_flower_priv *priv = app->priv;\n+\tstruct nfp_ipv4_route_entry *entry;\n+\tstruct list_head *ptr, *storage;\n+\n+\tmutex_lock(&priv->nfp_neigh_off_lock);\n+\tlist_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) {\n+\t\tentry = list_entry(ptr, struct nfp_ipv4_route_entry, list);\n+\t\tif (entry->ipv4_addr == ipv4_addr) {\n+\t\t\tmutex_unlock(&priv->nfp_neigh_off_lock);\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\tentry = kmalloc(sizeof(*entry), GFP_KERNEL);\n+\tif (!entry) {\n+\t\tmutex_unlock(&priv->nfp_neigh_off_lock);\n+\t\tnfp_flower_cmsg_warn(app, \"Mem error when storing new route.\\n\");\n+\t\treturn;\n+\t}\n+\n+\tentry->ipv4_addr = ipv4_addr;\n+\tlist_add_tail(&entry->list, &priv->nfp_neigh_off_list);\n+\tmutex_unlock(&priv->nfp_neigh_off_lock);\n+}\n+\n+static void nfp_tun_del_route_from_cache(struct nfp_app *app, __be32 ipv4_addr)\n+{\n+\tstruct nfp_flower_priv *priv = app->priv;\n+\tstruct nfp_ipv4_route_entry *entry;\n+\tstruct list_head *ptr, *storage;\n+\n+\tmutex_lock(&priv->nfp_neigh_off_lock);\n+\tlist_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) {\n+\t\tentry = list_entry(ptr, struct nfp_ipv4_route_entry, list);\n+\t\tif (entry->ipv4_addr == ipv4_addr) {\n+\t\t\tlist_del(&entry->list);\n+\t\t\tkfree(entry);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\tmutex_unlock(&priv->nfp_neigh_off_lock);\n+}\n+\n+static void\n+nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,\n+\t\t    struct flowi4 *flow, struct neighbour *neigh)\n+{\n+\tstruct nfp_tun_neigh payload;\n+\n+\t/* Only offload representor IPv4s for now. */\n+\tif (!nfp_netdev_is_nfp_repr(netdev))\n+\t\treturn;\n+\n+\tmemset(&payload, 0, sizeof(struct nfp_tun_neigh));\n+\tpayload.dst_ipv4 = flow->daddr;\n+\n+\t/* If entry has expired send dst IP with all other fields 0. */\n+\tif (!(neigh->nud_state & NUD_VALID)) {\n+\t\tnfp_tun_del_route_from_cache(app, payload.dst_ipv4);\n+\t\t/* Trigger ARP to verify invalid neighbour state. */\n+\t\tneigh_event_send(neigh, NULL);\n+\t\tgoto send_msg;\n+\t}\n+\n+\t/* Have a valid neighbour so populate rest of entry. */\n+\tpayload.src_ipv4 = flow->saddr;\n+\tether_addr_copy(payload.src_addr, netdev->dev_addr);\n+\tneigh_ha_snapshot(payload.dst_addr, neigh, netdev);\n+\tpayload.port_id = cpu_to_be32(nfp_repr_get_port_id(netdev));\n+\t/* Add destination of new route to NFP cache. */\n+\tnfp_tun_add_route_to_cache(app, payload.dst_ipv4);\n+\n+send_msg:\n+\tnfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH,\n+\t\t\t\t sizeof(struct nfp_tun_neigh),\n+\t\t\t\t (unsigned char *)&payload);\n+}\n+\n+static int\n+nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,\n+\t\t\t    void *ptr)\n+{\n+\tstruct nfp_flower_priv *app_priv;\n+\tstruct netevent_redirect *redir;\n+\tstruct flowi4 flow = {};\n+\tstruct neighbour *n;\n+\tstruct nfp_app *app;\n+\tstruct rtable *rt;\n+\tint err;\n+\n+\tswitch (event) {\n+\tcase NETEVENT_REDIRECT:\n+\t\tredir = (struct netevent_redirect *)ptr;\n+\t\tn = redir->neigh;\n+\t\tbreak;\n+\tcase NETEVENT_NEIGH_UPDATE:\n+\t\tn = (struct neighbour *)ptr;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn NOTIFY_DONE;\n+\t}\n+\n+\tflow.daddr = *(__be32 *)n->primary_key;\n+\n+\t/* Only concerned with route changes for representors. */\n+\tif (!nfp_netdev_is_nfp_repr(n->dev))\n+\t\treturn NOTIFY_DONE;\n+\n+\tapp_priv = container_of(nb, struct nfp_flower_priv, nfp_tun_neigh_nb);\n+\tapp = app_priv->app;\n+\n+\t/* Only concerned with changes to routes already added to NFP. */\n+\tif (!nfp_tun_has_route(app, flow.daddr))\n+\t\treturn NOTIFY_DONE;\n+\n+#if IS_ENABLED(CONFIG_INET)\n+\t/* Do a route lookup to populate flow data. */\n+\trt = ip_route_output_key(dev_net(n->dev), &flow);\n+\terr = PTR_ERR_OR_ZERO(rt);\n+\tif (err)\n+\t\treturn NOTIFY_DONE;\n+#else\n+\treturn NOTIFY_DONE;\n+#endif\n+\n+\tflow.flowi4_proto = IPPROTO_UDP;\n+\tnfp_tun_write_neigh(n->dev, app, &flow, n);\n+\n+\treturn NOTIFY_OK;\n+}\n+\n+void nfp_tunnel_request_route(struct nfp_app *app, struct sk_buff *skb)\n+{\n+\tstruct nfp_tun_req_route_ipv4 *payload;\n+\tstruct net_device *netdev;\n+\tstruct flowi4 flow = {};\n+\tstruct neighbour *n;\n+\tstruct rtable *rt;\n+\tint err;\n+\n+\tpayload = nfp_flower_cmsg_get_data(skb);\n+\n+\tnetdev = nfp_app_repr_get(app, be32_to_cpu(payload->ingress_port));\n+\tif (!netdev)\n+\t\tgoto route_fail_warning;\n+\n+\tflow.daddr = payload->ipv4_addr;\n+\tflow.flowi4_proto = IPPROTO_UDP;\n+\n+#if IS_ENABLED(CONFIG_INET)\n+\t/* Do a route lookup on same namespace as ingress port. */\n+\trt = ip_route_output_key(dev_net(netdev), &flow);\n+\terr = PTR_ERR_OR_ZERO(rt);\n+\tif (err)\n+\t\tgoto route_fail_warning;\n+#else\n+\tgoto route_fail_warning;\n+#endif\n+\n+\t/* Get the neighbour entry for the lookup */\n+\tn = dst_neigh_lookup(&rt->dst, &flow.daddr);\n+\tip_rt_put(rt);\n+\tif (!n)\n+\t\tgoto route_fail_warning;\n+\tnfp_tun_write_neigh(n->dev, app, &flow, n);\n+\tneigh_release(n);\n+\treturn;\n+\n+route_fail_warning:\n+\tnfp_flower_cmsg_warn(app, \"Requested route not found.\\n\");\n+}\n+\n static void nfp_tun_write_ipv4_list(struct nfp_app *app)\n {\n \tstruct nfp_flower_priv *priv = app->priv;\n@@ -434,10 +664,19 @@ int nfp_tunnel_config_start(struct nfp_app *app)\n \tmutex_init(&priv->nfp_ipv4_off_lock);\n \tINIT_LIST_HEAD(&priv->nfp_ipv4_off_list);\n \n+\t/* Initialise priv data for neighbour offloading. */\n+\tmutex_init(&priv->nfp_neigh_off_lock);\n+\tINIT_LIST_HEAD(&priv->nfp_neigh_off_list);\n+\tpriv->nfp_tun_neigh_nb.notifier_call = nfp_tun_neigh_event_handler;\n+\n \terr = register_netdevice_notifier(&priv->nfp_tun_mac_nb);\n \tif (err)\n \t\tgoto err_free_mac_ida;\n \n+\terr = register_netevent_notifier(&priv->nfp_tun_neigh_nb);\n+\tif (err)\n+\t\tgoto err_unreg_mac_nb;\n+\n \t/* Parse netdevs already registered for MACs that need offloaded. */\n \trtnl_lock();\n \tfor_each_netdev(&init_net, netdev)\n@@ -446,6 +685,8 @@ int nfp_tunnel_config_start(struct nfp_app *app)\n \n \treturn 0;\n \n+err_unreg_mac_nb:\n+\tunregister_netdevice_notifier(&priv->nfp_tun_mac_nb);\n err_free_mac_ida:\n \tida_destroy(&priv->nfp_mac_off_ids);\n \treturn err;\n@@ -455,11 +696,13 @@ void nfp_tunnel_config_stop(struct nfp_app *app)\n {\n \tstruct nfp_tun_mac_offload_entry *mac_entry;\n \tstruct nfp_flower_priv *priv = app->priv;\n+\tstruct nfp_ipv4_route_entry *route_entry;\n \tstruct nfp_tun_mac_non_nfp_idx *mac_idx;\n \tstruct nfp_ipv4_addr_entry *ip_entry;\n \tstruct list_head *ptr, *storage;\n \n \tunregister_netdevice_notifier(&priv->nfp_tun_mac_nb);\n+\tunregister_netevent_notifier(&priv->nfp_tun_neigh_nb);\n \n \t/* Free any memory that may be occupied by MAC list. */\n \tmutex_lock(&priv->nfp_mac_off_lock);\n@@ -491,4 +734,14 @@ void nfp_tunnel_config_stop(struct nfp_app *app)\n \t\tkfree(ip_entry);\n \t}\n \tmutex_unlock(&priv->nfp_ipv4_off_lock);\n+\n+\t/* Free any memory that may be occupied by the route list. */\n+\tmutex_lock(&priv->nfp_neigh_off_lock);\n+\tlist_for_each_safe(ptr, storage, &priv->nfp_neigh_off_list) {\n+\t\troute_entry = list_entry(ptr, struct nfp_ipv4_route_entry,\n+\t\t\t\t\t list);\n+\t\tlist_del(&route_entry->list);\n+\t\tkfree(route_entry);\n+\t}\n+\tmutex_unlock(&priv->nfp_neigh_off_lock);\n }\n",
    "prefixes": [
        "net-next",
        "6/7"
    ]
}