1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2023 Marvell. 3 */ 4 5 #include <errno.h> 6 #include <stdbool.h> 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 12 #include <rte_common.h> 13 #include <rte_ethdev.h> 14 #include <rte_graph.h> 15 #include <rte_graph_worker.h> 16 #include <rte_lcore.h> 17 #include <rte_node_eth_api.h> 18 19 #include "module_api.h" 20 21 static int 22 l2fwd_pattern_configure(void) 23 { 24 struct rte_graph_param graph_conf; 25 const char **node_patterns; 26 uint64_t pcap_pkts_count; 27 struct lcore_conf *qconf; 28 uint16_t nb_patterns; 29 uint8_t pcap_ena; 30 char *pcap_file; 31 int lcore_id; 32 33 nb_patterns = 0; 34 node_patterns = malloc((ETHDEV_RX_QUEUE_PER_LCORE_MAX + nb_patterns) * 35 sizeof(*node_patterns)); 36 if (!node_patterns) 37 return -ENOMEM; 38 39 memset(&graph_conf, 0, sizeof(graph_conf)); 40 graph_conf.node_patterns = node_patterns; 41 42 /* Pcap config */ 43 graph_pcap_config_get(&pcap_ena, &pcap_pkts_count, &pcap_file); 44 graph_conf.pcap_enable = pcap_ena; 45 graph_conf.num_pkt_to_capture = pcap_pkts_count; 46 graph_conf.pcap_filename = strdup(pcap_file); 47 48 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 49 rte_graph_t graph_id; 50 rte_edge_t i; 51 52 if (rte_lcore_is_enabled(lcore_id) == 0) 53 continue; 54 55 qconf = &lcore_conf[lcore_id]; 56 57 /* Skip graph creation if no source exists */ 58 if (!qconf->n_rx_queue) 59 continue; 60 61 /* Add rx node patterns of this lcore */ 62 for (i = 0; i < qconf->n_rx_queue; i++) { 63 graph_conf.node_patterns[nb_patterns + i] = 64 qconf->rx_queue_list[i].node_name; 65 } 66 67 graph_conf.nb_node_patterns = nb_patterns + i; 68 graph_conf.socket_id = rte_lcore_to_socket_id(lcore_id); 69 70 snprintf(qconf->name, sizeof(qconf->name), "worker_%u", 71 lcore_id); 72 73 graph_id = rte_graph_create(qconf->name, &graph_conf); 74 if (graph_id == RTE_GRAPH_ID_INVALID) 75 rte_exit(EXIT_FAILURE, 76 "rte_graph_create(): graph_id invalid" 77 " for lcore %u\n", lcore_id); 78 79 qconf->graph_id = graph_id; 80 qconf->graph = rte_graph_lookup(qconf->name); 81 /* >8 End of graph initialization. */ 82 if (!qconf->graph) 83 rte_exit(EXIT_FAILURE, 84 "rte_graph_lookup(): graph %s not found\n", 85 qconf->name); 86 } 87 88 /* Launch per-lcore init on every worker lcore */ 89 rte_eal_mp_remote_launch(graph_walk_start, NULL, SKIP_MAIN); 90 91 /* Accumulate and print stats on main until exit */ 92 if (rte_graph_has_stats_feature() && app_graph_stats_enabled()) 93 graph_stats_print(); 94 95 return 0; 96 } 97 98 static int 99 ethdev_rx_to_tx_node_link(uint32_t lcore_id) 100 { 101 char name[RTE_NODE_NAMESIZE]; 102 const char *next_node = name; 103 struct lcore_conf *qconf; 104 uint16_t queue, port_id; 105 rte_node_t rx_id; 106 int16_t txport; 107 int rc = 0; 108 109 qconf = &lcore_conf[lcore_id]; 110 111 for (queue = 0; queue < qconf->n_rx_queue; ++queue) { 112 port_id = qconf->rx_queue_list[queue].port_id; 113 txport = ethdev_txport_by_rxport_get(port_id); 114 if (txport >= 0) { 115 rx_id = rte_node_from_name(qconf->rx_queue_list[queue].node_name); 116 snprintf(name, sizeof(name), "ethdev_tx-%u", txport); 117 rte_node_edge_update(rx_id, RTE_EDGE_ID_INVALID, &next_node, 1); 118 rc = rte_node_ethdev_rx_next_update(rx_id, name); 119 if (rc) 120 goto exit; 121 } else { 122 rc = -EINVAL; 123 goto exit; 124 } 125 } 126 exit: 127 return rc; 128 } 129 130 131 int 132 usecase_l2fwd_configure(struct rte_node_ethdev_config *conf, uint16_t nb_confs, uint16_t nb_graphs) 133 { 134 uint32_t lcore_id; 135 int rc; 136 137 rc = rte_node_eth_config(conf, nb_confs, nb_graphs); 138 if (rc) 139 rte_exit(EXIT_FAILURE, "rte_node_eth_config: err=%d\n", rc); 140 141 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 142 rc = ethdev_rx_to_tx_node_link(lcore_id); 143 if (rc) 144 rte_exit(EXIT_FAILURE, "rte_node_eth_config: err=%d\n", rc); 145 } 146 147 rc = l2fwd_pattern_configure(); 148 if (rc) 149 rte_exit(EXIT_FAILURE, "l2fwd_pattern_failure: err=%d\n", rc); 150 151 return rc; 152 } 153