[v3,3/3] examples/l3fwd-graph: add IPv6 lookup and rewrite support

Message ID 20230531113743.1929627-3-amitprakashs@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series [v3,1/3] lib: add IPv6 lookup node |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation fail Compilation issues
ci/intel-Testing success Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/github-robot: build success github build: passed
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-testing warning Testing issues
ci/iol-aarch64-compile-testing success Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/iol-aarch64-unit-testing success Testing PASS
ci/iol-abi-testing success Testing PASS
ci/iol-unit-testing success Testing PASS
ci/iol-x86_64-compile-testing success Testing PASS

Commit Message

Amit Prakash Shukla May 31, 2023, 11:37 a.m. UTC
  From: Sunil Kumar Kori <skori@marvell.com>

Similar to ipv4, to support IPv6 lookup and rewrite node
routes and rewrite data needs to be added.

Patch adds routes for ipv6 to validate ip6_lookup node
and  rewrite data to validate ip6_rewrite node.

Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
---
v2:
- Performance related changes

v3:
- Removing redundant dynamic variable

 doc/guides/sample_app_ug/l3_forward_graph.rst | 40 ++++++----
 examples/l3fwd-graph/main.c                   | 77 ++++++++++++++++++-
 2 files changed, 98 insertions(+), 19 deletions(-)
  

Comments

Nithin Dabilpuram June 5, 2023, 4:32 p.m. UTC | #1
Acked-by: Nithin Dabilpuram <ndabilpuram@marvell.com>

