1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
7 #include <netinet/in.h>
8 #ifdef RTE_EXEC_ENV_LINUX
10 #include <linux/if_tun.h>
12 #include <sys/ioctl.h>
16 #include <rte_mempool.h>
18 #include <rte_ethdev.h>
19 #include <rte_swx_port_ethdev.h>
20 #include <rte_swx_port_fd.h>
21 #include <rte_swx_port_ring.h>
22 #include <rte_swx_port_source_sink.h>
23 #include <rte_swx_table_em.h>
24 #include <rte_swx_table_wm.h>
25 #include <rte_swx_pipeline.h>
26 #include <rte_swx_ctl.h>
33 TAILQ_HEAD(mempool_list, mempool);
38 TAILQ_HEAD(link_list, link);
43 TAILQ_HEAD(ring_list, ring);
48 TAILQ_HEAD(tap_list, tap);
53 TAILQ_HEAD(pipeline_list, pipeline);
59 struct mempool_list mempool_list;
60 struct link_list link_list;
61 struct ring_list ring_list;
62 struct pipeline_list pipeline_list;
63 struct tap_list tap_list;
69 #define BUFFER_SIZE_MIN (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
72 mempool_create(struct obj *obj, const char *name, struct mempool_params *params)
74 struct mempool *mempool;
75 struct rte_mempool *m;
77 /* Check input params */
79 mempool_find(obj, name) ||
81 (params->buffer_size < BUFFER_SIZE_MIN) ||
82 (params->pool_size == 0))
86 m = rte_pktmbuf_pool_create(
91 params->buffer_size - sizeof(struct rte_mbuf),
98 mempool = calloc(1, sizeof(struct mempool));
99 if (mempool == NULL) {
105 strlcpy(mempool->name, name, sizeof(mempool->name));
107 mempool->buffer_size = params->buffer_size;
109 /* Node add to list */
110 TAILQ_INSERT_TAIL(&obj->mempool_list, mempool, node);
116 mempool_find(struct obj *obj, const char *name)
118 struct mempool *mempool;
123 TAILQ_FOREACH(mempool, &obj->mempool_list, node)
124 if (strcmp(mempool->name, name) == 0)
133 static struct rte_eth_conf port_conf_default = {
136 .mq_mode = ETH_MQ_RX_NONE,
137 .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */
138 .split_hdr_size = 0, /* Header split buffer size */
148 .mq_mode = ETH_MQ_TX_NONE,
153 #define RETA_CONF_SIZE (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE)
156 rss_setup(uint16_t port_id,
158 struct link_params_rss *rss)
160 struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE];
165 memset(reta_conf, 0, sizeof(reta_conf));
167 for (i = 0; i < reta_size; i++)
168 reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX;
170 for (i = 0; i < reta_size; i++) {
171 uint32_t reta_id = i / RTE_RETA_GROUP_SIZE;
172 uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE;
173 uint32_t rss_qs_pos = i % rss->n_queues;
175 reta_conf[reta_id].reta[reta_pos] =
176 (uint16_t) rss->queue_id[rss_qs_pos];
180 status = rte_eth_dev_rss_reta_update(port_id,
188 link_create(struct obj *obj, const char *name, struct link_params *params)
190 struct rte_eth_dev_info port_info;
191 struct rte_eth_conf port_conf;
193 struct link_params_rss *rss;
194 struct mempool *mempool;
199 /* Check input params */
200 if ((name == NULL) ||
201 link_find(obj, name) ||
203 (params->rx.n_queues == 0) ||
204 (params->rx.queue_size == 0) ||
205 (params->tx.n_queues == 0) ||
206 (params->tx.queue_size == 0))
209 port_id = params->port_id;
210 if (params->dev_name) {
211 status = rte_eth_dev_get_port_by_name(params->dev_name,
217 if (!rte_eth_dev_is_valid_port(port_id))
220 if (rte_eth_dev_info_get(port_id, &port_info) != 0)
223 mempool = mempool_find(obj, params->rx.mempool_name);
227 rss = params->rx.rss;
229 if ((port_info.reta_size == 0) ||
230 (port_info.reta_size > ETH_RSS_RETA_SIZE_512))
233 if ((rss->n_queues == 0) ||
234 (rss->n_queues >= LINK_RXQ_RSS_MAX))
237 for (i = 0; i < rss->n_queues; i++)
238 if (rss->queue_id[i] >= port_info.max_rx_queues)
246 memcpy(&port_conf, &port_conf_default, sizeof(port_conf));
248 port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
249 port_conf.rx_adv_conf.rss_conf.rss_hf =
250 (ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP) &
251 port_info.flow_type_rss_offloads;
254 cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id);
255 if (cpu_id == (uint32_t) SOCKET_ID_ANY)
258 status = rte_eth_dev_configure(
267 if (params->promiscuous) {
268 status = rte_eth_promiscuous_enable(port_id);
274 for (i = 0; i < params->rx.n_queues; i++) {
275 status = rte_eth_rx_queue_setup(
278 params->rx.queue_size,
288 for (i = 0; i < params->tx.n_queues; i++) {
289 status = rte_eth_tx_queue_setup(
292 params->tx.queue_size,
301 status = rte_eth_dev_start(port_id);
306 status = rss_setup(port_id, port_info.reta_size, rss);
309 rte_eth_dev_stop(port_id);
315 status = rte_eth_dev_set_link_up(port_id);
316 if ((status < 0) && (status != -ENOTSUP)) {
317 rte_eth_dev_stop(port_id);
321 /* Node allocation */
322 link = calloc(1, sizeof(struct link));
324 rte_eth_dev_stop(port_id);
329 strlcpy(link->name, name, sizeof(link->name));
330 link->port_id = port_id;
331 rte_eth_dev_get_name_by_port(port_id, link->dev_name);
332 link->n_rxq = params->rx.n_queues;
333 link->n_txq = params->tx.n_queues;
335 /* Node add to list */
336 TAILQ_INSERT_TAIL(&obj->link_list, link, node);
342 link_is_up(struct obj *obj, const char *name)
344 struct rte_eth_link link_params;
347 /* Check input params */
351 link = link_find(obj, name);
356 if (rte_eth_link_get(link->port_id, &link_params) < 0)
359 return (link_params.link_status == ETH_LINK_DOWN) ? 0 : 1;
363 link_find(struct obj *obj, const char *name)
370 TAILQ_FOREACH(link, &obj->link_list, node)
371 if (strcmp(link->name, name) == 0)
378 link_next(struct obj *obj, struct link *link)
380 return (link == NULL) ?
381 TAILQ_FIRST(&obj->link_list) : TAILQ_NEXT(link, node);
388 ring_create(struct obj *obj, const char *name, struct ring_params *params)
392 unsigned int flags = RING_F_SP_ENQ | RING_F_SC_DEQ;
394 /* Check input params */
395 if (!name || ring_find(obj, name) || !params || !params->size)
409 /* Node allocation */
410 ring = calloc(1, sizeof(struct ring));
417 strlcpy(ring->name, name, sizeof(ring->name));
419 /* Node add to list */
420 TAILQ_INSERT_TAIL(&obj->ring_list, ring, node);
426 ring_find(struct obj *obj, const char *name)
433 TAILQ_FOREACH(ring, &obj->ring_list, node)
434 if (strcmp(ring->name, name) == 0)
443 #define TAP_DEV "/dev/net/tun"
446 tap_find(struct obj *obj, const char *name)
453 TAILQ_FOREACH(tap, &obj->tap_list, node)
454 if (strcmp(tap->name, name) == 0)
461 tap_next(struct obj *obj, struct tap *tap)
463 return (tap == NULL) ?
464 TAILQ_FIRST(&obj->tap_list) : TAILQ_NEXT(tap, node);
467 #ifndef RTE_EXEC_ENV_LINUX
470 tap_create(struct obj *obj __rte_unused, const char *name __rte_unused)
478 tap_create(struct obj *obj, const char *name)
484 /* Check input params */
485 if ((name == NULL) ||
489 /* Resource create */
490 fd = open(TAP_DEV, O_RDWR | O_NONBLOCK);
494 memset(&ifr, 0, sizeof(ifr));
495 ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
496 strlcpy(ifr.ifr_name, name, IFNAMSIZ);
498 status = ioctl(fd, TUNSETIFF, (void *) &ifr);
504 /* Node allocation */
505 tap = calloc(1, sizeof(struct tap));
511 strlcpy(tap->name, name, sizeof(tap->name));
514 /* Node add to list */
515 TAILQ_INSERT_TAIL(&obj->tap_list, tap, node);
525 #ifndef PIPELINE_MSGQ_SIZE
526 #define PIPELINE_MSGQ_SIZE 64
530 pipeline_create(struct obj *obj, const char *name, int numa_node)
532 struct pipeline *pipeline;
533 struct rte_swx_pipeline *p = NULL;
536 /* Check input params */
537 if ((name == NULL) ||
538 pipeline_find(obj, name))
541 /* Resource create */
542 status = rte_swx_pipeline_config(&p, numa_node);
546 status = rte_swx_pipeline_port_in_type_register(p,
548 &rte_swx_port_ethdev_reader_ops);
552 status = rte_swx_pipeline_port_out_type_register(p,
554 &rte_swx_port_ethdev_writer_ops);
558 status = rte_swx_pipeline_port_in_type_register(p,
560 &rte_swx_port_ring_reader_ops);
564 status = rte_swx_pipeline_port_out_type_register(p,
566 &rte_swx_port_ring_writer_ops);
571 status = rte_swx_pipeline_port_in_type_register(p,
573 &rte_swx_port_source_ops);
578 status = rte_swx_pipeline_port_out_type_register(p,
580 &rte_swx_port_sink_ops);
584 status = rte_swx_pipeline_port_in_type_register(p,
586 &rte_swx_port_fd_reader_ops);
590 status = rte_swx_pipeline_port_out_type_register(p,
592 &rte_swx_port_fd_writer_ops);
596 status = rte_swx_pipeline_table_type_register(p,
598 RTE_SWX_TABLE_MATCH_EXACT,
599 &rte_swx_table_exact_match_ops);
603 status = rte_swx_pipeline_table_type_register(p,
605 RTE_SWX_TABLE_MATCH_WILDCARD,
606 &rte_swx_table_wildcard_match_ops);
610 /* Node allocation */
611 pipeline = calloc(1, sizeof(struct pipeline));
612 if (pipeline == NULL)
616 strlcpy(pipeline->name, name, sizeof(pipeline->name));
618 pipeline->timer_period_ms = 10;
620 /* Node add to list */
621 TAILQ_INSERT_TAIL(&obj->pipeline_list, pipeline, node);
626 rte_swx_pipeline_free(p);
631 pipeline_find(struct obj *obj, const char *name)
633 struct pipeline *pipeline;
638 TAILQ_FOREACH(pipeline, &obj->pipeline_list, node)
639 if (strcmp(name, pipeline->name) == 0)
653 obj = calloc(1, sizeof(struct obj));
657 TAILQ_INIT(&obj->mempool_list);
658 TAILQ_INIT(&obj->link_list);
659 TAILQ_INIT(&obj->ring_list);
660 TAILQ_INIT(&obj->pipeline_list);
661 TAILQ_INIT(&obj->tap_list);