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