On Wed, May 31, 2023 at 5:08 PM Amit Prakash Shukla
<amitprakashs@marvell.com> wrote:
>
> From: Sunil Kumar Kori <skori@marvell.com>
>
> Similar to ipv4, to support IPv6 lookup and rewrite node
> routes and rewrite data needs to be added.
>
> Patch adds routes for ipv6 to validate ip6_lookup node
> and  rewrite data to validate ip6_rewrite node.
>
> Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
> Signed-off-by: Amit Prakash Shukla <amitprakashs@marvell.com>
> ---
> v2:
> - Performance related changes
>
> v3:
> - Removing redundant dynamic variable
>
>  doc/guides/sample_app_ug/l3_forward_graph.rst | 40 ++++++----
>  examples/l3fwd-graph/main.c                   | 77 ++++++++++++++++++-
>  2 files changed, 98 insertions(+), 19 deletions(-)
>
> diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
> index 585ac8c898..23f86e4785 100644
> --- a/doc/guides/sample_app_ug/l3_forward_graph.rst
> +++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
> @@ -12,7 +12,8 @@ Overview
>  --------
>
>  The application demonstrates the use of the graph framework and graph nodes
> -``ethdev_rx``, ``ip4_lookup``, ``ip4_rewrite``, ``ethdev_tx`` and ``pkt_drop`` in DPDK to
> +``ethdev_rx``, ``pkt_cls``, ``ip4_lookup``/``ip6_lookup``,
> +``ip4_rewrite``/``ip6_rewrite``, ``ethdev_tx`` and ``pkt_drop`` in DPDK to
>  implement packet forwarding.
>
>  The initialization is very similar to those of the :doc:`l3_forward`.
> @@ -24,13 +25,15 @@ TTL update and finally Tx is implemented inside graph nodes. These nodes are
>  interconnected in graph framework. Application main loop needs to walk over
>  graph using ``rte_graph_walk()`` with graph objects created one per worker lcore.
>
> -The lookup method is as per implementation of ``ip4_lookup`` graph node.
> +The lookup method is as per implementation of ``ip4_lookup``/``ip6_lookup`` graph node.
>  The ID of the output interface for the input packet is the next hop returned by
>  the LPM lookup. The set of LPM rules used by the application is statically
> -configured and provided to ``ip4_lookup`` graph node and ``ip4_rewrite`` graph node
> -using node control API ``rte_node_ip4_route_add()`` and ``rte_node_ip4_rewrite_add()``.
> +configured and provided to ``ip4_lookup``/``ip6_lookup`` graph node and
> +``ip4_rewrite``/``ip6_rewrite`` graph node using node control API
> +``rte_node_ip4_route_add()``/``rte_node_ip6_route_add`` and
> +``rte_node_ip4_rewrite_add()``/``rte_node_ip6_rewrite_add``.
>
> -In the sample application, only IPv4 forwarding is supported as of now.
> +In the sample application, IPv4 and IPv6 forwarding is supported.
>
>  Compiling the Application
>  -------------------------
> @@ -149,8 +152,8 @@ lead to the clone of ``ethdev_rx`` and ``ethdev_tx`` nodes as ``ethdev_rx-X-Y``
>  In case of ``ethdev_tx-X`` nodes, tx queue id assigned per instance of the node
>  is same as graph id.
>
> -These cloned nodes along with existing static nodes such as ``ip4_lookup`` and
> -``ip4_rewrite`` will be used in graph creation to associate node's to lcore
> +These cloned nodes along with existing static nodes such as ``ip4_lookup``/``ip6_lookup``
> +and ``ip4_rewrite``/``ip6_rewrite`` will be used in graph creation to associate node's to lcore
>  specific graph object.
>
>  .. literalinclude:: ../../../examples/l3fwd-graph/main.c
> @@ -186,20 +189,21 @@ Forwarding data(Route, Next-Hop) addition
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>  Once graph objects are created, node specific info like routes and rewrite
> -headers will be provided run-time using ``rte_node_ip4_route_add()`` and
> -``rte_node_ip4_rewrite_add()`` API.
> +headers will be provided run-time using ``rte_node_ip4_route_add()``/
> +``rte_node_ip6_route_add`` and ``rte_node_ip4_rewrite_add()``/``rte_node_ip6_rewrite_add``
> +API.
>
>  .. note::
>
> -    Since currently ``ip4_lookup`` and ``ip4_rewrite`` nodes don't support
> -    lock-less mechanisms(RCU, etc) to add run-time forwarding data like route and
> -    rewrite data, forwarding data is added before packet processing loop is
> -    launched on worker lcore.
> +    Since currently ``ip4_lookup``/``ip6_lookup`` and ``ip4_rewrite``/``ip6_rewrite``
> +    nodes don't support lock-less mechanisms(RCU, etc) to add run-time forwarding
> +    data like route and rewrite data, forwarding data is added before packet
> +    processing loop is launched on worker lcore.
>
>  .. literalinclude:: ../../../examples/l3fwd-graph/main.c
>      :language: c
> -    :start-after: Add route to ip4 graph infra. 8<
> -    :end-before: >8 End of adding route to ip4 graph infa.
> +    :start-after: Add routes and rewrite data to graph infra. 8<
> +    :end-before: >8 End of adding routes and rewrite data to graph infa.
>      :dedent: 1
>
>  Packet Forwarding using Graph Walk
> @@ -215,8 +219,10 @@ specific graph object that was already created.
>
>      rte_graph_walk() will walk over all the sources nodes i.e ``ethdev_rx-X-Y``
>      associated with a given graph and Rx the available packets and enqueue them
> -    to the following node ``ip4_lookup`` which then will enqueue them to ``ip4_rewrite``
> -    node if LPM lookup succeeds. ``ip4_rewrite`` node then will update Ethernet header
> +    to the following node ``pkt_cls`` which based on the packet type will enqueue
> +    them to ``ip4_lookup``/``ip6_lookup`` which then will enqueue them to
> +    ``ip4_rewrite``/``ip6_rewrite`` node if LPM lookup succeeds.
> +    ``ip4_rewrite``/``ip6_rewrite`` node then will update Ethernet header
>      as per next-hop data and transmit the packet via port 'Z' by enqueuing
>      to ``ethdev_tx-Z`` node instance in its graph object.
>
> diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
> index 5feeab4f0f..0c82e24513 100644
> --- a/examples/l3fwd-graph/main.c
> +++ b/examples/l3fwd-graph/main.c
> @@ -27,9 +27,11 @@
>  #include <rte_launch.h>
>  #include <rte_lcore.h>
>  #include <rte_log.h>
> +#include <rte_lpm6.h>
>  #include <rte_mempool.h>
>  #include <rte_node_eth_api.h>
>  #include <rte_node_ip4_api.h>
> +#include <rte_node_ip6_api.h>
>  #include <rte_per_lcore.h>
>  #include <rte_string_fns.h>
>  #include <rte_vect.h>
> @@ -142,6 +144,12 @@ struct ipv4_l3fwd_lpm_route {
>         uint8_t if_out;
>  };
>
> +struct ipv6_l3fwd_lpm_route {
> +       uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE];
> +       uint8_t depth;
> +       uint8_t if_out;
> +};
> +
>  #define IPV4_L3FWD_LPM_NUM_ROUTES                                              \
>         (sizeof(ipv4_l3fwd_lpm_route_array) /                                  \
>          sizeof(ipv4_l3fwd_lpm_route_array[0]))
> @@ -153,6 +161,28 @@ static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
>         {RTE_IPV4(198, 18, 6, 0), 24, 6}, {RTE_IPV4(198, 18, 7, 0), 24, 7},
>  };
>
> +#define IPV6_L3FWD_LPM_NUM_ROUTES                                              \
> +       (sizeof(ipv6_l3fwd_lpm_route_array) /                                  \
> +        sizeof(ipv6_l3fwd_lpm_route_array[0]))
> +static struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
> +       {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +       0x00}, 48, 0},
> +       {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +       0x01}, 48, 1},
> +       {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +       0x02}, 48, 2},
> +       {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +       0x03}, 48, 3},
> +       {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +       0x04}, 48, 4},
> +       {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +       0x05}, 48, 5},
> +       {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +       0x06}, 48, 6},
> +       {{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +       0x02}, 48, 7},
> +};
> +
>  static int
>  check_lcore_params(void)
>  {
> @@ -1128,7 +1158,7 @@ main(int argc, char **argv)
>         memset(&rewrite_data, 0, sizeof(rewrite_data));
>         rewrite_len = sizeof(rewrite_data);
>
> -       /* Add route to ip4 graph infra. 8< */
> +       /* Add routes and rewrite data to graph infra. 8< */
>         for (i = 0; i < IPV4_L3FWD_LPM_NUM_ROUTES; i++) {
>                 char route_str[INET6_ADDRSTRLEN * 4];
>                 char abuf[INET6_ADDRSTRLEN];
> @@ -1172,7 +1202,50 @@ main(int argc, char **argv)
>                 RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n",
>                         route_str, i);
>         }
> -       /* >8 End of adding route to ip4 graph infa. */
> +
> +       for (i = 0; i < IPV6_L3FWD_LPM_NUM_ROUTES; i++) {
> +               char route_str[INET6_ADDRSTRLEN * 4];
> +               char abuf[INET6_ADDRSTRLEN];
> +               struct in6_addr in6;
> +               uint32_t dst_port;
> +
> +               /* Skip unused ports */
> +               if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
> +                    enabled_port_mask) == 0)
> +                       continue;
> +
> +               dst_port = ipv6_l3fwd_lpm_route_array[i].if_out;
> +
> +               memcpy(in6.s6_addr, ipv6_l3fwd_lpm_route_array[i].ip, RTE_LPM6_IPV6_ADDR_SIZE);
> +               snprintf(route_str, sizeof(route_str), "%s / %d (%d)",
> +                        inet_ntop(AF_INET6, &in6, abuf, sizeof(abuf)),
> +                        ipv6_l3fwd_lpm_route_array[i].depth,
> +                        ipv6_l3fwd_lpm_route_array[i].if_out);
> +
> +               /* Use route index 'i' as next hop id */
> +               ret = rte_node_ip6_route_add(ipv6_l3fwd_lpm_route_array[i].ip,
> +                       ipv6_l3fwd_lpm_route_array[i].depth, i,
> +                       RTE_NODE_IP6_LOOKUP_NEXT_REWRITE);
> +
> +               if (ret < 0)
> +                       rte_exit(EXIT_FAILURE,
> +                                "Unable to add ip6 route %s to graph\n",
> +                                route_str);
> +
> +               memcpy(rewrite_data, val_eth + dst_port, rewrite_len);
> +
> +               /* Add next hop rewrite data for id 'i' */
> +               ret = rte_node_ip6_rewrite_add(i, rewrite_data,
> +                                              rewrite_len, dst_port);
> +               if (ret < 0)
> +                       rte_exit(EXIT_FAILURE,
> +                                "Unable to add next hop %u for "
> +                                "route %s\n", i, route_str);
> +
> +               RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n",
> +                       route_str, i);
> +       }
> +       /* >8 End of adding routes and rewrite data to graph infa. */
>
>         /* Launch per-lcore init on every worker lcore */
>         rte_eal_mp_remote_launch(graph_main_loop, NULL, SKIP_MAIN);
> --
> 2.25.1
>
  

