mbuf: extend meaning of QinQ stripped bit
[dpdk.git] / examples / l2fwd-event / l2fwd_poll.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include "l2fwd_poll.h"
6
7 static inline void
8 l2fwd_poll_simple_forward(struct l2fwd_resources *rsrc, struct rte_mbuf *m,
9                           uint32_t portid)
10 {
11         struct rte_eth_dev_tx_buffer *buffer;
12         uint32_t dst_port;
13         int sent;
14
15         dst_port = rsrc->dst_ports[portid];
16
17         if (rsrc->mac_updating)
18                 l2fwd_mac_updating(m, dst_port, &rsrc->eth_addr[dst_port]);
19
20         buffer = ((struct l2fwd_poll_resources *)rsrc->poll_rsrc)->tx_buffer[
21                                                                 dst_port];
22         sent = rte_eth_tx_buffer(dst_port, 0, buffer, m);
23         if (sent)
24                 rsrc->port_stats[dst_port].tx += sent;
25 }
26
27 /* main poll mode processing loop */
28 static void
29 l2fwd_poll_main_loop(struct l2fwd_resources *rsrc)
30 {
31         uint64_t prev_tsc, diff_tsc, cur_tsc, drain_tsc;
32         struct l2fwd_poll_resources *poll_rsrc = rsrc->poll_rsrc;
33         struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
34         struct rte_eth_dev_tx_buffer *buf;
35         struct lcore_queue_conf *qconf;
36         uint32_t i, j, port_id, nb_rx;
37         struct rte_mbuf *m;
38         uint32_t lcore_id;
39         int32_t sent;
40
41         drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S *
42                         BURST_TX_DRAIN_US;
43         prev_tsc = 0;
44
45         lcore_id = rte_lcore_id();
46         qconf = &poll_rsrc->lcore_queue_conf[lcore_id];
47
48         if (qconf->n_rx_port == 0) {
49                 printf("lcore %u has nothing to do\n", lcore_id);
50                 return;
51         }
52
53         printf("entering main loop on lcore %u\n", lcore_id);
54
55         for (i = 0; i < qconf->n_rx_port; i++) {
56
57                 port_id = qconf->rx_port_list[i];
58                 printf(" -- lcoreid=%u port_id=%u\n", lcore_id, port_id);
59
60         }
61
62         while (!rsrc->force_quit) {
63
64                 cur_tsc = rte_rdtsc();
65
66                 /*
67                  * TX burst queue drain
68                  */
69                 diff_tsc = cur_tsc - prev_tsc;
70                 if (unlikely(diff_tsc > drain_tsc)) {
71                         for (i = 0; i < qconf->n_rx_port; i++) {
72                                 port_id =
73                                         rsrc->dst_ports[qconf->rx_port_list[i]];
74                                 buf = poll_rsrc->tx_buffer[port_id];
75                                 sent = rte_eth_tx_buffer_flush(port_id, 0, buf);
76                                 if (sent)
77                                         rsrc->port_stats[port_id].tx += sent;
78                         }
79
80                         prev_tsc = cur_tsc;
81                 }
82
83                 /*
84                  * Read packet from RX queues
85                  */
86                 for (i = 0; i < qconf->n_rx_port; i++) {
87
88                         port_id = qconf->rx_port_list[i];
89                         nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst,
90                                                  MAX_PKT_BURST);
91
92                         rsrc->port_stats[port_id].rx += nb_rx;
93
94                         for (j = 0; j < nb_rx; j++) {
95                                 m = pkts_burst[j];
96                                 rte_prefetch0(rte_pktmbuf_mtod(m, void *));
97                                 l2fwd_poll_simple_forward(rsrc, m, port_id);
98                         }
99                 }
100         }
101 }
102
103 static void
104 l2fwd_poll_lcore_config(struct l2fwd_resources *rsrc)
105 {
106         struct l2fwd_poll_resources *poll_rsrc = rsrc->poll_rsrc;
107         struct lcore_queue_conf *qconf = NULL;
108         uint32_t rx_lcore_id = 0;
109         uint16_t port_id;
110
111         /* Initialize the port/queue configuration of each logical core */
112         RTE_ETH_FOREACH_DEV(port_id) {
113                 /* skip ports that are not enabled */
114                 if ((rsrc->enabled_port_mask & (1 << port_id)) == 0)
115                         continue;
116
117                 /* get the lcore_id for this port */
118                 while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
119                        rx_lcore_id == rte_get_master_lcore() ||
120                        poll_rsrc->lcore_queue_conf[rx_lcore_id].n_rx_port ==
121                        rsrc->rx_queue_per_lcore) {
122                         rx_lcore_id++;
123                         if (rx_lcore_id >= RTE_MAX_LCORE)
124                                 rte_panic("Not enough cores\n");
125                 }
126
127                 if (qconf != &poll_rsrc->lcore_queue_conf[rx_lcore_id]) {
128                         /* Assigned a new logical core in the loop above. */
129                         qconf = &poll_rsrc->lcore_queue_conf[rx_lcore_id];
130                 }
131
132                 qconf->rx_port_list[qconf->n_rx_port] = port_id;
133                 qconf->n_rx_port++;
134                 printf("Lcore %u: RX port %u\n", rx_lcore_id, port_id);
135         }
136 }
137
138 static void
139 l2fwd_poll_init_tx_buffers(struct l2fwd_resources *rsrc)
140 {
141         struct l2fwd_poll_resources *poll_rsrc = rsrc->poll_rsrc;
142         uint16_t port_id;
143         int ret;
144
145         RTE_ETH_FOREACH_DEV(port_id) {
146                 /* Initialize TX buffers */
147                 poll_rsrc->tx_buffer[port_id] = rte_zmalloc_socket("tx_buffer",
148                                 RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
149                                 rte_eth_dev_socket_id(port_id));
150                 if (poll_rsrc->tx_buffer[port_id] == NULL)
151                         rte_panic("Cannot allocate buffer for tx on port %u\n",
152                                   port_id);
153
154                 rte_eth_tx_buffer_init(poll_rsrc->tx_buffer[port_id],
155                                        MAX_PKT_BURST);
156
157                 ret = rte_eth_tx_buffer_set_err_callback(
158                                 poll_rsrc->tx_buffer[port_id],
159                                 rte_eth_tx_buffer_count_callback,
160                                 &rsrc->port_stats[port_id].dropped);
161                 if (ret < 0)
162                         rte_panic("Cannot set error callback for tx buffer on port %u\n",
163                                   port_id);
164         }
165 }
166
167 void
168 l2fwd_poll_resource_setup(struct l2fwd_resources *rsrc)
169 {
170         struct l2fwd_poll_resources *poll_rsrc;
171
172         poll_rsrc = rte_zmalloc("l2fwd_poll_rsrc",
173                                 sizeof(struct l2fwd_poll_resources), 0);
174         if (poll_rsrc == NULL)
175                 rte_panic("Failed to allocate resources for l2fwd poll mode\n");
176
177         rsrc->poll_rsrc = poll_rsrc;
178         l2fwd_poll_lcore_config(rsrc);
179         l2fwd_poll_init_tx_buffers(rsrc);
180
181         poll_rsrc->poll_main_loop = l2fwd_poll_main_loop;
182 }