net/hns3: fix timing in mailbox
[dpdk.git] / drivers / net / ark / ark_pktgen.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_pktgen.h"
11 #include "ark_logs.h"
12
13 #define ARK_MAX_STR_LEN 64
14 union OPTV {
15         int INT;
16         int BOOL;
17         uint64_t LONG;
18         char STR[ARK_MAX_STR_LEN];
19 };
20
21 enum OPTYPE {
22         OTINT,
23         OTLONG,
24         OTBOOL,
25         OTSTRING
26 };
27
28 struct OPTIONS {
29         char opt[ARK_MAX_STR_LEN];
30         enum OPTYPE t;
31         union OPTV v;
32 };
33
34 static struct OPTIONS toptions[] = {
35         {{"configure"}, OTBOOL, {1} },
36         {{"dg-mode"}, OTBOOL, {1} },
37         {{"run"}, OTBOOL, {0} },
38         {{"pause"}, OTBOOL, {0} },
39         {{"reset"}, OTBOOL, {0} },
40         {{"dump"}, OTBOOL, {0} },
41         {{"gen_forever"}, OTBOOL, {0} },
42         {{"en_slaved_start"}, OTBOOL, {0} },
43         {{"vary_length"}, OTBOOL, {0} },
44         {{"incr_payload"}, OTBOOL, {0} },
45         {{"incr_first_byte"}, OTBOOL, {0} },
46         {{"ins_seq_num"}, OTBOOL, {0} },
47         {{"ins_time_stamp"}, OTBOOL, {1} },
48         {{"ins_udp_hdr"}, OTBOOL, {0} },
49         {{"num_pkts"}, OTLONG, .v.LONG = 100000000},
50         {{"payload_byte"}, OTINT, {0x55} },
51         {{"pkt_spacing"}, OTINT, {130} },
52         {{"pkt_size_min"}, OTINT, {2006} },
53         {{"pkt_size_max"}, OTINT, {1514} },
54         {{"pkt_size_incr"}, OTINT, {1} },
55         {{"eth_type"}, OTINT, {0x0800} },
56         {{"src_mac_addr"}, OTLONG, .v.LONG = 0xdC3cF6425060L},
57         {{"dst_mac_addr"}, OTLONG, .v.LONG = 0x112233445566L},
58         {{"hdr_dW0"}, OTINT, {0x0016e319} },
59         {{"hdr_dW1"}, OTINT, {0x27150004} },
60         {{"hdr_dW2"}, OTINT, {0x76967bda} },
61         {{"hdr_dW3"}, OTINT, {0x08004500} },
62         {{"hdr_dW4"}, OTINT, {0x005276ed} },
63         {{"hdr_dW5"}, OTINT, {0x40004006} },
64         {{"hdr_dW6"}, OTINT, {0x56cfc0a8} },
65         {{"start_offset"}, OTINT, {0} },
66         {{"bytes_per_cycle"}, OTINT, {10} },
67         {{"shaping"}, OTBOOL, {0} },
68         {{"dst_ip"}, OTSTRING, .v.STR = "169.254.10.240"},
69         {{"dst_port"}, OTINT, {65536} },
70         {{"src_port"}, OTINT, {65536} },
71 };
72
73 ark_pkt_gen_t
74 ark_pktgen_init(void *adr, int ord, int l2_mode)
75 {
76         struct ark_pkt_gen_inst *inst =
77                 rte_malloc("ark_pkt_gen_inst_pmd",
78                            sizeof(struct ark_pkt_gen_inst), 0);
79         if (inst == NULL) {
80                 ARK_PMD_LOG(ERR, "Failed to malloc ark_pkt_gen_inst.\n");
81                 return inst;
82         }
83         inst->regs = (struct ark_pkt_gen_regs *)adr;
84         inst->ordinal = ord;
85         inst->l2_mode = l2_mode;
86         return inst;
87 }
88
89 void
90 ark_pktgen_uninit(ark_pkt_gen_t handle)
91 {
92         rte_free(handle);
93 }
94
95 void
96 ark_pktgen_run(ark_pkt_gen_t handle)
97 {
98         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
99
100         inst->regs->pkt_start_stop = 1;
101 }
102
103 uint32_t
104 ark_pktgen_paused(ark_pkt_gen_t handle)
105 {
106         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
107         uint32_t r = inst->regs->pkt_start_stop;
108
109         return (((r >> 16) & 1) == 1);
110 }
111
112 void
113 ark_pktgen_pause(ark_pkt_gen_t handle)
114 {
115         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
116         int cnt = 0;
117
118         inst->regs->pkt_start_stop = 0;
119
120         while (!ark_pktgen_paused(handle)) {
121                 usleep(1000);
122                 if (cnt++ > 100) {
123                         ARK_PMD_LOG(NOTICE, "Pktgen %d failed to pause.\n",
124                                     inst->ordinal);
125                         break;
126                 }
127         }
128         ARK_PMD_LOG(DEBUG, "Pktgen %d paused.\n", inst->ordinal);
129 }
130
131 void
132 ark_pktgen_reset(ark_pkt_gen_t handle)
133 {
134         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
135
136         if (!ark_pktgen_is_running(handle) &&
137             !ark_pktgen_paused(handle)) {
138                 ARK_PMD_LOG(DEBUG, "Pktgen %d is not running"
139                               " and is not paused. No need to reset.\n",
140                               inst->ordinal);
141                 return;
142         }
143
144         if (ark_pktgen_is_running(handle) &&
145             !ark_pktgen_paused(handle)) {
146                 ARK_PMD_LOG(DEBUG,
147                               "Pktgen %d is not paused. Pausing first.\n",
148                               inst->ordinal);
149                 ark_pktgen_pause(handle);
150         }
151
152         ARK_PMD_LOG(DEBUG, "Resetting pktgen %d.\n", inst->ordinal);
153         inst->regs->pkt_start_stop = (1 << 8);
154 }
155
156 uint32_t
157 ark_pktgen_tx_done(ark_pkt_gen_t handle)
158 {
159         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
160         uint32_t r = inst->regs->pkt_start_stop;
161
162         return (((r >> 24) & 1) == 1);
163 }
164
165 uint32_t
166 ark_pktgen_is_running(ark_pkt_gen_t handle)
167 {
168         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
169         uint32_t r = inst->regs->pkt_start_stop;
170
171         return ((r & 1) == 1);
172 }
173
174 uint32_t
175 ark_pktgen_is_gen_forever(ark_pkt_gen_t handle)
176 {
177         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
178         uint32_t r = inst->regs->pkt_ctrl;
179
180         return (((r >> 24) & 1) == 1);
181 }
182
183 void
184 ark_pktgen_wait_done(ark_pkt_gen_t handle)
185 {
186         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
187         int wait_cycle = 10;
188
189         if (ark_pktgen_is_gen_forever(handle))
190                 ARK_PMD_LOG(NOTICE, "Pktgen wait_done will not terminate"
191                             " because gen_forever=1\n");
192
193         while (!ark_pktgen_tx_done(handle) && (wait_cycle > 0)) {
194                 usleep(1000);
195                 wait_cycle--;
196                 ARK_PMD_LOG(DEBUG,
197                               "Waiting for pktgen %d to finish sending...\n",
198                               inst->ordinal);
199         }
200         ARK_PMD_LOG(DEBUG, "Pktgen %d done.\n", inst->ordinal);
201 }
202
203 uint32_t
204 ark_pktgen_get_pkts_sent(ark_pkt_gen_t handle)
205 {
206         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
207         return inst->regs->pkts_sent;
208 }
209
210 void
211 ark_pktgen_set_payload_byte(ark_pkt_gen_t handle, uint32_t b)
212 {
213         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
214         inst->regs->pkt_payload = b;
215 }
216
217 void
218 ark_pktgen_set_pkt_spacing(ark_pkt_gen_t handle, uint32_t x)
219 {
220         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
221         inst->regs->pkt_spacing = x;
222 }
223
224 void
225 ark_pktgen_set_pkt_size_min(ark_pkt_gen_t handle, uint32_t x)
226 {
227         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
228         inst->regs->pkt_size_min = x;
229 }
230
231 void
232 ark_pktgen_set_pkt_size_max(ark_pkt_gen_t handle, uint32_t x)
233 {
234         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
235         inst->regs->pkt_size_max = x;
236 }
237
238 void
239 ark_pktgen_set_pkt_size_incr(ark_pkt_gen_t handle, uint32_t x)
240 {
241         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
242         inst->regs->pkt_size_incr = x;
243 }
244
245 void
246 ark_pktgen_set_num_pkts(ark_pkt_gen_t handle, uint32_t x)
247 {
248         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
249         inst->regs->num_pkts = x;
250 }
251
252 void
253 ark_pktgen_set_src_mac_addr(ark_pkt_gen_t handle, uint64_t mac_addr)
254 {
255         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
256         inst->regs->src_mac_addr_h = (mac_addr >> 32) & 0xffff;
257         inst->regs->src_mac_addr_l = mac_addr & 0xffffffff;
258 }
259
260 void
261 ark_pktgen_set_dst_mac_addr(ark_pkt_gen_t handle, uint64_t mac_addr)
262 {
263         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
264         inst->regs->dst_mac_addr_h = (mac_addr >> 32) & 0xffff;
265         inst->regs->dst_mac_addr_l = mac_addr & 0xffffffff;
266 }
267
268 void
269 ark_pktgen_set_eth_type(ark_pkt_gen_t handle, uint32_t x)
270 {
271         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
272         inst->regs->eth_type = x;
273 }
274
275 void
276 ark_pktgen_set_hdr_dW(ark_pkt_gen_t handle, uint32_t *hdr)
277 {
278         uint32_t i;
279         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
280
281         for (i = 0; i < 7; i++)
282                 inst->regs->hdr_dw[i] = hdr[i];
283 }
284
285 void
286 ark_pktgen_set_start_offset(ark_pkt_gen_t handle, uint32_t x)
287 {
288         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
289
290         inst->regs->start_offset = x;
291 }
292
293 static struct OPTIONS *
294 options(const char *id)
295 {
296         unsigned int i;
297
298         for (i = 0; i < sizeof(toptions) / sizeof(struct OPTIONS); i++) {
299                 if (strcmp(id, toptions[i].opt) == 0)
300                         return &toptions[i];
301         }
302
303         ARK_PMD_LOG(ERR,
304                     "Pktgen: Could not find requested option!, "
305                     "option = %s\n",
306                     id
307                     );
308         return NULL;
309 }
310
311 static int pmd_set_arg(char *arg, char *val);
312 static int
313 pmd_set_arg(char *arg, char *val)
314 {
315         struct OPTIONS *o = options(arg);
316
317         if (o) {
318                 switch (o->t) {
319                 case OTINT:
320                 case OTBOOL:
321                         o->v.INT = atoi(val);
322                         break;
323                 case OTLONG:
324                         o->v.INT = atoll(val);
325                         break;
326                 case OTSTRING:
327                         strlcpy(o->v.STR, val, ARK_MAX_STR_LEN);
328                         break;
329                 }
330                 return 1;
331         }
332         return 0;
333 }
334
335 /******
336  * Arg format = "opt0=v,opt_n=v ..."
337  ******/
338 void
339 ark_pktgen_parse(char *args)
340 {
341         char *argv, *v;
342         const char toks[] = " =\n\t\v\f \r";
343         argv = strtok(args, toks);
344         v = strtok(NULL, toks);
345         while (argv && v) {
346                 pmd_set_arg(argv, v);
347                 argv = strtok(NULL, toks);
348                 v = strtok(NULL, toks);
349         }
350 }
351
352 static int32_t parse_ipv4_string(char const *ip_address);
353 static int32_t
354 parse_ipv4_string(char const *ip_address)
355 {
356         unsigned int ip[4];
357
358         if (sscanf(ip_address, "%u.%u.%u.%u",
359                    &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
360                 return 0;
361         return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
362 }
363
364 static void
365 ark_pktgen_set_pkt_ctrl(ark_pkt_gen_t handle,
366                         uint32_t gen_forever,
367                         uint32_t en_slaved_start,
368                         uint32_t vary_length,
369                         uint32_t incr_payload,
370                         uint32_t incr_first_byte,
371                         uint32_t ins_seq_num,
372                         uint32_t ins_udp_hdr,
373                         uint32_t ins_time_stamp)
374 {
375         uint32_t r;
376         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)handle;
377
378         if (!inst->l2_mode)
379                 ins_udp_hdr = 0;
380
381         r = ((gen_forever << 24) |
382              (en_slaved_start << 20) |
383              (vary_length << 16) |
384              (incr_payload << 12) |
385              (incr_first_byte << 8) |
386              (ins_time_stamp << 5) |
387              (ins_seq_num << 4) |
388              ins_udp_hdr);
389
390         inst->regs->bytes_per_cycle = options("bytes_per_cycle")->v.INT;
391         if (options("shaping")->v.BOOL)
392                 r = r | (1 << 28);      /* enable shaping */
393
394         inst->regs->pkt_ctrl = r;
395 }
396
397 void
398 ark_pktgen_setup(ark_pkt_gen_t handle)
399 {
400         uint32_t hdr[7];
401         int32_t dst_ip = parse_ipv4_string(options("dst_ip")->v.STR);
402
403         if (!options("pause")->v.BOOL &&
404             (!options("reset")->v.BOOL &&
405              (options("configure")->v.BOOL))) {
406                 ark_pktgen_set_payload_byte(handle,
407                                             options("payload_byte")->v.INT);
408                 ark_pktgen_set_src_mac_addr(handle,
409                                             options("src_mac_addr")->v.INT);
410                 ark_pktgen_set_dst_mac_addr(handle,
411                                             options("dst_mac_addr")->v.LONG);
412                 ark_pktgen_set_eth_type(handle,
413                                         options("eth_type")->v.INT);
414
415                 if (options("dg-mode")->v.BOOL) {
416                         hdr[0] = options("hdr_dW0")->v.INT;
417                         hdr[1] = options("hdr_dW1")->v.INT;
418                         hdr[2] = options("hdr_dW2")->v.INT;
419                         hdr[3] = options("hdr_dW3")->v.INT;
420                         hdr[4] = options("hdr_dW4")->v.INT;
421                         hdr[5] = options("hdr_dW5")->v.INT;
422                         hdr[6] = options("hdr_dW6")->v.INT;
423                 } else {
424                         hdr[0] = dst_ip;
425                         hdr[1] = options("dst_port")->v.INT;
426                         hdr[2] = options("src_port")->v.INT;
427                         hdr[3] = 0;
428                         hdr[4] = 0;
429                         hdr[5] = 0;
430                         hdr[6] = 0;
431                 }
432                 ark_pktgen_set_hdr_dW(handle, hdr);
433                 ark_pktgen_set_num_pkts(handle,
434                                         options("num_pkts")->v.INT);
435                 ark_pktgen_set_pkt_size_min(handle,
436                                             options("pkt_size_min")->v.INT);
437                 ark_pktgen_set_pkt_size_max(handle,
438                                             options("pkt_size_max")->v.INT);
439                 ark_pktgen_set_pkt_size_incr(handle,
440                                              options("pkt_size_incr")->v.INT);
441                 ark_pktgen_set_pkt_spacing(handle,
442                                            options("pkt_spacing")->v.INT);
443                 ark_pktgen_set_start_offset(handle,
444                                             options("start_offset")->v.INT);
445                 ark_pktgen_set_pkt_ctrl(handle,
446                                         options("gen_forever")->v.BOOL,
447                                         options("en_slaved_start")->v.BOOL,
448                                         options("vary_length")->v.BOOL,
449                                         options("incr_payload")->v.BOOL,
450                                         options("incr_first_byte")->v.BOOL,
451                                         options("ins_seq_num")->v.INT,
452                                         options("ins_udp_hdr")->v.BOOL,
453                                         options("ins_time_stamp")->v.INT);
454         }
455
456         if (options("pause")->v.BOOL)
457                 ark_pktgen_pause(handle);
458
459         if (options("reset")->v.BOOL)
460                 ark_pktgen_reset(handle);
461         if (options("run")->v.BOOL) {
462                 ARK_PMD_LOG(DEBUG, "Starting packet generator on port %d\n",
463                                 options("port")->v.INT);
464                 ark_pktgen_run(handle);
465         }
466 }
467
468 void *
469 ark_pktgen_delay_start(void *arg)
470 {
471         struct ark_pkt_gen_inst *inst = (struct ark_pkt_gen_inst *)arg;
472
473         /* This function is used exclusively for regression testing, We
474          * perform a blind sleep here to ensure that the external test
475          * application has time to setup the test before we generate packets
476          */
477         usleep(100000);
478         ark_pktgen_run(inst);
479         return NULL;
480 }