Patch

diff --git a/doc/guides/sample_app_ug/l3_forward_graph.rst b/doc/guides/sample_app_ug/l3_forward_graph.rst
index 585ac8c898..23f86e4785 100644
--- a/doc/guides/sample_app_ug/l3_forward_graph.rst
+++ b/doc/guides/sample_app_ug/l3_forward_graph.rst
@@ -12,7 +12,8 @@  Overview
 --------
 
 The application demonstrates the use of the graph framework and graph nodes
-``ethdev_rx``, ``ip4_lookup``, ``ip4_rewrite``, ``ethdev_tx`` and ``pkt_drop`` in DPDK to
+``ethdev_rx``, ``pkt_cls``, ``ip4_lookup``/``ip6_lookup``,
+``ip4_rewrite``/``ip6_rewrite``, ``ethdev_tx`` and ``pkt_drop`` in DPDK to
 implement packet forwarding.
 
 The initialization is very similar to those of the :doc:`l3_forward`.
@@ -24,13 +25,15 @@  TTL update and finally Tx is implemented inside graph nodes. These nodes are
 interconnected in graph framework. Application main loop needs to walk over
 graph using ``rte_graph_walk()`` with graph objects created one per worker lcore.
 
-The lookup method is as per implementation of ``ip4_lookup`` graph node.
+The lookup method is as per implementation of ``ip4_lookup``/``ip6_lookup`` graph node.
 The ID of the output interface for the input packet is the next hop returned by
 the LPM lookup. The set of LPM rules used by the application is statically
