62b3673b8792c54dc1c3631bab920a90aa020da8
[deb_dpdk.git] / drivers / net / ark / ark_pktchkr.c
1 /*-
2  * BSD LICENSE
3  *
4  * Copyright (c) 2015-2017 Atomic Rules LLC
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  * * Neither the name of copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <getopt.h>
35 #include <sys/time.h>
36 #include <locale.h>
37 #include <unistd.h>
38
39 #include <rte_ethdev.h>
40 #include <rte_malloc.h>
41
42 #include "ark_pktchkr.h"
43 #include "ark_logs.h"
44
45 static int set_arg(char *arg, char *val);
46 static int ark_pktchkr_is_gen_forever(ark_pkt_chkr_t handle);
47
48 #define ARK_MAX_STR_LEN 64
49 union OPTV {
50         int INT;
51         int BOOL;
52         uint64_t LONG;
53         char STR[ARK_MAX_STR_LEN];
54 };
55
56 enum OPTYPE {
57         OTINT,
58         OTLONG,
59         OTBOOL,
60         OTSTRING
61 };
62
63 struct OPTIONS {
64         char opt[ARK_MAX_STR_LEN];
65         enum OPTYPE t;
66         union OPTV v;
67 };
68
69 static struct OPTIONS toptions[] = {
70         {{"configure"}, OTBOOL, {1} },
71         {{"port"}, OTINT, {0} },
72         {{"mac-dump"}, OTBOOL, {0} },
73         {{"dg-mode"}, OTBOOL, {1} },
74         {{"run"}, OTBOOL, {0} },
75         {{"stop"}, OTBOOL, {0} },
76         {{"dump"}, OTBOOL, {0} },
77         {{"en_resync"}, OTBOOL, {0} },
78         {{"tuser_err_val"}, OTINT, {1} },
79         {{"gen_forever"}, OTBOOL, {0} },
80         {{"en_slaved_start"}, OTBOOL, {0} },
81         {{"vary_length"}, OTBOOL, {0} },
82         {{"incr_payload"}, OTINT, {0} },
83         {{"incr_first_byte"}, OTBOOL, {0} },
84         {{"ins_seq_num"}, OTBOOL, {0} },
85         {{"ins_time_stamp"}, OTBOOL, {1} },
86         {{"ins_udp_hdr"}, OTBOOL, {0} },
87         {{"num_pkts"}, OTLONG, .v.LONG = 10000000000000L},
88         {{"payload_byte"}, OTINT, {0x55} },
89         {{"pkt_spacing"}, OTINT, {60} },
90         {{"pkt_size_min"}, OTINT, {2005} },
91         {{"pkt_size_max"}, OTINT, {1514} },
92         {{"pkt_size_incr"}, OTINT, {1} },
93         {{"eth_type"}, OTINT, {0x0800} },
94         {{"src_mac_addr"}, OTLONG, .v.LONG = 0xdC3cF6425060L},
95         {{"dst_mac_addr"}, OTLONG, .v.LONG = 0x112233445566L},
96         {{"hdr_dW0"}, OTINT, {0x0016e319} },
97         {{"hdr_dW1"}, OTINT, {0x27150004} },
98         {{"hdr_dW2"}, OTINT, {0x76967bda} },
99         {{"hdr_dW3"}, OTINT, {0x08004500} },
100         {{"hdr_dW4"}, OTINT, {0x005276ed} },
101         {{"hdr_dW5"}, OTINT, {0x40004006} },
102         {{"hdr_dW6"}, OTINT, {0x56cfc0a8} },
103         {{"start_offset"}, OTINT, {0} },
104         {{"dst_ip"}, OTSTRING, .v.STR = "169.254.10.240"},
105         {{"dst_port"}, OTINT, {65536} },
106         {{"src_port"}, OTINT, {65536} },
107 };
108
109 ark_pkt_chkr_t
110 ark_pktchkr_init(void *addr, int ord, int l2_mode)
111 {
112         struct ark_pkt_chkr_inst *inst =
113                 rte_malloc("ark_pkt_chkr_inst",
114                            sizeof(struct ark_pkt_chkr_inst), 0);
115         inst->sregs = (struct ark_pkt_chkr_stat_regs *)addr;
116         inst->cregs =
117                 (struct ark_pkt_chkr_ctl_regs *)(((uint8_t *)addr) + 0x100);
118         inst->ordinal = ord;
119         inst->l2_mode = l2_mode;
120         return inst;
121 }
122
123 void
124 ark_pktchkr_uninit(ark_pkt_chkr_t handle)
125 {
126         rte_free(handle);
127 }
128
129 void
130 ark_pktchkr_run(ark_pkt_chkr_t handle)
131 {
132         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
133
134         inst->sregs->pkt_start_stop = 0;
135         inst->sregs->pkt_start_stop = 0x1;
136 }
137
138 int
139 ark_pktchkr_stopped(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 >> 16) & 1) == 1);
145 }
146
147 void
148 ark_pktchkr_stop(ark_pkt_chkr_t handle)
149 {
150         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
151         int wait_cycle = 10;
152
153         inst->sregs->pkt_start_stop = 0;
154         while (!ark_pktchkr_stopped(handle) && (wait_cycle > 0)) {
155                 usleep(1000);
156                 wait_cycle--;
157                 PMD_DEBUG_LOG(DEBUG, "Waiting for pktchk %d to stop...\n",
158                               inst->ordinal);
159         }
160         PMD_DEBUG_LOG(DEBUG, "Pktchk %d stopped.\n", inst->ordinal);
161 }
162
163 int
164 ark_pktchkr_is_running(ark_pkt_chkr_t handle)
165 {
166         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
167         uint32_t r = inst->sregs->pkt_start_stop;
168
169         return ((r & 1) == 1);
170 }
171
172 static void
173 ark_pktchkr_set_pkt_ctrl(ark_pkt_chkr_t handle,
174                          uint32_t gen_forever,
175                          uint32_t vary_length,
176                          uint32_t incr_payload,
177                          uint32_t incr_first_byte,
178                          uint32_t ins_seq_num,
179                          uint32_t ins_udp_hdr,
180                          uint32_t en_resync,
181                          uint32_t tuser_err_val,
182                          uint32_t ins_time_stamp)
183 {
184         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
185         uint32_t r = (tuser_err_val << 16) | (en_resync << 0);
186
187         inst->sregs->pkt_ctrl = r;
188         if (!inst->l2_mode)
189                 ins_udp_hdr = 0;
190         r = ((gen_forever << 24) |
191              (vary_length << 16) |
192              (incr_payload << 12) |
193              (incr_first_byte << 8) |
194              (ins_time_stamp << 5) |
195              (ins_seq_num << 4) |
196              ins_udp_hdr);
197         inst->cregs->pkt_ctrl = r;
198 }
199
200 static
201 int
202 ark_pktchkr_is_gen_forever(ark_pkt_chkr_t handle)
203 {
204         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
205         uint32_t r = inst->cregs->pkt_ctrl;
206
207         return (((r >> 24) & 1) == 1);
208 }
209
210 int
211 ark_pktchkr_wait_done(ark_pkt_chkr_t handle)
212 {
213         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
214
215         if (ark_pktchkr_is_gen_forever(handle)) {
216                 PMD_DEBUG_LOG(ERR, "Pktchk wait_done will not terminate"
217                               " because gen_forever=1\n");
218                 return -1;
219         }
220         int wait_cycle = 10;
221
222         while (!ark_pktchkr_stopped(handle) && (wait_cycle > 0)) {
223                 usleep(1000);
224                 wait_cycle--;
225                 PMD_DEBUG_LOG(DEBUG, "Waiting for packet checker %d's"
226                               " internal pktgen to finish sending...\n",
227                               inst->ordinal);
228                 PMD_DEBUG_LOG(DEBUG, "Pktchk %d's pktgen done.\n",
229                               inst->ordinal);
230         }
231         return 0;
232 }
233
234 int
235 ark_pktchkr_get_pkts_sent(ark_pkt_chkr_t handle)
236 {
237         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
238
239         return inst->cregs->pkts_sent;
240 }
241
242 void
243 ark_pktchkr_set_payload_byte(ark_pkt_chkr_t handle, uint32_t b)
244 {
245         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
246
247         inst->cregs->pkt_payload = b;
248 }
249
250 void
251 ark_pktchkr_set_pkt_size_min(ark_pkt_chkr_t handle, uint32_t x)
252 {
253         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
254
255         inst->cregs->pkt_size_min = x;
256 }
257
258 void
259 ark_pktchkr_set_pkt_size_max(ark_pkt_chkr_t handle, uint32_t x)
260 {
261         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
262
263         inst->cregs->pkt_size_max = x;
264 }
265
266 void
267 ark_pktchkr_set_pkt_size_incr(ark_pkt_chkr_t handle, uint32_t x)
268 {
269         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
270
271         inst->cregs->pkt_size_incr = x;
272 }
273
274 void
275 ark_pktchkr_set_num_pkts(ark_pkt_chkr_t handle, uint32_t x)
276 {
277         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
278
279         inst->cregs->num_pkts = x;
280 }
281
282 void
283 ark_pktchkr_set_src_mac_addr(ark_pkt_chkr_t handle, uint64_t mac_addr)
284 {
285         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
286
287         inst->cregs->src_mac_addr_h = (mac_addr >> 32) & 0xffff;
288         inst->cregs->src_mac_addr_l = mac_addr & 0xffffffff;
289 }
290
291 void
292 ark_pktchkr_set_dst_mac_addr(ark_pkt_chkr_t handle, uint64_t mac_addr)
293 {
294         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
295
296         inst->cregs->dst_mac_addr_h = (mac_addr >> 32) & 0xffff;
297         inst->cregs->dst_mac_addr_l = mac_addr & 0xffffffff;
298 }
299
300 void
301 ark_pktchkr_set_eth_type(ark_pkt_chkr_t handle, uint32_t x)
302 {
303         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
304
305         inst->cregs->eth_type = x;
306 }
307
308 void
309 ark_pktchkr_set_hdr_dW(ark_pkt_chkr_t handle, uint32_t *hdr)
310 {
311         uint32_t i;
312         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
313
314         for (i = 0; i < 7; i++)
315                 inst->cregs->hdr_dw[i] = hdr[i];
316 }
317
318 void
319 ark_pktchkr_dump_stats(ark_pkt_chkr_t handle)
320 {
321         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
322
323         PMD_STATS_LOG(INFO, "pkts_rcvd      = (%'u)\n",
324                       inst->sregs->pkts_rcvd);
325         PMD_STATS_LOG(INFO, "bytes_rcvd     = (%'" PRIU64 ")\n",
326                       inst->sregs->bytes_rcvd);
327         PMD_STATS_LOG(INFO, "pkts_ok        = (%'u)\n",
328                       inst->sregs->pkts_ok);
329         PMD_STATS_LOG(INFO, "pkts_mismatch  = (%'u)\n",
330                       inst->sregs->pkts_mismatch);
331         PMD_STATS_LOG(INFO, "pkts_err       = (%'u)\n",
332                       inst->sregs->pkts_err);
333         PMD_STATS_LOG(INFO, "first_mismatch = (%'u)\n",
334                       inst->sregs->first_mismatch);
335         PMD_STATS_LOG(INFO, "resync_events  = (%'u)\n",
336                       inst->sregs->resync_events);
337         PMD_STATS_LOG(INFO, "pkts_missing   = (%'u)\n",
338                       inst->sregs->pkts_missing);
339         PMD_STATS_LOG(INFO, "min_latency    = (%'u)\n",
340                       inst->sregs->min_latency);
341         PMD_STATS_LOG(INFO, "max_latency    = (%'u)\n",
342                       inst->sregs->max_latency);
343 }
344
345 static struct OPTIONS *
346 options(const char *id)
347 {
348         unsigned int i;
349
350         for (i = 0; i < sizeof(toptions) / sizeof(struct OPTIONS); i++) {
351                 if (strcmp(id, toptions[i].opt) == 0)
352                         return &toptions[i];
353         }
354         PMD_DRV_LOG(ERR,
355                     "pktchkr: Could not find requested option!, option = %s\n",
356                     id);
357         return NULL;
358 }
359
360 static int
361 set_arg(char *arg, char *val)
362 {
363         struct OPTIONS *o = options(arg);
364
365         if (o) {
366                 switch (o->t) {
367                 case OTINT:
368                 case OTBOOL:
369                         o->v.INT = atoi(val);
370                         break;
371                 case OTLONG:
372                         o->v.INT = atoll(val);
373                         break;
374                 case OTSTRING:
375                         strncpy(o->v.STR, val, ARK_MAX_STR_LEN);
376                         break;
377                 }
378                 return 1;
379         }
380         return 0;
381 }
382
383 /******
384  * Arg format = "opt0=v,opt_n=v ..."
385  ******/
386 void
387 ark_pktchkr_parse(char *args)
388 {
389         char *argv, *v;
390         const char toks[] = "=\n\t\v\f \r";
391         argv = strtok(args, toks);
392         v = strtok(NULL, toks);
393         while (argv && v) {
394                 set_arg(argv, v);
395                 argv = strtok(NULL, toks);
396                 v = strtok(NULL, toks);
397         }
398 }
399
400 static int32_t parse_ipv4_string(char const *ip_address);
401 static int32_t
402 parse_ipv4_string(char const *ip_address)
403 {
404         unsigned int ip[4];
405
406         if (sscanf(ip_address, "%u.%u.%u.%u",
407                    &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
408                 return 0;
409         return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
410 }
411
412 void
413 ark_pktchkr_setup(ark_pkt_chkr_t handle)
414 {
415         uint32_t hdr[7];
416         int32_t dst_ip = parse_ipv4_string(options("dst_ip")->v.STR);
417
418         if (!options("stop")->v.BOOL && options("configure")->v.BOOL) {
419                 ark_pktchkr_set_payload_byte(handle,
420                                              options("payload_byte")->v.INT);
421                 ark_pktchkr_set_src_mac_addr(handle,
422                                              options("src_mac_addr")->v.INT);
423                 ark_pktchkr_set_dst_mac_addr(handle,
424                                              options("dst_mac_addr")->v.LONG);
425
426                 ark_pktchkr_set_eth_type(handle,
427                                          options("eth_type")->v.INT);
428                 if (options("dg-mode")->v.BOOL) {
429                         hdr[0] = options("hdr_dW0")->v.INT;
430                         hdr[1] = options("hdr_dW1")->v.INT;
431                         hdr[2] = options("hdr_dW2")->v.INT;
432                         hdr[3] = options("hdr_dW3")->v.INT;
433                         hdr[4] = options("hdr_dW4")->v.INT;
434                         hdr[5] = options("hdr_dW5")->v.INT;
435                         hdr[6] = options("hdr_dW6")->v.INT;
436                 } else {
437                         hdr[0] = dst_ip;
438                         hdr[1] = options("dst_port")->v.INT;
439                         hdr[2] = options("src_port")->v.INT;
440                         hdr[3] = 0;
441                         hdr[4] = 0;
442                         hdr[5] = 0;
443                         hdr[6] = 0;
444                 }
445                 ark_pktchkr_set_hdr_dW(handle, hdr);
446                 ark_pktchkr_set_num_pkts(handle,
447                                          options("num_pkts")->v.INT);
448                 ark_pktchkr_set_pkt_size_min(handle,
449                                              options("pkt_size_min")->v.INT);
450                 ark_pktchkr_set_pkt_size_max(handle,
451                                              options("pkt_size_max")->v.INT);
452                 ark_pktchkr_set_pkt_size_incr(handle,
453                                               options("pkt_size_incr")->v.INT);
454                 ark_pktchkr_set_pkt_ctrl(handle,
455                                          options("gen_forever")->v.BOOL,
456                                          options("vary_length")->v.BOOL,
457                                          options("incr_payload")->v.BOOL,
458                                          options("incr_first_byte")->v.BOOL,
459                                          options("ins_seq_num")->v.INT,
460                                          options("ins_udp_hdr")->v.BOOL,
461                                          options("en_resync")->v.BOOL,
462                                          options("tuser_err_val")->v.INT,
463                                          options("ins_time_stamp")->v.INT);
464         }
465
466         if (options("stop")->v.BOOL)
467                 ark_pktchkr_stop(handle);
468
469         if (options("run")->v.BOOL) {
470                 PMD_DEBUG_LOG(DEBUG, "Starting packet checker on port %d\n",
471                               options("port")->v.INT);
472                 ark_pktchkr_run(handle);
473         }
474 }