New upstream version 18.02
[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_driver.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         if (inst == NULL) {
116                 PMD_DRV_LOG(ERR, "Failed to malloc ark_pkt_chkr_inst.\n");
117                 return inst;
118         }
119         inst->sregs = (struct ark_pkt_chkr_stat_regs *)addr;
120         inst->cregs =
121                 (struct ark_pkt_chkr_ctl_regs *)(((uint8_t *)addr) + 0x100);
122         inst->ordinal = ord;
123         inst->l2_mode = l2_mode;
124         return inst;
125 }
126
127 void
128 ark_pktchkr_uninit(ark_pkt_chkr_t handle)
129 {
130         rte_free(handle);
131 }
132
133 void
134 ark_pktchkr_run(ark_pkt_chkr_t handle)
135 {
136         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
137
138         inst->sregs->pkt_start_stop = 0;
139         inst->sregs->pkt_start_stop = 0x1;
140 }
141
142 int
143 ark_pktchkr_stopped(ark_pkt_chkr_t handle)
144 {
145         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
146         uint32_t r = inst->sregs->pkt_start_stop;
147
148         return (((r >> 16) & 1) == 1);
149 }
150
151 void
152 ark_pktchkr_stop(ark_pkt_chkr_t handle)
153 {
154         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
155         int wait_cycle = 10;
156
157         inst->sregs->pkt_start_stop = 0;
158         while (!ark_pktchkr_stopped(handle) && (wait_cycle > 0)) {
159                 usleep(1000);
160                 wait_cycle--;
161                 PMD_DEBUG_LOG(DEBUG, "Waiting for pktchk %d to stop...\n",
162                               inst->ordinal);
163         }
164         PMD_DEBUG_LOG(DEBUG, "Pktchk %d stopped.\n", inst->ordinal);
165 }
166
167 int
168 ark_pktchkr_is_running(ark_pkt_chkr_t handle)
169 {
170         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
171         uint32_t r = inst->sregs->pkt_start_stop;
172
173         return ((r & 1) == 1);
174 }
175
176 static void
177 ark_pktchkr_set_pkt_ctrl(ark_pkt_chkr_t handle,
178                          uint32_t gen_forever,
179                          uint32_t vary_length,
180                          uint32_t incr_payload,
181                          uint32_t incr_first_byte,
182                          uint32_t ins_seq_num,
183                          uint32_t ins_udp_hdr,
184                          uint32_t en_resync,
185                          uint32_t tuser_err_val,
186                          uint32_t ins_time_stamp)
187 {
188         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
189         uint32_t r = (tuser_err_val << 16) | (en_resync << 0);
190
191         inst->sregs->pkt_ctrl = r;
192         if (!inst->l2_mode)
193                 ins_udp_hdr = 0;
194         r = ((gen_forever << 24) |
195              (vary_length << 16) |
196              (incr_payload << 12) |
197              (incr_first_byte << 8) |
198              (ins_time_stamp << 5) |
199              (ins_seq_num << 4) |
200              ins_udp_hdr);
201         inst->cregs->pkt_ctrl = r;
202 }
203
204 static
205 int
206 ark_pktchkr_is_gen_forever(ark_pkt_chkr_t handle)
207 {
208         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
209         uint32_t r = inst->cregs->pkt_ctrl;
210
211         return (((r >> 24) & 1) == 1);
212 }
213
214 int
215 ark_pktchkr_wait_done(ark_pkt_chkr_t handle)
216 {
217         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
218
219         if (ark_pktchkr_is_gen_forever(handle)) {
220                 PMD_DEBUG_LOG(ERR, "Pktchk wait_done will not terminate"
221                               " because gen_forever=1\n");
222                 return -1;
223         }
224         int wait_cycle = 10;
225
226         while (!ark_pktchkr_stopped(handle) && (wait_cycle > 0)) {
227                 usleep(1000);
228                 wait_cycle--;
229                 PMD_DEBUG_LOG(DEBUG, "Waiting for packet checker %d's"
230                               " internal pktgen to finish sending...\n",
231                               inst->ordinal);
232                 PMD_DEBUG_LOG(DEBUG, "Pktchk %d's pktgen done.\n",
233                               inst->ordinal);
234         }
235         return 0;
236 }
237
238 int
239 ark_pktchkr_get_pkts_sent(ark_pkt_chkr_t handle)
240 {
241         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
242
243         return inst->cregs->pkts_sent;
244 }
245
246 void
247 ark_pktchkr_set_payload_byte(ark_pkt_chkr_t handle, uint32_t b)
248 {
249         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
250
251         inst->cregs->pkt_payload = b;
252 }
253
254 void
255 ark_pktchkr_set_pkt_size_min(ark_pkt_chkr_t handle, uint32_t x)
256 {
257         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
258
259         inst->cregs->pkt_size_min = x;
260 }
261
262 void
263 ark_pktchkr_set_pkt_size_max(ark_pkt_chkr_t handle, uint32_t x)
264 {
265         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
266
267         inst->cregs->pkt_size_max = x;
268 }
269
270 void
271 ark_pktchkr_set_pkt_size_incr(ark_pkt_chkr_t handle, uint32_t x)
272 {
273         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
274
275         inst->cregs->pkt_size_incr = x;
276 }
277
278 void
279 ark_pktchkr_set_num_pkts(ark_pkt_chkr_t handle, uint32_t x)
280 {
281         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
282
283         inst->cregs->num_pkts = x;
284 }
285
286 void
287 ark_pktchkr_set_src_mac_addr(ark_pkt_chkr_t handle, uint64_t mac_addr)
288 {
289         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
290
291         inst->cregs->src_mac_addr_h = (mac_addr >> 32) & 0xffff;
292         inst->cregs->src_mac_addr_l = mac_addr & 0xffffffff;
293 }
294
295 void
296 ark_pktchkr_set_dst_mac_addr(ark_pkt_chkr_t handle, uint64_t mac_addr)
297 {
298         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
299
300         inst->cregs->dst_mac_addr_h = (mac_addr >> 32) & 0xffff;
301         inst->cregs->dst_mac_addr_l = mac_addr & 0xffffffff;
302 }
303
304 void
305 ark_pktchkr_set_eth_type(ark_pkt_chkr_t handle, uint32_t x)
306 {
307         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
308
309         inst->cregs->eth_type = x;
310 }
311
312 void
313 ark_pktchkr_set_hdr_dW(ark_pkt_chkr_t handle, uint32_t *hdr)
314 {
315         uint32_t i;
316         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
317
318         for (i = 0; i < 7; i++)
319                 inst->cregs->hdr_dw[i] = hdr[i];
320 }
321
322 void
323 ark_pktchkr_dump_stats(ark_pkt_chkr_t handle)
324 {
325         struct ark_pkt_chkr_inst *inst = (struct ark_pkt_chkr_inst *)handle;
326
327         PMD_STATS_LOG(INFO, "pkts_rcvd      = (%'u)\n",
328                       inst->sregs->pkts_rcvd);
329         PMD_STATS_LOG(INFO, "bytes_rcvd     = (%'" PRIU64 ")\n",
330                       inst->sregs->bytes_rcvd);
331         PMD_STATS_LOG(INFO, "pkts_ok        = (%'u)\n",
332                       inst->sregs->pkts_ok);
333         PMD_STATS_LOG(INFO, "pkts_mismatch  = (%'u)\n",
334                       inst->sregs->pkts_mismatch);
335         PMD_STATS_LOG(INFO, "pkts_err       = (%'u)\n",
336                       inst->sregs->pkts_err);
337         PMD_STATS_LOG(INFO, "first_mismatch = (%'u)\n",
338                       inst->sregs->first_mismatch);
339         PMD_STATS_LOG(INFO, "resync_events  = (%'u)\n",
340                       inst->sregs->resync_events);
341         PMD_STATS_LOG(INFO, "pkts_missing   = (%'u)\n",
342                       inst->sregs->pkts_missing);
343         PMD_STATS_LOG(INFO, "min_latency    = (%'u)\n",
344                       inst->sregs->min_latency);
345         PMD_STATS_LOG(INFO, "max_latency    = (%'u)\n",
346                       inst->sregs->max_latency);
347 }
348
349 static struct OPTIONS *
350 options(const char *id)
351 {
352         unsigned int i;
353
354         for (i = 0; i < sizeof(toptions) / sizeof(struct OPTIONS); i++) {
355                 if (strcmp(id, toptions[i].opt) == 0)
356                         return &toptions[i];
357         }
358         PMD_DRV_LOG(ERR,
359                     "pktchkr: Could not find requested option!, option = %s\n",
360                     id);
361         return NULL;
362 }
363
364 static int
365 set_arg(char *arg, char *val)
366 {
367         struct OPTIONS *o = options(arg);
368
369         if (o) {
370                 switch (o->t) {
371                 case OTINT:
372                 case OTBOOL:
373                         o->v.INT = atoi(val);
374                         break;
375                 case OTLONG:
376                         o->v.INT = atoll(val);
377                         break;
378                 case OTSTRING:
379                         snprintf(o->v.STR, ARK_MAX_STR_LEN, "%s", val);
380                         break;
381                 }
382                 return 1;
383         }
384         return 0;
385 }
386
387 /******
388  * Arg format = "opt0=v,opt_n=v ..."
389  ******/
390 void
391 ark_pktchkr_parse(char *args)
392 {
393         char *argv, *v;
394         const char toks[] = "=\n\t\v\f \r";
395         argv = strtok(args, toks);
396         v = strtok(NULL, toks);
397         while (argv && v) {
398                 set_arg(argv, v);
399                 argv = strtok(NULL, toks);
400                 v = strtok(NULL, toks);
401         }
402 }
403
404 static int32_t parse_ipv4_string(char const *ip_address);
405 static int32_t
406 parse_ipv4_string(char const *ip_address)
407 {
408         unsigned int ip[4];
409
410         if (sscanf(ip_address, "%u.%u.%u.%u",
411                    &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
412                 return 0;
413         return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
414 }
415
416 void
417 ark_pktchkr_setup(ark_pkt_chkr_t handle)
418 {
419         uint32_t hdr[7];
420         int32_t dst_ip = parse_ipv4_string(options("dst_ip")->v.STR);
421
422         if (!options("stop")->v.BOOL && options("configure")->v.BOOL) {
423                 ark_pktchkr_set_payload_byte(handle,
424                                              options("payload_byte")->v.INT);
425                 ark_pktchkr_set_src_mac_addr(handle,
426                                              options("src_mac_addr")->v.INT);
427                 ark_pktchkr_set_dst_mac_addr(handle,
428                                              options("dst_mac_addr")->v.LONG);
429
430                 ark_pktchkr_set_eth_type(handle,
431                                          options("eth_type")->v.INT);
432                 if (options("dg-mode")->v.BOOL) {
433                         hdr[0] = options("hdr_dW0")->v.INT;
434                         hdr[1] = options("hdr_dW1")->v.INT;
435                         hdr[2] = options("hdr_dW2")->v.INT;
436                         hdr[3] = options("hdr_dW3")->v.INT;
437                         hdr[4] = options("hdr_dW4")->v.INT;
438                         hdr[5] = options("hdr_dW5")->v.INT;
439                         hdr[6] = options("hdr_dW6")->v.INT;
440                 } else {
441                         hdr[0] = dst_ip;
442                         hdr[1] = options("dst_port")->v.INT;
443                         hdr[2] = options("src_port")->v.INT;
444                         hdr[3] = 0;
445                         hdr[4] = 0;
446                         hdr[5] = 0;
447                         hdr[6] = 0;
448                 }
449                 ark_pktchkr_set_hdr_dW(handle, hdr);
450                 ark_pktchkr_set_num_pkts(handle,
451                                          options("num_pkts")->v.INT);
452                 ark_pktchkr_set_pkt_size_min(handle,
453                                              options("pkt_size_min")->v.INT);
454                 ark_pktchkr_set_pkt_size_max(handle,
455                                              options("pkt_size_max")->v.INT);
456                 ark_pktchkr_set_pkt_size_incr(handle,
457                                               options("pkt_size_incr")->v.INT);
458                 ark_pktchkr_set_pkt_ctrl(handle,
459                                          options("gen_forever")->v.BOOL,
460                                          options("vary_length")->v.BOOL,
461                                          options("incr_payload")->v.BOOL,
462                                          options("incr_first_byte")->v.BOOL,
463                                          options("ins_seq_num")->v.INT,
464                                          options("ins_udp_hdr")->v.BOOL,
465                                          options("en_resync")->v.BOOL,
466                                          options("tuser_err_val")->v.INT,
467                                          options("ins_time_stamp")->v.INT);
468         }
469
470         if (options("stop")->v.BOOL)
471                 ark_pktchkr_stop(handle);
472
473         if (options("run")->v.BOOL) {
474                 PMD_DEBUG_LOG(DEBUG, "Starting packet checker on port %d\n",
475                               options("port")->v.INT);
476                 ark_pktchkr_run(handle);
477         }
478 }