1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <rte_ethdev.h> 9 #include <rte_string_fns.h> 10 11 #include "link.h" 12 #include "mempool.h" 13 14 static struct link_list link_list; 15 16 int 17 link_init(void) 18 { 19 TAILQ_INIT(&link_list); 20 21 return 0; 22 } 23 24 struct link * 25 link_find(const char *name) 26 { 27 struct link *link; 28 29 if (name == NULL) 30 return NULL; 31 32 TAILQ_FOREACH(link, &link_list, node) 33 if (strcmp(link->name, name) == 0) 34 return link; 35 36 return NULL; 37 } 38 39 struct link * 40 link_next(struct link *link) 41 { 42 return (link == NULL) ? TAILQ_FIRST(&link_list) : TAILQ_NEXT(link, node); 43 } 44 45 static struct rte_eth_conf port_conf_default = { 46 .link_speeds = 0, 47 .rxmode = { 48 .mq_mode = RTE_ETH_MQ_RX_NONE, 49 .mtu = 9000 - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN), /* Jumbo frame MTU */ 50 }, 51 .rx_adv_conf = { 52 .rss_conf = { 53 .rss_key = NULL, 54 .rss_key_len = 40, 55 .rss_hf = 0, 56 }, 57 }, 58 .txmode = { 59 .mq_mode = RTE_ETH_MQ_TX_NONE, 60 }, 61 .lpbk_mode = 0, 62 }; 63 64 #define RETA_CONF_SIZE (RTE_ETH_RSS_RETA_SIZE_512 / RTE_ETH_RETA_GROUP_SIZE) 65 66 static int 67 rss_setup(uint16_t port_id, 68 uint16_t reta_size, 69 struct link_params_rss *rss) 70 { 71 struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE]; 72 uint32_t i; 73 int status; 74 75 /* RETA setting */ 76 memset(reta_conf, 0, sizeof(reta_conf)); 77 78 for (i = 0; i < reta_size; i++) 79 reta_conf[i / RTE_ETH_RETA_GROUP_SIZE].mask = UINT64_MAX; 80 81 for (i = 0; i < reta_size; i++) { 82 uint32_t reta_id = i / RTE_ETH_RETA_GROUP_SIZE; 83 uint32_t reta_pos = i % RTE_ETH_RETA_GROUP_SIZE; 84 uint32_t rss_qs_pos = i % rss->n_queues; 85 86 reta_conf[reta_id].reta[reta_pos] = 87 (uint16_t) rss->queue_id[rss_qs_pos]; 88 } 89 90 /* RETA update */ 91 status = rte_eth_dev_rss_reta_update(port_id, 92 reta_conf, 93 reta_size); 94 95 return status; 96 } 97 98 struct link * 99 link_create(const char *name, struct link_params *params) 100 { 101 struct rte_eth_dev_info port_info; 102 struct rte_eth_conf port_conf; 103 struct link *link; 104 struct link_params_rss *rss; 105 struct mempool *mempool; 106 uint32_t cpu_id, i; 107 int status; 108 uint16_t port_id; 109 110 /* Check input params */ 111 if ((name == NULL) || 112 link_find(name) || 113 (params == NULL) || 114 (params->rx.n_queues == 0) || 115 (params->rx.queue_size == 0) || 116 (params->tx.n_queues == 0) || 117 (params->tx.queue_size == 0)) 118 return NULL; 119 120 port_id = params->port_id; 121 if (params->dev_name) { 122 status = rte_eth_dev_get_port_by_name(params->dev_name, 123 &port_id); 124 125 if (status) 126 return NULL; 127 } else 128 if (!rte_eth_dev_is_valid_port(port_id)) 129 return NULL; 130 131 if (rte_eth_dev_info_get(port_id, &port_info) != 0) 132 return NULL; 133 134 mempool = mempool_find(params->rx.mempool_name); 135 if (mempool == NULL) 136 return NULL; 137 138 rss = params->rx.rss; 139 if (rss) { 140 if ((port_info.reta_size == 0) || 141 (port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512)) 142 return NULL; 143 144 if ((rss->n_queues == 0) || 145 (rss->n_queues >= LINK_RXQ_RSS_MAX)) 146 return NULL; 147 148 for (i = 0; i < rss->n_queues; i++) 149 if (rss->queue_id[i] >= port_info.max_rx_queues) 150 return NULL; 151 } 152 153 /** 154 * Resource create 155 */ 156 /* Port */ 157 memcpy(&port_conf, &port_conf_default, sizeof(port_conf)); 158 if (rss) { 159 port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS; 160 port_conf.rx_adv_conf.rss_conf.rss_hf = 161 (RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP) & 162 port_info.flow_type_rss_offloads; 163 } 164 165 cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id); 166 if (cpu_id == (uint32_t) SOCKET_ID_ANY) 167 cpu_id = 0; 168 169 status = rte_eth_dev_configure( 170 port_id, 171 params->rx.n_queues, 172 params->tx.n_queues, 173 &port_conf); 174 175 if (status < 0) 176 return NULL; 177 178 if (params->promiscuous) { 179 status = rte_eth_promiscuous_enable(port_id); 180 if (status != 0) 181 return NULL; 182 } 183 184 /* Port RX */ 185 for (i = 0; i < params->rx.n_queues; i++) { 186 status = rte_eth_rx_queue_setup( 187 port_id, 188 i, 189 params->rx.queue_size, 190 cpu_id, 191 NULL, 192 mempool->m); 193 194 if (status < 0) 195 return NULL; 196 } 197 198 /* Port TX */ 199 for (i = 0; i < params->tx.n_queues; i++) { 200 status = rte_eth_tx_queue_setup( 201 port_id, 202 i, 203 params->tx.queue_size, 204 cpu_id, 205 NULL); 206 207 if (status < 0) 208 return NULL; 209 } 210 211 /* Port start */ 212 status = rte_eth_dev_start(port_id); 213 if (status < 0) 214 return NULL; 215 216 if (rss) { 217 status = rss_setup(port_id, port_info.reta_size, rss); 218 219 if (status) { 220 rte_eth_dev_stop(port_id); 221 return NULL; 222 } 223 } 224 225 /* Port link up */ 226 status = rte_eth_dev_set_link_up(port_id); 227 if ((status < 0) && (status != -ENOTSUP)) { 228 rte_eth_dev_stop(port_id); 229 return NULL; 230 } 231 232 /* Node allocation */ 233 link = calloc(1, sizeof(struct link)); 234 if (link == NULL) { 235 rte_eth_dev_stop(port_id); 236 return NULL; 237 } 238 239 /* Node fill in */ 240 strlcpy(link->name, name, sizeof(link->name)); 241 link->port_id = port_id; 242 link->n_rxq = params->rx.n_queues; 243 link->n_txq = params->tx.n_queues; 244 245 /* Node add to list */ 246 TAILQ_INSERT_TAIL(&link_list, link, node); 247 248 return link; 249 } 250 251 int 252 link_is_up(const char *name) 253 { 254 struct rte_eth_link link_params; 255 struct link *link; 256 257 /* Check input params */ 258 if (name == NULL) 259 return 0; 260 261 link = link_find(name); 262 if (link == NULL) 263 return 0; 264 265 /* Resource */ 266 if (rte_eth_link_get(link->port_id, &link_params) < 0) 267 return 0; 268 269 return (link_params.link_status == RTE_ETH_LINK_DOWN) ? 0 : 1; 270 } 271