xref: /dpdk/examples/pipeline/obj.c (revision 02d36ef6a9528e0f4a3403956e66bcea5fadbf8c)
1b77f6600SCristian Dumitrescu /* SPDX-License-Identifier: BSD-3-Clause
2b77f6600SCristian Dumitrescu  * Copyright(c) 2020 Intel Corporation
3b77f6600SCristian Dumitrescu  */
4b77f6600SCristian Dumitrescu 
5b77f6600SCristian Dumitrescu #include <stdlib.h>
6b77f6600SCristian Dumitrescu #include <string.h>
7e2b8dc52SVenkata Suresh Kumar P #include <netinet/in.h>
8e2b8dc52SVenkata Suresh Kumar P #ifdef RTE_EXEC_ENV_LINUX
9e2b8dc52SVenkata Suresh Kumar P #include <linux/if.h>
10e2b8dc52SVenkata Suresh Kumar P #include <linux/if_tun.h>
11e2b8dc52SVenkata Suresh Kumar P #endif
12e2b8dc52SVenkata Suresh Kumar P #include <sys/ioctl.h>
13e2b8dc52SVenkata Suresh Kumar P #include <fcntl.h>
14e2b8dc52SVenkata Suresh Kumar P #include <unistd.h>
15b77f6600SCristian Dumitrescu 
16b77f6600SCristian Dumitrescu #include <rte_mbuf.h>
17b77f6600SCristian Dumitrescu #include <rte_ethdev.h>
18b77f6600SCristian Dumitrescu #include <rte_swx_ctl.h>
19b77f6600SCristian Dumitrescu 
20b77f6600SCristian Dumitrescu #include "obj.h"
21b77f6600SCristian Dumitrescu 
22b77f6600SCristian Dumitrescu /*
23b77f6600SCristian Dumitrescu  * link
24b77f6600SCristian Dumitrescu  */
25b77f6600SCristian Dumitrescu TAILQ_HEAD(link_list, link);
26b77f6600SCristian Dumitrescu 
27b77f6600SCristian Dumitrescu /*
2877a41301SCristian Dumitrescu  * ring
2977a41301SCristian Dumitrescu  */
3077a41301SCristian Dumitrescu TAILQ_HEAD(ring_list, ring);
3177a41301SCristian Dumitrescu 
3277a41301SCristian Dumitrescu /*
33b77f6600SCristian Dumitrescu  * obj
34b77f6600SCristian Dumitrescu  */
35b77f6600SCristian Dumitrescu struct obj {
36b77f6600SCristian Dumitrescu 	struct link_list link_list;
3777a41301SCristian Dumitrescu 	struct ring_list ring_list;
38b77f6600SCristian Dumitrescu };
39b77f6600SCristian Dumitrescu 
40b77f6600SCristian Dumitrescu /*
41b77f6600SCristian Dumitrescu  * link
42b77f6600SCristian Dumitrescu  */
43b77f6600SCristian Dumitrescu static struct rte_eth_conf port_conf_default = {
44b77f6600SCristian Dumitrescu 	.link_speeds = 0,
45b77f6600SCristian Dumitrescu 	.rxmode = {
46295968d1SFerruh Yigit 		.mq_mode = RTE_ETH_MQ_RX_NONE,
471bb4a528SFerruh Yigit 		.mtu = 9000 - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN), /* Jumbo frame MTU */
48b77f6600SCristian Dumitrescu 	},
49b77f6600SCristian Dumitrescu 	.rx_adv_conf = {
50b77f6600SCristian Dumitrescu 		.rss_conf = {
51b77f6600SCristian Dumitrescu 			.rss_key = NULL,
52b77f6600SCristian Dumitrescu 			.rss_key_len = 40,
53b77f6600SCristian Dumitrescu 			.rss_hf = 0,
54b77f6600SCristian Dumitrescu 		},
55b77f6600SCristian Dumitrescu 	},
56b77f6600SCristian Dumitrescu 	.txmode = {
57295968d1SFerruh Yigit 		.mq_mode = RTE_ETH_MQ_TX_NONE,
58b77f6600SCristian Dumitrescu 	},
59b77f6600SCristian Dumitrescu 	.lpbk_mode = 0,
60b77f6600SCristian Dumitrescu };
61b77f6600SCristian Dumitrescu 
62295968d1SFerruh Yigit #define RETA_CONF_SIZE     (RTE_ETH_RSS_RETA_SIZE_512 / RTE_ETH_RETA_GROUP_SIZE)
63b77f6600SCristian Dumitrescu 
64b77f6600SCristian Dumitrescu static int
65b77f6600SCristian Dumitrescu rss_setup(uint16_t port_id,
66b77f6600SCristian Dumitrescu 	uint16_t reta_size,
67b77f6600SCristian Dumitrescu 	struct link_params_rss *rss)
68b77f6600SCristian Dumitrescu {
69b77f6600SCristian Dumitrescu 	struct rte_eth_rss_reta_entry64 reta_conf[RETA_CONF_SIZE];
70b77f6600SCristian Dumitrescu 	uint32_t i;
71b77f6600SCristian Dumitrescu 	int status;
72b77f6600SCristian Dumitrescu 
73b77f6600SCristian Dumitrescu 	/* RETA setting */
74b77f6600SCristian Dumitrescu 	memset(reta_conf, 0, sizeof(reta_conf));
75b77f6600SCristian Dumitrescu 
76b77f6600SCristian Dumitrescu 	for (i = 0; i < reta_size; i++)
77295968d1SFerruh Yigit 		reta_conf[i / RTE_ETH_RETA_GROUP_SIZE].mask = UINT64_MAX;
78b77f6600SCristian Dumitrescu 
79b77f6600SCristian Dumitrescu 	for (i = 0; i < reta_size; i++) {
80295968d1SFerruh Yigit 		uint32_t reta_id = i / RTE_ETH_RETA_GROUP_SIZE;
81295968d1SFerruh Yigit 		uint32_t reta_pos = i % RTE_ETH_RETA_GROUP_SIZE;
82b77f6600SCristian Dumitrescu 		uint32_t rss_qs_pos = i % rss->n_queues;
83b77f6600SCristian Dumitrescu 
84b77f6600SCristian Dumitrescu 		reta_conf[reta_id].reta[reta_pos] =
85b77f6600SCristian Dumitrescu 			(uint16_t) rss->queue_id[rss_qs_pos];
86b77f6600SCristian Dumitrescu 	}
87b77f6600SCristian Dumitrescu 
88b77f6600SCristian Dumitrescu 	/* RETA update */
89b77f6600SCristian Dumitrescu 	status = rte_eth_dev_rss_reta_update(port_id,
90b77f6600SCristian Dumitrescu 		reta_conf,
91b77f6600SCristian Dumitrescu 		reta_size);
92b77f6600SCristian Dumitrescu 
93b77f6600SCristian Dumitrescu 	return status;
94b77f6600SCristian Dumitrescu }
95b77f6600SCristian Dumitrescu 
96b77f6600SCristian Dumitrescu struct link *
97b77f6600SCristian Dumitrescu link_create(struct obj *obj, const char *name, struct link_params *params)
98b77f6600SCristian Dumitrescu {
99b77f6600SCristian Dumitrescu 	struct rte_eth_dev_info port_info;
100b77f6600SCristian Dumitrescu 	struct rte_eth_conf port_conf;
101b77f6600SCristian Dumitrescu 	struct link *link;
102b77f6600SCristian Dumitrescu 	struct link_params_rss *rss;
103*02d36ef6SCristian Dumitrescu 	struct rte_mempool *mempool;
104b77f6600SCristian Dumitrescu 	uint32_t cpu_id, i;
105b77f6600SCristian Dumitrescu 	int status;
106f31c80f8SCristian Dumitrescu 	uint16_t port_id = 0;
107b77f6600SCristian Dumitrescu 
108b77f6600SCristian Dumitrescu 	/* Check input params */
109b77f6600SCristian Dumitrescu 	if ((name == NULL) ||
110b77f6600SCristian Dumitrescu 		link_find(obj, name) ||
111b77f6600SCristian Dumitrescu 		(params == NULL) ||
112b77f6600SCristian Dumitrescu 		(params->rx.n_queues == 0) ||
113b77f6600SCristian Dumitrescu 		(params->rx.queue_size == 0) ||
114b77f6600SCristian Dumitrescu 		(params->tx.n_queues == 0) ||
115b77f6600SCristian Dumitrescu 		(params->tx.queue_size == 0))
116b77f6600SCristian Dumitrescu 		return NULL;
117b77f6600SCristian Dumitrescu 
118f31c80f8SCristian Dumitrescu 	status = rte_eth_dev_get_port_by_name(name, &port_id);
119b77f6600SCristian Dumitrescu 	if (status)
120b77f6600SCristian Dumitrescu 		return NULL;
121b77f6600SCristian Dumitrescu 
122b77f6600SCristian Dumitrescu 	if (rte_eth_dev_info_get(port_id, &port_info) != 0)
123b77f6600SCristian Dumitrescu 		return NULL;
124b77f6600SCristian Dumitrescu 
125*02d36ef6SCristian Dumitrescu 	mempool = rte_mempool_lookup(params->rx.mempool_name);
126*02d36ef6SCristian Dumitrescu 	if (!mempool)
127b77f6600SCristian Dumitrescu 		return NULL;
128b77f6600SCristian Dumitrescu 
129b77f6600SCristian Dumitrescu 	rss = params->rx.rss;
130b77f6600SCristian Dumitrescu 	if (rss) {
131b77f6600SCristian Dumitrescu 		if ((port_info.reta_size == 0) ||
132295968d1SFerruh Yigit 			(port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512))
133b77f6600SCristian Dumitrescu 			return NULL;
134b77f6600SCristian Dumitrescu 
135b77f6600SCristian Dumitrescu 		if ((rss->n_queues == 0) ||
136b77f6600SCristian Dumitrescu 			(rss->n_queues >= LINK_RXQ_RSS_MAX))
137b77f6600SCristian Dumitrescu 			return NULL;
138b77f6600SCristian Dumitrescu 
139b77f6600SCristian Dumitrescu 		for (i = 0; i < rss->n_queues; i++)
140b77f6600SCristian Dumitrescu 			if (rss->queue_id[i] >= port_info.max_rx_queues)
141b77f6600SCristian Dumitrescu 				return NULL;
142b77f6600SCristian Dumitrescu 	}
143b77f6600SCristian Dumitrescu 
144b77f6600SCristian Dumitrescu 	/**
145b77f6600SCristian Dumitrescu 	 * Resource create
146b77f6600SCristian Dumitrescu 	 */
147b77f6600SCristian Dumitrescu 	/* Port */
148b77f6600SCristian Dumitrescu 	memcpy(&port_conf, &port_conf_default, sizeof(port_conf));
149b77f6600SCristian Dumitrescu 	if (rss) {
150295968d1SFerruh Yigit 		port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;
151b77f6600SCristian Dumitrescu 		port_conf.rx_adv_conf.rss_conf.rss_hf =
152295968d1SFerruh Yigit 			(RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP) &
153b77f6600SCristian Dumitrescu 			port_info.flow_type_rss_offloads;
154b77f6600SCristian Dumitrescu 	}
155b77f6600SCristian Dumitrescu 
156b77f6600SCristian Dumitrescu 	cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id);
157b77f6600SCristian Dumitrescu 	if (cpu_id == (uint32_t) SOCKET_ID_ANY)
158b77f6600SCristian Dumitrescu 		cpu_id = 0;
159b77f6600SCristian Dumitrescu 
160b77f6600SCristian Dumitrescu 	status = rte_eth_dev_configure(
161b77f6600SCristian Dumitrescu 		port_id,
162b77f6600SCristian Dumitrescu 		params->rx.n_queues,
163b77f6600SCristian Dumitrescu 		params->tx.n_queues,
164b77f6600SCristian Dumitrescu 		&port_conf);
165b77f6600SCristian Dumitrescu 
166b77f6600SCristian Dumitrescu 	if (status < 0)
167b77f6600SCristian Dumitrescu 		return NULL;
168b77f6600SCristian Dumitrescu 
169b77f6600SCristian Dumitrescu 	if (params->promiscuous) {
170b77f6600SCristian Dumitrescu 		status = rte_eth_promiscuous_enable(port_id);
171b77f6600SCristian Dumitrescu 		if (status != 0)
172b77f6600SCristian Dumitrescu 			return NULL;
173b77f6600SCristian Dumitrescu 	}
174b77f6600SCristian Dumitrescu 
175b77f6600SCristian Dumitrescu 	/* Port RX */
176b77f6600SCristian Dumitrescu 	for (i = 0; i < params->rx.n_queues; i++) {
177b77f6600SCristian Dumitrescu 		status = rte_eth_rx_queue_setup(
178b77f6600SCristian Dumitrescu 			port_id,
179b77f6600SCristian Dumitrescu 			i,
180b77f6600SCristian Dumitrescu 			params->rx.queue_size,
181b77f6600SCristian Dumitrescu 			cpu_id,
182b77f6600SCristian Dumitrescu 			NULL,
183*02d36ef6SCristian Dumitrescu 			mempool);
184b77f6600SCristian Dumitrescu 
185b77f6600SCristian Dumitrescu 		if (status < 0)
186b77f6600SCristian Dumitrescu 			return NULL;
187b77f6600SCristian Dumitrescu 	}
188b77f6600SCristian Dumitrescu 
189b77f6600SCristian Dumitrescu 	/* Port TX */
190b77f6600SCristian Dumitrescu 	for (i = 0; i < params->tx.n_queues; i++) {
191b77f6600SCristian Dumitrescu 		status = rte_eth_tx_queue_setup(
192b77f6600SCristian Dumitrescu 			port_id,
193b77f6600SCristian Dumitrescu 			i,
194b77f6600SCristian Dumitrescu 			params->tx.queue_size,
195b77f6600SCristian Dumitrescu 			cpu_id,
196b77f6600SCristian Dumitrescu 			NULL);
197b77f6600SCristian Dumitrescu 
198b77f6600SCristian Dumitrescu 		if (status < 0)
199b77f6600SCristian Dumitrescu 			return NULL;
200b77f6600SCristian Dumitrescu 	}
201b77f6600SCristian Dumitrescu 
202b77f6600SCristian Dumitrescu 	/* Port start */
203b77f6600SCristian Dumitrescu 	status = rte_eth_dev_start(port_id);
204b77f6600SCristian Dumitrescu 	if (status < 0)
205b77f6600SCristian Dumitrescu 		return NULL;
206b77f6600SCristian Dumitrescu 
207b77f6600SCristian Dumitrescu 	if (rss) {
208b77f6600SCristian Dumitrescu 		status = rss_setup(port_id, port_info.reta_size, rss);
209b77f6600SCristian Dumitrescu 
210b77f6600SCristian Dumitrescu 		if (status) {
211b77f6600SCristian Dumitrescu 			rte_eth_dev_stop(port_id);
212b77f6600SCristian Dumitrescu 			return NULL;
213b77f6600SCristian Dumitrescu 		}
214b77f6600SCristian Dumitrescu 	}
215b77f6600SCristian Dumitrescu 
216b77f6600SCristian Dumitrescu 	/* Port link up */
217b77f6600SCristian Dumitrescu 	status = rte_eth_dev_set_link_up(port_id);
218b77f6600SCristian Dumitrescu 	if ((status < 0) && (status != -ENOTSUP)) {
219b77f6600SCristian Dumitrescu 		rte_eth_dev_stop(port_id);
220b77f6600SCristian Dumitrescu 		return NULL;
221b77f6600SCristian Dumitrescu 	}
222b77f6600SCristian Dumitrescu 
223b77f6600SCristian Dumitrescu 	/* Node allocation */
224b77f6600SCristian Dumitrescu 	link = calloc(1, sizeof(struct link));
225b77f6600SCristian Dumitrescu 	if (link == NULL) {
226b77f6600SCristian Dumitrescu 		rte_eth_dev_stop(port_id);
227b77f6600SCristian Dumitrescu 		return NULL;
228b77f6600SCristian Dumitrescu 	}
229b77f6600SCristian Dumitrescu 
230b77f6600SCristian Dumitrescu 	/* Node fill in */
231b77f6600SCristian Dumitrescu 	strlcpy(link->name, name, sizeof(link->name));
232b77f6600SCristian Dumitrescu 	link->port_id = port_id;
233b77f6600SCristian Dumitrescu 	link->n_rxq = params->rx.n_queues;
234b77f6600SCristian Dumitrescu 	link->n_txq = params->tx.n_queues;
235b77f6600SCristian Dumitrescu 
236b77f6600SCristian Dumitrescu 	/* Node add to list */
237b77f6600SCristian Dumitrescu 	TAILQ_INSERT_TAIL(&obj->link_list, link, node);
238b77f6600SCristian Dumitrescu 
239b77f6600SCristian Dumitrescu 	return link;
240b77f6600SCristian Dumitrescu }
241b77f6600SCristian Dumitrescu 
242b77f6600SCristian Dumitrescu int
243b77f6600SCristian Dumitrescu link_is_up(struct obj *obj, const char *name)
244b77f6600SCristian Dumitrescu {
245b77f6600SCristian Dumitrescu 	struct rte_eth_link link_params;
246b77f6600SCristian Dumitrescu 	struct link *link;
247b77f6600SCristian Dumitrescu 
248b77f6600SCristian Dumitrescu 	/* Check input params */
249b77f6600SCristian Dumitrescu 	if (!obj || !name)
250b77f6600SCristian Dumitrescu 		return 0;
251b77f6600SCristian Dumitrescu 
252b77f6600SCristian Dumitrescu 	link = link_find(obj, name);
253b77f6600SCristian Dumitrescu 	if (link == NULL)
254b77f6600SCristian Dumitrescu 		return 0;
255b77f6600SCristian Dumitrescu 
256b77f6600SCristian Dumitrescu 	/* Resource */
257b77f6600SCristian Dumitrescu 	if (rte_eth_link_get(link->port_id, &link_params) < 0)
258b77f6600SCristian Dumitrescu 		return 0;
259b77f6600SCristian Dumitrescu 
260295968d1SFerruh Yigit 	return (link_params.link_status == RTE_ETH_LINK_DOWN) ? 0 : 1;
261b77f6600SCristian Dumitrescu }
262b77f6600SCristian Dumitrescu 
263b77f6600SCristian Dumitrescu struct link *
264b77f6600SCristian Dumitrescu link_find(struct obj *obj, const char *name)
265b77f6600SCristian Dumitrescu {
266b77f6600SCristian Dumitrescu 	struct link *link;
267b77f6600SCristian Dumitrescu 
268b77f6600SCristian Dumitrescu 	if (!obj || !name)
269b77f6600SCristian Dumitrescu 		return NULL;
270b77f6600SCristian Dumitrescu 
271b77f6600SCristian Dumitrescu 	TAILQ_FOREACH(link, &obj->link_list, node)
272b77f6600SCristian Dumitrescu 		if (strcmp(link->name, name) == 0)
273b77f6600SCristian Dumitrescu 			return link;
274b77f6600SCristian Dumitrescu 
275b77f6600SCristian Dumitrescu 	return NULL;
276b77f6600SCristian Dumitrescu }
277b77f6600SCristian Dumitrescu 
278b77f6600SCristian Dumitrescu struct link *
279b77f6600SCristian Dumitrescu link_next(struct obj *obj, struct link *link)
280b77f6600SCristian Dumitrescu {
281b77f6600SCristian Dumitrescu 	return (link == NULL) ?
282b77f6600SCristian Dumitrescu 		TAILQ_FIRST(&obj->link_list) : TAILQ_NEXT(link, node);
283b77f6600SCristian Dumitrescu }
284b77f6600SCristian Dumitrescu 
285b77f6600SCristian Dumitrescu /*
28677a41301SCristian Dumitrescu  * ring
28777a41301SCristian Dumitrescu  */
28877a41301SCristian Dumitrescu struct ring *
28977a41301SCristian Dumitrescu ring_create(struct obj *obj, const char *name, struct ring_params *params)
29077a41301SCristian Dumitrescu {
29177a41301SCristian Dumitrescu 	struct ring *ring;
29277a41301SCristian Dumitrescu 	struct rte_ring *r;
29377a41301SCristian Dumitrescu 	unsigned int flags = RING_F_SP_ENQ | RING_F_SC_DEQ;
29477a41301SCristian Dumitrescu 
29577a41301SCristian Dumitrescu 	/* Check input params */
29677a41301SCristian Dumitrescu 	if (!name || ring_find(obj, name) || !params || !params->size)
29777a41301SCristian Dumitrescu 		return NULL;
29877a41301SCristian Dumitrescu 
29977a41301SCristian Dumitrescu 	/**
30077a41301SCristian Dumitrescu 	 * Resource create
30177a41301SCristian Dumitrescu 	 */
30277a41301SCristian Dumitrescu 	r = rte_ring_create(
30377a41301SCristian Dumitrescu 		name,
30477a41301SCristian Dumitrescu 		params->size,
30577a41301SCristian Dumitrescu 		params->numa_node,
30677a41301SCristian Dumitrescu 		flags);
30777a41301SCristian Dumitrescu 	if (!r)
30877a41301SCristian Dumitrescu 		return NULL;
30977a41301SCristian Dumitrescu 
31077a41301SCristian Dumitrescu 	/* Node allocation */
31177a41301SCristian Dumitrescu 	ring = calloc(1, sizeof(struct ring));
31277a41301SCristian Dumitrescu 	if (!ring) {
31377a41301SCristian Dumitrescu 		rte_ring_free(r);
31477a41301SCristian Dumitrescu 		return NULL;
31577a41301SCristian Dumitrescu 	}
31677a41301SCristian Dumitrescu 
31777a41301SCristian Dumitrescu 	/* Node fill in */
31877a41301SCristian Dumitrescu 	strlcpy(ring->name, name, sizeof(ring->name));
31977a41301SCristian Dumitrescu 
32077a41301SCristian Dumitrescu 	/* Node add to list */
32177a41301SCristian Dumitrescu 	TAILQ_INSERT_TAIL(&obj->ring_list, ring, node);
32277a41301SCristian Dumitrescu 
32377a41301SCristian Dumitrescu 	return ring;
32477a41301SCristian Dumitrescu }
32577a41301SCristian Dumitrescu 
32677a41301SCristian Dumitrescu struct ring *
32777a41301SCristian Dumitrescu ring_find(struct obj *obj, const char *name)
32877a41301SCristian Dumitrescu {
32977a41301SCristian Dumitrescu 	struct ring *ring;
33077a41301SCristian Dumitrescu 
33177a41301SCristian Dumitrescu 	if (!obj || !name)
33277a41301SCristian Dumitrescu 		return NULL;
33377a41301SCristian Dumitrescu 
33477a41301SCristian Dumitrescu 	TAILQ_FOREACH(ring, &obj->ring_list, node)
33577a41301SCristian Dumitrescu 		if (strcmp(ring->name, name) == 0)
33677a41301SCristian Dumitrescu 			return ring;
33777a41301SCristian Dumitrescu 
33877a41301SCristian Dumitrescu 	return NULL;
33977a41301SCristian Dumitrescu }
34077a41301SCristian Dumitrescu 
34177a41301SCristian Dumitrescu /*
342b77f6600SCristian Dumitrescu  * obj
343b77f6600SCristian Dumitrescu  */
344b77f6600SCristian Dumitrescu struct obj *
345b77f6600SCristian Dumitrescu obj_init(void)
346b77f6600SCristian Dumitrescu {
347b77f6600SCristian Dumitrescu 	struct obj *obj;
348b77f6600SCristian Dumitrescu 
349b77f6600SCristian Dumitrescu 	obj = calloc(1, sizeof(struct obj));
350b77f6600SCristian Dumitrescu 	if (!obj)
351b77f6600SCristian Dumitrescu 		return NULL;
352b77f6600SCristian Dumitrescu 
353b77f6600SCristian Dumitrescu 	TAILQ_INIT(&obj->link_list);
35477a41301SCristian Dumitrescu 	TAILQ_INIT(&obj->ring_list);
355b77f6600SCristian Dumitrescu 
356b77f6600SCristian Dumitrescu 	return obj;
357b77f6600SCristian Dumitrescu }
358