-configured and provided to ``ip4_lookup`` graph node and ``ip4_rewrite`` graph node
-using node control API ``rte_node_ip4_route_add()`` and ``rte_node_ip4_rewrite_add()``.
+configured and provided to ``ip4_lookup``/``ip6_lookup`` graph node and
+``ip4_rewrite``/``ip6_rewrite`` graph node using node control API
+``rte_node_ip4_route_add()``/``rte_node_ip6_route_add`` and
+``rte_node_ip4_rewrite_add()``/``rte_node_ip6_rewrite_add``.
 
-In the sample application, only IPv4 forwarding is supported as of now.
+In the sample application, IPv4 and IPv6 forwarding is supported.
 
 Compiling the Application
 -------------------------
@@ -149,8 +152,8 @@  lead to the clone of ``ethdev_rx`` and ``ethdev_tx`` nodes as ``ethdev_rx-X-Y``
 In case of ``ethdev_tx-X`` nodes, tx queue id assigned per instance of the node
 is same as graph id.
 
-These cloned nodes along with existing static nodes such as ``ip4_lookup`` and
-``ip4_rewrite`` will be used in graph creation to associate node's to lcore
+These cloned nodes along with existing static nodes such as ``ip4_lookup``/``ip6_lookup``
+and ``ip4_rewrite``/``ip6_rewrite`` will be used in graph creation to associate node's to lcore
 specific graph object.
 
 .. literalinclude:: ../../../examples/l3fwd-graph/main.c
