From patchwork Wed Oct 18 06:33:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 132839 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id D8EA043196; Wed, 18 Oct 2023 08:35:12 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C1FB242D3F; Wed, 18 Oct 2023 08:34:16 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 012B4427DE for ; Wed, 18 Oct 2023 08:34:13 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39HKE4OM009764 for ; Tue, 17 Oct 2023 23:34:13 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=N264vlMS3pckIG77FVtnwdKbmLow24KA5EsFGCSg2GI=; b=DE1/gJTaUq30PQKQ+QeA4Q5ZVLah1iWqgbkTtFgRPfeU4ld73Hb1eaxMLZsdFOKmu4f9 vsuMUfdjjntAWsvdjOEp3pNwD82yMTaPl0sC/n6hdmykQeuQTBXHqpjuelGzkHKjhgLA FqXWSxS2gQsxv/moX6Hjqpl+VCj1jyDSlbiNt3JXo8yKb9AuuJIqbvYvX3BGH7RAx2ac PkZIXrO041dYGtjsFs+KfQdaF058hIWCs++f64M6GJYS/RI+06HN4SklVC3RcpqbL2cO 58uKwbD8aIDaKMcA5dQHnCWATYnHPWwkyT/LlPfHX4rSD5GE+lmQI2WCPHSm/ivukxPW uQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3tt1481qft-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 17 Oct 2023 23:34:12 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 17 Oct 2023 23:34:11 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 17 Oct 2023 23:34:10 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 048D33F7048; Tue, 17 Oct 2023 23:34:09 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v9 10/12] app/graph: support graph command line interfaces Date: Wed, 18 Oct 2023 12:03:45 +0530 Message-ID: <20231018063347.68081-11-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231018063347.68081-1-skori@marvell.com> References: <20230929095814.692890-2-skori@marvell.com> <20231018063347.68081-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: cCtKUfFeshfS2Gz2a8KSB82frYIKs2IE X-Proofpoint-ORIG-GUID: cCtKUfFeshfS2Gz2a8KSB82frYIKs2IE X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-18_04,2023-10-17_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla Adds graph module to create a graph for a given use case like l3fwd. Following commands are exposed: - graph [bsz ] [tmo ] [coremask ] \ model pcap_enable <0 | 1> num_pcap_pkts \ pcap_file - graph start - graph stats show - help graph Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/cli.c | 4 + app/graph/ethdev_rx.c | 2 +- app/graph/graph.c | 550 +++++++++++++++++++++++++++++++++++++ app/graph/graph.h | 21 ++ app/graph/graph_priv.h | 70 +++++ app/graph/ip4_route.c | 5 +- app/graph/ip6_route.c | 5 +- app/graph/meson.build | 1 + app/graph/module_api.h | 1 + app/graph/neigh.c | 10 +- doc/guides/tools/graph.rst | 19 +- 11 files changed, 681 insertions(+), 7 deletions(-) create mode 100644 app/graph/graph.c create mode 100644 app/graph/graph.h create mode 100644 app/graph/graph_priv.h diff --git a/app/graph/cli.c b/app/graph/cli.c index ad7d7deadf..30b12312d6 100644 --- a/app/graph/cli.c +++ b/app/graph/cli.c @@ -20,6 +20,10 @@ #define MAX_LINE_SIZE 2048 cmdline_parse_ctx_t modules_ctx[] = { + (cmdline_parse_inst_t *)&graph_config_cmd_ctx, + (cmdline_parse_inst_t *)&graph_start_cmd_ctx, + (cmdline_parse_inst_t *)&graph_stats_cmd_ctx, + (cmdline_parse_inst_t *)&graph_help_cmd_ctx, (cmdline_parse_inst_t *)&mempool_config_cmd_ctx, (cmdline_parse_inst_t *)&mempool_help_cmd_ctx, (cmdline_parse_inst_t *)ðdev_show_cmd_ctx, diff --git a/app/graph/ethdev_rx.c b/app/graph/ethdev_rx.c index f2cb8cf9a5..03f8effcca 100644 --- a/app/graph/ethdev_rx.c +++ b/app/graph/ethdev_rx.c @@ -69,7 +69,7 @@ ethdev_rx_map_add(char *name, uint32_t queue, uint32_t core) if (rc) return -EINVAL; - coremask = 0xff; /* FIXME: Read from graph configuration */ + coremask = graph_coremask_get(); if (!(coremask & (1 << core))) return -EINVAL; diff --git a/app/graph/graph.c b/app/graph/graph.c new file mode 100644 index 0000000000..4396f02da5 --- /dev/null +++ b/app/graph/graph.c @@ -0,0 +1,550 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "graph_priv.h" +#include "module_api.h" + +#define RTE_LOGTYPE_APP_GRAPH RTE_LOGTYPE_USER1 + +static const char +cmd_graph_help[] = "graph bsz tmo coremask " + "model pcap_enable <0 | 1> num_pcap_pkts " + "pcap_file "; + +static const char * const supported_usecases[] = {"l3fwd"}; +struct graph_config graph_config; +bool graph_started; + +/* Check the link rc of all ports in up to 9s, and print them finally */ +static void +check_all_ports_link_status(uint32_t port_mask) +{ +#define CHECK_INTERVAL 100 /* 100ms */ +#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ + char link_rc_text[RTE_ETH_LINK_MAX_STR_LEN]; + uint8_t count, all_ports_up, print_flag = 0; + struct rte_eth_link link; + uint16_t portid; + int rc; + + printf("\nChecking link status..."); + fflush(stdout); + for (count = 0; count <= MAX_CHECK_TIME; count++) { + if (force_quit) + return; + + all_ports_up = 1; + RTE_ETH_FOREACH_DEV(portid) + { + if (force_quit) + return; + + if ((port_mask & (1 << portid)) == 0) + continue; + + memset(&link, 0, sizeof(link)); + rc = rte_eth_link_get_nowait(portid, &link); + if (rc < 0) { + all_ports_up = 0; + if (print_flag == 1) + printf("Port %u link get failed: %s\n", + portid, rte_strerror(-rc)); + continue; + } + + /* Print link rc if flag set */ + if (print_flag == 1) { + rte_eth_link_to_str(link_rc_text, sizeof(link_rc_text), + &link); + printf("Port %d %s\n", portid, link_rc_text); + continue; + } + + /* Clear all_ports_up flag if any link down */ + if (link.link_status == RTE_ETH_LINK_DOWN) { + all_ports_up = 0; + break; + } + } + + /* After finally printing all link rc, get out */ + if (print_flag == 1) + break; + + if (all_ports_up == 0) { + printf("."); + fflush(stdout); + rte_delay_ms(CHECK_INTERVAL); + } + + /* Set the print_flag if all ports up or timeout */ + if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { + print_flag = 1; + printf("Done\n"); + } + } +} + +static bool +parser_usecases_read(char *usecases) +{ + bool valid = false; + uint32_t i, j = 0; + char *token; + + token = strtok(usecases, ","); + while (token != NULL) { + for (i = 0; i < RTE_DIM(supported_usecases); i++) { + if (strcmp(supported_usecases[i], token) == 0) { + graph_config.usecases[j].enabled = true; + rte_strscpy(graph_config.usecases[j].name, token, 31); + valid = true; + j++; + break; + } + } + token = strtok(NULL, ","); + } + + return valid; +} + +static uint64_t +graph_worker_count_get(void) +{ + uint64_t nb_worker = 0; + uint64_t coremask; + + coremask = graph_config.params.coremask; + while (coremask) { + if (coremask & 0x1) + nb_worker++; + + coremask = (coremask >> 1); + } + + return nb_worker; +} + +static struct rte_node_ethdev_config * +graph_rxtx_node_config_get(uint32_t *num_conf, uint32_t *num_graphs) +{ + uint32_t n_tx_queue, nb_conf = 0, lcore_id; + uint16_t queueid, portid, nb_graphs = 0; + uint8_t nb_rx_queue, queue; + struct lcore_conf *qconf; + + n_tx_queue = graph_worker_count_get(); + if (n_tx_queue > RTE_MAX_ETHPORTS) + n_tx_queue = RTE_MAX_ETHPORTS; + + RTE_ETH_FOREACH_DEV(portid) { + /* Skip ports that are not enabled */ + if ((enabled_port_mask & (1 << portid)) == 0) { + printf("\nSkipping disabled port %d\n", portid); + continue; + } + + nb_rx_queue = ethdev_rx_num_rx_queues_get(portid); + + /* Setup ethdev node config */ + ethdev_conf[nb_conf].port_id = portid; + ethdev_conf[nb_conf].num_rx_queues = nb_rx_queue; + ethdev_conf[nb_conf].num_tx_queues = n_tx_queue; + ethdev_conf[nb_conf].mp = ethdev_mempool_list_by_portid(portid); + ethdev_conf[nb_conf].mp_count = 1; /* Check with pools */ + + nb_conf++; + } + + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (rte_lcore_is_enabled(lcore_id) == 0) + continue; + + qconf = &lcore_conf[lcore_id]; + printf("\nInitializing rx queues on lcore %u ... ", lcore_id); + fflush(stdout); + + /* Init RX queues */ + for (queue = 0; queue < qconf->n_rx_queue; ++queue) { + portid = qconf->rx_queue_list[queue].port_id; + queueid = qconf->rx_queue_list[queue].queue_id; + + /* Add this queue node to its graph */ + snprintf(qconf->rx_queue_list[queue].node_name, RTE_NODE_NAMESIZE, + "ethdev_rx-%u-%u", portid, queueid); + } + if (qconf->n_rx_queue) + nb_graphs++; + } + + printf("\n"); + + ethdev_start(); + check_all_ports_link_status(enabled_port_mask); + + *num_conf = nb_conf; + *num_graphs = nb_graphs; + return ethdev_conf; +} + +static void +graph_stats_print_to_file(void) +{ + struct rte_graph_cluster_stats_param s_param; + struct rte_graph_cluster_stats *stats; + const char *pattern = "worker_*"; + FILE *fp = NULL; + size_t sz, len; + + /* Prepare stats object */ + fp = fopen("/tmp/graph_stats.txt", "w+"); + if (fp == NULL) + rte_exit(EXIT_FAILURE, "Errot in opening stats file\n"); + + memset(&s_param, 0, sizeof(s_param)); + s_param.f = fp; + s_param.socket_id = SOCKET_ID_ANY; + s_param.graph_patterns = &pattern; + s_param.nb_graph_patterns = 1; + + stats = rte_graph_cluster_stats_create(&s_param); + if (stats == NULL) + rte_exit(EXIT_FAILURE, "Unable to create stats object\n"); + + /* Clear screen and move to top left */ + rte_graph_cluster_stats_get(stats, 0); + rte_delay_ms(1E3); + + fseek(fp, 0L, SEEK_END); + sz = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + len = strlen(conn->msg_out); + conn->msg_out += len; + + sz = fread(conn->msg_out, sizeof(char), sz, fp); + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; + rte_graph_cluster_stats_destroy(stats); + + fclose(fp); +} + +static void +cli_graph_stats(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + graph_stats_print_to_file(); +} + +bool +graph_status_get(void) +{ + return graph_started; +} + +static void +cli_graph_start(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct rte_node_ethdev_config *conf; + uint32_t nb_graphs = 0, nb_conf, i; + int rc = -EINVAL; + + conf = graph_rxtx_node_config_get(&nb_conf, &nb_graphs); + for (i = 0; i < MAX_GRAPH_USECASES; i++) { + if (!strcmp(graph_config.usecases[i].name, "l3fwd")) { + if (graph_config.usecases[i].enabled) { + RTE_SET_USED(conf); + break; + } + } + } + + if (!rc) + graph_started = true; +} + +static int +graph_config_add(char *usecases, struct graph_config *config) +{ + uint64_t lcore_id, core_num; + uint64_t eal_coremask = 0; + + if (!parser_usecases_read(usecases)) + return -EINVAL; + + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (rte_lcore_is_enabled(lcore_id)) + eal_coremask |= RTE_BIT64(lcore_id); + } + + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + core_num = 1 << lcore_id; + if (config->params.coremask & core_num) { + if (eal_coremask & core_num) + continue; + else + return -EINVAL; + } + } + + graph_config.params.bsz = config->params.bsz; + graph_config.params.tmo = config->params.tmo; + graph_config.params.coremask = config->params.coremask; + graph_config.model = config->model; + graph_config.pcap_ena = config->pcap_ena; + graph_config.num_pcap_pkts = config->num_pcap_pkts; + graph_config.pcap_file = strdup(config->pcap_file); + + return 0; +} + +void +graph_pcap_config_get(uint8_t *pcap_ena, uint64_t *num_pkts, char **file) +{ + + *pcap_ena = graph_config.pcap_ena; + *num_pkts = graph_config.num_pcap_pkts; + *file = graph_config.pcap_file; +} + +int +graph_walk_start(void *conf) +{ + struct lcore_conf *qconf; + struct rte_graph *graph; + uint32_t lcore_id; + + RTE_SET_USED(conf); + + lcore_id = rte_lcore_id(); + qconf = &lcore_conf[lcore_id]; + graph = qconf->graph; + + if (!graph) { + RTE_LOG(INFO, APP_GRAPH, "Lcore %u has nothing to do\n", lcore_id); + return 0; + } + + RTE_LOG(INFO, APP_GRAPH, "Entering main loop on lcore %u, graph %s(%p)\n", lcore_id, + qconf->name, graph); + + while (likely(!force_quit)) + rte_graph_walk(graph); + + return 0; +} + +void +graph_stats_print(void) +{ + const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; + const char clr[] = {27, '[', '2', 'J', '\0'}; + struct rte_graph_cluster_stats_param s_param; + struct rte_graph_cluster_stats *stats; + const char *pattern = "worker_*"; + + /* Prepare stats object */ + memset(&s_param, 0, sizeof(s_param)); + s_param.f = stdout; + s_param.socket_id = SOCKET_ID_ANY; + s_param.graph_patterns = &pattern; + s_param.nb_graph_patterns = 1; + + stats = rte_graph_cluster_stats_create(&s_param); + if (stats == NULL) + rte_exit(EXIT_FAILURE, "Unable to create stats object\n"); + + while (!force_quit) { + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); + rte_graph_cluster_stats_get(stats, 0); + rte_delay_ms(1E3); + if (app_graph_exit()) + force_quit = true; + } + + rte_graph_cluster_stats_destroy(stats); +} + +uint64_t +graph_coremask_get(void) +{ + return graph_config.params.coremask; +} + +static void +cli_graph(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) +{ + struct graph_config_cmd_tokens *res = parsed_result; + struct graph_config config; + char *model_name; + uint8_t model; + int rc; + + model_name = res->model_name; + if (strcmp(model_name, "default") == 0) { + model = GRAPH_MODEL_RTC; + } else if (strcmp(model_name, "rtc") == 0) { + model = GRAPH_MODEL_RTC; + } else if (strcmp(model_name, "mcd") == 0) { + model = GRAPH_MODEL_MCD; + } else { + printf(MSG_ARG_NOT_FOUND, "model arguments"); + return; + } + + config.params.bsz = res->size; + config.params.tmo = res->ns; + config.params.coremask = res->mask; + config.model = model; + config.pcap_ena = res->pcap_ena; + config.num_pcap_pkts = res->num_pcap_pkts; + config.pcap_file = res->pcap_file; + rc = graph_config_add(res->usecase, &config); + if (rc < 0) { + cli_exit(); + printf(MSG_CMD_FAIL, res->graph); + rte_exit(EXIT_FAILURE, "coremask is Invalid\n"); + } +} + +static void +cli_graph_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + size_t len; + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n", + "----------------------------- graph command help -----------------------------", + cmd_graph_help, "graph start"); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +cmdline_parse_token_string_t graph_display_graph = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_display_stats = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, stats, "stats"); +cmdline_parse_token_string_t graph_display_show = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, show, "show"); + +cmdline_parse_inst_t graph_stats_cmd_ctx = { + .f = cli_graph_stats, + .data = NULL, + .help_str = "graph stats show", + .tokens = { + (void *)&graph_display_graph, + (void *)&graph_display_stats, + (void *)&graph_display_show, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_config_start_graph = + TOKEN_STRING_INITIALIZER(struct graph_start_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_config_start = + TOKEN_STRING_INITIALIZER(struct graph_start_cmd_tokens, start, "start"); + +cmdline_parse_inst_t graph_start_cmd_ctx = { + .f = cli_graph_start, + .data = NULL, + .help_str = "graph start", + .tokens = { + (void *)&graph_config_start_graph, + (void *)&graph_config_start, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_config_add_graph = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_config_add_usecase = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, usecase, NULL); +cmdline_parse_token_string_t graph_config_add_coremask = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, coremask, "coremask"); +cmdline_parse_token_num_t graph_config_add_mask = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, mask, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_bsz = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, bsz, "bsz"); +cmdline_parse_token_num_t graph_config_add_size = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, size, RTE_UINT16); +cmdline_parse_token_string_t graph_config_add_tmo = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, tmo, "tmo"); +cmdline_parse_token_num_t graph_config_add_ns = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, ns, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_model = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, model, "model"); +cmdline_parse_token_string_t graph_config_add_model_name = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, model_name, "rtc#mcd#default"); +cmdline_parse_token_string_t graph_config_add_capt_ena = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_ena, "pcap_enable"); +cmdline_parse_token_num_t graph_config_add_pcap_ena = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, pcap_ena, RTE_UINT8); +cmdline_parse_token_string_t graph_config_add_capt_pkts_count = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_pkts_count, "num_pcap_pkts"); +cmdline_parse_token_num_t graph_config_add_num_pcap_pkts = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, num_pcap_pkts, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_capt_file = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_file, "pcap_file"); +cmdline_parse_token_string_t graph_config_add_pcap_file = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, pcap_file, NULL); + +cmdline_parse_inst_t graph_config_cmd_ctx = { + .f = cli_graph, + .data = NULL, + .help_str = cmd_graph_help, + .tokens = { + (void *)&graph_config_add_graph, + (void *)&graph_config_add_usecase, + (void *)&graph_config_add_coremask, + (void *)&graph_config_add_mask, + (void *)&graph_config_add_bsz, + (void *)&graph_config_add_size, + (void *)&graph_config_add_tmo, + (void *)&graph_config_add_ns, + (void *)&graph_config_add_model, + (void *)&graph_config_add_model_name, + (void *)&graph_config_add_capt_ena, + (void *)&graph_config_add_pcap_ena, + (void *)&graph_config_add_capt_pkts_count, + (void *)&graph_config_add_num_pcap_pkts, + (void *)&graph_config_add_capt_file, + (void *)&graph_config_add_pcap_file, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_help_cmd = + TOKEN_STRING_INITIALIZER(struct graph_help_cmd_tokens, help, "help"); +cmdline_parse_token_string_t graph_help_graph = + TOKEN_STRING_INITIALIZER(struct graph_help_cmd_tokens, graph, "graph"); + +cmdline_parse_inst_t graph_help_cmd_ctx = { + .f = cli_graph_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)&graph_help_cmd, + (void *)&graph_help_graph, + NULL, + }, +}; diff --git a/app/graph/graph.h b/app/graph/graph.h new file mode 100644 index 0000000000..a14fa37ccd --- /dev/null +++ b/app/graph/graph.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_H +#define APP_GRAPH_H + +#include + +extern cmdline_parse_inst_t graph_config_cmd_ctx; +extern cmdline_parse_inst_t graph_start_cmd_ctx; +extern cmdline_parse_inst_t graph_stats_cmd_ctx; +extern cmdline_parse_inst_t graph_help_cmd_ctx; + +int graph_walk_start(void *conf); +void graph_stats_print(void); +void graph_pcap_config_get(uint8_t *pcap_ena, uint64_t *num_pkts, char **file); +uint64_t graph_coremask_get(void); +bool graph_status_get(void); + +#endif diff --git a/app/graph/graph_priv.h b/app/graph/graph_priv.h new file mode 100644 index 0000000000..a48a35daa3 --- /dev/null +++ b/app/graph/graph_priv.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_PRIV_H +#define APP_GRAPH_PRIV_H + +#define MAX_GRAPH_USECASES 32 + +struct graph_help_cmd_tokens { + cmdline_fixed_string_t help; + cmdline_fixed_string_t graph; +}; + +struct graph_start_cmd_tokens { + cmdline_fixed_string_t graph; + cmdline_fixed_string_t start; +}; + +struct graph_stats_cmd_tokens { + cmdline_fixed_string_t show; + cmdline_fixed_string_t graph; + cmdline_fixed_string_t stats; +}; + +struct graph_config_cmd_tokens { + cmdline_fixed_string_t graph; + cmdline_fixed_string_t usecase; + cmdline_fixed_string_t bsz; + cmdline_fixed_string_t tmo; + cmdline_fixed_string_t coremask; + cmdline_fixed_string_t model; + cmdline_fixed_string_t capt_ena; + cmdline_fixed_string_t capt_pkts_count; + cmdline_fixed_string_t capt_file; + cmdline_fixed_string_t model_name; + cmdline_fixed_string_t pcap_file; + uint16_t size; + uint64_t ns; + uint64_t mask; + uint64_t num_pcap_pkts; + uint8_t pcap_ena; +}; + +enum graph_model { + GRAPH_MODEL_RTC = 0x01, + GRAPH_MODEL_MCD = 0x02, +}; + +struct usecases { + char name[32]; + bool enabled; +}; + +struct usecase_params { + uint64_t coremask; + uint32_t bsz; + uint32_t tmo; +}; + +struct graph_config { + struct usecases usecases[MAX_GRAPH_USECASES]; + struct usecase_params params; + enum graph_model model; + uint64_t num_pcap_pkts; + char *pcap_file; + uint8_t pcap_ena; +}; + +#endif diff --git a/app/graph/ip4_route.c b/app/graph/ip4_route.c index db3354c270..fc83586427 100644 --- a/app/graph/ip4_route.c +++ b/app/graph/ip4_route.c @@ -97,11 +97,14 @@ route_ip4_add(struct route_ipv4_config *route) ipv4route->via = route->via; ipv4route->is_used = true; - /* FIXME: Get graph status here and then update table */ + if (!graph_status_get()) + goto exit; + rc = route4_rewirte_table_update(ipv4route); if (rc) goto free; +exit: TAILQ_INSERT_TAIL(&route4, ipv4route, next); return 0; free: diff --git a/app/graph/ip6_route.c b/app/graph/ip6_route.c index e793cde830..1fa4865220 100644 --- a/app/graph/ip6_route.c +++ b/app/graph/ip6_route.c @@ -102,11 +102,14 @@ route_ip6_add(struct route_ipv6_config *route) } ipv6route->is_used = true; - /* FIXME: Get graph status here and then update table */ + if (!graph_status_get()) + goto exit; + rc = route6_rewirte_table_update(ipv6route); if (rc) goto free; +exit: TAILQ_INSERT_TAIL(&route6, ipv6route, next); return 0; free: diff --git a/app/graph/meson.build b/app/graph/meson.build index d8391d5cae..15d16a302e 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -14,6 +14,7 @@ sources = files( 'conn.c', 'ethdev_rx.c', 'ethdev.c', + 'graph.c', 'ip4_route.c', 'ip6_route.c', 'main.c', diff --git a/app/graph/module_api.h b/app/graph/module_api.h index 56b7c94ecc..392dcfb222 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -12,6 +12,7 @@ #include "conn.h" #include "ethdev.h" #include "ethdev_rx.h" +#include "graph.h" #include "mempool.h" #include "neigh.h" #include "route.h" diff --git a/app/graph/neigh.c b/app/graph/neigh.c index 0cee502719..22be7361e3 100644 --- a/app/graph/neigh.c +++ b/app/graph/neigh.c @@ -154,11 +154,14 @@ neigh_ip4_add(uint32_t ip, uint64_t mac) v4_config->mac = mac; v4_config->is_used = true; - /* FIXME: Get graph status here and then update table */ + if (!graph_status_get()) + goto exit; + rc = ip4_rewrite_node_add(v4_config); if (rc) goto free; +exit: TAILQ_INSERT_TAIL(&neigh4, v4_config, next); return 0; free: @@ -187,11 +190,14 @@ neigh_ip6_add(uint8_t *ip, uint64_t mac) v6_config->mac = mac; v6_config->is_used = true; - /* FIXME: Get graph status here and then update table */ + if (!graph_status_get()) + goto exit; + rc = ip6_rewrite_node_add(v6_config); if (rc) goto free; +exit: TAILQ_INSERT_TAIL(&neigh6, v6_config, next); return 0; free: diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index cf738b7a39..c27c2f1be3 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -74,10 +74,25 @@ file to express the requested use case configuration. - Description - Dynamic - Optional - * - Dummy command - - Dummy command description + * - graph [bsz ] [tmo ] [coremask ] model + pcap_enable <0 | 1> num_pcap_pkts pcap_file + - Command to express the desired use case. Also enables/disable pcap capturing - No - No + * - graph start + - Command to start the graph. + This command triggers that no more commands are left to be parsed and graph + initialization can be started now. It must be the last command in ``.cli`` + - No + - No + * - graph stats show + - Command to dump current graph statistics + - Yes + - Yes + * - help graph + - Command to dump graph help message + - Yes + - Yes * - mempool size buffers cache numa - Command to create mempool which will be further associated to RxQ to dequeue the packets - No