Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2015-2018 Atomic Rules LLC
3 : : */
4 : :
5 : : #include <stdlib.h>
6 : : #include <unistd.h>
7 : :
8 : : #include <rte_string_fns.h>
9 : : #include <rte_malloc.h>
10 : : #include <rte_thread.h>
11 : :
12 : : #include "ark_pktgen.h"
13 : : #include "ark_logs.h"
14 : :
15 : : #define ARK_MAX_STR_LEN 64
16 : : union OPTV {
17 : : int INT;
18 : : int BOOL;
19 : : uint64_t LONG;
20 : : char STR[ARK_MAX_STR_LEN];
21 : : };
22 : :
23 : : enum OPTYPE {
24 : : OTINT,
25 : : OTLONG,
26 : : OTBOOL,
27 : : OTSTRING
28 : : };
29 : :
30 : : struct OPTIONS {
31 : : char opt[ARK_MAX_STR_LEN];
32 : : enum OPTYPE t;
33 : : union OPTV v;
34 : : };
35 : :
36 : : static struct OPTIONS toptions[] = {
37 : : {{"configure"}, OTBOOL, {1} },
38 : : {{"dg-mode"}, OTBOOL, {1} },
39 : : {{"run"}, OTBOOL, {0} },
40 : : {{"pause"}, OTBOOL, {0} },
41 : : {{"reset"}, OTBOOL, {0} },
42 : : {{"dump"}, OTBOOL, {0} },
43 : : {{"gen_forever"}, OTBOOL, {0} },
44 : : {{"en_slaved_start"}, OTBOOL, {0} },
45 : : {{"vary_length"}, OTBOOL, {0} },
46 : : {{"incr_payload"}, OTBOOL, {0} },
47 : : {{"incr_first_byte"}, OTBOOL, {0} },
48 : : {{"ins_seq_num"}, OTBOOL, {0} },
49 : : {{"ins_time_stamp"}, OTBOOL, {1} },
50 : : {{"ins_udp_hdr"}, OTBOOL, {0} },
51 : : {{"num_pkts"}, OTLONG, .v.LONG = 100000000},
52 : : {{"payload_byte"}, OTINT, {0x55} },
53 : : {{"pkt_spacing"}, OTINT, {130} },
54 : : {{"pkt_size_min"}, OTINT, {2006} },
55 : : {{"pkt_size_max"}, OTINT, {1514} },
56 : : {{"pkt_size_incr"}, OTINT, {1} },
57 : : {{"eth_type"}, OTINT, {0x0800} },
58 : : {{"src_mac_addr"}, OTLONG, .v.LONG = 0xdC3cF6425060L},
59 : : {{"dst_mac_addr"}, OTLONG, .v.LONG = 0x112233445566L},
60 : : {{"hdr_dW0"}, OTINT, {0x0016e319} },
61 : : {{"hdr_dW1"}, OTINT, {0x27150004} },
62 : : {{"hdr_dW2"}, OTINT, {0x76967bda} },
63 : : {{"hdr_dW3"}, OTINT, {0x08004500} },
64 : : {{"hdr_dW4"}, OTINT, {0x005276ed} },
65 : : {{"hdr_dW5"}, OTINT, {0x40004006} },
66 : : {{"hdr_dW6"}, OTINT, {0x56cfc0a8} },
67 : : {{"start_offset"}, OTINT, {0} },
68 : : {{"bytes_per_cycle"}, OTINT, {10} },
69 : : {{"shaping"}, OTBOOL, {0} },
70 : : {{"dst_ip"}, OTSTRING, .v.STR = "169.254.10.240"},
71 : : {{"dst_port"}, OTINT, {65536} },
72 : : {{"src_port"}, OTINT, {65536} },
73 : : };
74 : :
75 : : ark_pkt_gen_t
76 : 0 : ark_pktgen_init(void *adr, int ord, int l2_mode)
77 : : {
78 : : struct ark_pkt_gen_inst *inst =
79 : 0 : rte_malloc("ark_pkt_gen_inst_pmd",
80 : : sizeof(struct ark_pkt_gen_inst), 0);
81 [ # # ]: 0 : if (inst == NULL) {
82 : 0 : ARK_PMD_LOG(ERR, "Failed to malloc ark_pkt_gen_inst.\n");
83 : 0 : return inst;
84 : : }
85 : 0 : inst->regs = (struct ark_pkt_gen_regs *)adr;
86 : 0 : inst->ordinal = ord;
87 : 0 : inst->l2_mode = l2_mode;
88 : 0 : return inst;
89 : : }
90 : :
91 : : void
92 : 0 : ark_pktgen_uninit(ark_pkt_gen_t handle)
93 : : {
94 : 0 : rte_free(handle);
95 : 0 : }
96 : :
97 : : void
98 : 0 : ark_pktgen_run(ark_pkt_gen_t handle)
99 : : {
100 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
101 : :
102 : 0 : inst->regs->pkt_start_stop = 1;
103 : 0 : }
104 : :
105 : : uint32_t
106 : 0 : ark_pktgen_paused(ark_pkt_gen_t handle)
107 : : {
108 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
109 : 0 : uint32_t r = inst->regs->pkt_start_stop;
110 : :
111 [ # # # # ]: 0 : return (((r >> 24) & 1) == 1) || (((r >> 16) & 1) == 1) || (r == 0);
112 : : }
113 : :
114 : : void
115 : 0 : ark_pktgen_pause(ark_pkt_gen_t handle)
116 : : {
117 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
118 : : int cnt = 0;
119 : :
120 : 0 : inst->regs->pkt_start_stop = 0;
121 : :
122 [ # # ]: 0 : while (!ark_pktgen_paused(handle)) {
123 : 0 : usleep(1000);
124 [ # # ]: 0 : if (cnt++ > 100) {
125 : 0 : ARK_PMD_LOG(NOTICE, "Pktgen %d failed to pause.\n",
126 : : inst->ordinal);
127 : 0 : break;
128 : : }
129 : : }
130 : 0 : ARK_PMD_LOG(DEBUG, "Pktgen %d paused.\n", inst->ordinal);
131 : 0 : }
132 : :
133 : : void
134 : 0 : ark_pktgen_reset(ark_pkt_gen_t handle)
135 : : {
136 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
137 : :
138 [ # # # # ]: 0 : if (!ark_pktgen_is_running(handle) &&
139 : 0 : !ark_pktgen_paused(handle)) {
140 : 0 : ARK_PMD_LOG(DEBUG, "Pktgen %d is not running"
141 : : " and is not paused. No need to reset.\n",
142 : : inst->ordinal);
143 : 0 : return;
144 : : }
145 : :
146 [ # # # # ]: 0 : if (ark_pktgen_is_running(handle) &&
147 : 0 : !ark_pktgen_paused(handle)) {
148 : 0 : ARK_PMD_LOG(DEBUG,
149 : : "Pktgen %d is not paused. Pausing first.\n",
150 : : inst->ordinal);
151 : 0 : ark_pktgen_pause(handle);
152 : : }
153 : :
154 : 0 : ARK_PMD_LOG(DEBUG, "Resetting pktgen %d.\n", inst->ordinal);
155 : 0 : inst->regs->pkt_start_stop = (1 << 8);
156 : : }
157 : :
158 : : uint32_t
159 : 0 : ark_pktgen_tx_done(ark_pkt_gen_t handle)
160 : : {
161 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
162 : 0 : uint32_t r = inst->regs->pkt_start_stop;
163 : :
164 : 0 : return (((r >> 24) & 1) == 1);
165 : : }
166 : :
167 : : uint32_t
168 : 0 : ark_pktgen_is_running(ark_pkt_gen_t handle)
169 : : {
170 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
171 : 0 : uint32_t r = inst->regs->pkt_start_stop;
172 : :
173 : 0 : return ((r & 1) == 1);
174 : : }
175 : :
176 : : uint32_t
177 : 0 : ark_pktgen_is_gen_forever(ark_pkt_gen_t handle)
178 : : {
179 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
180 : 0 : uint32_t r = inst->regs->pkt_ctrl;
181 : :
182 : 0 : return (((r >> 24) & 1) == 1);
183 : : }
184 : :
185 : : void
186 : 0 : ark_pktgen_wait_done(ark_pkt_gen_t handle)
187 : : {
188 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
189 : : int wait_cycle = 10;
190 : :
191 [ # # ]: 0 : if (ark_pktgen_is_gen_forever(handle))
192 : 0 : ARK_PMD_LOG(NOTICE, "Pktgen wait_done will not terminate"
193 : : " because gen_forever=1\n");
194 : :
195 [ # # # # ]: 0 : while (!ark_pktgen_tx_done(handle) && (wait_cycle > 0)) {
196 : 0 : usleep(1000);
197 : 0 : wait_cycle--;
198 : 0 : ARK_PMD_LOG(DEBUG,
199 : : "Waiting for pktgen %d to finish sending...\n",
200 : : inst->ordinal);
201 : : }
202 : 0 : ARK_PMD_LOG(DEBUG, "Pktgen %d done.\n", inst->ordinal);
203 : 0 : }
204 : :
205 : : uint32_t
206 : 0 : ark_pktgen_get_pkts_sent(ark_pkt_gen_t handle)
207 : : {
208 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
209 : 0 : return inst->regs->pkts_sent;
210 : : }
211 : :
212 : : void
213 : 0 : ark_pktgen_set_payload_byte(ark_pkt_gen_t handle, uint32_t b)
214 : : {
215 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
216 : 0 : inst->regs->pkt_payload = b;
217 : 0 : }
218 : :
219 : : void
220 : 0 : ark_pktgen_set_pkt_spacing(ark_pkt_gen_t handle, uint32_t x)
221 : : {
222 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
223 : 0 : inst->regs->pkt_spacing = x;
224 : 0 : }
225 : :
226 : : void
227 : 0 : ark_pktgen_set_pkt_size_min(ark_pkt_gen_t handle, uint32_t x)
228 : : {
229 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
230 : 0 : inst->regs->pkt_size_min = x;
231 : 0 : }
232 : :
233 : : void
234 : 0 : ark_pktgen_set_pkt_size_max(ark_pkt_gen_t handle, uint32_t x)
235 : : {
236 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
237 : 0 : inst->regs->pkt_size_max = x;
238 : 0 : }
239 : :
240 : : void
241 : 0 : ark_pktgen_set_pkt_size_incr(ark_pkt_gen_t handle, uint32_t x)
242 : : {
243 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
244 : 0 : inst->regs->pkt_size_incr = x;
245 : 0 : }
246 : :
247 : : void
248 : 0 : ark_pktgen_set_num_pkts(ark_pkt_gen_t handle, uint32_t x)
249 : : {
250 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
251 : 0 : inst->regs->num_pkts = x;
252 : 0 : }
253 : :
254 : : void
255 : 0 : ark_pktgen_set_src_mac_addr(ark_pkt_gen_t handle, uint64_t mac_addr)
256 : : {
257 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
258 : 0 : inst->regs->src_mac_addr_h = (mac_addr >> 32) & 0xffff;
259 : 0 : inst->regs->src_mac_addr_l = mac_addr & 0xffffffff;
260 : 0 : }
261 : :
262 : : void
263 : 0 : ark_pktgen_set_dst_mac_addr(ark_pkt_gen_t handle, uint64_t mac_addr)
264 : : {
265 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
266 : 0 : inst->regs->dst_mac_addr_h = (mac_addr >> 32) & 0xffff;
267 : 0 : inst->regs->dst_mac_addr_l = mac_addr & 0xffffffff;
268 : 0 : }
269 : :
270 : : void
271 : 0 : ark_pktgen_set_eth_type(ark_pkt_gen_t handle, uint32_t x)
272 : : {
273 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
274 : 0 : inst->regs->eth_type = x;
275 : 0 : }
276 : :
277 : : void
278 : 0 : ark_pktgen_set_hdr_dW(ark_pkt_gen_t handle, uint32_t *hdr)
279 : : {
280 : : uint32_t i;
281 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
282 : :
283 [ # # ]: 0 : for (i = 0; i < 7; i++)
284 : 0 : inst->regs->hdr_dw[i] = hdr[i];
285 : 0 : }
286 : :
287 : : void
288 : 0 : ark_pktgen_set_start_offset(ark_pkt_gen_t handle, uint32_t x)
289 : : {
290 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
291 : :
292 : 0 : inst->regs->start_offset = x;
293 : 0 : }
294 : :
295 : : static struct OPTIONS *
296 : 0 : options(const char *id)
297 : : {
298 : : unsigned int i;
299 : :
300 [ # # ]: 0 : for (i = 0; i < sizeof(toptions) / sizeof(struct OPTIONS); i++) {
301 [ # # ]: 0 : if (strcmp(id, toptions[i].opt) == 0)
302 : 0 : return &toptions[i];
303 : : }
304 : :
305 : 0 : ARK_PMD_LOG(ERR,
306 : : "Pktgen: Could not find requested option!, "
307 : : "option = %s\n",
308 : : id
309 : : );
310 : 0 : return NULL;
311 : : }
312 : :
313 : : static int pmd_set_arg(char *arg, char *val);
314 : : static int
315 : 0 : pmd_set_arg(char *arg, char *val)
316 : : {
317 : 0 : struct OPTIONS *o = options(arg);
318 : :
319 [ # # ]: 0 : if (o) {
320 [ # # # # ]: 0 : switch (o->t) {
321 : : case OTINT:
322 : : case OTBOOL:
323 : 0 : o->v.INT = atoi(val);
324 : 0 : break;
325 : : case OTLONG:
326 : 0 : o->v.INT = atoll(val);
327 : 0 : break;
328 : 0 : case OTSTRING:
329 : 0 : strlcpy(o->v.STR, val, ARK_MAX_STR_LEN);
330 : : break;
331 : : }
332 : 0 : return 1;
333 : : }
334 : : return 0;
335 : : }
336 : :
337 : : /******
338 : : * Arg format = "opt0=v,opt_n=v ..."
339 : : ******/
340 : : void
341 : 0 : ark_pktgen_parse(char *args)
342 : : {
343 : : char *argv, *v;
344 : 0 : const char toks[] = " =\n\t\v\f \r";
345 : 0 : argv = strtok(args, toks);
346 : 0 : v = strtok(NULL, toks);
347 [ # # ]: 0 : while (argv && v) {
348 : 0 : pmd_set_arg(argv, v);
349 : 0 : argv = strtok(NULL, toks);
350 : 0 : v = strtok(NULL, toks);
351 : : }
352 : 0 : }
353 : :
354 : : static int32_t parse_ipv4_string(char const *ip_address);
355 : : static int32_t
356 : 0 : parse_ipv4_string(char const *ip_address)
357 : : {
358 : : unsigned int ip[4];
359 : :
360 [ # # ]: 0 : if (sscanf(ip_address, "%u.%u.%u.%u",
361 : : &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
362 : : return 0;
363 : 0 : return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
364 : : }
365 : :
366 : : static void
367 : 0 : ark_pktgen_set_pkt_ctrl(ark_pkt_gen_t handle,
368 : : uint32_t gen_forever,
369 : : uint32_t en_slaved_start,
370 : : uint32_t vary_length,
371 : : uint32_t incr_payload,
372 : : uint32_t incr_first_byte,
373 : : uint32_t ins_seq_num,
374 : : uint32_t ins_udp_hdr,
375 : : uint32_t ins_time_stamp)
376 : : {
377 : : uint32_t r;
378 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
379 : :
380 [ # # ]: 0 : if (!inst->l2_mode)
381 : : ins_udp_hdr = 0;
382 : :
383 : 0 : r = ((gen_forever << 24) |
384 : 0 : (en_slaved_start << 20) |
385 : 0 : (vary_length << 16) |
386 : 0 : (incr_payload << 12) |
387 : 0 : (incr_first_byte << 8) |
388 : 0 : (ins_time_stamp << 5) |
389 : 0 : (ins_seq_num << 4) |
390 : : ins_udp_hdr);
391 : :
392 : 0 : inst->regs->bytes_per_cycle = options("bytes_per_cycle")->v.INT;
393 [ # # ]: 0 : if (options("shaping")->v.BOOL)
394 : 0 : r = r | (1 << 28); /* enable shaping */
395 : :
396 : 0 : inst->regs->pkt_ctrl = r;
397 : 0 : }
398 : :
399 : : void
400 : 0 : ark_pktgen_setup(ark_pkt_gen_t handle)
401 : : {
402 : : uint32_t hdr[7];
403 : 0 : int32_t dst_ip = parse_ipv4_string(options("dst_ip")->v.STR);
404 : :
405 [ # # ]: 0 : if (!options("pause")->v.BOOL &&
406 [ # # ]: 0 : (!options("reset")->v.BOOL &&
407 [ # # ]: 0 : (options("configure")->v.BOOL))) {
408 : 0 : ark_pktgen_set_payload_byte(handle,
409 : 0 : options("payload_byte")->v.INT);
410 : 0 : ark_pktgen_set_src_mac_addr(handle,
411 : 0 : options("src_mac_addr")->v.INT);
412 : 0 : ark_pktgen_set_dst_mac_addr(handle,
413 : 0 : options("dst_mac_addr")->v.LONG);
414 : 0 : ark_pktgen_set_eth_type(handle,
415 : 0 : options("eth_type")->v.INT);
416 : :
417 [ # # ]: 0 : if (options("dg-mode")->v.BOOL) {
418 : 0 : hdr[0] = options("hdr_dW0")->v.INT;
419 : 0 : hdr[1] = options("hdr_dW1")->v.INT;
420 : 0 : hdr[2] = options("hdr_dW2")->v.INT;
421 : 0 : hdr[3] = options("hdr_dW3")->v.INT;
422 : 0 : hdr[4] = options("hdr_dW4")->v.INT;
423 : 0 : hdr[5] = options("hdr_dW5")->v.INT;
424 : 0 : hdr[6] = options("hdr_dW6")->v.INT;
425 : : } else {
426 : 0 : hdr[0] = dst_ip;
427 : 0 : hdr[1] = options("dst_port")->v.INT;
428 : 0 : hdr[2] = options("src_port")->v.INT;
429 : 0 : hdr[3] = 0;
430 : 0 : hdr[4] = 0;
431 : 0 : hdr[5] = 0;
432 : 0 : hdr[6] = 0;
433 : : }
434 : 0 : ark_pktgen_set_hdr_dW(handle, hdr);
435 : 0 : ark_pktgen_set_num_pkts(handle,
436 : 0 : options("num_pkts")->v.INT);
437 : 0 : ark_pktgen_set_pkt_size_min(handle,
438 : 0 : options("pkt_size_min")->v.INT);
439 : 0 : ark_pktgen_set_pkt_size_max(handle,
440 : 0 : options("pkt_size_max")->v.INT);
441 : 0 : ark_pktgen_set_pkt_size_incr(handle,
442 : 0 : options("pkt_size_incr")->v.INT);
443 : 0 : ark_pktgen_set_pkt_spacing(handle,
444 : 0 : options("pkt_spacing")->v.INT);
445 : 0 : ark_pktgen_set_start_offset(handle,
446 : 0 : options("start_offset")->v.INT);
447 : 0 : ark_pktgen_set_pkt_ctrl(handle,
448 : 0 : options("gen_forever")->v.BOOL,
449 : 0 : options("en_slaved_start")->v.BOOL,
450 : 0 : options("vary_length")->v.BOOL,
451 : 0 : options("incr_payload")->v.BOOL,
452 : 0 : options("incr_first_byte")->v.BOOL,
453 : 0 : options("ins_seq_num")->v.INT,
454 : 0 : options("ins_udp_hdr")->v.BOOL,
455 : 0 : options("ins_time_stamp")->v.INT);
456 : : }
457 : :
458 [ # # ]: 0 : if (options("pause")->v.BOOL)
459 : 0 : ark_pktgen_pause(handle);
460 : :
461 [ # # ]: 0 : if (options("reset")->v.BOOL)
462 : 0 : ark_pktgen_reset(handle);
463 [ # # ]: 0 : if (options("run")->v.BOOL) {
464 : 0 : ARK_PMD_LOG(DEBUG, "Starting packet generator on port %d\n",
465 : : options("port")->v.INT);
466 : 0 : ark_pktgen_run(handle);
467 : : }
468 : 0 : }
469 : :
470 : : uint32_t
471 : 0 : ark_pktgen_delay_start(void *arg)
472 : : {
473 : : struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)arg;
474 : :
475 : : /* This function is used exclusively for regression testing, We
476 : : * perform a blind sleep here to ensure that the external test
477 : : * application has time to setup the test before we generate packets
478 : : */
479 : 0 : rte_thread_detach(rte_thread_self());
480 : 0 : usleep(100000);
481 : 0 : ark_pktgen_run(inst);
482 : 0 : return 0;
483 : : }
|