Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Red Hat Corp.
3 : : */
4 : :
5 : : #include <stdarg.h>
6 : : #include <stdio.h>
7 : : #include <stdlib.h>
8 : : #include <stdbool.h>
9 : : #include <string.h>
10 : : #include <errno.h>
11 : : #include <stdint.h>
12 : : #include <unistd.h>
13 : : #include <inttypes.h>
14 : :
15 : : #include <sys/queue.h>
16 : : #include <sys/stat.h>
17 : :
18 : : #include <rte_common.h>
19 : : #include <rte_log.h>
20 : : #include <rte_debug.h>
21 : : #include <rte_cycles.h>
22 : : #include <rte_memory.h>
23 : : #include <rte_launch.h>
24 : : #include <rte_eal.h>
25 : : #include <rte_per_lcore.h>
26 : : #include <rte_lcore.h>
27 : : #include <rte_memcpy.h>
28 : : #include <rte_mempool.h>
29 : : #include <rte_mbuf.h>
30 : : #include <rte_ethdev.h>
31 : : #include <rte_flow.h>
32 : : #include <rte_malloc.h>
33 : :
34 : : #include "testpmd.h"
35 : : #include "5tswap.h"
36 : : #include "macfwd.h"
37 : : #if defined(RTE_ARCH_X86)
38 : : #include "macswap_sse.h"
39 : : #elif defined(__ARM_NEON)
40 : : #include "macswap_neon.h"
41 : : #else
42 : : #include "macswap.h"
43 : : #endif
44 : :
45 : : #define NOISY_STRSIZE 256
46 : : #define NOISY_RING "noisy_ring_%d\n"
47 : :
48 : : struct noisy_config {
49 : : struct rte_ring *f;
50 : : uint64_t prev_time;
51 : : char *vnf_mem;
52 : : bool do_buffering;
53 : : bool do_flush;
54 : : bool do_sim;
55 : : };
56 : :
57 : : struct noisy_config *noisy_cfg[RTE_MAX_ETHPORTS];
58 : :
59 : : static inline void
60 : 0 : do_write(char *vnf_mem)
61 : : {
62 : 0 : uint64_t i = rte_rand();
63 : 0 : uint64_t w = rte_rand();
64 : :
65 : 0 : vnf_mem[i % ((noisy_lkup_mem_sz * 1024 * 1024) /
66 : 0 : RTE_CACHE_LINE_SIZE)] = w;
67 : 0 : }
68 : :
69 : : static inline void
70 : : do_read(char *vnf_mem)
71 : : {
72 : : uint64_t r __rte_unused;
73 : 0 : uint64_t i = rte_rand();
74 : :
75 : : r = vnf_mem[i % ((noisy_lkup_mem_sz * 1024 * 1024) /
76 : : RTE_CACHE_LINE_SIZE)];
77 : : r++;
78 : : }
79 : :
80 : : static inline void
81 : : do_readwrite(char *vnf_mem)
82 : : {
83 : : do_read(vnf_mem);
84 : 0 : do_write(vnf_mem);
85 : : }
86 : :
87 : : /*
88 : : * Simulate route lookups as defined by commandline parameters
89 : : */
90 : : static void
91 : 0 : sim_memory_lookups(struct noisy_config *ncf, uint16_t nb_pkts)
92 : : {
93 : : uint16_t i, j;
94 : :
95 : 0 : for (i = 0; i < nb_pkts; i++) {
96 : 0 : for (j = 0; j < noisy_lkup_num_writes; j++)
97 : 0 : do_write(ncf->vnf_mem);
98 : 0 : for (j = 0; j < noisy_lkup_num_reads; j++)
99 : : do_read(ncf->vnf_mem);
100 : 0 : for (j = 0; j < noisy_lkup_num_reads_writes; j++)
101 : 0 : do_readwrite(ncf->vnf_mem);
102 : : }
103 : 0 : }
104 : :
105 : : /*
106 : : * Forwarding of packets in noisy VNF mode. Forward packets but perform
107 : : * memory operations first as specified on cmdline.
108 : : *
109 : : * Depending on which commandline parameters are specified we have
110 : : * different cases to handle:
111 : : *
112 : : * 1. No FIFO size was given, so we don't do buffering of incoming
113 : : * packets. This case is pretty much what iofwd does but in this case
114 : : * we also do simulation of memory accesses (depending on which
115 : : * parameters were specified for it).
116 : : * 2. User wants do buffer packets in a FIFO and sent out overflowing
117 : : * packets.
118 : : * 3. User wants a FIFO and specifies a time in ms to flush all packets
119 : : * out of the FIFO
120 : : * 4. Cases 2 and 3 combined
121 : : */
122 : : static uint16_t
123 : 0 : noisy_eth_tx_burst(struct fwd_stream *fs, uint16_t nb_rx, struct rte_mbuf **pkts_burst)
124 : : {
125 : 0 : const uint64_t freq_khz = rte_get_timer_hz() / 1000;
126 : 0 : struct noisy_config *ncf = noisy_cfg[fs->rx_port];
127 : : struct rte_mbuf *tmp_pkts[MAX_PKT_BURST];
128 : : uint16_t nb_deqd = 0;
129 : : uint16_t nb_tx = 0;
130 : : uint16_t nb_enqd;
131 : : unsigned int fifo_free;
132 : : uint64_t delta_ms;
133 : : bool needs_flush = false;
134 : : uint64_t now;
135 : :
136 : 0 : if (unlikely(nb_rx == 0)) {
137 : 0 : if (!ncf->do_buffering)
138 : 0 : goto end;
139 : : else
140 : 0 : goto flush;
141 : : }
142 : :
143 : 0 : if (!ncf->do_buffering) {
144 : 0 : if (ncf->do_sim)
145 : 0 : sim_memory_lookups(ncf, nb_rx);
146 : 0 : nb_tx = common_fwd_stream_transmit(fs, pkts_burst, nb_rx);
147 : 0 : goto end;
148 : : }
149 : :
150 : 0 : fifo_free = rte_ring_free_count(ncf->f);
151 : 0 : if (fifo_free >= nb_rx) {
152 : 0 : nb_enqd = rte_ring_enqueue_burst(ncf->f, (void **) pkts_burst, nb_rx, NULL);
153 : 0 : if (nb_enqd < nb_rx) {
154 : 0 : fs->fwd_dropped += nb_rx - nb_enqd;
155 : 0 : rte_pktmbuf_free_bulk(&pkts_burst[nb_enqd], nb_rx - nb_enqd);
156 : : }
157 : : } else {
158 : 0 : nb_deqd = rte_ring_dequeue_burst(ncf->f, (void **) tmp_pkts, nb_rx, NULL);
159 : 0 : nb_enqd = rte_ring_enqueue_burst(ncf->f, (void **) pkts_burst, nb_deqd, NULL);
160 : 0 : if (nb_deqd > 0)
161 : 0 : nb_tx = common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
162 : : }
163 : :
164 : 0 : if (ncf->do_sim)
165 : 0 : sim_memory_lookups(ncf, nb_enqd);
166 : :
167 : 0 : flush:
168 : 0 : if (ncf->do_flush) {
169 : 0 : if (!ncf->prev_time)
170 : 0 : now = ncf->prev_time = rte_get_timer_cycles();
171 : : else
172 : : now = rte_get_timer_cycles();
173 : 0 : delta_ms = (now - ncf->prev_time) / freq_khz;
174 : 0 : needs_flush = delta_ms >= noisy_tx_sw_buf_flush_time &&
175 : 0 : noisy_tx_sw_buf_flush_time > 0 && !nb_tx;
176 : : }
177 : 0 : while (needs_flush && !rte_ring_empty(ncf->f)) {
178 : : nb_deqd = rte_ring_dequeue_burst(ncf->f, (void **)tmp_pkts,
179 : : MAX_PKT_BURST, NULL);
180 : 0 : nb_tx += common_fwd_stream_transmit(fs, tmp_pkts, nb_deqd);
181 : 0 : ncf->prev_time = rte_get_timer_cycles();
182 : : }
183 : 0 : end:
184 : 0 : return nb_tx;
185 : : }
186 : :
187 : : static bool
188 : 0 : pkt_burst_io(struct fwd_stream *fs)
189 : : {
190 : : struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
191 : : uint16_t nb_rx;
192 : : uint16_t nb_tx;
193 : :
194 : 0 : nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
195 : 0 : nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
196 : :
197 : 0 : return nb_rx > 0 || nb_tx > 0;
198 : : }
199 : :
200 : : static bool
201 : 0 : pkt_burst_mac(struct fwd_stream *fs)
202 : : {
203 : : struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
204 : : uint16_t nb_rx;
205 : : uint16_t nb_tx;
206 : :
207 : 0 : nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
208 : 0 : if (likely(nb_rx != 0))
209 : 0 : do_macfwd(pkts_burst, nb_rx, fs);
210 : 0 : nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
211 : :
212 : 0 : return nb_rx > 0 || nb_tx > 0;
213 : : }
214 : :
215 : : static bool
216 : 0 : pkt_burst_macswap(struct fwd_stream *fs)
217 : : {
218 : : struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
219 : : uint16_t nb_rx;
220 : : uint16_t nb_tx;
221 : :
222 : 0 : nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
223 : 0 : if (likely(nb_rx != 0))
224 : 0 : do_macswap(pkts_burst, nb_rx, &ports[fs->tx_port]);
225 : 0 : nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
226 : :
227 : 0 : return nb_rx > 0 || nb_tx > 0;
228 : : }
229 : :
230 : : static bool
231 : 0 : pkt_burst_5tswap(struct fwd_stream *fs)
232 : : {
233 : : struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
234 : : uint16_t nb_rx;
235 : : uint16_t nb_tx;
236 : :
237 : 0 : nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst);
238 : 0 : if (likely(nb_rx != 0))
239 : 0 : do_5tswap(pkts_burst, nb_rx, fs);
240 : 0 : nb_tx = noisy_eth_tx_burst(fs, nb_rx, pkts_burst);
241 : :
242 : 0 : return nb_rx > 0 || nb_tx > 0;
243 : : }
244 : :
245 : : static void
246 : 0 : noisy_fwd_end(portid_t pi)
247 : : {
248 : 0 : rte_ring_free(noisy_cfg[pi]->f);
249 : 0 : rte_free(noisy_cfg[pi]->vnf_mem);
250 : 0 : rte_free(noisy_cfg[pi]);
251 : 0 : }
252 : :
253 : : static int
254 : 0 : noisy_fwd_begin(portid_t pi)
255 : : {
256 : : struct noisy_config *n;
257 : : char name[NOISY_STRSIZE];
258 : :
259 : 0 : noisy_cfg[pi] = rte_zmalloc("testpmd noisy fifo and timers",
260 : : sizeof(struct noisy_config),
261 : : RTE_CACHE_LINE_SIZE);
262 : 0 : if (noisy_cfg[pi] == NULL) {
263 : 0 : rte_exit(EXIT_FAILURE,
264 : : "rte_zmalloc(%d) struct noisy_config) failed\n",
265 : : (int) pi);
266 : : }
267 : : n = noisy_cfg[pi];
268 : 0 : n->do_buffering = noisy_tx_sw_bufsz > 0;
269 : 0 : n->do_sim = noisy_lkup_num_writes + noisy_lkup_num_reads +
270 : : noisy_lkup_num_reads_writes;
271 : 0 : n->do_flush = noisy_tx_sw_buf_flush_time > 0;
272 : :
273 : 0 : if (n->do_buffering) {
274 : : snprintf(name, NOISY_STRSIZE, NOISY_RING, pi);
275 : 0 : n->f = rte_ring_create(name, noisy_tx_sw_bufsz,
276 : 0 : rte_socket_id(), 0);
277 : 0 : if (!n->f)
278 : 0 : rte_exit(EXIT_FAILURE,
279 : : "rte_ring_create(%d), size %d) failed\n",
280 : : (int) pi,
281 : : noisy_tx_sw_bufsz);
282 : : }
283 : 0 : if (noisy_lkup_mem_sz > 0) {
284 : 0 : n->vnf_mem = (char *) rte_zmalloc("vnf sim memory",
285 : : noisy_lkup_mem_sz * 1024 * 1024,
286 : : RTE_CACHE_LINE_SIZE);
287 : 0 : if (!n->vnf_mem)
288 : 0 : rte_exit(EXIT_FAILURE,
289 : : "rte_zmalloc(%" PRIu64 ") for vnf memory) failed\n",
290 : : noisy_lkup_mem_sz);
291 : 0 : } else if (n->do_sim) {
292 : 0 : rte_exit(EXIT_FAILURE,
293 : : "--noisy-lkup-memory-size must be > 0\n");
294 : : }
295 : :
296 : 0 : if (noisy_fwd_mode == NOISY_FWD_MODE_IO)
297 : 0 : noisy_vnf_engine.packet_fwd = pkt_burst_io;
298 : 0 : else if (noisy_fwd_mode == NOISY_FWD_MODE_MAC)
299 : 0 : noisy_vnf_engine.packet_fwd = pkt_burst_mac;
300 : 0 : else if (noisy_fwd_mode == NOISY_FWD_MODE_MACSWAP)
301 : 0 : noisy_vnf_engine.packet_fwd = pkt_burst_macswap;
302 : 0 : else if (noisy_fwd_mode == NOISY_FWD_MODE_5TSWAP)
303 : 0 : noisy_vnf_engine.packet_fwd = pkt_burst_5tswap;
304 : : else
305 : 0 : rte_exit(EXIT_FAILURE,
306 : : " Invalid noisy_fwd_mode specified\n");
307 : :
308 : 0 : noisy_vnf_engine.status = noisy_fwd_mode_desc[noisy_fwd_mode];
309 : :
310 : 0 : return 0;
311 : : }
312 : :
313 : : struct fwd_engine noisy_vnf_engine = {
314 : : .fwd_mode_name = "noisy",
315 : : .port_fwd_begin = noisy_fwd_begin,
316 : : .port_fwd_end = noisy_fwd_end,
317 : : .stream_init = common_fwd_stream_init,
318 : : .packet_fwd = pkt_burst_io,
319 : : };
|