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