blob: 035cb47662d32a9d7520401bb3f730f954621b70 [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * Sigma Control API DUT (station/AP)
3 * Copyright (c) 2010, Atheros Communications, Inc.
4 * Copyright (c) 2011-2015, Qualcomm Atheros, Inc.
5 * All Rights Reserved.
6 * Licensed under the Clear BSD license. See README for more details.
7 */
8
9#include "sigma_dut.h"
Pradeep Reddy POTTETI3f8c0b32016-05-03 16:06:37 +053010#include "wpa_helpers.h"
Jouni Malinencd4e3c32015-10-29 12:39:56 +020011
12#define TG_MAX_CLIENTS_CONNECTIONS 1
13
14
15static int cmd_traffic_agent_config(struct sigma_dut *dut,
16 struct sigma_conn *conn,
17 struct sigma_cmd *cmd)
18{
19 struct sigma_stream *s;
20 const char *val;
21 char buf[100];
22
23 if (dut->num_streams == MAX_SIGMA_STREAMS) {
24 send_resp(dut, conn, SIGMA_ERROR, "errorCode,No more "
25 "concurrent traffic streams supported");
26 return 0;
27 }
28
29 s = &dut->streams[dut->num_streams];
30 free(s->stats);
31 memset(s, 0, sizeof(*s));
32 s->sock = -1;
33 s->no_timestamps = dut->no_timestamps;
34
35 val = get_param(cmd, "profile");
36 if (!val)
37 return -1;
38
39 if (strcasecmp(val, "File_Transfer") == 0)
40 s->profile = SIGMA_PROFILE_FILE_TRANSFER;
41 else if (strcasecmp(val, "Multicast") == 0)
42 s->profile = SIGMA_PROFILE_MULTICAST;
43 else if (strcasecmp(val, "IPTV") == 0)
44 s->profile = SIGMA_PROFILE_IPTV;
45 else if (strcasecmp(val, "Transaction") == 0)
46 s->profile = SIGMA_PROFILE_TRANSACTION;
47 else if (strcasecmp(val, "Start_Sync") == 0)
48 s->profile = SIGMA_PROFILE_START_SYNC;
49 else if (strcasecmp(val, "Uapsd") == 0)
50 s->profile = SIGMA_PROFILE_UAPSD;
51 else {
52 send_resp(dut, conn, SIGMA_INVALID, "errorCode,Unsupported "
53 "profile");
54 return 0;
55 }
56
57 val = get_param(cmd, "direction");
58 if (!val)
59 return -1;
60 if (strcasecmp(val, "send") == 0)
61 s->sender = 1;
62 else if (strcasecmp(val, "receive") == 0)
63 s->sender = 0;
64 else
65 return -1;
66
67 val = get_param(cmd, "destination");
68 if (val) {
69 if (inet_aton(val, &s->dst) == 0)
70 return -1;
71 }
72
73 val = get_param(cmd, "source");
74 if (val) {
75 if (inet_aton(val, &s->src) == 0)
76 return -1;
77 }
78
79 val = get_param(cmd, "destinationPort");
80 if (val)
81 s->dst_port = atoi(val);
82
83 val = get_param(cmd, "sourcePort");
84 if (val)
85 s->src_port = atoi(val);
86
87 val = get_param(cmd, "frameRate");
88 if (val)
89 s->frame_rate = atoi(val);
90
91 val = get_param(cmd, "duration");
92 if (val)
93 s->duration = atoi(val);
94
95 val = get_param(cmd, "payloadSize");
96 if (val)
97 s->payload_size = atoi(val);
98
99 val = get_param(cmd, "startDelay");
100 if (val)
101 s->start_delay = atoi(val);
102
103 val = get_param(cmd, "maxCnt");
104 if (val)
105 s->max_cnt = atoi(val);
106
107 val = get_param(cmd, "trafficClass");
108 if (val) {
109 if (strcasecmp(val, "Voice") == 0)
110 s->tc = SIGMA_TC_VOICE;
111 else if (strcasecmp(val, "Video") == 0)
112 s->tc = SIGMA_TC_VIDEO;
113 else if (strcasecmp(val, "Background") == 0)
114 s->tc = SIGMA_TC_BACKGROUND;
115 else if (strcasecmp(val, "BestEffort") == 0)
116 s->tc = SIGMA_TC_BEST_EFFORT;
117 else
118 return -1;
119 }
120
121 val = get_param(cmd, "userpriority");
122 if (val) {
123 s->user_priority_set = 1;
124 s->user_priority = atoi(val);
125 }
126
Pradeep Reddy POTTETI79594042015-11-23 12:59:12 +0530127 val = get_param(cmd, "tagName");
128 if (val) {
129 strncpy(s->test_name, val, sizeof(s->test_name));
130 s->test_name[sizeof(s->test_name) - 1] = '\0';
131 sigma_dut_print(dut, DUT_MSG_DEBUG,
132 "Traffic agent: U-APSD console tagname %s",
133 s->test_name);
134 }
135
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200136 if (dut->throughput_pktsize && s->frame_rate == 0 && s->sender &&
137 dut->throughput_pktsize != s->payload_size &&
138 (s->profile == SIGMA_PROFILE_FILE_TRANSFER ||
139 s->profile == SIGMA_PROFILE_IPTV ||
140 s->profile == SIGMA_PROFILE_UAPSD)) {
Jouni Malinenc2493f82016-06-05 18:01:33 +0300141 sigma_dut_print(dut, DUT_MSG_INFO,
142 "Traffic agent: Override throughput test payload size %u -> %u",
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200143 s->payload_size, dut->throughput_pktsize);
144 s->payload_size = dut->throughput_pktsize;
145 }
146
147 val = get_param(cmd, "transProtoType");
148 if (val) {
149 if (strcmp(val, "1") == 0)
150 s->trans_proto = IPPROTO_TCP;
151 else if (strcmp(val, "0") == 0)
152 s->trans_proto = IPPROTO_UDP;
153 else
154 return -1;
155 } else {
156 s->trans_proto = IPPROTO_UDP;
157 }
158
159 if (s->profile == SIGMA_PROFILE_IPTV && !s->sender && !s->no_timestamps)
160 {
161 s->stats = calloc(MAX_SIGMA_STATS,
162 sizeof(struct sigma_frame_stats));
163 if (s->stats == NULL)
164 return -1;
165 }
166
167 dut->stream_id++;
168 dut->num_streams++;
169
170 s->stream_id = dut->stream_id;
171 snprintf(buf, sizeof(buf), "streamID,%d", s->stream_id);
172 send_resp(dut, conn, SIGMA_COMPLETE, buf);
173 return 0;
174}
175
176
177static void stop_stream(struct sigma_stream *s)
178{
179 if (s && s->started) {
180 pthread_join(s->thr, NULL);
181 if (s->sock != -1) {
182 close(s->sock);
183 s->sock = -1;
184 }
185
186 s->started = 0;
187 }
188}
189
190
191static int cmd_traffic_agent_reset(struct sigma_dut *dut,
192 struct sigma_conn *conn,
193 struct sigma_cmd *cmd)
194{
195 int i;
196 for (i = 0; i < dut->num_streams; i++) {
197 struct sigma_stream *s = &dut->streams[i];
198 s->stop = 1;
199 stop_stream(s);
200 }
201 dut->num_streams = 0;
202 memset(&dut->streams, 0, sizeof(dut->streams));
203 return 1;
204}
205
206
207static int get_stream_id(const char *str, int streams[MAX_SIGMA_STREAMS])
208{
209 int count;
210
211 count = 0;
212 for (;;) {
213 if (count == MAX_SIGMA_STREAMS)
214 return -1;
215 streams[count] = atoi(str);
216 if (streams[count] == 0)
217 return -1;
218 count++;
219 str = strchr(str, ' ');
220 if (str == NULL)
221 break;
222 while (*str == ' ')
223 str++;
224 }
225
226 return count;
227}
228
229
230static int open_socket_file_transfer(struct sigma_dut *dut,
231 struct sigma_stream *s)
232{
233 struct sockaddr_in addr;
234 int sock_opt_val = 1;
235
236 s->sock = socket(PF_INET, IPPROTO_UDP == s->trans_proto ? SOCK_DGRAM :
237 SOCK_STREAM, s->trans_proto);
238 if (s->sock < 0) {
239 perror("socket");
240 return -1;
241 }
242
243 if (setsockopt(s->sock, SOL_SOCKET, SO_REUSEADDR, &sock_opt_val,
244 sizeof(sock_opt_val)) < 0) {
245 perror("setsockopt");
246 close(s->sock);
247 s->sock = -1;
248 return -1;
249 }
250
251 memset(&addr, 0, sizeof(addr));
252 addr.sin_family = AF_INET;
253 addr.sin_port = htons(s->sender ? s->src_port : s->dst_port);
254 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: sender=%d "
255 "bind port %d", s->sender, ntohs(addr.sin_port));
256 if (bind(s->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
257 perror("bind");
258 close(s->sock);
259 s->sock = -1;
260 return -1;
261 }
262
263 if (s->profile == SIGMA_PROFILE_MULTICAST && !s->sender)
264 return 0;
265
266 if (s->trans_proto == IPPROTO_TCP && s->sender == 0) {
267 if (listen(s->sock, TG_MAX_CLIENTS_CONNECTIONS ) < 0) {
268 sigma_dut_print(dut, DUT_MSG_INFO,
269 "Listen failed with error %d: %s",
270 errno, strerror(errno));
271 close(s->sock);
272 s->sock = -1;
273 return -1;
274 }
275 } else {
276 memset(&addr, 0, sizeof(addr));
277 addr.sin_family = AF_INET;
278 addr.sin_addr.s_addr = s->sender ? s->dst.s_addr :
279 s->src.s_addr;
280 addr.sin_port = htons(s->sender ? s->dst_port : s->src_port);
281 sigma_dut_print(dut, DUT_MSG_DEBUG,
282 "Traffic agent: connect %s:%d",
283 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
284 if (connect(s->sock, (struct sockaddr *) &addr, sizeof(addr)) <
285 0) {
286 perror("connect");
287 close(s->sock);
288 s->sock = -1;
289 return -1;
290 }
291 }
292
293 return 0;
294}
295
296
297static int open_socket_multicast(struct sigma_dut *dut, struct sigma_stream *s)
298{
299 if (open_socket_file_transfer(dut, s) < 0)
300 return -1;
301
302 if (!s->sender) {
303 struct ip_mreq mr;
304 memset(&mr, 0, sizeof(mr));
305 mr.imr_multiaddr.s_addr = s->dst.s_addr;
306 mr.imr_interface.s_addr = htonl(INADDR_ANY);
307 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: "
308 "IP_ADD_MEMBERSHIP %s", inet_ntoa(s->dst));
309 if (setsockopt(s->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
310 (void *) &mr, sizeof(mr)) < 0) {
311 sigma_dut_print(dut, DUT_MSG_INFO,
312 "setsockopt[IP_ADD_MEMBERSHIP]: %s",
313 strerror(errno));
314 /*
315 * Continue anyway since this can happen, e.g., if the
316 * default route is missing. This is not critical for
317 * multicast RX testing.
318 */
319 }
320 }
321
322 return 0;
323}
324
325
326static int set_socket_prio(struct sigma_stream *s)
327{
328 int tos = 0x00;
329
330 switch (s->tc) {
331 case SIGMA_TC_VOICE:
332 if (s->user_priority_set) {
333 if (s->user_priority == 6)
334 tos = 48 << 2;
335 else if (s->user_priority == 7)
336 tos = 56 << 2;
337 else
338 return -1;
339 } else
340 tos = 0xe0; /* DSCP = 56 */
341 break;
342 case SIGMA_TC_VIDEO:
343 if (s->user_priority_set) {
344 if (s->user_priority == 4)
345 tos = 32 << 2;
346 else if (s->user_priority == 5)
347 tos = 40 << 2;
348 else
349 return -1;
350 } else
351 tos = 0xa0; /* DSCP = 40 */
352 break;
353 case SIGMA_TC_BACKGROUND:
354 if (s->user_priority_set) {
355 if (s->user_priority == 1)
356 tos = 8 << 2;
357 else if (s->user_priority == 2)
358 tos = 16 << 2;
359 else
360 return -1;
361 } else
362 tos = 0x20; /* DSCP = 8 */
363 break;
364 case SIGMA_TC_BEST_EFFORT:
365 if (s->user_priority_set) {
366 if (s->user_priority == 0)
367 tos = 0 << 2;
368 else if (s->user_priority == 3)
369 tos = 20 << 2;
370 else
371 return -1;
372 } else
373 tos = 0x00; /* DSCP = 0 */
374 break;
375 }
376
377 if (setsockopt(s->sock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
378 perror("setsockopt");
379 return -1;
380 }
381
382 return 0;
383}
384
385
386static int open_socket(struct sigma_dut *dut, struct sigma_stream *s)
387{
388 switch (s->profile) {
389 case SIGMA_PROFILE_FILE_TRANSFER:
390 return open_socket_file_transfer(dut, s);
391 case SIGMA_PROFILE_MULTICAST:
392 return open_socket_multicast(dut, s);
393 case SIGMA_PROFILE_IPTV:
394 if (open_socket_file_transfer(dut, s) < 0)
395 return -1;
396 return set_socket_prio(s);
397 case SIGMA_PROFILE_TRANSACTION:
398 return open_socket_file_transfer(dut, s);
399 case SIGMA_PROFILE_UAPSD:
400 return open_socket_file_transfer(dut, s);
401 case SIGMA_PROFILE_START_SYNC:
402 sigma_dut_print(dut, DUT_MSG_INFO, "Traffic stream profile %d "
403 "not yet supported", s->profile);
404 /* TODO */
405 break;
406 }
407
408 return -1;
409}
410
411
412static void send_file_fast(struct sigma_stream *s, char *pkt)
413{
414 struct timeval stop, now;
415 int res;
416 unsigned int counter = 0;
417
418 gettimeofday(&stop, NULL);
419 stop.tv_sec += s->duration;
420
421 while (!s->stop) {
422 counter++;
423 WPA_PUT_BE32(&pkt[8], counter);
424
425 if ((counter & 0xf) == 0) {
426 gettimeofday(&now, NULL);
427 if (now.tv_sec > stop.tv_sec ||
428 (now.tv_sec == stop.tv_sec &&
429 now.tv_usec >= stop.tv_usec))
430 break;
431 }
432
433 s->tx_act_frames++;
434 res = send(s->sock, pkt, s->payload_size, 0);
435 if (res >= 0) {
436 s->tx_frames++;
437 s->tx_payload_bytes += res;
438 } else {
439 switch (errno) {
440 case EAGAIN:
441 case ENOBUFS:
442 usleep(1000);
443 break;
444 case ECONNRESET:
445 case EPIPE:
446 s->stop = 1;
447 break;
448 default:
449 perror("send");
450 break;
451 }
452 }
453 }
454}
455
456
457static void send_file(struct sigma_stream *s)
458{
459 char *pkt;
460 struct timeval stop, now, start;
461 int res;
vamsi krishna2c650812016-05-16 17:43:22 +0530462 unsigned int counter = 0, total_sleep_usec = 0, total_pkts;
463 int sleep_usec = 0;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200464
465 if (s->duration <= 0 || s->frame_rate < 0 || s->payload_size < 20)
466 return;
467
468 pkt = malloc(s->payload_size);
469 if (pkt == NULL)
470 return;
471 memset(pkt, 1, s->payload_size);
472 strncpy(pkt, "1345678", s->payload_size);
473
474 if (s->frame_rate == 0 && s->no_timestamps) {
475 send_file_fast(s, pkt);
476 free(pkt);
477 return;
478 }
479
480 gettimeofday(&stop, NULL);
481 stop.tv_sec += s->duration;
482
vamsi krishna2c650812016-05-16 17:43:22 +0530483 total_pkts = s->duration * s ->frame_rate;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200484
485 gettimeofday(&start, NULL);
486
487 while (!s->stop) {
488 counter++;
489 WPA_PUT_BE32(&pkt[8], counter);
490
vamsi krishna2c650812016-05-16 17:43:22 +0530491 if (sleep_usec) {
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200492 usleep(sleep_usec);
vamsi krishna2c650812016-05-16 17:43:22 +0530493 total_sleep_usec += sleep_usec;
494 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200495
496 gettimeofday(&now, NULL);
497 if (now.tv_sec > stop.tv_sec ||
498 (now.tv_sec == stop.tv_sec && now.tv_usec >= stop.tv_usec))
499 break;
500
vamsi krishna2c650812016-05-16 17:43:22 +0530501 if (s->frame_rate && (unsigned int) s->tx_frames >= total_pkts)
502 break;
503
504 if (s->frame_rate == 0 || s->tx_frames == 0)
505 sleep_usec = 0;
506 else if (sleep_usec || s->frame_rate < 10 ||
507 counter % (s->frame_rate / 10) == 0) {
508 /* Recalculate sleep_usec for every 100 ms approximately
509 */
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200510 struct timeval tmp;
vamsi krishna2c650812016-05-16 17:43:22 +0530511 int diff, duration;
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200512
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200513 timersub(&now, &start, &tmp);
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200514
vamsi krishna2c650812016-05-16 17:43:22 +0530515 diff = tmp.tv_sec * 1000000 + tmp.tv_usec;
516 duration = (1000000 / s->frame_rate) * s->tx_frames;
517
518 if (duration > diff)
519 sleep_usec = (total_sleep_usec +
520 (duration - diff)) / s->tx_frames;
521 else
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200522 sleep_usec = 0;
523 }
524
525 WPA_PUT_BE32(&pkt[12], now.tv_sec);
526 WPA_PUT_BE32(&pkt[16], now.tv_usec);
527
528 s->tx_act_frames++;
529 res = send(s->sock, pkt, s->payload_size, 0);
530 if (res >= 0) {
531 s->tx_frames++;
532 s->tx_payload_bytes += res;
533 } else {
534 switch (errno) {
535 case EAGAIN:
536 case ENOBUFS:
537 usleep(1000);
538 break;
539 case ECONNRESET:
540 case EPIPE:
541 s->stop = 1;
542 break;
543 default:
544 perror("send");
545 break;
546 }
547 }
548 }
549
vamsi krishna2c650812016-05-16 17:43:22 +0530550 sigma_dut_print(s->dut, DUT_MSG_DEBUG,
551 "send_file: counter %u s->tx_frames %d total_sleep_usec %u",
552 counter, s->tx_frames, total_sleep_usec);
553
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200554 free(pkt);
555}
556
557
558static void send_transaction(struct sigma_stream *s)
559{
560 char *pkt, *rpkt;
561 struct timeval stop, now;
562 int res;
563 unsigned int counter = 0, rcounter;
564 int wait_time;
565 fd_set rfds;
566 struct timeval tv;
567
568 if (s->duration <= 0 || s->frame_rate <= 0 || s->payload_size < 20)
569 return;
570
571 pkt = malloc(s->payload_size);
572 if (pkt == NULL)
573 return;
574 rpkt = malloc(s->payload_size);
575 if (rpkt == NULL) {
576 free(pkt);
577 return;
578 }
579 memset(pkt, 1, s->payload_size);
580 strncpy(pkt, "1345678", s->payload_size);
581
582 gettimeofday(&stop, NULL);
583 stop.tv_sec += s->duration;
584
585 wait_time = 1000000 / s->frame_rate;
586
587 while (!s->stop) {
588 counter++;
589 if (s->max_cnt && (int) counter > s->max_cnt)
590 break;
591 WPA_PUT_BE32(&pkt[8], counter);
592
593 gettimeofday(&now, NULL);
594 if (now.tv_sec > stop.tv_sec ||
595 (now.tv_sec == stop.tv_sec && now.tv_usec >= stop.tv_usec))
596 break;
597 WPA_PUT_BE32(&pkt[12], now.tv_sec);
598 WPA_PUT_BE32(&pkt[16], now.tv_usec);
599
600 res = send(s->sock, pkt, s->payload_size, 0);
601 if (res >= 0) {
602 s->tx_frames++;
603 s->tx_payload_bytes += res;
604 } else {
605 switch (errno) {
606 case EAGAIN:
607 case ENOBUFS:
608 usleep(1000);
609 break;
610 case ECONNRESET:
611 case EPIPE:
612 s->stop = 1;
613 break;
614 default:
615 perror("send");
616 break;
617 }
618 }
619
620 /* Wait for response */
621 tv.tv_sec = 0;
622 tv.tv_usec = wait_time;
623 FD_ZERO(&rfds);
624 FD_SET(s->sock, &rfds);
625 res = select(s->sock + 1, &rfds, NULL, NULL, &tv);
626 if (res < 0) {
627 if (errno == EINTR)
628 continue;
629 perror("select");
630 break;
631 }
632
633 if (res == 0) {
634 /* timeout */
635 continue;
636 }
637
638 if (FD_ISSET(s->sock, &rfds)) {
639 /* response received */
640 res = recv(s->sock, rpkt, s->payload_size, 0);
641 if (res < 0) {
642 perror("recv");
643 break;
644 }
645 rcounter = WPA_GET_BE32(&rpkt[8]);
646 if (rcounter != counter)
647 s->out_of_seq_frames++;
648 s->rx_frames++;
649 s->rx_payload_bytes += res;
650 }
651 }
652
653 free(pkt);
654 free(rpkt);
655}
656
657
658static void * send_thread(void *ctx)
659{
660 struct sigma_stream *s = ctx;
661
662 sleep(s->start_delay);
663
664 switch (s->profile) {
665 case SIGMA_PROFILE_FILE_TRANSFER:
666 send_file(s);
667 break;
668 case SIGMA_PROFILE_MULTICAST:
669 send_file(s);
670 break;
671 case SIGMA_PROFILE_IPTV:
672 send_file(s);
673 break;
674 case SIGMA_PROFILE_TRANSACTION:
675 send_transaction(s);
676 break;
677 case SIGMA_PROFILE_START_SYNC:
678 break;
679 case SIGMA_PROFILE_UAPSD:
Pradeep Reddy POTTETI79594042015-11-23 12:59:12 +0530680 send_uapsd_console(s);
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200681 break;
682 }
683
684 return NULL;
685}
686
687
688struct traffic_agent_send_data {
689 struct sigma_dut *dut;
690 struct sigma_conn *conn;
691 int streams[MAX_SIGMA_STREAMS];
692 int count;
693};
694
695
696static struct sigma_stream * get_stream(struct sigma_dut *dut, int id)
697{
698 int i;
699
700 for (i = 0; i < dut->num_streams; i++) {
701 if ((unsigned int) id == dut->streams[i].stream_id)
702 return &dut->streams[i];
703 }
704
705 return NULL;
706}
707
708
709static void * send_report_thread(void *ctx)
710{
711 struct traffic_agent_send_data *data = ctx;
712 struct sigma_dut *dut = data->dut;
713 struct sigma_conn *conn = data->conn;
714 int i, ret;
715 char buf[100 + MAX_SIGMA_STREAMS * 60], *pos;
716
717 for (i = 0; i < data->count; i++) {
718 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: waiting "
719 "for stream %d send to complete",
720 data->streams[i]);
721 stop_stream(get_stream(dut, data->streams[i]));
722 }
723
724 buf[0] = '\0';
725 pos = buf;
726
727 pos += snprintf(pos, buf + sizeof(buf) - pos, "streamID,");
728 for (i = 0; i < data->count; i++) {
729 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
730 i > 0 ? " " : "", data->streams[i]);
731 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
732 break;
733 pos += ret;
734 }
735
736 if (dut->program == PROGRAM_60GHZ) {
737 sigma_dut_print(dut, DUT_MSG_INFO, "reporting tx_act_frames");
738 pos += snprintf(pos, buf + sizeof(buf) - pos, ",txActFrames,");
739 for (i = 0; i < data->count; i++) {
740 struct sigma_stream *s;
741
742 s = get_stream(dut, data->streams[i]);
743 if (!s)
744 continue;
745 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
746 i > 0 ? " " : "", s->tx_act_frames);
747 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
748 break;
749 pos += ret;
750 }
751 }
752
753 pos += snprintf(pos, buf + sizeof(buf) - pos, ",txFrames,");
754 for (i = 0; i < data->count; i++) {
755 struct sigma_stream *s = get_stream(dut, data->streams[i]);
756
757 if (!s)
758 continue;
759 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
760 i > 0 ? " " : "", s->tx_frames);
761 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
762 break;
763 pos += ret;
764 }
765
766 pos += snprintf(pos, buf + sizeof(buf) - pos, ",rxFrames,");
767 for (i = 0; i < data->count; i++) {
768 struct sigma_stream *s = get_stream(dut, data->streams[i]);
769
770 if (!s)
771 continue;
772 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
773 i > 0 ? " " : "", s->rx_frames);
774 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
775 break;
776 pos += ret;
777 }
778
779 pos += snprintf(pos, buf + sizeof(buf) - pos, ",txPayloadBytes,");
780 for (i = 0; i < data->count; i++) {
781 struct sigma_stream *s = get_stream(dut, data->streams[i]);
782
783 if (!s)
784 continue;
785 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%llu",
786 i > 0 ? " " : "", s->tx_payload_bytes);
787 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
788 break;
789 pos += ret;
790 }
791
792 pos += snprintf(pos, buf + sizeof(buf) - pos, ",rxPayloadBytes,");
793 for (i = 0; i < data->count; i++) {
794 struct sigma_stream *s = get_stream(dut, data->streams[i]);
795
796 if (!s)
797 continue;
798 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%llu",
799 i > 0 ? " " : "", s->rx_payload_bytes);
800 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
801 break;
802 pos += ret;
803 }
804
805 pos += snprintf(pos, buf + sizeof(buf) - pos, ",outOfSequenceFrames,");
806 for (i = 0; i < data->count; i++) {
807 struct sigma_stream *s = get_stream(dut, data->streams[i]);
808
809 if (!s)
810 continue;
811 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
812 i > 0 ? " " : "", s->out_of_seq_frames);
813 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
814 break;
815 pos += ret;
816 }
817
818 for (i = 0; i < data->count; i++) {
819 struct sigma_stream *s = get_stream(dut, data->streams[i]);
820 if (!s)
821 continue;
822 s->ta_send_in_progress = 0;
823 if (s->trans_proto == IPPROTO_TCP) {
824 /*
825 * Close the socket to make sure client side close the
826 * network before the server. Otherwise, the server
827 * might get "Address already in use" when trying to
828 * reuse the port.
829 */
830 close(s->sock);
831 s->sock = -1;
832 sigma_dut_print(dut, DUT_MSG_DEBUG,
833 "Closed the sender socket");
834 }
835 }
836
837 buf[sizeof(buf) - 1] = '\0';
838
839 if (conn->s < 0)
840 sigma_dut_print(dut, DUT_MSG_INFO, "Cannot send traffic_agent response since control socket has already been closed");
841 else
842 send_resp(dut, conn, SIGMA_COMPLETE, buf);
843 conn->waiting_completion = 0;
844
845 free(data);
846
847 return NULL;
848}
849
850
851static int cmd_traffic_agent_send(struct sigma_dut *dut,
852 struct sigma_conn *conn,
853 struct sigma_cmd *cmd)
854{
855 const char *val;
856 int i, j, res;
857 char buf[100];
858 struct traffic_agent_send_data *data;
859
860 val = get_param(cmd, "streamID");
861 if (val == NULL)
862 return -1;
863
864 data = calloc(1, sizeof(*data));
865 if (data == NULL)
866 return -1;
867 data->dut = dut;
868 data->conn = conn;
869
870 data->count = get_stream_id(val, data->streams);
871 if (data->count < 0) {
872 free(data);
873 return -1;
874 }
875 for (i = 0; i < data->count; i++) {
876 struct sigma_stream *s = get_stream(dut, data->streams[i]);
877
878 if (!s) {
879 snprintf(buf, sizeof(buf), "errorCode,StreamID %d "
880 "not configured", data->streams[i]);
881 send_resp(dut, conn, SIGMA_INVALID, buf);
882 free(data);
883 return 0;
884 }
885 for (j = 0; j < i; j++)
886 if (data->streams[i] == data->streams[j])
887 return -1;
888 if (!s->sender) {
889 snprintf(buf, sizeof(buf), "errorCode,Not configured "
890 "as sender for streamID %d", data->streams[i]);
891 send_resp(dut, conn, SIGMA_INVALID, buf);
892 free(data);
893 return 0;
894 }
895 if (s->ta_send_in_progress) {
896 send_resp(dut, conn, SIGMA_ERROR,
897 "errorCode,Multiple concurrent send cmds on same streamID not supported");
898 free(data);
899 return 0;
900 }
901 }
902
903 for (i = 0; i < data->count; i++) {
904 struct sigma_stream *s = get_stream(dut, data->streams[i]);
905
906 if (!s)
907 continue;
908 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: open "
909 "socket for send stream %d", data->streams[i]);
910 if (open_socket(dut, s) < 0) {
911 free(data);
912 return -2;
913 }
914 }
915
916 for (i = 0; i < data->count; i++) {
917 struct sigma_stream *s = get_stream(dut, data->streams[i]);
918
919 if (!s)
920 continue;
Pradeep Reddy POTTETI79594042015-11-23 12:59:12 +0530921
922 /*
923 * Provide dut context to the thread to support debugging and
924 * returning of error messages.
925 */
926 s->dut = dut;
927
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200928 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: start "
929 "send for stream %d", data->streams[i]);
930 res = pthread_create(&s->thr, NULL, send_thread, s);
931 if (res) {
932 sigma_dut_print(dut, DUT_MSG_INFO, "pthread_create "
933 "failed: %d", res);
934 free(data);
935 return -2;
936 }
937 s->started = 1;
938 }
939
940 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: start a thread to track sending streams");
941 conn->waiting_completion = 1;
942 res = pthread_create(&dut->thr, NULL, send_report_thread, data);
943 if (res) {
944 sigma_dut_print(dut, DUT_MSG_INFO, "pthread_create failed: %d",
945 res);
946 free(data);
947 conn->waiting_completion = 0;
948 return -2;
949 }
950
951 for (i = 0; i < data->count; i++) {
952 struct sigma_stream *s = get_stream(dut, data->streams[i]);
953
954 if (s)
955 s->ta_send_in_progress = 1;
956 }
957
958 /* Command will be completed in send_report_thread() */
959
960 return 0;
961}
962
963
964static void receive_file(struct sigma_stream *s)
965{
966 struct timeval tv, now;
967 fd_set rfds;
968 int res;
969 char *pkt;
970 int pktlen;
971 unsigned int last_rx = 0, counter;
972
973 pktlen = 65536 + 1;
974 pkt = malloc(pktlen);
975 if (pkt == NULL)
976 return;
977
978 while (!s->stop) {
979 FD_ZERO(&rfds);
980 FD_SET(s->sock, &rfds);
981 tv.tv_sec = 0;
982 tv.tv_usec = 300000;
983 res = select(s->sock + 1, &rfds, NULL, NULL, &tv);
984 if (res < 0) {
985 perror("select");
986 usleep(10000);
987 } else if (FD_ISSET(s->sock, &rfds)) {
988 res = recv(s->sock, pkt, pktlen, 0);
989 if (res >= 0) {
990 s->rx_frames++;
991 s->rx_payload_bytes += res;
992
993 counter = WPA_GET_BE32(&pkt[8]);
994 if (counter < last_rx)
995 s->out_of_seq_frames++;
996 last_rx = counter;
997 } else {
998 perror("recv");
999 break;
1000 }
1001
1002 if (res >= 20 && s->stats &&
1003 s->num_stats < MAX_SIGMA_STATS) {
1004 struct sigma_frame_stats *stats;
1005 stats = &s->stats[s->num_stats];
1006 s->num_stats++;
1007 gettimeofday(&now, NULL);
1008 stats->seqnum = counter;
1009 stats->local_sec = now.tv_sec;
1010 stats->local_usec = now.tv_usec;
1011 stats->remote_sec = WPA_GET_BE32(&pkt[12]);
1012 stats->remote_usec = WPA_GET_BE32(&pkt[16]);
1013 }
1014 }
1015 }
1016
1017 free(pkt);
1018}
1019
1020
1021static void receive_transaction(struct sigma_stream *s)
1022{
1023 struct timeval tv;
1024 fd_set rfds;
1025 int res;
1026 char *pkt;
1027 int pktlen;
1028 unsigned int last_rx = 0, counter;
1029 struct sockaddr_in addr;
1030 socklen_t addrlen;
1031
1032 if (s->payload_size)
1033 pktlen = s->payload_size;
1034 else
1035 pktlen = 65536 + 1;
1036 pkt = malloc(pktlen);
1037 if (pkt == NULL)
1038 return;
1039
1040 while (!s->stop) {
1041 FD_ZERO(&rfds);
1042 FD_SET(s->sock, &rfds);
1043 tv.tv_sec = 0;
1044 tv.tv_usec = 300000;
1045 res = select(s->sock + 1, &rfds, NULL, NULL, &tv);
1046 if (res < 0) {
1047 perror("select");
1048 usleep(10000);
1049 } else if (FD_ISSET(s->sock, &rfds)) {
1050 addrlen = sizeof(addr);
1051 res = recvfrom(s->sock, pkt, pktlen, 0,
1052 (struct sockaddr *) &addr, &addrlen);
1053 if (res < 0) {
1054 perror("recv");
1055 break;
1056 }
1057
1058 s->rx_frames++;
1059 s->rx_payload_bytes += res;
1060
1061 counter = WPA_GET_BE32(&pkt[8]);
1062 if (counter < last_rx)
1063 s->out_of_seq_frames++;
1064 last_rx = counter;
1065
1066 /* send response */
1067 res = sendto(s->sock, pkt, pktlen, 0,
1068 (struct sockaddr *) &addr, addrlen);
1069 if (res < 0) {
1070 perror("sendto");
1071 } else {
1072 s->tx_frames++;
1073 s->tx_payload_bytes += res;
1074 }
1075 }
1076 }
1077
1078 free(pkt);
1079}
1080
1081
1082static void * receive_thread(void *ctx)
1083{
1084 struct sigma_stream *s = ctx;
1085
1086 if (s->trans_proto == IPPROTO_TCP) {
1087 /* Wait for socket to be accepted */
1088 struct sockaddr_in connected_addr;
1089 int connected_sock; /* returned from accept on sock */
1090 socklen_t connected_addr_len = sizeof(connected_addr);
1091
1092 sigma_dut_print(s->dut, DUT_MSG_DEBUG,
1093 "Traffic agent: Waiting on accept");
1094 connected_sock = accept(s->sock,
1095 (struct sockaddr *) &connected_addr,
1096 &connected_addr_len);
1097 if (connected_sock < 0) {
1098 sigma_dut_print(s->dut, DUT_MSG_ERROR,
1099 "Traffic agent: Failed to accept: %s",
1100 strerror(errno));
1101 return NULL;
1102 }
1103
1104 sigma_dut_print(s->dut, DUT_MSG_DEBUG,
1105 "Traffic agent: Accepted client closing parent socket and talk over connected sock.");
1106 close(s->sock);
1107 s->sock = connected_sock;
1108 }
1109
1110 switch (s->profile) {
1111 case SIGMA_PROFILE_FILE_TRANSFER:
1112 receive_file(s);
1113 break;
1114 case SIGMA_PROFILE_MULTICAST:
1115 receive_file(s);
1116 break;
1117 case SIGMA_PROFILE_IPTV:
1118 receive_file(s);
1119 break;
1120 case SIGMA_PROFILE_TRANSACTION:
1121 receive_transaction(s);
1122 break;
1123 case SIGMA_PROFILE_START_SYNC:
1124 break;
1125 case SIGMA_PROFILE_UAPSD:
1126 receive_uapsd(s);
1127 break;
1128 }
1129
1130 return NULL;
1131}
1132
1133
1134static int cmd_traffic_agent_receive_start(struct sigma_dut *dut,
1135 struct sigma_conn *conn,
1136 struct sigma_cmd *cmd)
1137{
1138 const char *val;
1139 int streams[MAX_SIGMA_STREAMS];
1140 int i, j, count;
1141 char buf[100];
1142
1143 val = get_param(cmd, "streamID");
1144 if (val == NULL)
1145 return -1;
1146 count = get_stream_id(val, streams);
1147 if (count < 0)
1148 return -1;
1149 for (i = 0; i < count; i++) {
1150 struct sigma_stream *s = get_stream(dut, streams[i]);
1151
1152 if (!s) {
1153 snprintf(buf, sizeof(buf), "errorCode,StreamID %d "
1154 "not configured", streams[i]);
1155 send_resp(dut, conn, SIGMA_INVALID, buf);
1156 return 0;
1157 }
1158 for (j = 0; j < i; j++)
1159 if (streams[i] == streams[j])
1160 return -1;
1161 if (s->sender) {
1162 snprintf(buf, sizeof(buf), "errorCode,Not configured "
1163 "as receiver for streamID %d", streams[i]);
1164 send_resp(dut, conn, SIGMA_INVALID, buf);
1165 return 0;
1166 }
1167 }
1168
1169 for (i = 0; i < count; i++) {
1170 struct sigma_stream *s = get_stream(dut, streams[i]);
1171
1172 if (!s)
1173 continue;
1174 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: open "
1175 "receive socket for stream %d", streams[i]);
1176 if (open_socket(dut, s) < 0)
1177 return -2;
1178 }
1179
1180 for (i = 0; i < count; i++) {
1181 struct sigma_stream *s = get_stream(dut, streams[i]);
1182 int res;
1183
1184 if (!s)
1185 continue;
1186 /*
1187 * Provide dut context to the thread to support debugging and
1188 * returning of error messages. Similarly, provide interface
Pradeep Reddy POTTETI3f8c0b32016-05-03 16:06:37 +05301189 * information to the thread. If the Interface parameter is not
1190 * passed, get it from get_station_ifname() since the interface
1191 * name is needed for power save mode configuration for Uapsd
1192 * cases.
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001193 */
1194 s->dut = dut;
1195 val = get_param(cmd, "Interface");
Pradeep Reddy POTTETI3f8c0b32016-05-03 16:06:37 +05301196 strncpy(s->ifname, (val ? val : get_station_ifname()),
1197 sizeof(s->ifname));
1198 s->ifname[sizeof(s->ifname) - 1] = '\0';
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001199
1200 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: start "
1201 "receive for stream %d", streams[i]);
1202 res = pthread_create(&s->thr, NULL, receive_thread, s);
1203 if (res) {
1204 sigma_dut_print(dut, DUT_MSG_INFO, "pthread_create "
1205 "failed: %d", res);
1206 return -2;
1207 }
1208 s->started = 1;
1209 }
1210
1211 return 1;
1212}
1213
1214
1215static void write_frame_stats(struct sigma_dut *dut, struct sigma_stream *s,
1216 int id)
1217{
1218 char fname[128];
1219 FILE *f;
1220 unsigned int i;
1221
1222 snprintf(fname, sizeof(fname), SIGMA_TMPDIR "/e2e%u-%d.txt",
1223 (unsigned int) time(NULL), id);
1224 f = fopen(fname, "w");
1225 if (f == NULL) {
1226 sigma_dut_print(dut, DUT_MSG_INFO, "Could not write %s",
1227 fname);
1228 return;
1229 }
1230 fprintf(f, "seqnum:local_sec:local_usec:remote_sec:remote_usec\n");
1231
1232 sigma_dut_print(dut, DUT_MSG_DEBUG, "Writing frame stats to %s",
1233 fname);
1234
1235 for (i = 0; i < s->num_stats; i++) {
1236 struct sigma_frame_stats *stats = &s->stats[i];
1237 fprintf(f, "%u:%u:%u:%u:%u\n", stats->seqnum,
1238 stats->local_sec, stats->local_usec,
1239 stats->remote_sec, stats->remote_usec);
1240 }
1241
1242 fclose(f);
1243}
1244
1245
1246static int cmd_traffic_agent_receive_stop(struct sigma_dut *dut,
1247 struct sigma_conn *conn,
1248 struct sigma_cmd *cmd)
1249{
1250 const char *val;
1251 int streams[MAX_SIGMA_STREAMS];
1252 int i, j, ret, count;
1253 char buf[100 + MAX_SIGMA_STREAMS * 60], *pos;
1254
1255 val = get_param(cmd, "streamID");
1256 if (val == NULL)
1257 return -1;
1258 count = get_stream_id(val, streams);
1259 if (count < 0)
1260 return -1;
1261 for (i = 0; i < count; i++) {
1262 struct sigma_stream *s = get_stream(dut, streams[i]);
1263
1264 if (!s) {
1265 snprintf(buf, sizeof(buf), "errorCode,StreamID %d "
1266 "not configured", streams[i]);
1267 send_resp(dut, conn, SIGMA_INVALID, buf);
1268 return 0;
1269 }
1270 for (j = 0; j < i; j++)
1271 if (streams[i] == streams[j])
1272 return -1;
1273 if (!s->started) {
1274 snprintf(buf, sizeof(buf), "errorCode,Receive not "
1275 "started for streamID %d", streams[i]);
1276 send_resp(dut, conn, SIGMA_INVALID, buf);
1277 return 0;
1278 }
1279 }
1280
1281 for (i = 0; i < count; i++) {
1282 struct sigma_stream *s = get_stream(dut, streams[i]);
1283
1284 if (s)
1285 s->stop = 1;
1286 }
1287
1288 for (i = 0; i < count; i++) {
1289 struct sigma_stream *s = get_stream(dut, streams[i]);
1290
1291 if (!s)
1292 continue;
1293 sigma_dut_print(dut, DUT_MSG_DEBUG, "Traffic agent: stop "
1294 "receive for stream %d", streams[i]);
1295 stop_stream(s);
1296 }
1297
1298 buf[0] = '\0';
1299 pos = buf;
1300
1301 pos += snprintf(pos, buf + sizeof(buf) - pos, "streamID,");
1302 for (i = 0; i < count; i++) {
1303 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
1304 i > 0 ? " " : "", streams[i]);
1305 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
1306 break;
1307 pos += ret;
1308 }
1309
1310 if (dut->program == PROGRAM_60GHZ) {
1311 pos += snprintf(pos, buf + sizeof(buf) - pos, ",txActFrames,");
1312 for (i = 0; i < count; i++) {
1313 struct sigma_stream *s = get_stream(dut, streams[i]);
1314
1315 if (!s)
1316 continue;
1317 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
1318 i > 0 ? " " : "", s->tx_act_frames);
1319 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
1320 break;
1321 pos += ret;
1322 }
1323 }
1324
1325 pos += snprintf(pos, buf + sizeof(buf) - pos, ",txFrames,");
1326 for (i = 0; i < count; i++) {
1327 struct sigma_stream *s = get_stream(dut, streams[i]);
1328
1329 if (!s)
1330 continue;
1331 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
1332 i > 0 ? " " : "", s->tx_frames);
1333 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
1334 break;
1335 pos += ret;
1336 }
1337
1338 pos += snprintf(pos, buf + sizeof(buf) - pos, ",rxFrames,");
1339 for (i = 0; i < count; i++) {
1340 struct sigma_stream *s = get_stream(dut, streams[i]);
1341
1342 if (!s)
1343 continue;
1344 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
1345 i > 0 ? " " : "", s->rx_frames);
1346 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
1347 break;
1348 pos += ret;
1349 }
1350
1351 pos += snprintf(pos, buf + sizeof(buf) - pos, ",txPayloadBytes,");
1352 for (i = 0; i < count; i++) {
1353 struct sigma_stream *s = get_stream(dut, streams[i]);
1354
1355 if (!s)
1356 continue;
1357 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%llu",
1358 i > 0 ? " " : "", s->tx_payload_bytes);
1359 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
1360 break;
1361 pos += ret;
1362 }
1363
1364 pos += snprintf(pos, buf + sizeof(buf) - pos, ",rxPayloadBytes,");
1365 for (i = 0; i < count; i++) {
1366 struct sigma_stream *s = get_stream(dut, streams[i]);
1367
1368 if (!s)
1369 continue;
1370 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%llu",
1371 i > 0 ? " " : "", s->rx_payload_bytes);
1372 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
1373 break;
1374 pos += ret;
1375 }
1376
1377 pos += snprintf(pos, buf + sizeof(buf) - pos, ",outOfSequenceFrames,");
1378 for (i = 0; i < count; i++) {
1379 struct sigma_stream *s = get_stream(dut, streams[i]);
1380
1381 if (!s)
1382 continue;
1383 ret = snprintf(pos, buf + sizeof(buf) - pos, "%s%d",
1384 i > 0 ? " " : "", s->out_of_seq_frames);
1385 if (ret < 0 || ret >= buf + sizeof(buf) - pos)
1386 break;
1387 pos += ret;
1388 }
1389
1390 buf[sizeof(buf) - 1] = '\0';
1391
1392 send_resp(dut, conn, SIGMA_COMPLETE, buf);
1393
1394 for (i = 0; i < count; i++) {
1395 struct sigma_stream *s = get_stream(dut, streams[i]);
1396
1397 if (!s)
1398 continue;
1399 if (s->profile == SIGMA_PROFILE_IPTV && s->num_stats > 0 &&
1400 dut->write_stats)
1401 write_frame_stats(dut, s, streams[i]);
1402 free(s->stats);
1403 s->stats = NULL;
1404 s->num_stats = 0;
1405 }
1406
1407 return 0;
1408}
1409
1410
1411static int cmd_traffic_agent_version(struct sigma_dut *dut,
1412 struct sigma_conn *conn,
1413 struct sigma_cmd *cmd)
1414{
1415 send_resp(dut, conn, SIGMA_COMPLETE, "version,1.0");
1416 return 0;
1417}
1418
1419
1420void traffic_agent_register_cmds(void)
1421{
1422 sigma_dut_reg_cmd("traffic_agent_config", NULL,
1423 cmd_traffic_agent_config);
1424 sigma_dut_reg_cmd("traffic_agent_reset", NULL,
1425 cmd_traffic_agent_reset);
1426 sigma_dut_reg_cmd("traffic_agent_send", NULL,
1427 cmd_traffic_agent_send);
1428 sigma_dut_reg_cmd("traffic_agent_receive_start", NULL,
1429 cmd_traffic_agent_receive_start);
1430 sigma_dut_reg_cmd("traffic_agent_receive_stop", NULL,
1431 cmd_traffic_agent_receive_stop);
1432 sigma_dut_reg_cmd("traffic_agent_version", NULL,
1433 cmd_traffic_agent_version);
1434}