O-RAN E Maintenance Release contribution for ODULOW
[o-du/phy.git] / fhi_lib / lib / ethernet / ethernet.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 /**
20  * @brief This file has all definitions for the Ethernet Data Interface Layer
21  * @file ethernet.c
22  * @ingroup group_lte_source_auxlib
23  * @author Intel Corporation
24  **/
25
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdint.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <sys/queue.h>
33 #include <err.h>
34 #include <assert.h>
35
36 #include <linux/limits.h>
37 #include <sys/types.h>
38 #include <stdlib.h>
39 #include <math.h>
40 #include <immintrin.h>
41 #include <rte_config.h>
42 #include <rte_common.h>
43 #include <rte_log.h>
44 #include <rte_memory.h>
45 #include <rte_memzone.h>
46 #include <rte_eal.h>
47 #include <rte_per_lcore.h>
48 #include <rte_launch.h>
49 #include <rte_atomic.h>
50 #include <rte_cycles.h>
51 #include <rte_prefetch.h>
52 #include <rte_lcore.h>
53 #include <rte_per_lcore.h>
54 #include <rte_branch_prediction.h>
55 #include <rte_interrupts.h>
56 #include <rte_pci.h>
57 #include <rte_debug.h>
58 #include <rte_ether.h>
59 #include <rte_ethdev.h>
60 #include <rte_ring.h>
61 #include <rte_mempool.h>
62 #include <rte_mbuf.h>
63 #include <rte_errno.h>
64
65 #include "ethernet.h"
66 #include "ethdi.h"
67
68 /* mbuf pools */
69 struct rte_mempool *_eth_mbuf_pool          = NULL;
70 struct rte_mempool *_eth_mbuf_pool_indirect = NULL;
71 struct rte_mempool *_eth_mbuf_pool_rx     = NULL;
72 struct rte_mempool *_eth_mbuf_pkt_gen       = NULL;
73
74 struct rte_mempool *socket_direct_pool    = NULL;
75 struct rte_mempool *socket_indirect_pool  = NULL;
76
77 struct rte_mempool *_eth_mbuf_pool_vf_rx[16][RTE_MAX_QUEUES_PER_PORT] = {NULL};
78 struct rte_mempool *_eth_mbuf_pool_vf_small[16]    = {NULL};
79
80 void
81 xran_init_mbuf_pool(uint32_t mtu)
82 {
83     uint16_t data_room_size = MBUF_POOL_ELEMENT;
84     printf("%s: socket %d\n",__FUNCTION__, rte_socket_id());
85
86     if (mtu <= 1500) {
87         data_room_size = MBUF_POOL_ELM_SMALL;
88 }
89
90     /* Init the buffer pool */
91     if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
92         _eth_mbuf_pool = rte_pktmbuf_pool_create("mempool", NUM_MBUFS,
93                 MBUF_CACHE, 0, data_room_size, rte_socket_id());
94         _eth_mbuf_pool_indirect = rte_pktmbuf_pool_create("mempool_indirect", NUM_MBUFS_VF,
95                 MBUF_CACHE, 0, 0, rte_socket_id());
96         _eth_mbuf_pkt_gen = rte_pktmbuf_pool_create("mempool_pkt_gen",
97                 NUM_MBUFS, MBUF_CACHE, 0, MBUF_POOL_PKT_GEN_ELM, rte_socket_id());
98     } else {
99         _eth_mbuf_pool = rte_mempool_lookup("mempool");
100         _eth_mbuf_pool_indirect = rte_mempool_lookup("mempool_indirect");
101         _eth_mbuf_pkt_gen = rte_mempool_lookup("mempool_pkt_gen");
102     }
103
104     if (_eth_mbuf_pool == NULL)
105         rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
106     if (_eth_mbuf_pool_indirect == NULL)
107         rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
108     if (_eth_mbuf_pkt_gen == NULL)
109         rte_panic("Cannot create packet gen pool: %s\n", rte_strerror(rte_errno));
110
111     if (socket_direct_pool == NULL)
112         socket_direct_pool = _eth_mbuf_pool;
113
114     if (socket_indirect_pool == NULL)
115         socket_indirect_pool = _eth_mbuf_pool_indirect;
116 }
117
118 /* Configure the Rx with optional split. */
119 int
120 rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
121            uint16_t nb_rx_desc, unsigned int socket_id,
122            struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp)
123 {
124     unsigned int i, mp_n;
125     int ret;
126 #ifndef RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT
127 #define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000
128 #endif
129     if ((rx_conf->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) == 0) {
130 #if (RTE_VER_YEAR >= 21)
131         rx_conf->rx_seg = NULL;
132         rx_conf->rx_nseg = 0;
133 #endif
134         ret = rte_eth_rx_queue_setup(port_id, rx_queue_id,
135                          nb_rx_desc, socket_id,
136                          rx_conf, mp);
137         return ret;
138
139     } else {
140         printf("rx_queue_setup error\n");
141         ret = -EINVAL;
142         return ret;
143     }
144 }
145
146 /* Init NIC port, then start the port */
147 void xran_init_port(int p_id, uint16_t num_rxq, uint32_t mtu)
148 {
149     static uint16_t nb_rxd = BURST_SIZE;
150     static uint16_t nb_txd = BURST_SIZE;
151     struct rte_ether_addr addr;
152     struct rte_eth_rxmode rxmode = {
153             .split_hdr_size = 0,
154               .max_rx_pkt_len = MAX_RX_LEN,
155             .offloads       = DEV_RX_OFFLOAD_JUMBO_FRAME
156             };
157     struct rte_eth_txmode txmode = {
158             .mq_mode        = ETH_MQ_TX_NONE,
159             .offloads       = DEV_TX_OFFLOAD_MULTI_SEGS
160             };
161     struct rte_eth_conf port_conf = {
162             .rxmode = rxmode,
163             .txmode = txmode
164             };
165     struct rte_eth_rxconf rxq_conf;
166     struct rte_eth_txconf txq_conf;
167
168     int ret;
169     struct rte_eth_dev_info dev_info;
170     const char *drv_name = "";
171     int sock_id = rte_eth_dev_socket_id(p_id);
172     char rx_pool_name[32]    = "";
173     uint16_t data_room_size = MBUF_POOL_ELEMENT;
174     uint16_t qi = 0;
175     uint32_t num_mbufs = 0;
176
177     if (mtu <= 1500) {
178         rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
179         rxmode.max_rx_pkt_len = RTE_ETHER_MAX_LEN;
180         data_room_size = MBUF_POOL_ELM_SMALL;
181     }
182
183     rte_eth_dev_info_get(p_id, &dev_info);
184     if (dev_info.driver_name)
185         drv_name = dev_info.driver_name;
186     printf("initializing port %d for TX, drv=%s\n", p_id, drv_name);
187
188     if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE){
189         printf("set DEV_TX_OFFLOAD_MBUF_FAST_FREE\n");
190         port_conf.txmode.offloads |=
191             DEV_TX_OFFLOAD_MBUF_FAST_FREE;
192     }
193
194     rte_eth_macaddr_get(p_id, &addr);
195
196     printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
197         " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
198         (unsigned)p_id,
199         addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2],
200         addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]);
201
202     if(num_rxq > 1) {
203         nb_rxd    = 2048;
204         num_mbufs = 2*nb_rxd-1;
205     } else {
206         nb_rxd    = BURST_SIZE;
207         num_mbufs = NUM_MBUFS;
208     }
209
210     /* Init port */
211     ret = rte_eth_dev_configure(p_id, num_rxq, 1, &port_conf);
212     if (ret < 0)
213         rte_panic("Cannot configure port %u (%d)\n", p_id, ret);
214
215     ret = rte_eth_dev_adjust_nb_rx_tx_desc(p_id, &nb_rxd,&nb_txd);
216
217     if (ret < 0) {
218         printf("\n");
219         rte_exit(EXIT_FAILURE, "Cannot adjust number of "
220             "descriptors: err=%d, port=%d\n", ret, p_id);
221     }
222     printf("Port %u: nb_rxd %d nb_txd %d\n", p_id, nb_rxd, nb_txd);
223
224     for (qi = 0; qi < num_rxq; qi++) {
225         snprintf(rx_pool_name, RTE_DIM(rx_pool_name), "%s_p_%d_q_%d", "mp_rx_", p_id, qi);
226         printf("[%d] %s num blocks %d\n", p_id, rx_pool_name, num_mbufs);
227         _eth_mbuf_pool_vf_rx[p_id][qi] = rte_pktmbuf_pool_create(rx_pool_name, num_mbufs,
228                     MBUF_CACHE, 0, data_room_size, rte_socket_id());
229
230         if (_eth_mbuf_pool_vf_rx[p_id][qi] == NULL)
231             rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
232     }
233
234     snprintf(rx_pool_name, RTE_DIM(rx_pool_name), "%s_%d", "mempool_small_", p_id);
235     printf("[%d] %s\n", p_id, rx_pool_name);
236     _eth_mbuf_pool_vf_small[p_id] = rte_pktmbuf_pool_create(rx_pool_name, NUM_MBUFS_VF,
237                 MBUF_CACHE, 0, MBUF_POOL_ELM_SMALL_INDIRECT, rte_socket_id());
238
239     if (_eth_mbuf_pool_vf_small[p_id] == NULL)
240         rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
241
242     /* Init RX queues */
243     fflush(stdout);
244     rxq_conf = dev_info.default_rxconf;
245
246     for (qi = 0; qi < num_rxq; qi++) {
247         ret = rx_queue_setup(p_id, qi, nb_rxd,
248                 sock_id, &rxq_conf, _eth_mbuf_pool_vf_rx[p_id][qi]);
249     }
250
251     if (ret < 0)
252         rte_panic("Cannot init RX for port %u (%d)\n",
253             p_id, ret);
254
255     /* Init TX queues */
256     fflush(stdout);
257     txq_conf = dev_info.default_txconf;
258
259     ret = rte_eth_tx_queue_setup(p_id, 0, nb_txd, sock_id, &txq_conf);
260     if (ret < 0)
261         rte_panic("Cannot init TX for port %u (%d)\n",
262                 p_id, ret);
263
264     ret = rte_eth_dev_set_ptypes(p_id, RTE_PTYPE_UNKNOWN, NULL, 0);
265     if (ret < 0)
266         rte_panic("Port %d: Failed to disable Ptype parsing\n", p_id);
267
268     /* Start port */
269     ret = rte_eth_dev_start(p_id);
270     if (ret < 0)
271         rte_panic("Cannot start port %u (%d)\n", p_id, ret);
272 }
273
274 void xran_init_port_mempool(int p_id, uint32_t mtu)
275 {
276     int ret;
277     int sock_id = rte_eth_dev_socket_id(p_id);
278     char rx_pool_name[32]    = "";
279     uint16_t data_room_size = MBUF_POOL_ELEMENT;
280
281     if (mtu <= 1500) {
282         data_room_size = MBUF_POOL_ELM_SMALL;
283 }
284
285     snprintf(rx_pool_name, RTE_DIM(rx_pool_name), "%s_%d", "mempool_small_", p_id);
286     printf("[%d] %s\n", p_id, rx_pool_name);
287     _eth_mbuf_pool_vf_small[p_id] = rte_pktmbuf_pool_create(rx_pool_name, NUM_MBUFS_VF,
288                 MBUF_CACHE, 0, MBUF_POOL_ELM_SMALL, rte_socket_id());
289
290     if (_eth_mbuf_pool_vf_small[p_id] == NULL)
291         rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
292
293
294 }
295
296 /* Prepend ethernet header, possibly vlan tag. */
297 void xran_add_eth_hdr_vlan(struct rte_ether_addr *dst, uint16_t ethertype, struct rte_mbuf *mb)
298 {
299     /* add in the ethernet header */
300     struct rte_ether_hdr *h = (struct rte_ether_hdr *)rte_pktmbuf_mtod(mb, struct rte_ether_hdr*);
301
302     PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed");
303
304     /* Fill in the ethernet header. */
305     rte_eth_macaddr_get(mb->port, &h->s_addr);          /* set source addr */
306     h->d_addr = *dst;                                   /* set dst addr */
307     h->ether_type = rte_cpu_to_be_16(ethertype);        /* ethertype too */
308
309 #if defined(DPDKIO_DEBUG) && DPDKIO_DEBUG > 1
310     {
311         char dst[RTE_ETHER_ADDR_FMT_SIZE] = "(empty)";
312         char src[RTE_ETHER_ADDR_FMT_SIZE] = "(empty)";
313
314         printf("*** packet for TX below (len %d) ***", rte_pktmbuf_pkt_len(mb));
315         rte_ether_format_addr(src, sizeof(src), &h->s_addr);
316         rte_ether_format_addr(dst, sizeof(dst), &h->d_addr);
317         printf("src: %s dst: %s ethertype: %.4X", src, dst, ethertype);
318     }
319 #endif
320 }
321
322