1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2020 Intel Corporation 3 */ 4 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <rte_mbuf.h> 9 #include <rte_ethdev.h> 10 11 #include "obj.h" 12 13 /* 14 * ethdev 15 */ 16 static struct rte_eth_conf port_conf_default = { 17 .link_speeds = 0, 18 .rxmode = { 19 .mq_mode = RTE_ETH_MQ_RX_NONE, 20 .mtu = 9000 - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN), /* Jumbo frame MTU */ 21 }, 22 .rx_adv_conf = { 23 .rss_conf = { 24 .rss_key = NULL, 25 .rss_key_len = 40, 26 .rss_hf = 0, 27 }, 28 }, 29 .txmode = { 30 .mq_mode = RTE_ETH_MQ_TX_NONE, 31 }, 32 .lpbk_mode = 0, 33 }; 34 35 #define RETA_CONF_SIZE (RTE_ETH_RSS_RETA_SIZE_512 / RTE_ETH_RETA_GROUP_SIZE) 36 37 static int 38 rss_setup(uint16_t port_id, 39 uint16_t reta_size, 40 struct ethdev_params_rss *rss) 41 { 42 struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE]; 43 uint32_t i; 44 int status; 45 46 /* RETA setting */ 47 memset(reta_conf, 0, sizeof(reta_conf)); 48 49 for (i = 0; i < reta_size; i++) 50 reta_conf[i / RTE_ETH_RETA_GROUP_SIZE].mask = UINT64_MAX; 51 52 for (i = 0; i < reta_size; i++) { 53 uint32_t reta_id = i / RTE_ETH_RETA_GROUP_SIZE; 54 uint32_t reta_pos = i % RTE_ETH_RETA_GROUP_SIZE; 55 uint32_t rss_qs_pos = i % rss->n_queues; 56 57 reta_conf[reta_id].reta[reta_pos] = 58 (uint16_t) rss->queue_id[rss_qs_pos]; 59 } 60 61 /* RETA update */ 62 status = rte_eth_dev_rss_reta_update(port_id, 63 reta_conf, 64 reta_size); 65 66 return status; 67 } 68 69 int 70 ethdev_config(const char *name, struct ethdev_params *params) 71 { 72 struct rte_eth_dev_info port_info; 73 struct rte_eth_conf port_conf; 74 struct ethdev_params_rss *rss; 75 struct rte_mempool *mempool; 76 uint32_t i; 77 int numa_node, status; 78 uint16_t port_id = 0; 79 80 /* Check input params */ 81 if (!name || 82 !name[0] || 83 !params || 84 !params->rx.n_queues || 85 !params->rx.queue_size || 86 !params->tx.n_queues || 87 !params->tx.queue_size) 88 return -EINVAL; 89 90 status = rte_eth_dev_get_port_by_name(name, &port_id); 91 if (status) 92 return -EINVAL; 93 94 status = rte_eth_dev_info_get(port_id, &port_info); 95 if (status) 96 return -EINVAL; 97 98 mempool = rte_mempool_lookup(params->rx.mempool_name); 99 if (!mempool) 100 return -EINVAL; 101 102 rss = params->rx.rss; 103 if (rss) { 104 if (!port_info.reta_size || port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512) 105 return -EINVAL; 106 107 if (!rss->n_queues || rss->n_queues >= ETHDEV_RXQ_RSS_MAX) 108 return -EINVAL; 109 110 for (i = 0; i < rss->n_queues; i++) 111 if (rss->queue_id[i] >= port_info.max_rx_queues) 112 return -EINVAL; 113 } 114 115 /* Port */ 116 memcpy(&port_conf, &port_conf_default, sizeof(port_conf)); 117 if (rss) { 118 uint64_t rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP; 119 120 port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS; 121 port_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf & port_info.flow_type_rss_offloads; 122 } 123 124 numa_node = rte_eth_dev_socket_id(port_id); 125 if (numa_node == SOCKET_ID_ANY) 126 numa_node = 0; 127 128 status = rte_eth_dev_configure( 129 port_id, 130 params->rx.n_queues, 131 params->tx.n_queues, 132 &port_conf); 133 134 if (status < 0) 135 return -EINVAL; 136 137 if (params->promiscuous) { 138 status = rte_eth_promiscuous_enable(port_id); 139 if (status) 140 return -EINVAL; 141 } 142 143 /* Port RX */ 144 for (i = 0; i < params->rx.n_queues; i++) { 145 status = rte_eth_rx_queue_setup( 146 port_id, 147 i, 148 params->rx.queue_size, 149 numa_node, 150 NULL, 151 mempool); 152 153 if (status < 0) 154 return -EINVAL; 155 } 156 157 /* Port TX */ 158 for (i = 0; i < params->tx.n_queues; i++) { 159 status = rte_eth_tx_queue_setup( 160 port_id, 161 i, 162 params->tx.queue_size, 163 numa_node, 164 NULL); 165 166 if (status < 0) 167 return -EINVAL; 168 } 169 170 /* Port start */ 171 status = rte_eth_dev_start(port_id); 172 if (status < 0) 173 return -EINVAL; 174 175 if (rss) { 176 status = rss_setup(port_id, port_info.reta_size, rss); 177 178 if (status) { 179 rte_eth_dev_stop(port_id); 180 return -EINVAL; 181 } 182 } 183 184 /* Port link up */ 185 status = rte_eth_dev_set_link_up(port_id); 186 if ((status < 0) && (status != -ENOTSUP)) { 187 rte_eth_dev_stop(port_id); 188 return -EINVAL; 189 } 190 191 return 0; 192 } 193