> -----Original Message----- > From: Rakesh Kudurumalla > Sent: Tuesday, December 5, 2023 2:57 PM > To: Sunil Kumar Kori ; Rakesh Kudurumalla > > Cc: dev@dpdk.org; Jerin Jacob Kollanukkaran ; Nithin > Kumar Dabilpuram > Subject: [PATCH v4 3/3] app/graph: implement port forward usecase > > Added portforward usecase.In this usecase packets received Rx port is > forwarded to respective Tx port. > > Signed-off-by: Rakesh Kudurumalla > --- > app/graph/ethdev.c | 12 ++ > app/graph/ethdev.h | 1 + > app/graph/examples/l2fwd.cli | 41 +++++ > app/graph/examples/l2fwd_pcap.cli | 37 +++++ > app/graph/graph.c | 8 +- > app/graph/l2fwd.c | 148 +++++++++++++++++++ > app/graph/l2fwd.h | 11 ++ > app/graph/meson.build | 1 + > app/graph/module_api.h | 1 + > doc/guides/tools/graph.rst | 27 ++++ > doc/guides/tools/img/graph-usecase-l2fwd.svg | 84 +++++++++++ > 11 files changed, 370 insertions(+), 1 deletion(-) create mode 100644 > app/graph/examples/l2fwd.cli create mode 100644 > app/graph/examples/l2fwd_pcap.cli create mode 100644 > app/graph/l2fwd.c create mode 100644 app/graph/l2fwd.h create mode > 100644 doc/guides/tools/img/graph-usecase-l2fwd.svg > > diff --git a/app/graph/ethdev.c b/app/graph/ethdev.c index > bceee659a2..d048a65555 100644 > --- a/app/graph/ethdev.c > +++ b/app/graph/ethdev.c > @@ -77,6 +77,18 @@ ethdev_port_by_id(uint16_t port_id) > return NULL; > } > > +int16_t > +find_txport_by_rxport(uint16_t portid_rx) { > + int portid = -EINVAL; > + struct ethdev *port; Need one line space here. > + port = ethdev_port_by_id(portid_rx); > + if (port) > + portid = port->config.tx_port_id; > + > + return portid; > +} > + > void * > ethdev_mempool_list_by_portid(uint16_t portid) { diff --git > a/app/graph/ethdev.h b/app/graph/ethdev.h index > 836052046b..946e14d801 100644 > --- a/app/graph/ethdev.h > +++ b/app/graph/ethdev.h > @@ -33,6 +33,7 @@ extern uint32_t enabled_port_mask; > > void ethdev_start(void); > void ethdev_stop(void); > +int16_t find_txport_by_rxport(uint16_t portid_rx); > void *ethdev_mempool_list_by_portid(uint16_t portid); int16_t > ethdev_portid_by_ip4(uint32_t ip, uint32_t mask); int16_t > ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask); diff --git > a/app/graph/examples/l2fwd.cli b/app/graph/examples/l2fwd.cli new file > mode 100644 index 0000000000..af24a5836a > --- /dev/null > +++ b/app/graph/examples/l2fwd.cli > @@ -0,0 +1,41 @@ > +; SPDX-License-Identifier: BSD-3-Clause ; Copyright(c) 2023 Marvell. > + > +; > +; Graph configuration for given usecase ; graph l2fwd coremask 0xff bsz > +32 tmo 10 model default pcap_enable 1 num_pcap_pkts 100000 pcap_file > +/tmp/output.pcap > + > +; > +; Mempools to be attached with ethdev > +; > +mempool mempool0 size 8192 buffers 4000 cache 256 numa 0 > + > +; > +; DPDK devices and configuration. > +; > +; Note: Customize the parameters below to match your setup. > +; > +ethdev 0002:01:00.1 rxq 1 txq 8 mempool0 ethdev 0002:01:00.4 rxq 1 txq > +8 mempool0 ethdev 0002:01:00.6 rxq 1 txq 8 mempool0 ethdev > 0002:02:00.0 > +rxq 1 txq 8 mempool0 > + > +; > +; L2 mac forwarding rules > +; Replace "L2 mac forwarding rules" --> "Rx/Tx port mapping" > +ethdev forward 0002:01:00.4 0002:02:00.0 ethdev forward 0002:01:00.1 > +0002:01:00.6 > + > +; > +; Port-Queue-Core mapping for ethdev_rx node ; ethdev_rx map port > +0002:02:00.0 queue 0 core 1 ethdev_rx map port 0002:01:00.6 queue 0 > +core 2 > + > +; > +; Graph start command to create graph. > +; > +; Note: No more command should come after this. > +; > +graph start > diff --git a/app/graph/examples/l2fwd_pcap.cli > b/app/graph/examples/l2fwd_pcap.cli > new file mode 100644 > index 0000000000..718347f568 > --- /dev/null > +++ b/app/graph/examples/l2fwd_pcap.cli > @@ -0,0 +1,37 @@ > +; SPDX-License-Identifier: BSD-3-Clause ; Copyright(c) 2023 Marvell. > + > +; > +; Graph configuration for given usecase ; graph l2fwd coremask 0xff bsz > +32 tmo 10 model default pcap_enable 1 num_pcap_pkts 100000 pcap_file > +/tmp/output.pcap > + > +; > +; Mempools to be attached with ethdev > +; > +mempool mempool0 size 8192 buffers 4000 cache 256 numa 0 > + > +; > +; DPDK devices and configuration. > +; > +; Note: Customize the parameters below to match your setup. > +; > +ethdev net_pcap0 rxq 1 txq 8 mempool0 > +ethdev net_pcap1 rxq 1 txq 8 mempool0 > + > +; > +; L2 mac forwarding rules > +; > +ethdev forward net_pcap1 net_pcap0 > + > +; > +; Port-Queue-Core mapping for ethdev_rx node ; ethdev_rx map port > +net_pcap0 queue 0 core 1 > + > +; > +; Graph start command to create graph. > +; > +; Note: No more command should come after this. > +; > +graph start > diff --git a/app/graph/graph.c b/app/graph/graph.c index > a65723a196..4e0441f1a7 100644 > --- a/app/graph/graph.c > +++ b/app/graph/graph.c > @@ -24,7 +24,7 @@ cmd_graph_help[] = "graph bsz > tmo coremask " > "model pcap_enable <0 | 1> > num_pcap_pkts " > "pcap_file "; > > -static const char * const supported_usecases[] = {"l3fwd"}; > +static const char * const supported_usecases[] = {"l3fwd", "l2fwd"}; > struct graph_config graph_config; > bool graph_started; > > @@ -273,6 +273,12 @@ cli_graph_start(__rte_unused void *parsed_result, > __rte_unused struct cmdline *c > break; > } > } > + if (!strcmp(graph_config.usecases[i].name, "l2fwd")) { > + if (graph_config.usecases[i].enabled) { > + rc = usecase_l2fwd_configure(conf, > nb_conf, nb_graphs); > + break; > + } > + } > } > > if (!rc) > diff --git a/app/graph/l2fwd.c b/app/graph/l2fwd.c new file mode 100644 > index 0000000000..a780caa394 > --- /dev/null > +++ b/app/graph/l2fwd.c > @@ -0,0 +1,148 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Marvell. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "module_api.h" > + > +static int > +l2fwd_pattern_configure(void) > +{ > + struct rte_graph_param graph_conf; > + const char **node_patterns; > + uint64_t pcap_pkts_count; > + struct lcore_conf *qconf; > + uint16_t nb_patterns; > + uint8_t pcap_ena; > + char *pcap_file; > + int lcore_id; > + > + nb_patterns = 0; > + node_patterns = malloc((ETHDEV_RX_QUEUE_PER_LCORE_MAX + > nb_patterns) * > + sizeof(*node_patterns)); > + if (!node_patterns) > + return -ENOMEM; > + > + memset(&graph_conf, 0, sizeof(graph_conf)); > + graph_conf.node_patterns = node_patterns; > + > + /* Pcap config */ > + graph_pcap_config_get(&pcap_ena, &pcap_pkts_count, > &pcap_file); > + graph_conf.pcap_enable = pcap_ena; > + graph_conf.num_pkt_to_capture = pcap_pkts_count; > + graph_conf.pcap_filename = strdup(pcap_file); > + > + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { > + rte_graph_t graph_id; > + rte_edge_t i; > + > + if (rte_lcore_is_enabled(lcore_id) == 0) > + continue; > + > + qconf = &lcore_conf[lcore_id]; > + > + /* Skip graph creation if no source exists */ > + if (!qconf->n_rx_queue) > + continue; > + > + /* Add rx node patterns of this lcore */ > + for (i = 0; i < qconf->n_rx_queue; i++) { > + graph_conf.node_patterns[nb_patterns + i] = > + qconf->rx_queue_list[i].node_name; > + } > + > + graph_conf.nb_node_patterns = nb_patterns + i; > + graph_conf.socket_id = rte_lcore_to_socket_id(lcore_id); > + > + snprintf(qconf->name, sizeof(qconf->name), "worker_%u", > + lcore_id); > + > + graph_id = rte_graph_create(qconf->name, &graph_conf); > + if (graph_id == RTE_GRAPH_ID_INVALID) > + rte_exit(EXIT_FAILURE, > + "rte_graph_create(): graph_id invalid" > + " for lcore %u\n", lcore_id); > + > + qconf->graph_id = graph_id; > + qconf->graph = rte_graph_lookup(qconf->name); > + /* >8 End of graph initialization. */ > + if (!qconf->graph) > + rte_exit(EXIT_FAILURE, > + "rte_graph_lookup(): graph %s not > found\n", > + qconf->name); > + } > + > + /* Launch per-lcore init on every worker lcore */ > + rte_eal_mp_remote_launch(graph_walk_start, NULL, SKIP_MAIN); > + > + /* Accumulate and print stats on main until exit */ > + if (rte_graph_has_stats_feature() && app_graph_stats_enabled()) > + graph_stats_print(); > + > + return 0; > +} > + > +static int > +ethdev_rx_to_tx_node_link(uint32_t lcore_id) { > + char name[RTE_NODE_NAMESIZE]; > + const char *next_node = name; > + struct lcore_conf *qconf; > + uint16_t queue, port_id; > + rte_node_t rx_id; > + int16_t txport; > + int rc; > + > + qconf = &lcore_conf[lcore_id]; > + > + for (queue = 0; queue < qconf->n_rx_queue; ++queue) { > + port_id = qconf->rx_queue_list[queue].port_id; > + txport = find_txport_by_rxport(port_id); > + if (txport) { > + rx_id = rte_node_from_name(qconf- > >rx_queue_list[queue].node_name); > + snprintf(name, sizeof(name), "ethdev_tx-%u", txport); > + rte_node_edge_update(rx_id, > RTE_EDGE_ID_INVALID, &next_node, 1); > + rc = rte_node_ethdev_rx_next_update(rx_id, name); > + if (rc) > + return rc; > + } > + } > + return 0; > +} > + > + > +int > +usecase_l2fwd_configure(struct rte_node_ethdev_config *conf, uint16_t > +nb_confs, uint16_t nb_graphs) { > + uint32_t lcore_id; > + int rc; > + > + rc = rte_node_eth_config(conf, nb_confs, nb_graphs); > + if (rc) > + rte_exit(EXIT_FAILURE, "rte_node_eth_config: err=%d\n", rc); > + > + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { > + rc = ethdev_rx_to_tx_node_link(lcore_id); > + if (rc) > + rte_exit(EXIT_FAILURE, "rte_node_eth_config: > err=%d\n", rc); > + } > + > + rc = l2fwd_pattern_configure(); > + if (rc) > + rte_exit(EXIT_FAILURE, "l2fwd_pattern_failure: err=%d\n", > rc); > + > + return rc; > +} > diff --git a/app/graph/l2fwd.h b/app/graph/l2fwd.h new file mode 100644 > index 0000000000..3486ce52b2 > --- /dev/null > +++ b/app/graph/l2fwd.h > @@ -0,0 +1,11 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Marvell. > + */ > + > +#ifndef APP_GRAPH_L2FWD_H > +#define APP_GRAPH_L2FWD_H > + > +int usecase_l2fwd_configure(struct rte_node_ethdev_config *conf, > uint16_t nb_conf, > + uint16_t nb_graphs); > + > +#endif > diff --git a/app/graph/meson.build b/app/graph/meson.build index > 5b0f966d99..edd6b17ebc 100644 > --- a/app/graph/meson.build > +++ b/app/graph/meson.build > @@ -17,6 +17,7 @@ sources = files( > 'graph.c', > 'ip4_route.c', > 'ip6_route.c', > + 'l2fwd.c', > 'l3fwd.c', > 'main.c', > 'mempool.c', > diff --git a/app/graph/module_api.h b/app/graph/module_api.h index > 7193e0b616..c80eeb704c 100644 > --- a/app/graph/module_api.h > +++ b/app/graph/module_api.h > @@ -13,6 +13,7 @@ > #include "ethdev.h" > #include "ethdev_rx.h" > #include "graph.h" > +#include "l2fwd.h" > #include "l3fwd.h" > #include "mempool.h" > #include "neigh.h" > diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index > 1855d12891..33b5e750b2 100644 > --- a/doc/guides/tools/graph.rst > +++ b/doc/guides/tools/graph.rst > @@ -77,6 +77,13 @@ This use case is supported for both H/W and PCAP > vdev network devices. > To demonstrate, corresponding ``.cli`` files are available at > ``app/graph/examples/`` named as ``l3fwd.cli`` and > ``l3fwd_pcap.cli`` respectively. > > +l2fwd > +~~~~~ > + > +This use case is supported for both H/W and PCAP vdev network devices. > +To demonstrate, corresponding ``.cli`` files are available at > +``app/graph/examples/`` named as ``l2fwd.cli`` and > ``l2fwd_pcap.cli`` respectively. > + > Example Commands > ^^^^^^^^^^^^^^^^ > For H/W devices > @@ -86,6 +93,9 @@ For H/W devices > ./dpdk-graph -c 0xff -a 0002:02:00.0 -a 0002:03:00.0 -- > -s /app/graph/examples/l3fwd.cli > > + ./dpdk-graph -c 0xff -a 0002:02:00.0 -a 0002:03:00.0 -- > + -s /app/graph/examples/l2fwd.cli > + > For net_pcapX devices > > .. code-block:: console > @@ -94,6 +104,10 @@ For net_pcapX devices > -- > vdev=net_pcap1,rx_pcap=in_net_pcap1.pcap,tx_pcap=out_net_pcap0.pca > p > -- -s /app/graph/examples/l3fwd_pcap.cli > > + ./dpdk-graph -c 0xff -- > vdev=net_pcap0,rx_pcap=in_net_pcap0.pcap,tx_pcap=out_net_pcap1.pca > p > + -- > vdev=net_pcap1,rx_pcap=in_net_pcap1.pcap,tx_pcap=out_net_pcap0.pca > p > + -- -s > + /app/graph/examples/l2fwd_pcap.cli > + > Verifying traffic > ^^^^^^^^^^^^^^^^^ > > @@ -110,6 +124,12 @@ For current use case, following routing table is > used: > On the successful execution of ``l3fwd.cli`` or ``l3fwd_pcap.cli``, user > needs to send traffic with mentioned DIP. > > +``l2fwd.cli`` and ``l2fwd_pcap.cli`` creates setup with two network > ports. > +Packet received on one port is forwarded to other port. > + > +On the successful execution of ``l2fwd.cli`` or ``l2fwd_pcap.cli``, > +user needs to send traffic on RX port. > + > For net_pcapX devices, required pcap file should be created and passed to > application. > These pcap files can be created in several ways. > Scapy is one of the method to get the same: > @@ -321,3 +341,10 @@ l3fwd > .. _figure_l3fwd_graph: > > .. figure:: img/graph-usecase-l3fwd.* > + > +l2fwd > +~~~~~ > + > +.. _figure_l2fwd_graph: > + > +.. figure:: img/graph-usecase-l2fwd.* > diff --git a/doc/guides/tools/img/graph-usecase-l2fwd.svg > b/doc/guides/tools/img/graph-usecase-l2fwd.svg > new file mode 100644 > index 0000000000..6b70af3380 > --- /dev/null > +++ b/doc/guides/tools/img/graph-usecase-l2fwd.svg > @@ -0,0 +1,84 @@ > + svg > +PUBLIC "-//W3C//DTD SVG 1.1//EN" > + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> > + > + > + > + > + +width="299pt" height="204pt" > + viewBox="0.00 0.00 299.40 204.00" xmlns="http://www.w3.org/2000/svg" > +xmlns:xlink="http://www.w3.org/1999/xlink"> > + dpdk_app_graph_l2fwd_nodes_flow > + > + > + > +ingress_port > + +y="-174.3" font-family="Times,serif" > +font-size="14.00">ingress_port > + > + > + > +ethdev_rx > + +ry="18"/> +font-family="Times,serif" font-size="14.00">ethdev_rx > + > + > +ingress_port->ethdev_rx > + +points="122.4,-119.18 118.9,-109.18 115.4,-119.18 122.4,-119.18"/> > + +font-family="Times,serif" font-size="14.00">ingress packet > + > + > +ethdev_tx > + +ry="18"/> +font-family="Times,serif" font-size="14.00">ethdev_tx > + > + > + > +ethdev_rx->ethdev_tx > + +points="80.12,-41.03 70.87,-35.87 74.88,-45.67 80.12,-41.03"/> > + > + > +pkt_drop > + +ry="18"/> +font-family="Times,serif" font-size="14.00">pkt_drop > + > + > +ethdev_rx->pkt_drop > + +points="163.34,-45.18 167.36,-35.38 158.11,-40.53 163.34,-45.18"/> > + > + > +egress_port > + +x="240.9" y="-174.3" font-family="Times,serif" > +font-size="14.00">egress_port > + > + > + > -- > 2.25.1