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