Front Haul Interface Library first seed code contribution
[o-du/phy.git] / fhi_lib / lib / ethernet / ethernet.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 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 /**
21  * @brief This file has all definitions for the Ethernet Data Interface Layer
22  * @file ethernet.c
23  * @ingroup group_lte_source_auxlib
24  * @author Intel Corporation
25  **/
26
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdint.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <sys/queue.h>
34 #include <err.h>
35 #include <assert.h>
36
37 #include <linux/limits.h>
38 #include <sys/types.h>
39 #include <stdlib.h>
40 #include <math.h>
41
42 #include <rte_config.h>
43 #include <rte_common.h>
44 #include <rte_log.h>
45 #include <rte_memory.h>
46 #include <rte_memcpy.h>
47 #include <rte_memzone.h>
48 #include <rte_eal.h>
49 #include <rte_per_lcore.h>
50 #include <rte_launch.h>
51 #include <rte_atomic.h>
52 #include <rte_cycles.h>
53 #include <rte_prefetch.h>
54 #include <rte_lcore.h>
55 #include <rte_per_lcore.h>
56 #include <rte_branch_prediction.h>
57 #include <rte_interrupts.h>
58 #include <rte_pci.h>
59 #include <rte_debug.h>
60 #include <rte_ether.h>
61 #include <rte_ethdev.h>
62 #include <rte_ring.h>
63 #include <rte_mempool.h>
64 #include <rte_mbuf.h>
65 #include <rte_errno.h>
66
67 #include "ethernet.h"
68 #include "ethdi.h"
69
70 /* Our mbuf pools. */
71 struct rte_mempool *_eth_mbuf_pool;
72 struct rte_mempool *_eth_mbuf_pool_rx;
73 struct rte_mempool *_eth_mbuf_pool_small;
74 struct rte_mempool *_eth_mbuf_pool_big;
75
76 /*
77  * Make sure the ring indexes are big enough to cover buf space x2
78  * This ring-buffer maintains the property head - tail <= RINGSIZE.
79  * head == tail:  ring buffer empty
80  * head - tail == RINGSIZE: ring buffer full
81  */
82 typedef uint16_t ring_idx;
83 static struct {
84     ring_idx head;
85     ring_idx read_head;
86     ring_idx tail;
87     char buf[1024];      /* needs power of 2! */
88 } io_ring = { {0}, 0, 0};
89
90 #define RINGSIZE sizeof(io_ring.buf)
91 #define RINGMASK (RINGSIZE - 1)
92
93
94 /*
95  * Display part of the message stored in the ring buffer.
96  * Might require multiple calls to print the full message.
97  * Will return 0 when nothing left to print.
98  */
99 int xran_show_delayed_message(void)
100 {
101     ring_idx tail = io_ring.tail;
102     ring_idx wlen = io_ring.read_head - tail; /* always within [0, RINGSIZE] */
103
104     if (wlen <= 0)
105         return 0;
106
107     tail &= RINGMASK;   /* modulo the range down now that we have wlen */
108
109     /* Make sure we're not going over buffer end. Next call will wrap. */
110     if (tail + wlen > RINGSIZE)
111         wlen = RINGSIZE - tail;
112
113     RTE_ASSERT(tail + wlen <= RINGSIZE);
114
115     /* We use write() here to avoid recaculating string length in fwrite(). */
116     const ssize_t written = write(STDOUT_FILENO, io_ring.buf + tail, wlen);
117     if (written <= 0)
118         return 0;   /* To avoid moving tail the wrong way on error. */
119
120     /* Move tail up. Only we touch it. And we only print from one core. */
121     io_ring.tail += written;
122
123     return written;     /* next invocation will print the rest if any */
124 }
125
126
127 void xran_init_mbuf_pool(void)
128 {
129     /* Init the buffer pool */
130     if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
131         _eth_mbuf_pool = rte_pktmbuf_pool_create("mempool", NUM_MBUFS,
132                 MBUF_CACHE, 0, MBUF_POOL_ELEMENT, rte_socket_id());
133         _eth_mbuf_pool_rx = rte_pktmbuf_pool_create("mempool_rx", NUM_MBUFS,
134                 MBUF_CACHE, 0, MBUF_POOL_ELEMENT, rte_socket_id());
135         _eth_mbuf_pool_small = rte_pktmbuf_pool_create("mempool_small",
136                 NUM_MBUFS, MBUF_CACHE, 0, MBUF_POOL_ELM_SMALL, rte_socket_id());
137         _eth_mbuf_pool_big = rte_pktmbuf_pool_create("mempool_big",
138                 NUM_MBUFS_BIG, 0, 0, MBUF_POOL_ELM_BIG, rte_socket_id());
139     } else {
140         _eth_mbuf_pool = rte_mempool_lookup("mempool");
141         _eth_mbuf_pool_rx = rte_mempool_lookup("mempool_rx");
142         _eth_mbuf_pool_small = rte_mempool_lookup("mempool_small");
143         _eth_mbuf_pool_big = rte_mempool_lookup("mempool_big");
144     }
145     if (_eth_mbuf_pool == NULL)
146         rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
147     if (_eth_mbuf_pool_rx == NULL)
148         rte_panic("Cannot create mbuf pool: %s\n", rte_strerror(rte_errno));
149     if (_eth_mbuf_pool_small == NULL)
150         rte_panic("Cannot create small mbuf pool: %s\n", rte_strerror(rte_errno));
151     if (_eth_mbuf_pool_big == NULL)
152         rte_panic("Cannot create big mbuf pool: %s\n", rte_strerror(rte_errno));
153 }
154
155 /* Init NIC port, then start the port */
156 void xran_init_port(int p_id,  struct ether_addr *p_lls_cu_addr)
157 {
158     char buf[ETHER_ADDR_FMT_SIZE];
159     struct ether_addr eth_addr;
160     struct rte_eth_rxmode rxmode =
161             { .split_hdr_size = 0,
162               .max_rx_pkt_len = MAX_RX_LEN,
163               .offloads=(DEV_RX_OFFLOAD_JUMBO_FRAME|DEV_RX_OFFLOAD_CRC_STRIP)
164             };
165     struct rte_eth_txmode txmode = {
166                 .mq_mode = ETH_MQ_TX_NONE
167             };
168     struct rte_eth_conf port_conf = {
169             .rxmode = rxmode,
170             .txmode = txmode
171             };
172     struct ether_addr pDstEthAddr;
173
174     struct rte_eth_rxconf rxq_conf;
175     struct rte_eth_txconf txq_conf;
176
177     int ret;
178     struct rte_eth_dev_info dev_info;
179     const char *drv_name = "";
180     int sock_id = rte_eth_dev_socket_id(p_id);
181
182    // ether_format_addr(buf, sizeof(buf), p_lls_cu_addr);
183    // printf("port %d set mac address %s\n", p_id, buf);
184    // rte_eth_dev_default_mac_addr_set(p_id, p_lls_cu_addr);
185
186     rte_eth_dev_info_get(p_id, &dev_info);
187     if (dev_info.driver_name)
188         drv_name = dev_info.driver_name;
189     printf("initializing port %d for TX, drv=%s\n", p_id, drv_name);
190
191     /* In order to receive packets from any server need to add broad case address
192     * for the port*/
193     pDstEthAddr.addr_bytes[0] = 0xFF;
194     pDstEthAddr.addr_bytes[1] = 0xFF;
195     pDstEthAddr.addr_bytes[2] = 0xFF;
196
197     pDstEthAddr.addr_bytes[3] = 0xFF;
198     pDstEthAddr.addr_bytes[4] = 0xFF;
199     pDstEthAddr.addr_bytes[5] = 0xFF;
200
201     rte_eth_macaddr_get(p_id, &eth_addr);
202     ether_format_addr(buf, sizeof(buf), &eth_addr);
203     printf("port %d mac address %s\n", p_id, buf);
204
205     struct ether_addr addr;
206     rte_eth_macaddr_get(p_id, &addr);
207
208 //    rte_eth_dev_mac_addr_add(p_id, &pDstEthAddr,1);
209    // rte_eth_dev_mac_addr_add(p_id, &addr, 1);
210
211     printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
212         " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
213         (unsigned)p_id,
214         addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2],
215         addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]);
216
217     /* Init port */
218     ret = rte_eth_dev_configure(p_id, 1, 1, &port_conf);
219     if (ret < 0)
220         rte_panic("Cannot configure port %u (%d)\n", p_id, ret);
221
222     /* Init RX queues */
223     rxq_conf = dev_info.default_rxconf;
224     ret = rte_eth_rx_queue_setup(p_id, 0, BURST_SIZE,
225         sock_id, &rxq_conf, _eth_mbuf_pool_rx);
226     if (ret < 0)
227         rte_panic("Cannot init RX for port %u (%d)\n",
228             p_id, ret);
229
230     /* Init TX queues */
231     txq_conf = dev_info.default_txconf;
232     ret = rte_eth_tx_queue_setup(p_id, 0, BURST_SIZE, sock_id, &txq_conf);
233     if (ret < 0)
234         rte_panic("Cannot init TX for port %u (%d)\n",
235                 p_id, ret);
236
237     /* Start port */
238     ret = rte_eth_dev_start(p_id);
239     if (ret < 0)
240         rte_panic("Cannot start port %u (%d)\n", p_id, ret);
241
242     rte_eth_promiscuous_enable(p_id);
243 }
244
245 void xran_memdump(void *addr, int len)
246 {
247     int i;
248     char tmp_buf[len * 2 + len / 16 + 1];
249     char *p = tmp_buf;
250
251     return;
252 #if 0
253     for (i = 0; i < len; ++i) {
254         sprintf(p, "%.2X ", ((uint8_t *)addr)[i]);
255         if (i % 16 == 15)
256             *p++ = '\n';
257     }
258     *p = 0;
259     nlog("%s", tmp_buf);
260 #endif
261 }
262
263
264 /* Prepend ethernet header, possibly vlan tag. */
265 void xran_add_eth_hdr_vlan(struct ether_addr *dst, uint16_t ethertype, struct rte_mbuf *mb, uint16_t vlan_tci)
266 {
267     /* add in the ethernet header */
268     struct ether_hdr *const h = (void *)rte_pktmbuf_prepend(mb, sizeof(*h));
269
270     PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed");
271
272     /* Fill in the ethernet header. */
273     rte_eth_macaddr_get(mb->port, &h->s_addr);          /* set source addr */
274     h->d_addr = *dst;                                   /* set dst addr */
275     h->ether_type = rte_cpu_to_be_16(ethertype);        /* ethertype too */
276
277 #if defined(DPDKIO_DEBUG) && DPDKIO_DEBUG > 1
278     {
279         char dst[ETHER_ADDR_FMT_SIZE] = "(empty)";
280         char src[ETHER_ADDR_FMT_SIZE] = "(empty)";
281
282         nlog("*** packet for TX below (len %d) ***", rte_pktmbuf_pkt_len(mb));
283         ether_format_addr(src, sizeof(src), &h->s_addr);
284         ether_format_addr(dst, sizeof(dst), &h->d_addr);
285         nlog("src: %s dst: %s ethertype: %.4X", src, dst, ethertype);
286     }
287 #endif
288 #ifdef VLAN_SUPPORT
289     mb->vlan_tci = vlan_tci;
290     dlog("Inserting vlan tag of %d", vlan_tci);
291     rte_vlan_insert(&mb);
292 #endif
293 }
294
295 int xran_send_message_burst(int dst_id, int pkt_type, void *body, int len)
296 {
297     struct rte_mbuf *mbufs[BURST_SIZE];
298     int i;
299     uint8_t *src = body;
300     const struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
301
302     /* We're limited by maximum mbuf size on the receive size.
303      * We can change this but this would be a bigger rework. */
304     RTE_ASSERT(len < MBUF_POOL_ELM_BIG);
305
306     /* Allocate the required number of mbufs. */
307     const uint8_t count = ceilf((float)len / MAX_DATA_SIZE);
308     if (rte_pktmbuf_alloc_bulk(_eth_mbuf_pool, mbufs, count) != 0)
309         rte_panic("Failed to allocate %d mbufs\n", count);
310
311     nlog("burst transfer with data size %lu", MAX_DATA_SIZE);
312     for (i = 0; len > 0; ++i) {
313         char *p;
314         struct burst_hdr *bhdr;
315         struct ethdi_hdr *edi_hdr;
316
317         /* Setup the ethdi_hdr. */
318         edi_hdr = (void *)rte_pktmbuf_append(mbufs[i], sizeof(*edi_hdr));
319         if (edi_hdr == NULL)
320             rte_panic("append of ethdi_hdr failed\n");
321         edi_hdr->pkt_type = PKT_BURST;
322         /* edi_hdr->source_id setup in tx_from_ring */
323         edi_hdr->dest_id = dst_id;
324
325         /* Setup the burst header */
326         bhdr = (void *)rte_pktmbuf_append(mbufs[i], sizeof(*bhdr));
327         if (bhdr == NULL)        /* append failed. */
328             rte_panic("mbuf prepend of burst_hdr failed\n");
329         bhdr->original_type = pkt_type;
330         bhdr->pkt_idx = i;       /* save the index of the burst chunk. */
331         bhdr->total_pkts = count;
332
333         /* now copy in the actual data */
334         const int curr_data_len = RTE_MIN(len, MAX_TX_LEN -
335                 rte_pktmbuf_pkt_len(mbufs[i]) - sizeof(struct ether_hdr));
336         p = (void *)rte_pktmbuf_append(mbufs[i], curr_data_len);
337         if (p == NULL)
338             rte_panic("mbuf append of %d data bytes failed\n", curr_data_len);
339         /* This copy is unavoidable, as we're splitting one big buffer
340          * into multiple mbufs. */
341         rte_memcpy(p, src, curr_data_len);
342
343         dlog("curr_data_len[%d] = %d", i, curr_data_len);
344         dlog("packet %d size %d", i, rte_pktmbuf_pkt_len(mbufs[i]));
345
346         /* Update our source data pointer and remaining length. */
347         len -= curr_data_len;
348         src += curr_data_len;
349     }
350
351     /* Now enqueue the full prepared burst. */
352     i = rte_ring_enqueue_bulk(ctx->tx_ring[0], (void **)mbufs, count, NULL);
353     PANIC_ON(i != count, "failed to enqueue all mbufs: %d/%d", i, count);
354     dlog("%d packets enqueued on port %d.", count, ctx->io_cfg.port);
355
356     return 1;
357 }