1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
8 #include <rte_mempool.h>
10 #include <rte_ethdev.h>
11 #include <rte_swx_port_ethdev.h>
12 #include <rte_swx_port_ring.h>
13 #include <rte_swx_port_source_sink.h>
14 #include <rte_swx_table_em.h>
15 #include <rte_swx_table_wm.h>
16 #include <rte_swx_pipeline.h>
17 #include <rte_swx_ctl.h>
24 TAILQ_HEAD(mempool_list, mempool);
29 TAILQ_HEAD(link_list, link);
34 TAILQ_HEAD(ring_list, ring);
39 TAILQ_HEAD(pipeline_list, pipeline);
45 struct mempool_list mempool_list;
46 struct link_list link_list;
47 struct ring_list ring_list;
48 struct pipeline_list pipeline_list;
54 #define BUFFER_SIZE_MIN (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
57 mempool_create(struct obj *obj, const char *name, struct mempool_params *params)
59 struct mempool *mempool;
60 struct rte_mempool *m;
62 /* Check input params */
64 mempool_find(obj, name) ||
66 (params->buffer_size < BUFFER_SIZE_MIN) ||
67 (params->pool_size == 0))
71 m = rte_pktmbuf_pool_create(
76 params->buffer_size - sizeof(struct rte_mbuf),
83 mempool = calloc(1, sizeof(struct mempool));
84 if (mempool == NULL) {
90 strlcpy(mempool->name, name, sizeof(mempool->name));
92 mempool->buffer_size = params->buffer_size;
94 /* Node add to list */
95 TAILQ_INSERT_TAIL(&obj->mempool_list, mempool, node);
101 mempool_find(struct obj *obj, const char *name)
103 struct mempool *mempool;
108 TAILQ_FOREACH(mempool, &obj->mempool_list, node)
109 if (strcmp(mempool->name, name) == 0)
118 static struct rte_eth_conf port_conf_default = {
121 .mq_mode = ETH_MQ_RX_NONE,
122 .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */
123 .split_hdr_size = 0, /* Header split buffer size */
133 .mq_mode = ETH_MQ_TX_NONE,
138 #define RETA_CONF_SIZE (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE)
141 rss_setup(uint16_t port_id,
143 struct link_params_rss *rss)
145 struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE];
150 memset(reta_conf, 0, sizeof(reta_conf));
152 for (i = 0; i < reta_size; i++)
153 reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX;
155 for (i = 0; i < reta_size; i++) {
156 uint32_t reta_id = i / RTE_RETA_GROUP_SIZE;
157 uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE;
158 uint32_t rss_qs_pos = i % rss->n_queues;
160 reta_conf[reta_id].reta[reta_pos] =
161 (uint16_t) rss->queue_id[rss_qs_pos];
165 status = rte_eth_dev_rss_reta_update(port_id,
173 link_create(struct obj *obj, const char *name, struct link_params *params)
175 struct rte_eth_dev_info port_info;
176 struct rte_eth_conf port_conf;
178 struct link_params_rss *rss;
179 struct mempool *mempool;
184 /* Check input params */
185 if ((name == NULL) ||
186 link_find(obj, name) ||
188 (params->rx.n_queues == 0) ||
189 (params->rx.queue_size == 0) ||
190 (params->tx.n_queues == 0) ||
191 (params->tx.queue_size == 0))
194 port_id = params->port_id;
195 if (params->dev_name) {
196 status = rte_eth_dev_get_port_by_name(params->dev_name,
202 if (!rte_eth_dev_is_valid_port(port_id))
205 if (rte_eth_dev_info_get(port_id, &port_info) != 0)
208 mempool = mempool_find(obj, params->rx.mempool_name);
212 rss = params->rx.rss;
214 if ((port_info.reta_size == 0) ||
215 (port_info.reta_size > ETH_RSS_RETA_SIZE_512))
218 if ((rss->n_queues == 0) ||
219 (rss->n_queues >= LINK_RXQ_RSS_MAX))
222 for (i = 0; i < rss->n_queues; i++)
223 if (rss->queue_id[i] >= port_info.max_rx_queues)
231 memcpy(&port_conf, &port_conf_default, sizeof(port_conf));
233 port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
234 port_conf.rx_adv_conf.rss_conf.rss_hf =
235 (ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP) &
236 port_info.flow_type_rss_offloads;
239 cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id);
240 if (cpu_id == (uint32_t) SOCKET_ID_ANY)
243 status = rte_eth_dev_configure(
252 if (params->promiscuous) {
253 status = rte_eth_promiscuous_enable(port_id);
259 for (i = 0; i < params->rx.n_queues; i++) {
260 status = rte_eth_rx_queue_setup(
263 params->rx.queue_size,
273 for (i = 0; i < params->tx.n_queues; i++) {
274 status = rte_eth_tx_queue_setup(
277 params->tx.queue_size,
286 status = rte_eth_dev_start(port_id);
291 status = rss_setup(port_id, port_info.reta_size, rss);
294 rte_eth_dev_stop(port_id);
300 status = rte_eth_dev_set_link_up(port_id);
301 if ((status < 0) && (status != -ENOTSUP)) {
302 rte_eth_dev_stop(port_id);
306 /* Node allocation */
307 link = calloc(1, sizeof(struct link));
309 rte_eth_dev_stop(port_id);
314 strlcpy(link->name, name, sizeof(link->name));
315 link->port_id = port_id;
316 rte_eth_dev_get_name_by_port(port_id, link->dev_name);
317 link->n_rxq = params->rx.n_queues;
318 link->n_txq = params->tx.n_queues;
320 /* Node add to list */
321 TAILQ_INSERT_TAIL(&obj->link_list, link, node);
327 link_is_up(struct obj *obj, const char *name)
329 struct rte_eth_link link_params;
332 /* Check input params */
336 link = link_find(obj, name);
341 if (rte_eth_link_get(link->port_id, &link_params) < 0)
344 return (link_params.link_status == ETH_LINK_DOWN) ? 0 : 1;
348 link_find(struct obj *obj, const char *name)
355 TAILQ_FOREACH(link, &obj->link_list, node)
356 if (strcmp(link->name, name) == 0)
363 link_next(struct obj *obj, struct link *link)
365 return (link == NULL) ?
366 TAILQ_FIRST(&obj->link_list) : TAILQ_NEXT(link, node);
373 ring_create(struct obj *obj, const char *name, struct ring_params *params)
377 unsigned int flags = RING_F_SP_ENQ | RING_F_SC_DEQ;
379 /* Check input params */
380 if (!name || ring_find(obj, name) || !params || !params->size)
394 /* Node allocation */
395 ring = calloc(1, sizeof(struct ring));
402 strlcpy(ring->name, name, sizeof(ring->name));
404 /* Node add to list */
405 TAILQ_INSERT_TAIL(&obj->ring_list, ring, node);
411 ring_find(struct obj *obj, const char *name)
418 TAILQ_FOREACH(ring, &obj->ring_list, node)
419 if (strcmp(ring->name, name) == 0)
428 #ifndef PIPELINE_MSGQ_SIZE
429 #define PIPELINE_MSGQ_SIZE 64
433 pipeline_create(struct obj *obj, const char *name, int numa_node)
435 struct pipeline *pipeline;
436 struct rte_swx_pipeline *p = NULL;
439 /* Check input params */
440 if ((name == NULL) ||
441 pipeline_find(obj, name))
444 /* Resource create */
445 status = rte_swx_pipeline_config(&p, numa_node);
449 status = rte_swx_pipeline_port_in_type_register(p,
451 &rte_swx_port_ethdev_reader_ops);
455 status = rte_swx_pipeline_port_out_type_register(p,
457 &rte_swx_port_ethdev_writer_ops);
461 status = rte_swx_pipeline_port_in_type_register(p,
463 &rte_swx_port_ring_reader_ops);
467 status = rte_swx_pipeline_port_out_type_register(p,
469 &rte_swx_port_ring_writer_ops);
474 status = rte_swx_pipeline_port_in_type_register(p,
476 &rte_swx_port_source_ops);
481 status = rte_swx_pipeline_port_out_type_register(p,
483 &rte_swx_port_sink_ops);
487 status = rte_swx_pipeline_table_type_register(p,
489 RTE_SWX_TABLE_MATCH_EXACT,
490 &rte_swx_table_exact_match_ops);
494 status = rte_swx_pipeline_table_type_register(p,
496 RTE_SWX_TABLE_MATCH_WILDCARD,
497 &rte_swx_table_wildcard_match_ops);
501 /* Node allocation */
502 pipeline = calloc(1, sizeof(struct pipeline));
503 if (pipeline == NULL)
507 strlcpy(pipeline->name, name, sizeof(pipeline->name));
509 pipeline->timer_period_ms = 10;
511 /* Node add to list */
512 TAILQ_INSERT_TAIL(&obj->pipeline_list, pipeline, node);
517 rte_swx_pipeline_free(p);
522 pipeline_find(struct obj *obj, const char *name)
524 struct pipeline *pipeline;
529 TAILQ_FOREACH(pipeline, &obj->pipeline_list, node)
530 if (strcmp(name, pipeline->name) == 0)
544 obj = calloc(1, sizeof(struct obj));
548 TAILQ_INIT(&obj->mempool_list);
549 TAILQ_INIT(&obj->link_list);
550 TAILQ_INIT(&obj->ring_list);
551 TAILQ_INIT(&obj->pipeline_list);