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
11 #include "ark_pktchkr.h"
12 #include "ark_logs.h"
13
14 static int set_arg(char *arg, char *val);
15 static int ark_pktchkr_is_gen_forever(ark_pkt_chkr_t handle);
16
17 #define ARK_MAX_STR_LEN 64
18 union OPTV {
19 int INT;
20 int BOOL;
21 uint64_t LONG;
22 char STR[ARK_MAX_STR_LEN];
23 };
24
25 enum OPTYPE {
26 OTINT,
27 OTLONG,
28 OTBOOL,
29 OTSTRING
30 };
31
32 struct OPTIONS {
33 char opt[ARK_MAX_STR_LEN];
34 enum OPTYPE t;
35 union OPTV v;
36 };
37
38 static struct OPTIONS toptions[] = {
39 {{"configure"}, OTBOOL, {1} },
40 {{"port"}, OTINT, {0} },
41 {{"mac-dump"}, OTBOOL, {0} },
42 {{"dg-mode"}, OTBOOL, {1} },
43 {{"run"}, OTBOOL, {0} },
44 {{"stop"}, OTBOOL, {0} },
45 {{"dump"}, OTBOOL, {0} },
46 {{"en_resync"}, OTBOOL, {0} },
47 {{"tuser_err_val"}, OTINT, {1} },
48 {{"gen_forever"}, OTBOOL, {0} },
49 {{"en_slaved_start"}, OTBOOL, {0} },
50 {{"vary_length"}, OTBOOL, {0} },
51 {{"incr_payload"}, OTINT, {0} },
52 {{"incr_first_byte"}, OTBOOL, {0} },
53 {{"ins_seq_num"}, OTBOOL, {0} },
54 {{"ins_time_stamp"}, OTBOOL, {1} },
55 {{"ins_udp_hdr"}, OTBOOL, {0} },
56 {{"num_pkts"}, OTLONG, .v.LONG = 10000000000000L},
57 {{"payload_byte"}, OTINT, {0x55} },
58 {{"pkt_spacing"}, OTINT, {60} },
59 {{"pkt_size_min"}, OTINT, {2005} },
60 {{"pkt_size_max"}, OTINT, {1514} },
61 {{"pkt_size_incr"}, OTINT, {1} },
62 {{"eth_type"}, OTINT, {0x0800} },
63 {{"src_mac_addr"}, OTLONG, .v.LONG = 0xdC3cF6425060L},
64 {{"dst_mac_addr"}, OTLONG, .v.LONG = 0x112233445566L},
65 {{"hdr_dW0"}, OTINT, {0x0016e319} },
66 {{"hdr_dW1"}, OTINT, {0x27150004} },
67 {{"hdr_dW2"}, OTINT, {0x76967bda} },
68 {{"hdr_dW3"}, OTINT, {0x08004500} },
69 {{"hdr_dW4"}, OTINT, {0x005276ed} },
70 {{"hdr_dW5"}, OTINT, {0x40004006} },
71 {{"hdr_dW6"}, OTINT, {0x56cfc0a8} },
72 {{"start_offset"}, OTINT, {0} },
73 {{"dst_ip"}, OTSTRING, .v.STR = "169.254.10.240"},
74 {{"dst_port"}, OTINT, {65536} },
75 {{"src_port"}, OTINT, {65536} },
76 };
77
78 ark_pkt_chkr_t
ark_pktchkr_init(void * addr,int ord,int l2_mode)79 ark_pktchkr_init(void *addr, int ord, int l2_mode)
80 {
81 struct ark_pkt_chkr_inst *inst =
82 rte_malloc("ark_pkt_chkr_inst",
83 sizeof(struct ark_pkt_chkr_inst), 0);
84 if (inst == NULL) {
85 ARK_PMD_LOG(ERR, "Failed to malloc ark_pkt_chkr_inst.\n");
86 return inst;
87 }
88 inst->sregs = (struct ark_pkt_chkr_stat_regs *)addr;
89 inst->cregs =
90 (struct ark_pkt_chkr_ctl_regs *)(((uint8_t *)addr) + 0x100);
91 inst->ordinal = ord;
92 inst->l2_mode = l2_mode;
93 return inst;
94 }
95
96 void
ark_pktchkr_uninit(ark_pkt_chkr_t handle)97 ark_pktchkr_uninit(ark_pkt_chkr_t handle)
98 {
99 rte_free(handle);
100 }
101
102 void
ark_pktchkr_run(ark_pkt_chkr_t handle)103 ark_pktchkr_run(ark_pkt_chkr_t handle)
104 {
105 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
106
107 inst->sregs->pkt_start_stop = 0;
108 inst->sregs->pkt_start_stop = 0x1;
109 }
110
111 int
ark_pktchkr_stopped(ark_pkt_chkr_t handle)112 ark_pktchkr_stopped(ark_pkt_chkr_t handle)
113 {
114 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
115 uint32_t r = inst->sregs->pkt_start_stop;
116
117 return (((r >> 16) & 1) == 1) || (r == 0);
118 }
119
120 void
ark_pktchkr_stop(ark_pkt_chkr_t handle)121 ark_pktchkr_stop(ark_pkt_chkr_t handle)
122 {
123 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
124 int wait_cycle = 10;
125
126 inst->sregs->pkt_start_stop = 0;
127 while (!ark_pktchkr_stopped(handle) && (wait_cycle > 0)) {
128 usleep(1000);
129 wait_cycle--;
130 ARK_PMD_LOG(DEBUG, "Waiting for pktchk %d to stop...\n",
131 inst->ordinal);
132 }
133 ARK_PMD_LOG(DEBUG, "Pktchk %d stopped.\n", inst->ordinal);
134 }
135
136 int
ark_pktchkr_is_running(ark_pkt_chkr_t handle)137 ark_pktchkr_is_running(ark_pkt_chkr_t handle)
138 {
139 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
140 uint32_t r = inst->sregs->pkt_start_stop;
141
142 return ((r & 1) == 1);
143 }
144
145 static void
ark_pktchkr_set_pkt_ctrl(ark_pkt_chkr_t handle,uint32_t gen_forever,uint32_t vary_length,uint32_t incr_payload,uint32_t incr_first_byte,uint32_t ins_seq_num,uint32_t ins_udp_hdr,uint32_t en_resync,uint32_t tuser_err_val,uint32_t ins_time_stamp)146 ark_pktchkr_set_pkt_ctrl(ark_pkt_chkr_t handle,
147 uint32_t gen_forever,
148 uint32_t vary_length,
149 uint32_t incr_payload,
150 uint32_t incr_first_byte,
151 uint32_t ins_seq_num,
152 uint32_t ins_udp_hdr,
153 uint32_t en_resync,
154 uint32_t tuser_err_val,
155 uint32_t ins_time_stamp)
156 {
157 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
158 uint32_t r = (tuser_err_val << 16) | (en_resync << 0);
159
160 inst->sregs->pkt_ctrl = r;
161 if (!inst->l2_mode)
162 ins_udp_hdr = 0;
163 r = ((gen_forever << 24) |
164 (vary_length << 16) |
165 (incr_payload << 12) |
166 (incr_first_byte << 8) |
167 (ins_time_stamp << 5) |
168 (ins_seq_num << 4) |
169 ins_udp_hdr);
170 inst->cregs->pkt_ctrl = r;
171 }
172
173 static
174 int
ark_pktchkr_is_gen_forever(ark_pkt_chkr_t handle)175 ark_pktchkr_is_gen_forever(ark_pkt_chkr_t handle)
176 {
177 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
178 uint32_t r = inst->cregs->pkt_ctrl;
179
180 return (((r >> 24) & 1) == 1);
181 }
182
183 int
ark_pktchkr_wait_done(ark_pkt_chkr_t handle)184 ark_pktchkr_wait_done(ark_pkt_chkr_t handle)
185 {
186 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
187
188 if (ark_pktchkr_is_gen_forever(handle)) {
189 ARK_PMD_LOG(NOTICE, "Pktchk wait_done will not terminate"
190 " because gen_forever=1\n");
191 return -1;
192 }
193 int wait_cycle = 10;
194
195 while (!ark_pktchkr_stopped(handle) && (wait_cycle > 0)) {
196 usleep(1000);
197 wait_cycle--;
198 ARK_PMD_LOG(DEBUG, "Waiting for packet checker %d's"
199 " internal pktgen to finish sending...\n",
200 inst->ordinal);
201 ARK_PMD_LOG(DEBUG, "Pktchk %d's pktgen done.\n",
202 inst->ordinal);
203 }
204 return 0;
205 }
206
207 int
ark_pktchkr_get_pkts_sent(ark_pkt_chkr_t handle)208 ark_pktchkr_get_pkts_sent(ark_pkt_chkr_t handle)
209 {
210 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
211
212 return inst->cregs->pkts_sent;
213 }
214
215 void
ark_pktchkr_set_payload_byte(ark_pkt_chkr_t handle,uint32_t b)216 ark_pktchkr_set_payload_byte(ark_pkt_chkr_t handle, uint32_t b)
217 {
218 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
219
220 inst->cregs->pkt_payload = b;
221 }
222
223 void
ark_pktchkr_set_pkt_size_min(ark_pkt_chkr_t handle,uint32_t x)224 ark_pktchkr_set_pkt_size_min(ark_pkt_chkr_t handle, uint32_t x)
225 {
226 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
227
228 inst->cregs->pkt_size_min = x;
229 }
230
231 void
ark_pktchkr_set_pkt_size_max(ark_pkt_chkr_t handle,uint32_t x)232 ark_pktchkr_set_pkt_size_max(ark_pkt_chkr_t handle, uint32_t x)
233 {
234 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
235
236 inst->cregs->pkt_size_max = x;
237 }
238
239 void
ark_pktchkr_set_pkt_size_incr(ark_pkt_chkr_t handle,uint32_t x)240 ark_pktchkr_set_pkt_size_incr(ark_pkt_chkr_t handle, uint32_t x)
241 {
242 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
243
244 inst->cregs->pkt_size_incr = x;
245 }
246
247 void
ark_pktchkr_set_num_pkts(ark_pkt_chkr_t handle,uint32_t x)248 ark_pktchkr_set_num_pkts(ark_pkt_chkr_t handle, uint32_t x)
249 {
250 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
251
252 inst->cregs->num_pkts = x;
253 }
254
255 void
ark_pktchkr_set_src_mac_addr(ark_pkt_chkr_t handle,uint64_t mac_addr)256 ark_pktchkr_set_src_mac_addr(ark_pkt_chkr_t handle, uint64_t mac_addr)
257 {
258 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
259
260 inst->cregs->src_mac_addr_h = (mac_addr >> 32) & 0xffff;
261 inst->cregs->src_mac_addr_l = mac_addr & 0xffffffff;
262 }
263
264 void
ark_pktchkr_set_dst_mac_addr(ark_pkt_chkr_t handle,uint64_t mac_addr)265 ark_pktchkr_set_dst_mac_addr(ark_pkt_chkr_t handle, uint64_t mac_addr)
266 {
267 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
268
269 inst->cregs->dst_mac_addr_h = (mac_addr >> 32) & 0xffff;
270 inst->cregs->dst_mac_addr_l = mac_addr & 0xffffffff;
271 }
272
273 void
ark_pktchkr_set_eth_type(ark_pkt_chkr_t handle,uint32_t x)274 ark_pktchkr_set_eth_type(ark_pkt_chkr_t handle, uint32_t x)
275 {
276 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
277
278 inst->cregs->eth_type = x;
279 }
280
281 void
ark_pktchkr_set_hdr_dW(ark_pkt_chkr_t handle,uint32_t * hdr)282 ark_pktchkr_set_hdr_dW(ark_pkt_chkr_t handle, uint32_t *hdr)
283 {
284 uint32_t i;
285 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
286
287 for (i = 0; i < 7; i++)
288 inst->cregs->hdr_dw[i] = hdr[i];
289 }
290
291 void
ark_pktchkr_dump_stats(ark_pkt_chkr_t handle)292 ark_pktchkr_dump_stats(ark_pkt_chkr_t handle)
293 {
294 struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
295
296 ARK_PMD_LOG(INFO, "pkts_rcvd = (%'u)\n",
297 inst->sregs->pkts_rcvd);
298 ARK_PMD_LOG(INFO, "bytes_rcvd = (%'" PRIU64 ")\n",
299 inst->sregs->bytes_rcvd);
300 ARK_PMD_LOG(INFO, "pkts_ok = (%'u)\n",
301 inst->sregs->pkts_ok);
302 ARK_PMD_LOG(INFO, "pkts_mismatch = (%'u)\n",
303 inst->sregs->pkts_mismatch);
304 ARK_PMD_LOG(INFO, "pkts_err = (%'u)\n",
305 inst->sregs->pkts_err);
306 ARK_PMD_LOG(INFO, "first_mismatch = (%'u)\n",
307 inst->sregs->first_mismatch);
308 ARK_PMD_LOG(INFO, "resync_events = (%'u)\n",
309 inst->sregs->resync_events);
310 ARK_PMD_LOG(INFO, "pkts_missing = (%'u)\n",
311 inst->sregs->pkts_missing);
312 ARK_PMD_LOG(INFO, "min_latency = (%'u)\n",
313 inst->sregs->min_latency);
314 ARK_PMD_LOG(INFO, "max_latency = (%'u)\n",
315 inst->sregs->max_latency);
316 }
317
318 static struct OPTIONS *
options(const char * id)319 options(const char *id)
320 {
321 unsigned int i;
322
323 for (i = 0; i < sizeof(toptions) / sizeof(struct OPTIONS); i++) {
324 if (strcmp(id, toptions[i].opt) == 0)
325 return &toptions[i];
326 }
327 ARK_PMD_LOG(ERR,
328 "pktchkr: Could not find requested option!, option = %s\n",
329 id);
330 return NULL;
331 }
332
333 static int
set_arg(char * arg,char * val)334 set_arg(char *arg, char *val)
335 {
336 struct OPTIONS *o = options(arg);
337
338 if (o) {
339 switch (o->t) {
340 case OTINT:
341 case OTBOOL:
342 o->v.INT = atoi(val);
343 break;
344 case OTLONG:
345 o->v.INT = atoll(val);
346 break;
347 case OTSTRING:
348 strlcpy(o->v.STR, val, ARK_MAX_STR_LEN);
349 break;
350 }
351 return 1;
352 }
353 return 0;
354 }
355
356 /******
357 * Arg format = "opt0=v,opt_n=v ..."
358 ******/
359 void
ark_pktchkr_parse(char * args)360 ark_pktchkr_parse(char *args)
361 {
362 char *argv, *v;
363 const char toks[] = "=\n\t\v\f \r";
364 argv = strtok(args, toks);
365 v = strtok(NULL, toks);
366 while (argv && v) {
367 set_arg(argv, v);
368 argv = strtok(NULL, toks);
369 v = strtok(NULL, toks);
370 }
371 }
372
373 static int32_t parse_ipv4_string(char const *ip_address);
374 static int32_t
parse_ipv4_string(char const * ip_address)375 parse_ipv4_string(char const *ip_address)
376 {
377 unsigned int ip[4];
378
379 if (sscanf(ip_address, "%u.%u.%u.%u",
380 &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
381 return 0;
382 return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
383 }
384
385 void
ark_pktchkr_setup(ark_pkt_chkr_t handle)386 ark_pktchkr_setup(ark_pkt_chkr_t handle)
387 {
388 uint32_t hdr[7];
389 int32_t dst_ip = parse_ipv4_string(options("dst_ip")->v.STR);
390
391 if (!options("stop")->v.BOOL && options("configure")->v.BOOL) {
392 ark_pktchkr_set_payload_byte(handle,
393 options("payload_byte")->v.INT);
394 ark_pktchkr_set_src_mac_addr(handle,
395 options("src_mac_addr")->v.INT);
396 ark_pktchkr_set_dst_mac_addr(handle,
397 options("dst_mac_addr")->v.LONG);
398
399 ark_pktchkr_set_eth_type(handle,
400 options("eth_type")->v.INT);
401 if (options("dg-mode")->v.BOOL) {
402 hdr[0] = options("hdr_dW0")->v.INT;
403 hdr[1] = options("hdr_dW1")->v.INT;
404 hdr[2] = options("hdr_dW2")->v.INT;
405 hdr[3] = options("hdr_dW3")->v.INT;
406 hdr[4] = options("hdr_dW4")->v.INT;
407 hdr[5] = options("hdr_dW5")->v.INT;
408 hdr[6] = options("hdr_dW6")->v.INT;
409 } else {
410 hdr[0] = dst_ip;
411 hdr[1] = options("dst_port")->v.INT;
412 hdr[2] = options("src_port")->v.INT;
413 hdr[3] = 0;
414 hdr[4] = 0;
415 hdr[5] = 0;
416 hdr[6] = 0;
417 }
418 ark_pktchkr_set_hdr_dW(handle, hdr);
419 ark_pktchkr_set_num_pkts(handle,
420 options("num_pkts")->v.INT);
421 ark_pktchkr_set_pkt_size_min(handle,
422 options("pkt_size_min")->v.INT);
423 ark_pktchkr_set_pkt_size_max(handle,
424 options("pkt_size_max")->v.INT);
425 ark_pktchkr_set_pkt_size_incr(handle,
426 options("pkt_size_incr")->v.INT);
427 ark_pktchkr_set_pkt_ctrl(handle,
428 options("gen_forever")->v.BOOL,
429 options("vary_length")->v.BOOL,
430 options("incr_payload")->v.BOOL,
431 options("incr_first_byte")->v.BOOL,
432 options("ins_seq_num")->v.INT,
433 options("ins_udp_hdr")->v.BOOL,
434 options("en_resync")->v.BOOL,
435 options("tuser_err_val")->v.INT,
436 options("ins_time_stamp")->v.INT);
437 }
438
439 if (options("stop")->v.BOOL)
440 ark_pktchkr_stop(handle);
441
442 if (options("run")->v.BOOL) {
443 ARK_PMD_LOG(DEBUG, "Starting packet checker on port %d\n",
444 options("port")->v.INT);
445 ark_pktchkr_run(handle);
446 }
447 }
448