@@ -186,20 +189,21 @@  Forwarding data(Route, Next-Hop) addition
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Once graph objects are created, node specific info like routes and rewrite
-headers will be provided run-time using ``rte_node_ip4_route_add()`` and
-``rte_node_ip4_rewrite_add()`` API.
+headers will be provided run-time using ``rte_node_ip4_route_add()``/
+``rte_node_ip6_route_add`` and ``rte_node_ip4_rewrite_add()``/``rte_node_ip6_rewrite_add``
+API.
 
 .. note::
 
-    Since currently ``ip4_lookup`` and ``ip4_rewrite`` nodes don't support
-    lock-less mechanisms(RCU, etc) to add run-time forwarding data like route and
-    rewrite data, forwarding data is added before packet processing loop is
-    launched on worker lcore.
+    Since currently ``ip4_lookup``/``ip6_lookup`` and ``ip4_rewrite``/``ip6_rewrite``
+    nodes don't support lock-less mechanisms(RCU, etc) to add run-time forwarding
+    data like route and rewrite data, forwarding data is added before packet
+    processing loop is launched on worker lcore.
 
 .. literalinclude:: ../../../examples/l3fwd-graph/main.c
     :language: c
-    :start-after: Add route to ip4 graph infra. 8<
-    :end-before: >8 End of adding route to ip4 graph infa.
+    :start-after: Add routes and rewrite data to graph infra. 8<
+    :end-before: >8 End of adding routes and rewrite data to graph infa.
     :dedent: 1
 
 Packet Forwarding using Graph Walk
@@ -215,8 +219,10 @@  specific graph object that was already created.
 
     rte_graph_walk() will walk over all the sources nodes i.e ``ethdev_rx-X-Y``
     associated with a given graph and Rx the available packets and enqueue them
-    to the following node ``ip4_lookup`` which then will enqueue them to ``ip4_rewrite``
-    node if LPM lookup succeeds. ``ip4_rewrite`` node then will update Ethernet header
+    to the following node ``pkt_cls`` which based on the packet type will enqueue
+    them to ``ip4_lookup``/``ip6_lookup`` which then will enqueue them to
+    ``ip4_rewrite``/``ip6_rewrite`` node if LPM lookup succeeds.
+    ``ip4_rewrite``/``ip6_rewrite`` node then will update Ethernet header
     as per next-hop data and transmit the packet via port 'Z' by enqueuing
     to ``ethdev_tx-Z`` node instance in its graph object.
 
diff --git a/examples/l3fwd-graph/main.c b/examples/l3fwd-graph/main.c
index 5feeab4f0f..0c82e24513 100644
--- a/examples/l3fwd-graph/main.c
+++ b/examples/l3fwd-graph/main.c
@@ -27,9 +27,11 @@ 
 #include <rte_launch.h>
 #include <rte_lcore.h>
 #include <rte_log.h>
+#include <rte_lpm6.h>
 #include <rte_mempool.h>
 #include <rte_node_eth_api.h>
 #include <rte_node_ip4_api.h>
+#include <rte_node_ip6_api.h>
 #include <rte_per_lcore.h>
 #include <rte_string_fns.h>
 #include <rte_vect.h>
@@ -142,6 +144,12 @@  struct ipv4_l3fwd_lpm_route {
 	uint8_t if_out;
 };
 
+struct ipv6_l3fwd_lpm_route {
+	uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE];
+	uint8_t depth;
+	uint8_t if_out;
+};
+
 #define IPV4_L3FWD_LPM_NUM_ROUTES                                              \
 	(sizeof(ipv4_l3fwd_lpm_route_array) /                                  \
 	 sizeof(ipv4_l3fwd_lpm_route_array[0]))
