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 static struct rte_eth_conf port_conf_default = { 40 .link_speeds = 0, 41 .rxmode = { 42 .mq_mode = ETH_MQ_RX_NONE, 43 44 .header_split = 0, /* Header split */ 45 .hw_ip_checksum = 0, /* IP checksum offload */ 46 .hw_vlan_filter = 0, /* VLAN filtering */ 47 .hw_vlan_strip = 0, /* VLAN strip */ 48 .hw_vlan_extend = 0, /* Extended VLAN */ 49 .jumbo_frame = 0, /* Jumbo frame support */ 50 .hw_strip_crc = 1, /* CRC strip by HW */ 51 .enable_scatter = 0, /* Scattered packets RX handler */ 52 53 .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */ 54 .split_hdr_size = 0, /* Header split buffer size */ 55 }, 56 .rx_adv_conf = { 57 .rss_conf = { 58 .rss_key = NULL, 59 .rss_key_len = 40, 60 .rss_hf = 0, 61 }, 62 }, 63 .txmode = { 64 .mq_mode = ETH_MQ_TX_NONE, 65 }, 66 .lpbk_mode = 0, 67 }; 68 69 #define RETA_CONF_SIZE (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE) 70 71 static int 72 rss_setup(uint16_t port_id, 73 uint16_t reta_size, 74 struct link_params_rss *rss) 75 { 76 struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE]; 77 uint32_t i; 78 int status; 79 80 /* RETA setting */ 81 memset(reta_conf, 0, sizeof(reta_conf)); 82 83 for (i = 0; i < reta_size; i++) 84 reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX; 85 86 for (i = 0; i < reta_size; i++) { 87 uint32_t reta_id = i / RTE_RETA_GROUP_SIZE; 88 uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE; 89 uint32_t rss_qs_pos = i % rss->n_queues; 90 91 reta_conf[reta_id].reta[reta_pos] = 92 (uint16_t) rss->queue_id[rss_qs_pos]; 93 } 94 95 /* RETA update */ 96 status = rte_eth_dev_rss_reta_update(port_id, 97 reta_conf, 98 reta_size); 99 100 return status; 101 } 102 103 struct link * 104 link_create(const char *name, struct link_params *params) 105 { 106 struct rte_eth_dev_info port_info; 107 struct rte_eth_conf port_conf; 108 struct link *link; 109 struct link_params_rss *rss; 110 struct mempool *mempool; 111 uint32_t cpu_id, i; 112 int status; 113 uint16_t port_id; 114 115 /* Check input params */ 116 if ((name == NULL) || 117 link_find(name) || 118 (params == NULL) || 119 (params->rx.n_queues == 0) || 120 (params->rx.queue_size == 0) || 121 (params->tx.n_queues == 0) || 122 (params->tx.queue_size == 0)) 123 return NULL; 124 125 port_id = params->port_id; 126 if (params->dev_name) { 127 status = rte_eth_dev_get_port_by_name(params->dev_name, 128 &port_id); 129 130 if (status) 131 return NULL; 132 } else 133 if (!rte_eth_dev_is_valid_port(port_id)) 134 return NULL; 135 136 rte_eth_dev_info_get(port_id, &port_info); 137 138 mempool = mempool_find(params->rx.mempool_name); 139 if (mempool == NULL) 140 return NULL; 141 142 rss = params->rx.rss; 143 if (rss) { 144 if ((port_info.reta_size == 0) || 145 (port_info.reta_size > ETH_RSS_RETA_SIZE_512)) 146 return NULL; 147 148 if ((rss->n_queues == 0) || 149 (rss->n_queues >= LINK_RXQ_RSS_MAX)) 150 return NULL; 151 152 for (i = 0; i < rss->n_queues; i++) 153 if (rss->queue_id[i] >= port_info.max_rx_queues) 154 return NULL; 155 } 156 157 /** 158 * Resource create 159 */ 160 /* Port */ 161 memcpy(&port_conf, &port_conf_default, sizeof(port_conf)); 162 if (rss) { 163 port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS; 164 port_conf.rx_adv_conf.rss_conf.rss_hf = 165 ETH_RSS_IPV4 | ETH_RSS_IPV6; 166 } 167 168 cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id); 169 if (cpu_id == (uint32_t) SOCKET_ID_ANY) 170 cpu_id = 0; 171 172 status = rte_eth_dev_configure( 173 port_id, 174 params->rx.n_queues, 175 params->tx.n_queues, 176 &port_conf); 177 178 if (status < 0) 179 return NULL; 180 181 if (params->promiscuous) 182 rte_eth_promiscuous_enable(port_id); 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 rte_eth_link_get(link->port_id, &link_params); 267 268 return (link_params.link_status == ETH_LINK_DOWN) ? 0 : 1; 269 } 270