* INTC Contribution to the O-RAN F Release for O-DU Low
[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] = {};
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     int ret;
125 #ifndef RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT
126 #define RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT 0x00100000
127 #endif
128     if ((rx_conf->offloads & RTE_ETH_RX_OFFLOAD_BUFFER_SPLIT) == 0) {
129 #if (RTE_VER_YEAR >= 21)
130         rx_conf->rx_seg = NULL;
131         rx_conf->rx_nseg = 0;
132 #endif
133         ret = rte_eth_rx_queue_setup(port_id, rx_queue_id,
134                          nb_rx_desc, socket_id,
135                          rx_conf, mp);
136         return ret;
137
138     } else {
139         printf("rx_queue_setup error\n");
140         ret = -EINVAL;
141         return ret;
142     }
143 }
144
145 /* Init NIC port, then start the port */
146 void xran_init_port(int p_id, uint16_t num_rxq, uint32_t mtu)
147 {
148     static uint16_t nb_rxd = BURST_SIZE;
149     static uint16_t nb_txd = BURST_SIZE;
150     struct rte_ether_addr addr;
151     struct rte_eth_rxmode rxmode = {
152             .split_hdr_size = 0,
153               .max_rx_pkt_len = MAX_RX_LEN,
154             .offloads       = DEV_RX_OFFLOAD_JUMBO_FRAME
155             };
156     struct rte_eth_txmode txmode = {
157             .mq_mode        = ETH_MQ_TX_NONE,
158             .offloads       = DEV_TX_OFFLOAD_MULTI_SEGS
159             };
160     struct rte_eth_conf port_conf = {
161             .rxmode = rxmode,
162             .txmode = txmode
163             };
164     struct rte_eth_rxconf rxq_conf;
165     struct rte_eth_txconf txq_conf;
166
167     int ret;
168     struct rte_eth_dev_info dev_info;
169     const char *drv_name = "";
170     int sock_id = rte_eth_dev_socket_id(p_id);
171     char rx_pool_name[32]    = "";
172     uint16_t data_room_size = MBUF_POOL_ELEMENT;
173     uint16_t qi = 0;
174     uint32_t num_mbufs = 0;
175
176     if (mtu <= 1500) {
177         rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
178         rxmode.max_rx_pkt_len = RTE_ETHER_MAX_LEN;
179         data_room_size = MBUF_POOL_ELM_SMALL;
180     }
181
182     rte_eth_dev_info_get(p_id, &dev_info);
183     if (dev_info.driver_name)
184         drv_name = dev_info.driver_name;
185     printf("initializing port %d for TX, drv=%s\n", p_id, drv_name);
186
187     if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE){
188         printf("set DEV_TX_OFFLOAD_MBUF_FAST_FREE\n");
189         port_conf.txmode.offloads |=
190             DEV_TX_OFFLOAD_MBUF_FAST_FREE;
191     }
192
193     rte_eth_macaddr_get(p_id, &addr);
194
195     printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
196         " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
197         (unsigned)p_id,
198         addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2],
199         addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]);
200
201     if(num_rxq > 1) {
202         nb_rxd    = 2048;
203         num_mbufs = 2*nb_rxd-1;
204     } else {
205         nb_rxd    = BURST_SIZE;
206         num_mbufs = NUM_MBUFS;
207     }
208
209     /* Init port */
210     ret = rte_eth_dev_configure(p_id, num_rxq, 1, &port_conf);
211     if (ret < 0)
212         rte_panic("Cannot configure port %u (%d)\n", p_id, ret);
213
214     ret = rte_eth_dev_adjust_nb_rx_tx_desc(p_id, &nb_rxd,&nb_txd);
215
216     if (ret < 0) {
217         printf("\n");
218         rte_exit(EXIT_FAILURE, "Cannot adjust number of "
219             "descriptors: err=%d, port=%d\n", ret, p_id);
220     }
221     printf("Port %u: nb_rxd %d nb_txd %d\n", p_id, nb_rxd, nb_txd);
222
223     for (qi = 0; qi < num_rxq; qi++) {
224         snprintf(rx_pool_name, RTE_DIM(rx_pool_name), "%s_p_%d_q_%d", "mp_rx_", p_id, qi);
225         printf("[%d] %s num blocks %d\n", p_id, rx_pool_name, num_mbufs);
226         _eth_mbuf_pool_vf_rx[p_id][qi] = rte_pktmbuf_pool_create(rx_pool_name, num_mbufs,
227                     MBUF_CACHE, 0, data_room_size, rte_socket_id());
228
229         if (_eth_mbuf_pool_vf_rx[p_id][qi] == NULL)
230             rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
231     }
232
233     snprintf(rx_pool_name, RTE_DIM(rx_pool_name), "%s_%d", "mempool_small_", p_id);
234     printf("[%d] %s\n", p_id, rx_pool_name);
235     _eth_mbuf_pool_vf_small[p_id] = rte_pktmbuf_pool_create(rx_pool_name, NUM_MBUFS_VF,
236                 MBUF_CACHE, 0, MBUF_POOL_ELM_SMALL_INDIRECT, rte_socket_id());
237
238     if (_eth_mbuf_pool_vf_small[p_id] == NULL)
239         rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
240
241     /* Init RX queues */
242     fflush(stdout);
243     rxq_conf = dev_info.default_rxconf;
244
245     for (qi = 0; qi < num_rxq; qi++) {
246         ret = rx_queue_setup(p_id, qi, nb_rxd,
247                 sock_id, &rxq_conf, _eth_mbuf_pool_vf_rx[p_id][qi]);
248     }
249
250     if (ret < 0)
251         rte_panic("Cannot init RX for port %u (%d)\n",
252             p_id, ret);
253
254     /* Init TX queues */
255     fflush(stdout);
256     txq_conf = dev_info.default_txconf;
257
258     ret = rte_eth_tx_queue_setup(p_id, 0, nb_txd, sock_id, &txq_conf);
259     if (ret < 0)
260         rte_panic("Cannot init TX for port %u (%d)\n",
261                 p_id, ret);
262
263     ret = rte_eth_dev_set_ptypes(p_id, RTE_PTYPE_UNKNOWN, NULL, 0);
264     if (ret < 0)
265         rte_panic("Port %d: Failed to disable Ptype parsing\n", p_id);
266
267     /* Start port */
268     ret = rte_eth_dev_start(p_id);
269     if (ret < 0)
270         rte_panic("Cannot start port %u (%d)\n", p_id, ret);
271 }
272
273 void xran_init_port_mempool(int p_id, uint32_t mtu)
274 {
275     char rx_pool_name[32]    = "";
276
277     snprintf(rx_pool_name, RTE_DIM(rx_pool_name), "%s_%d", "mempool_small_", p_id);
278     printf("[%d] %s\n", p_id, rx_pool_name);
279     _eth_mbuf_pool_vf_small[p_id] = rte_pktmbuf_pool_create(rx_pool_name, NUM_MBUFS_VF,
280                 MBUF_CACHE, 0, MBUF_POOL_ELM_SMALL, rte_socket_id());
281
282     if (_eth_mbuf_pool_vf_small[p_id] == NULL)
283         rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
284 }
285
286 /* Prepend ethernet header, possibly vlan tag. */
287 void xran_add_eth_hdr_vlan(struct rte_ether_addr *dst, uint16_t ethertype, struct rte_mbuf *mb)
288 {
289
290     /* add in the ethernet header */
291     struct rte_ether_hdr *h = (struct rte_ether_hdr *)rte_pktmbuf_mtod(mb, struct rte_ether_hdr*);
292
293     PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed");
294
295     /* Fill in the ethernet header. */
296     rte_eth_macaddr_get(mb->port, &h->s_addr);          /* set source addr */
297     h->d_addr = *dst;                                   /* set dst addr */
298     h->ether_type = rte_cpu_to_be_16(ethertype);        /* ethertype too */
299 #if 0
300     struct rte_ether_addr *s = &h->s_addr;
301     printf("src=%x:%x:%x:%x:%x:%x, dst=%x:%x:%x:%x:%x:%x\n", s->addr_bytes[0],
302             s->addr_bytes[1],
303             s->addr_bytes[2],
304             s->addr_bytes[3],
305             s->addr_bytes[4],
306             s->addr_bytes[5],
307             dst->addr_bytes[0],
308             dst->addr_bytes[1],
309             dst->addr_bytes[2],
310             dst->addr_bytes[3],
311             dst->addr_bytes[4],
312             dst->addr_bytes[5]
313     );
314 #endif
315 #if defined(DPDKIO_DEBUG) && DPDKIO_DEBUG > 1
316     {
317         char dst[RTE_ETHER_ADDR_FMT_SIZE] = "(empty)";
318         char src[RTE_ETHER_ADDR_FMT_SIZE] = "(empty)";
319
320         printf("*** packet for TX below (len %d) ***", rte_pktmbuf_pkt_len(mb));
321         rte_ether_format_addr(src, sizeof(src), &h->s_addr);
322         rte_ether_format_addr(dst, sizeof(dst), &h->d_addr);
323         printf("src: %s dst: %s ethertype: %.4X", src, dst, ethertype);
324     }
325 #endif
326 }
327
328