@@ -153,6 +161,28 @@  static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
 	{RTE_IPV4(198, 18, 6, 0), 24, 6}, {RTE_IPV4(198, 18, 7, 0), 24, 7},
 };
 
+#define IPV6_L3FWD_LPM_NUM_ROUTES                                              \
+	(sizeof(ipv6_l3fwd_lpm_route_array) /                                  \
+	 sizeof(ipv6_l3fwd_lpm_route_array[0]))
+static struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
+	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00}, 48, 0},
+	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01}, 48, 1},
+	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02}, 48, 2},
+	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x03}, 48, 3},
+	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x04}, 48, 4},
+	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x05}, 48, 5},
+	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x06}, 48, 6},
+	{{0x20, 0x01, 0xdb, 0x08, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x02}, 48, 7},
+};
+
 static int
 check_lcore_params(void)
 {
@@ -1128,7 +1158,7 @@  main(int argc, char **argv)
 	memset(&rewrite_data, 0, sizeof(rewrite_data));
 	rewrite_len = sizeof(rewrite_data);
 
-	/* Add route to ip4 graph infra. 8< */
+	/* Add routes and rewrite data to graph infra. 8< */
 	for (i = 0; i < IPV4_L3FWD_LPM_NUM_ROUTES; i++) {
 		char route_str[INET6_ADDRSTRLEN * 4];
 		char abuf[INET6_ADDRSTRLEN];
@@ -1172,7 +1202,50 @@  main(int argc, char **argv)
 		RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n",
 			route_str, i);
 	}
-	/* >8 End of adding route to ip4 graph infa. */
+
+	for (i = 0; i < IPV6_L3FWD_LPM_NUM_ROUTES; i++) {
+		char route_str[INET6_ADDRSTRLEN * 4];
+		char abuf[INET6_ADDRSTRLEN];
+		struct in6_addr in6;
+		uint32_t dst_port;
+
+		/* Skip unused ports */
+		if ((1 << ipv6_l3fwd_lpm_route_array[i].if_out &
+		     enabled_port_mask) == 0)
+			continue;
+
+		dst_port = ipv6_l3fwd_lpm_route_array[i].if_out;
+
+		memcpy(in6.s6_addr, ipv6_l3fwd_lpm_route_array[i].ip, RTE_LPM6_IPV6_ADDR_SIZE);
+		snprintf(route_str, sizeof(route_str), "%s / %d (%d)",
+			 inet_ntop(AF_INET6, &in6, abuf, sizeof(abuf)),
+			 ipv6_l3fwd_lpm_route_array[i].depth,
+			 ipv6_l3fwd_lpm_route_array[i].if_out);
+
+		/* Use route index 'i' as next hop id */
+		ret = rte_node_ip6_route_add(ipv6_l3fwd_lpm_route_array[i].ip,
+			ipv6_l3fwd_lpm_route_array[i].depth, i,
+			RTE_NODE_IP6_LOOKUP_NEXT_REWRITE);
+
+		if (ret < 0)
+			rte_exit(EXIT_FAILURE,
+				 "Unable to add ip6 route %s to graph\n",
+				 route_str);
+
+		memcpy(rewrite_data, val_eth + dst_port, rewrite_len);
+
+		/* Add next hop rewrite data for id 'i' */
+		ret = rte_node_ip6_rewrite_add(i, rewrite_data,
+					       rewrite_len, dst_port);
+		if (ret < 0)
+			rte_exit(EXIT_FAILURE,
+				 "Unable to add next hop %u for "
+				 "route %s\n", i, route_str);
+
+		RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n",
+			route_str, i);
+	}
+	/* >8 End of adding routes and rewrite data to graph infa. */
 
 	/* Launch per-lcore init on every worker lcore */
 	rte_eal_mp_remote_launch(graph_main_loop, NULL, SKIP_MAIN);