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_mempool.h> 9 #include <rte_mbuf.h> 10 #include <rte_ethdev.h> 11 #include <rte_swx_port_ethdev.h> 12 #include <rte_swx_port_source_sink.h> 13 #include <rte_swx_table_em.h> 14 #include <rte_swx_pipeline.h> 15 #include <rte_swx_ctl.h> 16 17 #include "obj.h" 18 19 /* 20 * mempool 21 */ 22 TAILQ_HEAD(mempool_list, mempool); 23 24 /* 25 * link 26 */ 27 TAILQ_HEAD(link_list, link); 28 29 /* 30 * pipeline 31 */ 32 TAILQ_HEAD(pipeline_list, pipeline); 33 34 /* 35 * obj 36 */ 37 struct obj { 38 struct mempool_list mempool_list; 39 struct link_list link_list; 40 struct pipeline_list pipeline_list; 41 }; 42 43 /* 44 * mempool 45 */ 46 #define BUFFER_SIZE_MIN (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) 47 48 struct mempool * 49 mempool_create(struct obj *obj, const char *name, struct mempool_params *params) 50 { 51 struct mempool *mempool; 52 struct rte_mempool *m; 53 54 /* Check input params */ 55 if ((name == NULL) || 56 mempool_find(obj, name) || 57 (params == NULL) || 58 (params->buffer_size < BUFFER_SIZE_MIN) || 59 (params->pool_size == 0)) 60 return NULL; 61 62 /* Resource create */ 63 m = rte_pktmbuf_pool_create( 64 name, 65 params->pool_size, 66 params->cache_size, 67 0, 68 params->buffer_size - sizeof(struct rte_mbuf), 69 params->cpu_id); 70 71 if (m == NULL) 72 return NULL; 73 74 /* Node allocation */ 75 mempool = calloc(1, sizeof(struct mempool)); 76 if (mempool == NULL) { 77 rte_mempool_free(m); 78 return NULL; 79 } 80 81 /* Node fill in */ 82 strlcpy(mempool->name, name, sizeof(mempool->name)); 83 mempool->m = m; 84 mempool->buffer_size = params->buffer_size; 85 86 /* Node add to list */ 87 TAILQ_INSERT_TAIL(&obj->mempool_list, mempool, node); 88 89 return mempool; 90 } 91 92 struct mempool * 93 mempool_find(struct obj *obj, const char *name) 94 { 95 struct mempool *mempool; 96 97 if (!obj || !name) 98 return NULL; 99 100 TAILQ_FOREACH(mempool, &obj->mempool_list, node) 101 if (strcmp(mempool->name, name) == 0) 102 return mempool; 103 104 return NULL; 105 } 106 107 /* 108 * link 109 */ 110 static struct rte_eth_conf port_conf_default = { 111 .link_speeds = 0, 112 .rxmode = { 113 .mq_mode = ETH_MQ_RX_NONE, 114 .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */ 115 .split_hdr_size = 0, /* Header split buffer size */ 116 }, 117 .rx_adv_conf = { 118 .rss_conf = { 119 .rss_key = NULL, 120 .rss_key_len = 40, 121 .rss_hf = 0, 122 }, 123 }, 124 .txmode = { 125 .mq_mode = ETH_MQ_TX_NONE, 126 }, 127 .lpbk_mode = 0, 128 }; 129 130 #define RETA_CONF_SIZE (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE) 131 132 static int 133 rss_setup(uint16_t port_id, 134 uint16_t reta_size, 135 struct link_params_rss *rss) 136 { 137 struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE]; 138 uint32_t i; 139 int status; 140 141 /* RETA setting */ 142 memset(reta_conf, 0, sizeof(reta_conf)); 143 144 for (i = 0; i < reta_size; i++) 145 reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX; 146 147 for (i = 0; i < reta_size; i++) { 148 uint32_t reta_id = i / RTE_RETA_GROUP_SIZE; 149 uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE; 150 uint32_t rss_qs_pos = i % rss->n_queues; 151 152 reta_conf[reta_id].reta[reta_pos] = 153 (uint16_t) rss->queue_id[rss_qs_pos]; 154 } 155 156 /* RETA update */ 157 status = rte_eth_dev_rss_reta_update(port_id, 158 reta_conf, 159 reta_size); 160 161 return status; 162 } 163 164 struct link * 165 link_create(struct obj *obj, const char *name, struct link_params *params) 166 { 167 struct rte_eth_dev_info port_info; 168 struct rte_eth_conf port_conf; 169 struct link *link; 170 struct link_params_rss *rss; 171 struct mempool *mempool; 172 uint32_t cpu_id, i; 173 int status; 174 uint16_t port_id; 175 176 /* Check input params */ 177 if ((name == NULL) || 178 link_find(obj, name) || 179 (params == NULL) || 180 (params->rx.n_queues == 0) || 181 (params->rx.queue_size == 0) || 182 (params->tx.n_queues == 0) || 183 (params->tx.queue_size == 0)) 184 return NULL; 185 186 port_id = params->port_id; 187 if (params->dev_name) { 188 status = rte_eth_dev_get_port_by_name(params->dev_name, 189 &port_id); 190 191 if (status) 192 return NULL; 193 } else 194 if (!rte_eth_dev_is_valid_port(port_id)) 195 return NULL; 196 197 if (rte_eth_dev_info_get(port_id, &port_info) != 0) 198 return NULL; 199 200 mempool = mempool_find(obj, params->rx.mempool_name); 201 if (mempool == NULL) 202 return NULL; 203 204 rss = params->rx.rss; 205 if (rss) { 206 if ((port_info.reta_size == 0) || 207 (port_info.reta_size > ETH_RSS_RETA_SIZE_512)) 208 return NULL; 209 210 if ((rss->n_queues == 0) || 211 (rss->n_queues >= LINK_RXQ_RSS_MAX)) 212 return NULL; 213 214 for (i = 0; i < rss->n_queues; i++) 215 if (rss->queue_id[i] >= port_info.max_rx_queues) 216 return NULL; 217 } 218 219 /** 220 * Resource create 221 */ 222 /* Port */ 223 memcpy(&port_conf, &port_conf_default, sizeof(port_conf)); 224 if (rss) { 225 port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS; 226 port_conf.rx_adv_conf.rss_conf.rss_hf = 227 (ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP) & 228 port_info.flow_type_rss_offloads; 229 } 230 231 cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id); 232 if (cpu_id == (uint32_t) SOCKET_ID_ANY) 233 cpu_id = 0; 234 235 status = rte_eth_dev_configure( 236 port_id, 237 params->rx.n_queues, 238 params->tx.n_queues, 239 &port_conf); 240 241 if (status < 0) 242 return NULL; 243 244 if (params->promiscuous) { 245 status = rte_eth_promiscuous_enable(port_id); 246 if (status != 0) 247 return NULL; 248 } 249 250 /* Port RX */ 251 for (i = 0; i < params->rx.n_queues; i++) { 252 status = rte_eth_rx_queue_setup( 253 port_id, 254 i, 255 params->rx.queue_size, 256 cpu_id, 257 NULL, 258 mempool->m); 259 260 if (status < 0) 261 return NULL; 262 } 263 264 /* Port TX */ 265 for (i = 0; i < params->tx.n_queues; i++) { 266 status = rte_eth_tx_queue_setup( 267 port_id, 268 i, 269 params->tx.queue_size, 270 cpu_id, 271 NULL); 272 273 if (status < 0) 274 return NULL; 275 } 276 277 /* Port start */ 278 status = rte_eth_dev_start(port_id); 279 if (status < 0) 280 return NULL; 281 282 if (rss) { 283 status = rss_setup(port_id, port_info.reta_size, rss); 284 285 if (status) { 286 rte_eth_dev_stop(port_id); 287 return NULL; 288 } 289 } 290 291 /* Port link up */ 292 status = rte_eth_dev_set_link_up(port_id); 293 if ((status < 0) && (status != -ENOTSUP)) { 294 rte_eth_dev_stop(port_id); 295 return NULL; 296 } 297 298 /* Node allocation */ 299 link = calloc(1, sizeof(struct link)); 300 if (link == NULL) { 301 rte_eth_dev_stop(port_id); 302 return NULL; 303 } 304 305 /* Node fill in */ 306 strlcpy(link->name, name, sizeof(link->name)); 307 link->port_id = port_id; 308 rte_eth_dev_get_name_by_port(port_id, link->dev_name); 309 link->n_rxq = params->rx.n_queues; 310 link->n_txq = params->tx.n_queues; 311 312 /* Node add to list */ 313 TAILQ_INSERT_TAIL(&obj->link_list, link, node); 314 315 return link; 316 } 317 318 int 319 link_is_up(struct obj *obj, const char *name) 320 { 321 struct rte_eth_link link_params; 322 struct link *link; 323 324 /* Check input params */ 325 if (!obj || !name) 326 return 0; 327 328 link = link_find(obj, name); 329 if (link == NULL) 330 return 0; 331 332 /* Resource */ 333 if (rte_eth_link_get(link->port_id, &link_params) < 0) 334 return 0; 335 336 return (link_params.link_status == ETH_LINK_DOWN) ? 0 : 1; 337 } 338 339 struct link * 340 link_find(struct obj *obj, const char *name) 341 { 342 struct link *link; 343 344 if (!obj || !name) 345 return NULL; 346 347 TAILQ_FOREACH(link, &obj->link_list, node) 348 if (strcmp(link->name, name) == 0) 349 return link; 350 351 return NULL; 352 } 353 354 struct link * 355 link_next(struct obj *obj, struct link *link) 356 { 357 return (link == NULL) ? 358 TAILQ_FIRST(&obj->link_list) : TAILQ_NEXT(link, node); 359 } 360 361 /* 362 * pipeline 363 */ 364 #ifndef PIPELINE_MSGQ_SIZE 365 #define PIPELINE_MSGQ_SIZE 64 366 #endif 367 368 struct pipeline * 369 pipeline_create(struct obj *obj, const char *name, int numa_node) 370 { 371 struct pipeline *pipeline; 372 struct rte_swx_pipeline *p = NULL; 373 int status; 374 375 /* Check input params */ 376 if ((name == NULL) || 377 pipeline_find(obj, name)) 378 return NULL; 379 380 /* Resource create */ 381 status = rte_swx_pipeline_config(&p, numa_node); 382 if (status) 383 goto error; 384 385 status = rte_swx_pipeline_port_in_type_register(p, 386 "ethdev", 387 &rte_swx_port_ethdev_reader_ops); 388 if (status) 389 goto error; 390 391 status = rte_swx_pipeline_port_out_type_register(p, 392 "ethdev", 393 &rte_swx_port_ethdev_writer_ops); 394 if (status) 395 goto error; 396 397 #ifdef RTE_PORT_PCAP 398 status = rte_swx_pipeline_port_in_type_register(p, 399 "source", 400 &rte_swx_port_source_ops); 401 if (status) 402 goto error; 403 #endif 404 405 status = rte_swx_pipeline_port_out_type_register(p, 406 "sink", 407 &rte_swx_port_sink_ops); 408 if (status) 409 goto error; 410 411 status = rte_swx_pipeline_table_type_register(p, 412 "exact", 413 RTE_SWX_TABLE_MATCH_EXACT, 414 &rte_swx_table_exact_match_ops); 415 if (status) 416 goto error; 417 418 /* Node allocation */ 419 pipeline = calloc(1, sizeof(struct pipeline)); 420 if (pipeline == NULL) 421 goto error; 422 423 /* Node fill in */ 424 strlcpy(pipeline->name, name, sizeof(pipeline->name)); 425 pipeline->p = p; 426 pipeline->timer_period_ms = 10; 427 428 /* Node add to list */ 429 TAILQ_INSERT_TAIL(&obj->pipeline_list, pipeline, node); 430 431 return pipeline; 432 433 error: 434 rte_swx_pipeline_free(p); 435 return NULL; 436 } 437 438 struct pipeline * 439 pipeline_find(struct obj *obj, const char *name) 440 { 441 struct pipeline *pipeline; 442 443 if (!obj || !name) 444 return NULL; 445 446 TAILQ_FOREACH(pipeline, &obj->pipeline_list, node) 447 if (strcmp(name, pipeline->name) == 0) 448 return pipeline; 449 450 return NULL; 451 } 452 453 /* 454 * obj 455 */ 456 struct obj * 457 obj_init(void) 458 { 459 struct obj *obj; 460 461 obj = calloc(1, sizeof(struct obj)); 462 if (!obj) 463 return NULL; 464 465 TAILQ_INIT(&obj->mempool_list); 466 TAILQ_INIT(&obj->link_list); 467 TAILQ_INIT(&obj->pipeline_list); 468 469 return obj; 470 } 471