get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 67239,
    "url": "https://patches.dpdk.org/api/patches/67239/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20200326165644.866053-29-jerinj@marvell.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20200326165644.866053-29-jerinj@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200326165644.866053-29-jerinj@marvell.com",
    "date": "2020-03-26T16:56:44",
    "name": "[v2,28/28] doc: add l3fwd graph application user guide",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "adfec2582650d7076e00e4c07a9d3e8dd17a31ae",
    "submitter": {
        "id": 1188,
        "url": "https://patches.dpdk.org/api/people/1188/?format=api",
        "name": "Jerin Jacob Kollanukkaran",
        "email": "jerinj@marvell.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20200326165644.866053-29-jerinj@marvell.com/mbox/",
    "series": [
        {
            "id": 9068,
            "url": "https://patches.dpdk.org/api/series/9068/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=9068",
            "date": "2020-03-26T16:56:16",
            "name": "graph: introduce graph subsystem",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/9068/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/67239/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/67239/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 38693A057C;\n\tThu, 26 Mar 2020 18:02:35 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 5B3831C139;\n\tThu, 26 Mar 2020 17:58:36 +0100 (CET)",
            "from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com\n [67.231.148.174]) by dpdk.org (Postfix) with ESMTP id ACC201C131\n for <dev@dpdk.org>; Thu, 26 Mar 2020 17:58:34 +0100 (CET)",
            "from pps.filterd (m0045849.ppops.net [127.0.0.1])\n by mx0a-0016f401.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id\n 02QGiTUk025262; Thu, 26 Mar 2020 09:58:32 -0700",
            "from sc-exch01.marvell.com ([199.233.58.181])\n by mx0a-0016f401.pphosted.com with ESMTP id 2ywg9nxgqx-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT);\n Thu, 26 Mar 2020 09:58:32 -0700",
            "from DC5-EXCH01.marvell.com (10.69.176.38) by SC-EXCH01.marvell.com\n (10.93.176.81) with Microsoft SMTP Server (TLS) id 15.0.1497.2;\n Thu, 26 Mar 2020 09:58:30 -0700",
            "from SC-EXCH01.marvell.com (10.93.176.81) by DC5-EXCH01.marvell.com\n (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.2;\n Thu, 26 Mar 2020 09:58:29 -0700",
            "from maili.marvell.com (10.93.176.43) by SC-EXCH01.marvell.com\n (10.93.176.81) with Microsoft SMTP Server id 15.0.1497.2 via Frontend\n Transport; Thu, 26 Mar 2020 09:58:29 -0700",
            "from jerin-lab.marvell.com (jerin-lab.marvell.com [10.28.34.14])\n by maili.marvell.com (Postfix) with ESMTP id 1A6A83F7040;\n Thu, 26 Mar 2020 09:58:24 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;\n h=from : to : cc :\n subject : date : message-id : in-reply-to : references : mime-version :\n content-transfer-encoding : content-type; s=pfpt0818;\n bh=qAjFHsCJ2f1J8bp9eSlI41hfrnjgw5q5Pf1GJo0PYR0=;\n b=y0y0Lj25NXkBe3QcXfeN/6kumfxROWjEqgZ7q0EENA0q62XZgJYSIESLjCMsZzs5ZPB0\n 2z87eOVBa/c7bNAJUoKssSwu5wlaBKNq9tOnovspqcCQujAhfns4eH9Na8UcbEFvAMTp\n LuIktS7ohdGbOzb8N7npbK0InToj6OBh9aW6+EFJyZj4S45eViVkhpvStErPdC61Q7W4\n dDRohmRcYkCurpav3V4fwB80hPQ3rvp9Wy/08B6b0J1uDfqQj7QlasM8DM7y6pJg1DpG\n A9danstVasneqE1v0/3raIdEOuuuILcug4BE0859LWo8zDtM7BYYioHP8zREYcvDmeUD kQ==",
        "From": "<jerinj@marvell.com>",
        "To": "Thomas Monjalon <thomas@monjalon.net>, John McNamara\n <john.mcnamara@intel.com>, Marko Kovacevic <marko.kovacevic@intel.com>,\n \"Ori Kam\" <orika@mellanox.com>,\n Bruce Richardson <bruce.richardson@intel.com>,\n \"Radu Nicolau\" <radu.nicolau@intel.com>, Akhil Goyal <akhil.goyal@nxp.com>,\n \"Tomasz Kantecki\" <tomasz.kantecki@intel.com>, Sunil Kumar Kori\n <skori@marvell.com>, Pavan Nikhilesh <pbhagavatula@marvell.com>, Nithin\n Dabilpuram <ndabilpuram@marvell.com>",
        "CC": "<dev@dpdk.org>, <david.marchand@redhat.com>, <mdr@ashroe.eu>,\n <mattias.ronnblom@ericsson.com>, <kirankumark@marvell.com>",
        "Date": "Thu, 26 Mar 2020 22:26:44 +0530",
        "Message-ID": "<20200326165644.866053-29-jerinj@marvell.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20200326165644.866053-1-jerinj@marvell.com>",
        "References": "<20200318213551.3489504-1-jerinj@marvell.com>\n <20200326165644.866053-1-jerinj@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Proofpoint-Virus-Version": "vendor=fsecure engine=2.50.10434:6.0.138, 18.0.645\n definitions=2020-03-26_08:2020-03-26,\n 2020-03-26 signatures=0",
        "Subject": "[dpdk-dev] [PATCH v2 28/28] doc: add l3fwd graph application user\n\tguide",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "From: Nithin Dabilpuram <ndabilpuram@marvell.com>\n\nAdding the user guide for l3fwd graph application.\n\nSigned-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com>\n---\n MAINTAINERS                                   |   1 +\n doc/guides/rel_notes/release_20_05.rst        |   8 +\n doc/guides/sample_app_ug/index.rst            |   1 +\n doc/guides/sample_app_ug/intro.rst            |   4 +\n doc/guides/sample_app_ug/l3_forward_graph.rst | 327 ++++++++++++++++++\n 5 files changed, 341 insertions(+)\n create mode 100644 doc/guides/sample_app_ug/l3_forward_graph.rst",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 1d2cf6caa..e8a87e119 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1583,6 +1583,7 @@ F: doc/guides/sample_app_ug/l3_forward.rst\n \n M: Nithin Dabilpuram <ndabilpuram@marvell.com>\n F: examples/l3fwd-graph/\n+F: doc/guides/sample_app_ug/l3_forward_graph.rst\n \n F: examples/link_status_interrupt/\n F: doc/guides/sample_app_ug/link_status_intr.rst\ndiff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst\nindex d208547ec..9d3e7bd69 100644\n--- a/doc/guides/rel_notes/release_20_05.rst\n+++ b/doc/guides/rel_notes/release_20_05.rst\n@@ -86,6 +86,14 @@ New Features\n     that can be configured through ``rte_node_ip4_rewrite_add`` function.\n   * Packet drop node: Frees the packets received to their respective mempool.\n \n+* **Added new l3fwd-graph sample application.**\n+\n+  Added an example application ``l3fwd-graph``. It demonstrates the usage of graph\n+  library and node library for packet processing. In addition to the library usage\n+  demonstration, this application can use for performance comparison with existing\n+  ``l3fwd`` (The static code without any nodes) with the modular ``l3fwd-graph``\n+  approach.\n+\n \n Removed Items\n -------------\ndiff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst\nindex ac3445147..cf9c1e44d 100644\n--- a/doc/guides/sample_app_ug/index.rst\n+++ b/doc/guides/sample_app_ug/index.rst\n@@ -29,6 +29,7 @@ Sample Applications User Guides\n     l2_forward_event\n     l2_forward_cat\n     l3_forward\n+    l3_forward_graph\n     l3_forward_power_man\n     l3_forward_access_ctrl\n     link_status_intr\ndiff --git a/doc/guides/sample_app_ug/intro.rst b/doc/guides/sample_app_ug/intro.rst\nindex 6cd0342a1..8ff223b16 100644\n--- a/doc/guides/sample_app_ug/intro.rst\n+++ b/doc/guides/sample_app_ug/intro.rst\n@@ -54,6 +54,10 @@ examples are highlighted below.\n   forwarding, or ``l3fwd`` application does forwarding based on Internet\n   Protocol, IPv4 or IPv6 like a simple router.\n \n+* :doc:`Network Layer 3 forwarding Graph<l3_forward_graph>`: The Network Layer3\n+  forwarding Graph, or ``l3fwd_graph`` application does forwarding based on IPv4\n+  like a simple router with DPDK Graph framework.\n+\n * :doc:`Hardware packet copying<ioat>`: The Hardware packet copying,\n   or ``ioatfwd`` application demonstrates how to use IOAT rawdev driver for\n   copying packets between two threads.\ndiff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst\nnew file mode 100644\nindex 000000000..73153f82b\n--- /dev/null\n+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst\n@@ -0,0 +1,327 @@\n+..  SPDX-License-Identifier: BSD-3-Clause\n+    Copyright(C) 2020 Marvell International Ltd.\n+\n+L3 Forwarding Graph Sample Application\n+======================================\n+\n+The L3 Forwarding Graph application is a simple example of packet processing\n+using the DPDK Graph framework. The application performs L3 forwarding using\n+Graph framework and nodes written for graph framework.\n+\n+Overview\n+--------\n+\n+The application demonstrates the use of the graph framework and graph nodes\n+``ethdev_rx``, ``ip4_lookup``, ``ip4_rewrite``, ``ethdev_tx`` and ``pkt_drop`` in DPDK to\n+implement packet forwarding.\n+\n+The initialization is very similar to those of the :doc:`l3_forward`.\n+There is also additional initialization of graph for graph object creation\n+and configuration per lcore.\n+Run-time path is main thing that differs from L3 forwarding sample application.\n+Difference is that forwarding logic starting from Rx, followed by LPM lookup,\n+TTL update and finally Tx is implemented inside graph nodes. These nodes are\n+interconnected in graph framework. Application main loop needs to walk over\n+graph using ``rte_graph_walk()`` with graph objects created one per slave lcore.\n+\n+The lookup method is as per implementation of ``ip4_lookup`` graph node.\n+The ID of the output interface for the input packet is the next hop returned by\n+the LPM lookup. The set of LPM rules used by the application is statically\n+configured and provided to ``ip4_lookup`` graph node and ``ip4_rewrite`` graph node\n+using node control API ``rte_node_ip4_route_add()`` and ``rte_node_ip4_rewrite_add()``.\n+\n+In the sample application, only IPv4 forwarding is supported as of now.\n+\n+Compiling the Application\n+-------------------------\n+\n+To compile the sample application see :doc:`compiling`.\n+\n+The application is located in the ``l3fwd-graph`` sub-directory.\n+\n+Running the Application\n+-----------------------\n+\n+The application has a number of command line options similar to l3fwd::\n+\n+    ./l3fwd-graph [EAL options] -- -p PORTMASK\n+                                   [-P]\n+                                   --config(port,queue,lcore)[,(port,queue,lcore)]\n+                                   [--eth-dest=X,MM:MM:MM:MM:MM:MM]\n+                                   [--enable-jumbo [--max-pkt-len PKTLEN]]\n+                                   [--no-numa]\n+                                   [--per-port-pool]\n+\n+Where,\n+\n+* ``-p PORTMASK:`` Hexadecimal bitmask of ports to configure\n+\n+* ``-P:`` Optional, sets all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address.\n+  Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted.\n+\n+* ``--config (port,queue,lcore)[,(port,queue,lcore)]:`` Determines which queues from which ports are mapped to which cores.\n+\n+* ``--eth-dest=X,MM:MM:MM:MM:MM:MM:`` Optional, ethernet destination for port X.\n+\n+* ``--enable-jumbo:`` Optional, enables jumbo frames.\n+\n+* ``--max-pkt-len:`` Optional, under the premise of enabling jumbo, maximum packet length in decimal (64-9600).\n+\n+* ``--no-numa:`` Optional, disables numa awareness.\n+\n+* ``--per-port-pool:`` Optional, set to use independent buffer pools per port. Without this option, single buffer pool is used for all ports.\n+\n+For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0,\n+while cores 8-15 and 24-31 appear on socket 1.\n+\n+To enable L3 forwarding between two ports, assuming that both ports are in the same socket, using two cores, cores 1 and 2,\n+(which are in the same socket too), use the following command:\n+\n+.. code-block:: console\n+\n+    ./build/l3fwd-graph -l 1,2 -n 4 -- -p 0x3 --config=\"(0,0,1),(1,0,2)\"\n+\n+In this command:\n+\n+*   The -l option enables cores 1, 2\n+\n+*   The -p option enables ports 0 and 1\n+\n+*   The --config option enables one queue on each port and maps each (port,queue) pair to a specific core.\n+    The following table shows the mapping in this example:\n+\n++----------+-----------+-----------+-------------------------------------+\n+| **Port** | **Queue** | **lcore** | **Description**                     |\n+|          |           |           |                                     |\n++----------+-----------+-----------+-------------------------------------+\n+| 0        | 0         | 1         | Map queue 0 from port 0 to lcore 1. |\n+|          |           |           |                                     |\n++----------+-----------+-----------+-------------------------------------+\n+| 1        | 0         | 2         | Map queue 0 from port 1 to lcore 2. |\n+|          |           |           |                                     |\n++----------+-----------+-----------+-------------------------------------+\n+\n+Refer to the *DPDK Getting Started Guide* for general information on running applications and\n+the Environment Abstraction Layer (EAL) options.\n+\n+.. _l3_fwd_graph_explanation:\n+\n+Explanation\n+-----------\n+\n+The following sections provide some explanation of the sample application code.\n+As mentioned in the overview section, the initialization is similar to that of\n+the :doc:`l3_forward`. Run-time path though similar in functionality to that of\n+:doc:`l3_forward`, major part of the implementation is in graph nodes via used\n+via ``librte_node`` library.\n+The following sections describe aspects that are specific to the L3 Forwarding\n+Graph sample application.\n+\n+Graph Node Pre-Init Configuration\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+After device configuration and device Rx, Tx queue setup is complete,\n+a minimal config of port id, num_rx_queues, num_tx_queues, mempools etc will\n+be passed to *ethdev_** node ctrl API ``rte_node_eth_config()``. This will be\n+lead to the clone of ``ethdev_rx`` and ``ethdev_tx`` nodes as ``ethdev_rx-X-Y`` and\n+``ethdev_tx-X`` where X, Y represent port id and queue id associated with them.\n+In case of ``ethdev_tx-X`` nodes, tx queue id assigned per instance of the node\n+is same as graph id.\n+\n+These cloned nodes along with existing static nodes such as ``ip4_lookup`` and\n+``ip4_rewrite`` will be used in graph creation to associate node's to lcore\n+specific graph object.\n+\n+.. code-block:: c\n+\n+    RTE_ETH_FOREACH_DEV(portid)\n+    {\n+\n+        /* ... */\n+        ret = rte_eth_dev_configure(portid, nb_rx_queue,\n+                                    n_tx_queue, &local_port_conf);\n+        /* ... */\n+\n+        /* Init one TX queue per couple (lcore,port) */\n+        queueid = 0;\n+        for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n+            /* ... */\n+            ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,\n+                                         socketid, txconf);\n+            /* ... */\n+            queueid++;\n+        }\n+\n+        /* Setup ethdev node config */\n+        ethdev_conf[nb_conf].port_id = portid;\n+        ethdev_conf[nb_conf].num_rx_queues = nb_rx_queue;\n+        ethdev_conf[nb_conf].num_tx_queues = n_tx_queue;\n+        if (!per_port_pool)\n+            ethdev_conf[nb_conf].mp = pktmbuf_pool[0];\n+        else\n+          ethdev_conf[nb_conf].mp = pktmbuf_pool[portid];\n+        ethdev_conf[nb_conf].mp_count = NB_SOCKETS;\n+\n+        nb_conf++;\n+        printf(\"\\n\");\n+    }\n+\n+    for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n+        /* Init RX queues */\n+        for (queue = 0; queue < qconf->n_rx_queue; ++queue) {\n+            /* ... */\n+            if (!per_port_pool)\n+                ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid,\n+                                             &rxq_conf, pktmbuf_pool[0][socketid]);\n+            else\n+              ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, socketid,\n+                                           &rxq_conf, pktmbuf_pool[portid][socketid]);\n+            /* ... */\n+        }\n+    }\n+\n+    /* Ethdev node config, skip rx queue mapping */\n+    ret = rte_node_eth_config(ethdev_conf, nb_conf, nb_graphs);\n+\n+Graph Initialization\n+~~~~~~~~~~~~~~~~~~~~\n+\n+Now a graph needs to be created with a specific set of nodes for every lcore.\n+A graph object returned after graph creation is a per lcore object and\n+cannot be shared between lcores. Since ``ethdev_tx-X`` node is per port node,\n+it can be associated with all the graphs created as all the lcores should have\n+Tx capability for every port. But ``ethdev_rx-X-Y`` node is created per\n+(port, rx_queue_id), so they should be associated with a graph based on\n+the application argument ``--config`` specifying rx queue mapping to lcore.\n+\n+.. note::\n+\n+    The Graph creation will fail if the passed set of shell node pattern's\n+    are not sufficient to meet their inter-dependency or even one node is not\n+    found with a given regex node pattern.\n+\n+.. code-block:: c\n+\n+    static const char *node_patterns[] = {\n+        \"ip4*\",\n+        \"ethdev_tx-*\",\n+        \"pkt_drop\",\n+    };\n+    uint16_t nb_patterns = RTE_DIM(node_patterns);\n+\n+    /* ... */\n+\n+    /* Create a graph object per lcore with common nodes and\n+     * lcore specific nodes based on application arguments\n+     */\n+    memset(&graph_conf, 0, sizeof(graph_conf));\n+\n+    /* Common set of nodes in every lcore's graph object */\n+    graph_conf.node_patterns = node_patterns;\n+\n+    for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n+        /* ... */\n+\n+        /* Skip graph creation if no source exists */\n+        if (!qconf->n_rx_queue)\n+            continue;\n+\n+        /* Add rx node patterns of this lcore based on --config */\n+        for (i = 0; i < qconf->n_rx_queue; i++) {\n+            graph_conf.node_patterns[nb_patterns + i] =\n+                                qconf->rx_queue_list[i].node_name;\n+        }\n+\n+        graph_conf.nb_node_patterns = nb_patterns + i;\n+        graph_conf.socket_id = rte_lcore_to_socket_id(lcore_id);\n+\n+        snprintf(qconf->name, sizeof(qconf->name), \"worker_%u\", lcore_id);\n+\n+        graph_id = rte_graph_create(qconf->name, &graph_conf);\n+\n+        /* ... */\n+\n+        qconf->graph = rte_graph_lookup(qconf->name);\n+\n+        /* ... */\n+    }\n+\n+Forwarding data(Route, Next-Hop) addition\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Once graph objects are created, node specific info like routes and rewrite\n+headers will be provided run-time using ``rte_node_ip4_route_add()`` and\n+``rte_node_ip4_rewrite_add()`` API.\n+\n+.. note::\n+\n+    Since currently ``ip4_lookup`` and ``ip4_rewrite`` nodes don't support\n+    lock-less mechanisms(RCU, etc) to add run-time forwarding data like route and\n+    rewrite data, forwarding data is added before packet processing loop is\n+    launched on slave lcore.\n+\n+.. code-block:: c\n+\n+    /* Add route to ip4 graph infra */\n+    for (i = 0; i < IPV4_L3FWD_LPM_NUM_ROUTES; i++) {\n+        /* ... */\n+\n+        dst_port = ipv4_l3fwd_lpm_route_array[i].if_out;\n+        next_hop = i;\n+\n+        /* ... */\n+        ret = rte_node_ip4_route_add(ipv4_l3fwd_lpm_route_array[i].ip,\n+                                     ipv4_l3fwd_lpm_route_array[i].depth, next_hop,\n+                                     RTE_NODE_IP4_LOOKUP_NEXT_REWRITE);\n+\n+        /* ... */\n+\n+        memcpy(rewrite_data, val_eth + dst_port, rewrite_len);\n+\n+        /* Add next hop for a given destination */\n+        ret = rte_node_ip4_rewrite_add(next_hop, rewrite_data,\n+                                       rewrite_len, dst_port);\n+\n+        RTE_LOG(INFO, L3FWD_GRAPH, \"Added route %s, next_hop %u\\n\",\n+                route_str, next_hop);\n+    }\n+\n+Packet Forwarding using Graph Walk\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Now that all the device configurations are done, graph creations are done and\n+forwarding data is updated with nodes, slave lcores will be launched with graph\n+main loop. Graph main loop is very simple in the sense that it needs to\n+continuously call a non-blocking API ``rte_graph_walk()`` with it's lcore\n+specific graph object that was already created.\n+\n+.. note::\n+\n+    rte_graph_walk() will walk over all the sources nodes i.e ``ethdev_rx-X-Y``\n+    associated with a given graph and Rx the available packets and enqueue them\n+    to the following node ``ip4_lookup`` which then will enqueue them to ``ip4_rewrite``\n+    node if LPM lookup succeeds. ``ip4_rewrite`` node then will update Ethernet header\n+    as per next-hop data and transmit the packet via port 'Z' by enqueuing\n+    to ``ethdev_tx-Z`` node instance in its graph object.\n+\n+.. code-block:: c\n+\n+    /* Main processing loop */\n+    static int\n+    graph_main_loop(void *conf)\n+    {\n+        // ...\n+\n+        lcore_id = rte_lcore_id();\n+        qconf = &lcore_conf[lcore_id];\n+        graph = qconf->graph;\n+\n+        RTE_LOG(INFO, L3FWD_GRAPH,\n+                \"Entering main loop on lcore %u, graph %s(%p)\\n\", lcore_id,\n+                qconf->name, graph);\n+\n+        /* Walk over graph until signal to quit */\n+        while (likely(!force_quit))\n+            rte_graph_walk(graph);\n+        return 0;\n+    }\n",
    "prefixes": [
        "v2",
        "28/28"
    ]
}