From: <jerinj@marvell.com> Cc: <dev@dpdk.org>, <thomas@monjalon.net>, <david.marchand@redhat.com>, <mdr@ashroe.eu>, <mattias.ronnblom@ericsson.com>, <kirankumark@marvell.com>, <pbhagavatula@marvell.com>, <ndabilpuram@marvell.com>, <xiao.w.wang@intel.com> Subject: [dpdk-dev] [PATCH v4 14/29] graph: add performance testcase Date: Sun, 5 Apr 2020 14:25:58 +0530 Message-ID: <20200405085613.1336841-15-jerinj@marvell.com> (raw) In-Reply-To: <20200405085613.1336841-1-jerinj@marvell.com> From: Pavan Nikhilesh <pbhagavatula@marvell.com> Add unit test framework to create and test performance of various graph models. example command to test: echo "graph_perf_autotest" | sudo ./build/app/test/dpdk-test -c 0x30 Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com> --- app/test/Makefile | 1 + app/test/meson.build | 1 + app/test/test_graph_perf.c | 1057 ++++++++++++++++++++++++++++++++++++ 3 files changed, 1059 insertions(+) create mode 100644 app/test/test_graph_perf.c diff --git a/app/test/Makefile b/app/test/Makefile index ce2e08e12..77276f300 100644 --- a/app/test/Makefile +++ b/app/test/Makefile @@ -223,6 +223,7 @@ endif ifeq ($(CONFIG_RTE_LIBRTE_GRAPH), y) SRCS-y += test_graph.c +SRCS-y += test_graph_perf.c endif ifeq ($(CONFIG_RTE_LIBRTE_RAWDEV),y) diff --git a/app/test/meson.build b/app/test/meson.build index 3cf850584..9006cc074 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -52,6 +52,7 @@ test_sources = files('commands.c', 'test_func_reentrancy.c', 'test_flow_classify.c', 'test_graph.c', + 'test_graph_perf.c', 'test_hash.c', 'test_hash_functions.c', 'test_hash_multiwriter.c', diff --git a/app/test/test_graph_perf.c b/app/test/test_graph_perf.c new file mode 100644 index 000000000..a629f1e35 --- /dev/null +++ b/app/test/test_graph_perf.c @@ -0,0 +1,1057 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2020 Marvell International Ltd. + */ +#include <inttypes.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> + +#include <rte_common.h> +#include <rte_cycles.h> +#include <rte_errno.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_lcore.h> +#include <rte_malloc.h> +#include <rte_mbuf.h> + +#include "test.h" + +#define TEST_GRAPH_PERF_MZ "graph_perf_data" +#define TEST_GRAPH_SRC_NAME "test_graph_perf_source" +#define TEST_GRAPH_SRC_BRST_ONE_NAME "test_graph_perf_source_one" +#define TEST_GRAPH_WRK_NAME "test_graph_perf_worker" +#define TEST_GRAPH_SNK_NAME "test_graph_perf_sink" + +#define SOURCES(map) RTE_DIM(map) +#define STAGES(map) RTE_DIM(map) +#define NODES_PER_STAGE(map) RTE_DIM(map[0]) +#define SINKS(map) RTE_DIM(map[0]) + +#define MAX_EDGES_PER_NODE 7 + +struct test_node_data { + uint8_t node_id; + uint8_t is_sink; + uint8_t next_nodes[MAX_EDGES_PER_NODE]; + uint8_t next_percentage[MAX_EDGES_PER_NODE]; +}; + +struct test_graph_perf { + uint16_t nb_nodes; + rte_graph_t graph_id; + struct test_node_data *node_data; +}; + +struct graph_lcore_data { + uint8_t done; + rte_graph_t graph_id; +}; + +static struct test_node_data * +graph_get_node_data(struct test_graph_perf *graph_data, rte_node_t id) +{ + struct test_node_data *node_data = NULL; + int i; + + for (i = 0; i < graph_data->nb_nodes; i++) + if (graph_data->node_data[i].node_id == id) { + node_data = &graph_data->node_data[i]; + break; + } + + return node_data; +} + +static int +test_node_ctx_init(const struct rte_graph *graph, struct rte_node *node) +{ + struct test_graph_perf *graph_data; + struct test_node_data *node_data; + const struct rte_memzone *mz; + rte_node_t nid = node->id; + rte_edge_t edge = 0; + int i; + + RTE_SET_USED(graph); + + mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ); + graph_data = mz->addr; + node_data = graph_get_node_data(graph_data, nid); + node->ctx[0] = node->nb_edges; + for (i = 0; i < node->nb_edges && !node_data->is_sink; i++, edge++) { + node->ctx[i + 1] = edge; + node->ctx[i + 9] = node_data->next_percentage[i]; + } + + return 0; +} + +/* Source node function */ +static uint16_t +test_perf_node_worker_source(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + uint16_t count; + int i; + + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + /* Create a proportional stream for every next */ + for (i = 0; i < node->ctx[0]; i++) { + count = (node->ctx[i + 9] * RTE_GRAPH_BURST_SIZE) / 100; + rte_node_next_stream_get(graph, node, node->ctx[i + 1], count); + rte_node_next_stream_put(graph, node, node->ctx[i + 1], count); + } + + return RTE_GRAPH_BURST_SIZE; +} + +static struct rte_node_register test_graph_perf_source = { + .name = TEST_GRAPH_SRC_NAME, + .process = test_perf_node_worker_source, + .flags = RTE_NODE_SOURCE_F, + .init = test_node_ctx_init, +}; + +RTE_NODE_REGISTER(test_graph_perf_source); + +static uint16_t +test_perf_node_worker_source_burst_one(struct rte_graph *graph, + struct rte_node *node, void **objs, + uint16_t nb_objs) +{ + uint16_t count; + int i; + + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + /* Create a proportional stream for every next */ + for (i = 0; i < node->ctx[0]; i++) { + count = (node->ctx[i + 9]) / 100; + rte_node_next_stream_get(graph, node, node->ctx[i + 1], count); + rte_node_next_stream_put(graph, node, node->ctx[i + 1], count); + } + + return 1; +} + +static struct rte_node_register test_graph_perf_source_burst_one = { + .name = TEST_GRAPH_SRC_BRST_ONE_NAME, + .process = test_perf_node_worker_source_burst_one, + .flags = RTE_NODE_SOURCE_F, + .init = test_node_ctx_init, +}; + +RTE_NODE_REGISTER(test_graph_perf_source_burst_one); + +/* Worker node function */ +static uint16_t +test_perf_node_worker(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + uint16_t next = 0; + uint16_t enq = 0; + uint16_t count; + int i; + + /* Move stream for single next node */ + if (node->ctx[0] == 1) { + rte_node_next_stream_move(graph, node, node->ctx[1]); + return nb_objs; + } + + /* Enqueue objects to next nodes proportionally */ + for (i = 0; i < node->ctx[0]; i++) { + next = node->ctx[i + 1]; + count = (node->ctx[i + 9] * nb_objs) / 100; + enq += count; + while (count) { + switch (count & (4 - 1)) { + case 0: + rte_node_enqueue_x4(graph, node, next, objs[0], + objs[1], objs[2], objs[3]); + objs += 4; + count -= 4; + break; + case 1: + rte_node_enqueue_x1(graph, node, next, objs[0]); + objs += 1; + count -= 1; + break; + case 2: + rte_node_enqueue_x2(graph, node, next, objs[0], + objs[1]); + objs += 2; + count -= 2; + break; + case 3: + rte_node_enqueue_x2(graph, node, next, objs[0], + objs[1]); + rte_node_enqueue_x1(graph, node, next, objs[0]); + objs += 3; + count -= 3; + break; + } + } + } + + if (enq != nb_objs) + rte_node_enqueue(graph, node, next, objs, nb_objs - enq); + + return nb_objs; +} + +static struct rte_node_register test_graph_perf_worker = { + .name = TEST_GRAPH_WRK_NAME, + .process = test_perf_node_worker, + .init = test_node_ctx_init, +}; + +RTE_NODE_REGISTER(test_graph_perf_worker); + +/* Last node in graph a.k.a sink node */ +static uint16_t +test_perf_node_sink(struct rte_graph *graph, struct rte_node *node, void **objs, + uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return nb_objs; +} + +static struct rte_node_register test_graph_perf_sink = { + .name = TEST_GRAPH_SNK_NAME, + .process = test_perf_node_sink, + .init = test_node_ctx_init, +}; + +RTE_NODE_REGISTER(test_graph_perf_sink); + +static int +graph_perf_setup(void) +{ + if (rte_lcore_count() < 2) { + printf("Test requires at least 2 lcores\n"); + return TEST_SKIPPED; + } + + return 0; +} + +static void +graph_perf_teardown(void) +{ +} + +static inline rte_node_t +graph_node_get(const char *pname, char *nname) +{ + rte_node_t pnode_id = rte_node_from_name(pname); + char lookup_name[RTE_NODE_NAMESIZE]; + rte_node_t node_id; + + snprintf(lookup_name, RTE_NODE_NAMESIZE, "%s-%s", pname, nname); + node_id = rte_node_from_name(lookup_name); + + if (node_id != RTE_NODE_ID_INVALID) { + if (rte_node_edge_count(node_id)) + rte_node_edge_shrink(node_id, 0); + return node_id; + } + + return rte_node_clone(pnode_id, nname); +} + +static uint16_t +graph_node_count_edges(uint32_t stage, uint16_t node, uint16_t nodes_per_stage, + uint8_t edge_map[][nodes_per_stage][nodes_per_stage], + char *ename[], struct test_node_data *node_data, + rte_node_t **node_map) +{ + uint8_t total_percent = 0; + uint16_t edges = 0; + int i; + + for (i = 0; i < nodes_per_stage && edges < MAX_EDGES_PER_NODE; i++) { + if (edge_map[stage + 1][i][node]) { + ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE); + snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s", + rte_node_id_to_name(node_map[stage + 1][i])); + node_data->next_nodes[edges] = node_map[stage + 1][i]; + node_data->next_percentage[edges] = + edge_map[stage + 1][i][node]; + edges++; + total_percent += edge_map[stage + 1][i][node]; + } + } + + if (edges >= MAX_EDGES_PER_NODE || (edges && total_percent != 100)) { + for (i = 0; i < edges; i++) + free(ename[i]); + return RTE_EDGE_ID_INVALID; + } + + return edges; +} + +static int +graph_init(const char *gname, uint8_t nb_srcs, uint8_t nb_sinks, + uint32_t stages, uint16_t nodes_per_stage, + uint8_t src_map[][nodes_per_stage], uint8_t snk_map[][nb_sinks], + uint8_t edge_map[][nodes_per_stage][nodes_per_stage], + uint8_t burst_one) +{ + struct test_graph_perf *graph_data; + char nname[RTE_NODE_NAMESIZE / 2]; + struct test_node_data *node_data; + char *ename[nodes_per_stage]; + struct rte_graph_param gconf; + const struct rte_memzone *mz; + uint8_t total_percent = 0; + rte_node_t *src_nodes; + rte_node_t *snk_nodes; + rte_node_t **node_map; + char **node_patterns; + rte_graph_t graph_id; + rte_edge_t edges; + rte_edge_t count; + uint32_t i, j, k; + + mz = rte_memzone_reserve(TEST_GRAPH_PERF_MZ, + sizeof(struct test_graph_perf), 0, 0); + if (mz == NULL) { + printf("Failed to allocate graph common memory\n"); + return -ENOMEM; + } + + graph_data = mz->addr; + graph_data->nb_nodes = 0; + graph_data->node_data = + malloc(sizeof(struct test_node_data) * + (nb_srcs + nb_sinks + stages * nodes_per_stage)); + if (graph_data->node_data == NULL) { + printf("Failed to reserve memzone for graph data\n"); + goto memzone_free; + } + + node_patterns = malloc(sizeof(char *) * + (nb_srcs + nb_sinks + stages * nodes_per_stage)); + if (node_patterns == NULL) { + printf("Failed to reserve memory for node patterns\n"); + goto data_free; + } + + src_nodes = malloc(sizeof(rte_node_t) * nb_srcs); + if (src_nodes == NULL) { + printf("Failed to reserve memory for src nodes\n"); + goto pattern_free; + } + + snk_nodes = malloc(sizeof(rte_node_t) * nb_sinks); + if (snk_nodes == NULL) { + printf("Failed to reserve memory for snk nodes\n"); + goto src_free; + } + + node_map = malloc(sizeof(rte_node_t *) * stages + + sizeof(rte_node_t) * nodes_per_stage * stages); + if (node_map == NULL) { + printf("Failed to reserve memory for node map\n"); + goto snk_free; + } + + /* Setup the Graph */ + for (i = 0; i < stages; i++) { + node_map[i] = + (rte_node_t *)(node_map + stages) + nodes_per_stage * i; + for (j = 0; j < nodes_per_stage; j++) { + total_percent = 0; + for (k = 0; k < nodes_per_stage; k++) + total_percent += edge_map[i][j][k]; + if (!total_percent) + continue; + node_patterns[graph_data->nb_nodes] = + malloc(RTE_NODE_NAMESIZE); + if (node_patterns[graph_data->nb_nodes] == NULL) { + printf("Failed to create memory for pattern\n"); + goto pattern_name_free; + } + + /* Clone a worker node */ + snprintf(nname, sizeof(nname), "%d-%d", i, j); + node_map[i][j] = + graph_node_get(TEST_GRAPH_WRK_NAME, nname); + if (node_map[i][j] == RTE_NODE_ID_INVALID) { + printf("Failed to create node[%s]\n", nname); + graph_data->nb_nodes++; + goto pattern_name_free; + } + snprintf(node_patterns[graph_data->nb_nodes], + RTE_NODE_NAMESIZE, "%s", + rte_node_id_to_name(node_map[i][j])); + node_data = + &graph_data->node_data[graph_data->nb_nodes]; + node_data->node_id = node_map[i][j]; + node_data->is_sink = false; + graph_data->nb_nodes++; + } + } + + for (i = 0; i < stages - 1; i++) { + for (j = 0; j < nodes_per_stage; j++) { + /* Count edges i.e connections of worker node to next */ + node_data = + graph_get_node_data(graph_data, node_map[i][j]); + edges = graph_node_count_edges(i, j, nodes_per_stage, + edge_map, ename, + node_data, node_map); + if (edges == RTE_EDGE_ID_INVALID) { + printf("Invalid edge configuration\n"); + goto pattern_name_free; + } + if (!edges) + continue; + + /* Connect a node in stage 'i' to nodes + * in stage 'i + 1' with edges. + */ + count = rte_node_edge_update( + node_map[i][j], 0, + (const char **)(uintptr_t)ename, edges); + for (k = 0; k < edges; k++) + free(ename[k]); + if (count != edges) { + printf("Couldn't add edges %d %d\n", edges, + count); + goto pattern_name_free; + } + } + } + + /* Setup Source nodes */ + for (i = 0; i < nb_srcs; i++) { + edges = 0; + total_percent = 0; + node_patterns[graph_data->nb_nodes] = malloc(RTE_NODE_NAMESIZE); + if (node_patterns[graph_data->nb_nodes] == NULL) { + printf("Failed to create memory for pattern\n"); + goto pattern_name_free; + } + /* Clone a source node */ + snprintf(nname, sizeof(nname), "%d", i); + src_nodes[i] = + graph_node_get(burst_one ? TEST_GRAPH_SRC_BRST_ONE_NAME + : TEST_GRAPH_SRC_NAME, + nname); + if (src_nodes[i] == RTE_NODE_ID_INVALID) { + printf("Failed to create node[%s]\n", nname); + graph_data->nb_nodes++; + goto pattern_name_free; + } + snprintf(node_patterns[graph_data->nb_nodes], RTE_NODE_NAMESIZE, + "%s", rte_node_id_to_name(src_nodes[i])); + node_data = &graph_data->node_data[graph_data->nb_nodes]; + node_data->node_id = src_nodes[i]; + node_data->is_sink = false; + graph_data->nb_nodes++; + + /* Prepare next node list to connect to */ + for (j = 0; j < nodes_per_stage; j++) { + if (!src_map[i][j]) + continue; + ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE); + snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s", + rte_node_id_to_name(node_map[0][j])); + node_data->next_nodes[edges] = node_map[0][j]; + node_data->next_percentage[edges] = src_map[i][j]; + edges++; + total_percent += src_map[i][j]; + } + + if (!edges) + continue; + if (edges >= MAX_EDGES_PER_NODE || total_percent != 100) { + printf("Invalid edge configuration\n"); + for (j = 0; j < edges; j++) + free(ename[j]); + goto pattern_name_free; + } + + /* Connect to list of next nodes using edges */ + count = rte_node_edge_update(src_nodes[i], 0, + (const char **)(uintptr_t)ename, + edges); + for (k = 0; k < edges; k++) + free(ename[k]); + if (count != edges) { + printf("Couldn't add edges %d %d\n", edges, count); + goto pattern_name_free; + } + } + + /* Setup Sink nodes */ + for (i = 0; i < nb_sinks; i++) { + node_patterns[graph_data->nb_nodes] = malloc(RTE_NODE_NAMESIZE); + if (node_patterns[graph_data->nb_nodes] == NULL) { + printf("Failed to create memory for pattern\n"); + goto pattern_name_free; + } + + /* Clone a sink node */ + snprintf(nname, sizeof(nname), "%d", i); + snk_nodes[i] = graph_node_get(TEST_GRAPH_SNK_NAME, nname); + if (snk_nodes[i] == RTE_NODE_ID_INVALID) { + printf("Failed to create node[%s]\n", nname); + graph_data->nb_nodes++; + goto pattern_name_free; + } + snprintf(node_patterns[graph_data->nb_nodes], RTE_NODE_NAMESIZE, + "%s", rte_node_id_to_name(snk_nodes[i])); + node_data = &graph_data->node_data[graph_data->nb_nodes]; + node_data->node_id = snk_nodes[i]; + node_data->is_sink = true; + graph_data->nb_nodes++; + } + + /* Connect last stage worker nodes to sink nodes */ + for (i = 0; i < nodes_per_stage; i++) { + edges = 0; + total_percent = 0; + node_data = graph_get_node_data(graph_data, + node_map[stages - 1][i]); + /* Prepare list of sink nodes to connect to */ + for (j = 0; j < nb_sinks; j++) { + if (!snk_map[i][j]) + continue; + ename[edges] = malloc(sizeof(char) * RTE_NODE_NAMESIZE); + snprintf(ename[edges], RTE_NODE_NAMESIZE, "%s", + rte_node_id_to_name(snk_nodes[j])); + node_data->next_nodes[edges] = snk_nodes[j]; + node_data->next_percentage[edges] = snk_map[i][j]; + edges++; + total_percent += snk_map[i][j]; + } + if (!edges) + continue; + if (edges >= MAX_EDGES_PER_NODE || total_percent != 100) { + printf("Invalid edge configuration\n"); + for (j = 0; j < edges; j++) + free(ename[i]); + goto pattern_name_free; + } + + /* Connect a worker node to a list of sink nodes */ + count = rte_node_edge_update(node_map[stages - 1][i], 0, + (const char **)(uintptr_t)ename, + edges); + for (k = 0; k < edges; k++) + free(ename[k]); + if (count != edges) { + printf("Couldn't add edges %d %d\n", edges, count); + goto pattern_name_free; + } + } + + /* Create a Graph */ + gconf.socket_id = SOCKET_ID_ANY; + gconf.nb_node_patterns = graph_data->nb_nodes; + gconf.node_patterns = (const char **)(uintptr_t)node_patterns; + + graph_id = rte_graph_create(gname, &gconf); + if (graph_id == RTE_GRAPH_ID_INVALID) { + printf("Graph creation failed with error = %d\n", rte_errno); + goto pattern_name_free; + } + graph_data->graph_id = graph_id; + + for (i = 0; i < graph_data->nb_nodes; i++) + free(node_patterns[i]); + free(snk_nodes); + free(src_nodes); + free(node_patterns); + return 0; + +pattern_name_free: + for (i = 0; i < graph_data->nb_nodes; i++) + free(node_patterns[i]); +snk_free: + free(snk_nodes); +src_free: + free(src_nodes); +pattern_free: + free(node_patterns); +data_free: + free(graph_data->node_data); +memzone_free: + rte_memzone_free(mz); + return -ENOMEM; +} + +/* Worker thread function */ +static int +_graph_perf_wrapper(void *args) +{ + struct graph_lcore_data *data = args; + struct rte_graph *graph; + + /* Lookup graph */ + graph = rte_graph_lookup(rte_graph_id_to_name(data->graph_id)); + + /* Graph walk until done */ + while (!data->done) + rte_graph_walk(graph); + + return 0; +} + +static int +measure_perf_get(rte_graph_t graph_id) +{ + const char *pattern = rte_graph_id_to_name(graph_id); + uint32_t lcore_id = rte_get_next_lcore(-1, 1, 0); + struct rte_graph_cluster_stats_param param; + struct rte_graph_cluster_stats *stats; + struct graph_lcore_data *data; + + data = rte_zmalloc("Graph_perf", sizeof(struct graph_lcore_data), + RTE_CACHE_LINE_SIZE); + data->graph_id = graph_id; + data->done = 0; + + /* Run graph worker thread function */ + rte_eal_remote_launch(_graph_perf_wrapper, data, lcore_id); + + /* Collect stats for few msecs */ + if (rte_graph_has_stats_feature()) { + memset(¶m, 0, sizeof(param)); + param.f = stdout; + param.socket_id = SOCKET_ID_ANY; + param.graph_patterns = &pattern; + param.nb_graph_patterns = 1; + + stats = rte_graph_cluster_stats_create(¶m); + if (stats == NULL) { + printf("Failed to create stats\n"); + return -ENOMEM; + } + + rte_delay_ms(3E2); + rte_graph_cluster_stats_get(stats, true); + rte_delay_ms(1E3); + rte_graph_cluster_stats_get(stats, false); + rte_graph_cluster_stats_destroy(stats); + } else + rte_delay_ms(1E3); + + data->done = 1; + rte_eal_wait_lcore(lcore_id); + + return 0; +} + +static inline void +graph_fini(void) +{ + const struct rte_memzone *mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ); + struct test_graph_perf *graph_data; + + if (mz == NULL) + return; + graph_data = mz->addr; + + rte_graph_destroy(rte_graph_id_to_name(graph_data->graph_id)); + free(graph_data->node_data); + rte_memzone_free(rte_memzone_lookup(TEST_GRAPH_PERF_MZ)); +} + +static int +measure_perf(void) +{ + const struct rte_memzone *mz; + struct test_graph_perf *graph_data; + + mz = rte_memzone_lookup(TEST_GRAPH_PERF_MZ); + graph_data = mz->addr; + + return measure_perf_get(graph_data->graph_id); +} + +static inline int +graph_hr_4s_1n_1src_1snk(void) +{ + return measure_perf(); +} + +static inline int +graph_hr_4s_1n_1src_1snk_brst_one(void) +{ + return measure_perf(); +} + +static inline int +graph_hr_4s_1n_2src_1snk(void) +{ + return measure_perf(); +} + +static inline int +graph_hr_4s_1n_1src_2snk(void) +{ + return measure_perf(); +} + +static inline int +graph_tree_4s_4n_1src_4snk(void) +{ + return measure_perf(); +} + +static inline int +graph_reverse_tree_3s_4n_1src_1snk(void) +{ + return measure_perf(); +} + +static inline int +graph_parallel_tree_5s_4n_4src_4snk(void) +{ + return measure_perf(); +} + +/* Graph Topology + * nodes per stage: 1 + * stages: 4 + * src: 1 + * sink: 1 + */ +static inline int +graph_init_hr(void) +{ + uint8_t edge_map[][1][1] = { + { {100} }, + { {100} }, + { {100} }, + { {100} }, + }; + uint8_t src_map[][1] = { {100} }; + uint8_t snk_map[][1] = { {100} }; + + return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map), + STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, + snk_map, edge_map, 0); +} + +/* Graph Topology + * nodes per stage: 1 + * stages: 4 + * src: 1 + * sink: 1 + */ +static inline int +graph_init_hr_brst_one(void) +{ + uint8_t edge_map[][1][1] = { + { {100} }, + { {100} }, + { {100} }, + { {100} }, + }; + uint8_t src_map[][1] = { {100} }; + uint8_t snk_map[][1] = { {100} }; + + return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map), + STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, + snk_map, edge_map, 1); +} + +/* Graph Topology + * nodes per stage: 1 + * stages: 4 + * src: 2 + * sink: 1 + */ +static inline int +graph_init_hr_multi_src(void) +{ + uint8_t edge_map[][1][1] = { + { {100} }, + { {100} }, + { {100} }, + { {100} }, + }; + uint8_t src_map[][1] = { + {100}, {100} + }; + uint8_t snk_map[][1] = { {100} }; + + return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map), + STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, + snk_map, edge_map, 0); +} + +/* Graph Topology + * nodes per stage: 1 + * stages: 4 + * src: 1 + * sink: 2 + */ +static inline int +graph_init_hr_multi_snk(void) +{ + uint8_t edge_map[][1][1] = { + { {100} }, + { {100} }, + { {100} }, + { {100} }, + }; + uint8_t src_map[][1] = { {100} }; + uint8_t snk_map[][2] = { {50, 50} }; + + return graph_init("graph_hr", SOURCES(src_map), SINKS(snk_map), + STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, + snk_map, edge_map, 0); +} + +/* Graph Topology + * nodes per stage: 4 + * stages: 4 + * src: 1 + * sink: 4 + */ +static inline int +graph_init_tree(void) +{ + uint8_t edge_map[][4][4] = { + { + {100, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} + }, + { + {50, 0, 0, 0}, + {50, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} + }, + { + {33, 33, 0, 0}, + {34, 34, 0, 0}, + {33, 33, 0, 0}, + {0, 0, 0, 0} + }, + { + {25, 25, 25, 0}, + {25, 25, 25, 0}, + {25, 25, 25, 0}, + {25, 25, 25, 0} + } + }; + uint8_t src_map[][4] = { {100, 0, 0, 0} }; + uint8_t snk_map[][4] = { + {100, 0, 0, 0}, + {0, 100, 0, 0}, + {0, 0, 100, 0}, + {0, 0, 0, 100} + }; + + return graph_init("graph_full_split", SOURCES(src_map), SINKS(snk_map), + STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, + snk_map, edge_map, 0); +} + +/* Graph Topology + * nodes per stage: 4 + * stages: 3 + * src: 1 + * sink: 1 + */ +static inline int +graph_init_reverse_tree(void) +{ + uint8_t edge_map[][4][4] = { + { + {25, 25, 25, 25}, + {25, 25, 25, 25}, + {25, 25, 25, 25}, + {25, 25, 25, 25} + }, + { + {33, 33, 33, 33}, + {33, 33, 33, 33}, + {34, 34, 34, 34}, + {0, 0, 0, 0} + }, + { + {50, 50, 50, 0}, + {50, 50, 50, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} + }, + }; + uint8_t src_map[][4] = { {25, 25, 25, 25} }; + uint8_t snk_map[][1] = { {100}, {100}, {0}, {0} }; + + return graph_init("graph_full_split", SOURCES(src_map), SINKS(snk_map), + STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, + snk_map, edge_map, 0); +} + +/* Graph Topology + * nodes per stage: 4 + * stages: 5 + * src: 4 + * sink: 4 + */ +static inline int +graph_init_parallel_tree(void) +{ + uint8_t edge_map[][4][4] = { + { + {100, 0, 0, 0}, + {0, 100, 0, 0}, + {0, 0, 100, 0}, + {0, 0, 0, 100} + }, + { + {100, 0, 0, 0}, + {0, 100, 0, 0}, + {0, 0, 100, 0}, + {0, 0, 0, 100} + }, + { + {100, 0, 0, 0}, + {0, 100, 0, 0}, + {0, 0, 100, 0}, + {0, 0, 0, 100} + }, + { + {100, 0, 0, 0}, + {0, 100, 0, 0}, + {0, 0, 100, 0}, + {0, 0, 0, 100} + }, + { + {100, 0, 0, 0}, + {0, 100, 0, 0}, + {0, 0, 100, 0}, + {0, 0, 0, 100} + }, + }; + uint8_t src_map[][4] = { + {100, 0, 0, 0}, + {0, 100, 0, 0}, + {0, 0, 100, 0}, + {0, 0, 0, 100} + }; + uint8_t snk_map[][4] = { + {100, 0, 0, 0}, + {0, 100, 0, 0}, + {0, 0, 100, 0}, + {0, 0, 0, 100} + }; + + return graph_init("graph_parallel", SOURCES(src_map), SINKS(snk_map), + STAGES(edge_map), NODES_PER_STAGE(edge_map), src_map, + snk_map, edge_map, 0); +} + +/** Graph Creation cheat sheet + * edge_map -> dictates graph flow from worker stage 0 to worker stage n-1. + * src_map -> dictates source nodes enqueue percentage to worker stage 0. + * snk_map -> dictates stage n-1 enqueue percentage to sink. + * + * Layout: + * edge_map[<nb_stages>][<nodes_per_stg>][<nodes_in_nxt_stg = nodes_per_stg>] + * src_map[<nb_sources>][<nodes_in_stage0 = nodes_per_stage>] + * snk_map[<nodes_in_stage(n-1) = nodes_per_stage>][<nb_sinks>] + * + * The last array dictates the percentage of received objs to enqueue to next + * stage. + * + * Note: edge_map[][0][] will always be unused as it will receive from source + * + * Example: + * Graph: + * http://bit.ly/2PqbqOy + * Each stage(n) connects to all nodes in the next stage in decreasing + * order. + * Since we can't resize the edge_map dynamically we get away by creating + * dummy nodes and assigning 0 percentages. + * Max nodes across all stages = 4 + * stages = 3 + * nb_src = 1 + * nb_snk = 1 + * // Stages + * edge_map[][4][4] = { + * // Nodes per stage + * { + * {25, 25, 25, 25}, + * {25, 25, 25, 25}, + * {25, 25, 25, 25}, + * {25, 25, 25, 25} + * }, // This will be unused. + * { + * // Nodes enabled in current stage + prev stage enq % + * {33, 33, 33, 33}, + * {33, 33, 33, 33}, + * {34, 34, 34, 34}, + * {0, 0, 0, 0} + * }, + * { + * {50, 50, 50, 0}, + * {50, 50, 50, 0}, + * {0, 0, 0, 0}, + * {0, 0, 0, 0} + * }, + * }; + * Above, each stage tells how much it should receive from previous except + * from stage_0. + * + * src_map[][4] = { {25, 25, 25, 25} }; + * Here, we tell each source the % it has to send to stage_0 nodes. In + * case we want 2 source node we can declare as + * src_map[][4] = { {25, 25, 25, 25}, {25, 25, 25, 25} }; + * + * snk_map[][1] = { {100}, {100}, {0}, {0} } + * Here, we tell stage - 1 nodes how much to enqueue to sink_0. + * If we have 2 sinks we can do as follows + * snk_map[][2] = { {50, 50}, {50, 50}, {0, 0}, {0, 0} } + */ + +static struct unit_test_suite graph_perf_testsuite = { + .suite_name = "Graph library performance test suite", + .setup = graph_perf_setup, + .teardown = graph_perf_teardown, + .unit_test_cases = { + TEST_CASE_ST(graph_init_hr, graph_fini, + graph_hr_4s_1n_1src_1snk), + TEST_CASE_ST(graph_init_hr_brst_one, graph_fini, + graph_hr_4s_1n_1src_1snk_brst_one), + TEST_CASE_ST(graph_init_hr_multi_src, graph_fini, + graph_hr_4s_1n_2src_1snk), + TEST_CASE_ST(graph_init_hr_multi_snk, graph_fini, + graph_hr_4s_1n_1src_2snk), + TEST_CASE_ST(graph_init_tree, graph_fini, + graph_tree_4s_4n_1src_4snk), + TEST_CASE_ST(graph_init_reverse_tree, graph_fini, + graph_reverse_tree_3s_4n_1src_1snk), + TEST_CASE_ST(graph_init_parallel_tree, graph_fini, + graph_parallel_tree_5s_4n_4src_4snk), + TEST_CASES_END(), /**< NULL terminate unit test array */ + }, +}; + +static int +test_graph_perf_func(void) +{ + return unit_test_suite_runner(&graph_perf_testsuite); +} + +REGISTER_TEST_COMMAND(graph_perf_autotest, test_graph_perf_func); -- 2.25.1
next prev parent reply index Thread overview: 219+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-03-18 21:35 [dpdk-dev] [PATCH v1 00/26] graph: introduce graph subsystem jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 01/26] graph: define the public API for graph support jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 02/26] graph: implement node registration jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 03/26] graph: implement node operations jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 04/26] graph: implement node debug routines jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 05/26] graph: implement internal graph operation helpers jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 06/26] graph: populate fastpath memory for graph reel jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 07/26] graph: implement create and destroy APIs jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 08/26] graph: implement graph operation APIs jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 09/26] graph: implement Graphviz export jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 10/26] graph: implement debug routines jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 11/26] graph: implement stats support jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 12/26] graph: implement fastpath API routines jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 13/26] graph: add unit test case jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 14/26] graph: add performance testcase jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 15/26] node: add log infra and null node jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 16/26] node: add ethdev Rx node jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 17/26] node: add ethdev Tx node jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 18/26] node: add ethdev Rx and Tx node ctrl API jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 19/26] node: ipv4 lookup for arm64 jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 20/26] node: ipv4 lookup for x86 jerinj 2020-03-19 12:25 ` Ray Kinsella 2020-03-19 14:22 ` [dpdk-dev] [EXT] " Pavan Nikhilesh Bhagavatula 2020-03-19 15:50 ` Ray Kinsella 2020-03-19 16:13 ` Pavan Nikhilesh Bhagavatula 2020-03-20 9:14 ` Ray Kinsella 2020-03-24 9:40 ` Pavan Nikhilesh Bhagavatula 2020-03-24 14:38 ` Ray Kinsella 2020-03-26 9:56 ` Pavan Nikhilesh Bhagavatula 2020-03-26 16:54 ` Ray Kinsella 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 21/26] node: add ipv4 rewrite node jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 22/26] node: add ipv4 rewrite and lookup ctrl API jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 23/26] node: add pkt drop node jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 24/26] l3fwd-graph: add graph based l3fwd skeleton jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 25/26] l3fwd-graph: add ethdev configuration changes jerinj 2020-03-18 21:35 ` [dpdk-dev] [PATCH v1 26/26] l3fwd-graph: add graph config and main loop jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 00/28] graph: introduce graph subsystem jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 01/28] graph: define the public API for graph support jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 02/28] graph: implement node registration jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 03/28] graph: implement node operations jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 04/28] graph: implement node debug routines jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 05/28] graph: implement internal graph operation helpers jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 06/28] graph: populate fastpath memory for graph reel jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 07/28] graph: implement create and destroy APIs jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 08/28] graph: implement graph operation APIs jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 09/28] graph: implement Graphviz export jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 10/28] graph: implement debug routines jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 11/28] graph: implement stats support jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 12/28] graph: implement fastpath API routines jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 13/28] graph: add unit test case jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 14/28] graph: add performance testcase jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 15/28] node: add log infra and null node jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 16/28] node: add ethdev Rx node jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 17/28] node: add ethdev Tx node jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 18/28] node: add ethdev Rx and Tx node ctrl API jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 19/28] node: ipv4 lookup for arm64 jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 20/28] node: ipv4 lookup for x86 jerinj 2020-03-27 8:40 ` Jerin Jacob 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 21/28] node: add ipv4 rewrite node jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 22/28] node: add ipv4 rewrite and lookup ctrl API jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 23/28] node: add pkt drop node jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 24/28] l3fwd-graph: add graph based l3fwd skeleton jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 25/28] l3fwd-graph: add ethdev configuration changes jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 26/28] l3fwd-graph: add graph config and main loop jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 27/28] doc: add graph library programmer's guide guide jerinj 2020-03-26 16:56 ` [dpdk-dev] [PATCH v2 28/28] doc: add l3fwd graph application user guide jerinj 2020-03-27 6:49 ` [dpdk-dev] [PATCH v2 00/28] graph: introduce graph subsystem Jerin Jacob 2020-03-27 10:42 ` Thomas Monjalon 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 00/29] " jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 01/29] graph: define the public API for graph support jerinj 2020-04-03 9:26 ` Wang, Xiao W 2020-04-04 12:15 ` Jerin Jacob 2020-04-06 12:36 ` Andrzej Ostruszka 2020-04-06 14:59 ` Jerin Jacob 2020-04-06 16:09 ` Andrzej Ostruszka 2020-04-07 10:27 ` Jerin Jacob 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 02/29] graph: implement node registration jerinj 2020-04-03 10:44 ` Wang, Xiao W 2020-04-04 12:29 ` Jerin Jacob 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 03/29] graph: implement node operations jerinj 2020-04-03 10:54 ` Wang, Xiao W 2020-04-04 13:07 ` Jerin Jacob 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 04/29] graph: implement node debug routines jerinj 2020-04-04 7:57 ` Wang, Xiao W 2020-04-04 13:12 ` Jerin Jacob 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 05/29] graph: implement internal graph operation helpers jerinj 2020-04-06 13:47 ` Wang, Xiao W 2020-04-06 14:08 ` Jerin Jacob 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 06/29] graph: populate fastpath memory for graph reel jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 07/29] graph: implement create and destroy APIs jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 08/29] graph: implement graph operation APIs jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 09/29] graph: implement Graphviz export jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 10/29] graph: implement debug routines jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 11/29] graph: implement stats support jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 12/29] graph: implement fastpath API routines jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 13/29] graph: add unit test case jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 14/29] graph: add performance testcase jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 15/29] node: add log infra and null node jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 16/29] node: add ethdev Rx node jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 17/29] node: add ethdev Tx node jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 18/29] node: add ethdev Rx and Tx node ctrl API jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 19/29] node: add generic ipv4 lookup node jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 20/29] node: ipv4 lookup for arm64 jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 21/29] node: ipv4 lookup for x86 jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 22/29] node: add ipv4 rewrite node jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 23/29] node: add ipv4 rewrite and lookup ctrl API jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 24/29] node: add packet drop node jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 25/29] l3fwd-graph: add graph based l3fwd skeleton jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 26/29] l3fwd-graph: add ethdev configuration changes jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 27/29] l3fwd-graph: add graph config and main loop jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 28/29] doc: add graph library programmer's guide guide jerinj 2020-03-31 19:29 ` [dpdk-dev] [PATCH v3 29/29] doc: add l3fwd graph application user guide jerinj 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 00/29] graph: introduce graph subsystem jerinj 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 01/29] graph: define the public API for graph support jerinj 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 02/29] graph: implement node registration jerinj 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 03/29] graph: implement node operations jerinj 2020-04-06 17:57 ` Andrzej Ostruszka 2020-04-07 2:43 ` [dpdk-dev] [EXT] " Kiran Kumar Kokkilagadda 2020-04-07 8:47 ` Andrzej Ostruszka 2020-04-07 10:20 ` Jerin Jacob 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 04/29] graph: implement node debug routines jerinj 2020-04-06 18:17 ` Andrzej Ostruszka 2020-04-07 10:22 ` Jerin Jacob 2020-04-07 11:50 ` Andrzej Ostruszka 2020-04-07 12:09 ` Jerin Jacob 2020-04-07 12:50 ` Andrzej Ostruszka 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 05/29] graph: implement internal graph operation helpers jerinj 2020-04-07 12:16 ` Andrzej Ostruszka 2020-04-07 12:27 ` Jerin Jacob 2020-04-07 12:54 ` Andrzej Ostruszka 2020-04-07 13:31 ` Jerin Jacob 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 06/29] graph: populate fastpath memory for graph reel jerinj 2020-04-08 17:30 ` Andrzej Ostruszka 2020-04-09 2:44 ` Kiran Kumar Kokkilagadda 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 07/29] graph: implement create and destroy APIs jerinj 2020-04-08 16:57 ` Andrzej Ostruszka 2020-04-08 17:23 ` Jerin Jacob 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 08/29] graph: implement graph operation APIs jerinj 2020-04-08 17:49 ` Andrzej Ostruszka 2020-04-08 19:18 ` Jerin Jacob 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 09/29] graph: implement Graphviz export jerinj 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 10/29] graph: implement debug routines jerinj 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 11/29] graph: implement stats support jerinj 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 12/29] graph: implement fastpath API routines jerinj 2020-04-09 23:07 ` Andrzej Ostruszka 2020-04-10 9:18 ` Jerin Jacob 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 13/29] graph: add unit test case jerinj 2020-04-05 8:55 ` jerinj [this message] 2020-04-05 8:55 ` [dpdk-dev] [PATCH v4 15/29] node: add log infra and null node jerinj 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 16/29] node: add ethdev Rx node jerinj 2020-04-09 23:05 ` Andrzej Ostruszka 2020-04-10 7:00 ` Nithin Dabilpuram 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 17/29] node: add ethdev Tx node jerinj 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 18/29] node: add ethdev Rx and Tx node ctrl API jerinj 2020-04-09 23:07 ` Andrzej Ostruszka 2020-04-10 5:09 ` Nithin Dabilpuram 2020-04-10 8:22 ` Nithin Dabilpuram 2020-04-10 12:52 ` Andrzej Ostruszka 2020-04-10 14:54 ` [dpdk-dev] [EXT] " Nithin Dabilpuram 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 19/29] node: add generic ipv4 lookup node jerinj 2020-04-09 23:07 ` Andrzej Ostruszka 2020-04-10 10:20 ` Nithin Dabilpuram 2020-04-10 14:41 ` Nithin Dabilpuram 2020-04-10 15:17 ` Andrzej Ostruszka 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 20/29] node: ipv4 lookup for arm64 jerinj 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 21/29] node: ipv4 lookup for x86 jerinj 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 22/29] node: add ipv4 rewrite node jerinj 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 23/29] node: add ipv4 rewrite and lookup ctrl API jerinj 2020-04-09 23:04 ` Andrzej Ostruszka 2020-04-10 7:24 ` Nithin Dabilpuram 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 24/29] node: add packet drop node jerinj 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 25/29] l3fwd-graph: add graph based l3fwd skeleton jerinj 2020-04-09 23:04 ` Andrzej Ostruszka 2020-04-10 8:23 ` Nithin Dabilpuram 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 26/29] l3fwd-graph: add ethdev configuration changes jerinj 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 27/29] l3fwd-graph: add graph config and main loop jerinj 2020-04-09 23:04 ` Andrzej Ostruszka 2020-04-10 9:29 ` Nithin Dabilpuram 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 28/29] doc: add graph library programmer's guide guide jerinj 2020-04-05 8:56 ` [dpdk-dev] [PATCH v4 29/29] doc: add l3fwd graph application user guide jerinj 2020-04-09 23:13 ` [dpdk-dev] [PATCH v4 00/29] graph: introduce graph subsystem Andrzej Ostruszka 2020-04-10 9:07 ` Jerin Jacob 2020-04-11 14:13 ` [dpdk-dev] [PATCH v5 " jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 01/29] graph: define the public API for graph support jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 02/29] graph: implement node registration jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 03/29] graph: implement node operations jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 04/29] graph: implement node debug routines jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 05/29] graph: implement internal graph operation helpers jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 06/29] graph: populate fastpath memory for graph reel jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 07/29] graph: implement create and destroy APIs jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 08/29] graph: implement graph operation APIs jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 09/29] graph: implement Graphviz export jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 10/29] graph: implement debug routines jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 11/29] graph: implement stats support jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 12/29] graph: implement fastpath API routines jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 13/29] graph: add unit test case jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 14/29] graph: add performance testcase jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 15/29] node: add log infra and null node jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 16/29] node: add ethdev Rx node jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 17/29] node: add ethdev Tx node jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 18/29] node: add ethdev Rx and Tx node ctrl API jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 19/29] node: add generic ipv4 lookup node jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 20/29] node: ipv4 lookup for arm64 jerinj 2020-05-12 9:31 ` David Marchand 2020-05-12 9:50 ` [dpdk-dev] [EXT] " Nithin Dabilpuram 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 21/29] node: ipv4 lookup for x86 jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 22/29] node: add ipv4 rewrite node jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 23/29] node: add ipv4 rewrite and lookup ctrl API jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 24/29] node: add packet drop node jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 25/29] l3fwd-graph: add graph based l3fwd skeleton jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 26/29] l3fwd-graph: add ethdev configuration changes jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 27/29] l3fwd-graph: add graph config and main loop jerinj 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 28/29] doc: add graph library programmer's guide guide jerinj 2020-05-11 9:27 ` David Marchand 2020-05-11 9:30 ` Jerin Jacob 2020-04-11 14:14 ` [dpdk-dev] [PATCH v5 29/29] doc: add l3fwd graph application user guide jerinj 2020-04-30 8:07 ` [dpdk-dev] [PATCH v5 00/29] graph: introduce graph subsystem Tom Barbette 2020-04-30 8:42 ` Jerin Jacob 2020-05-05 21:44 ` Thomas Monjalon
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200405085613.1336841-15-jerinj@marvell.com \ --to=jerinj@marvell.com \ --cc=david.marchand@redhat.com \ --cc=dev@dpdk.org \ --cc=kirankumark@marvell.com \ --cc=mattias.ronnblom@ericsson.com \ --cc=mdr@ashroe.eu \ --cc=ndabilpuram@marvell.com \ --cc=pbhagavatula@marvell.com \ --cc=thomas@monjalon.net \ --cc=xiao.w.wang@intel.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
DPDK-dev Archive on lore.kernel.org Archives are clonable: git clone --mirror https://lore.kernel.org/dpdk-dev/0 dpdk-dev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 dpdk-dev dpdk-dev/ https://lore.kernel.org/dpdk-dev \ dev@dpdk.org public-inbox-index dpdk-dev Example config snippet for mirrors Newsgroup available over NNTP: nntp://nntp.lore.kernel.org/org.dpdk.dev AGPL code for this site: git clone https://public-inbox.org/public-inbox.git