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