/*
 * wfaStaGetStats():
 * The function is to retrieve the statistics of the I/F's layer 2 txFrames, 
 * rxFrames, txMulticast, rxMulticast, fcsErrors/crc, and txRetries.
 * Currently there is not definition how to use these info. 
 */
int wfaStaGetStats(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	int ret = 0;
	caStaGetStatsResp_t statsResp;
	FILE *fd;
	char cmdStr[256];

	DPRINT_INFO(WFA_OUT, "Entering wfaStaGetStats ...\n");

	if ((fd = popen("/tmp/ASD/wl dump stats | grep txframe | awk '{print $2,\"\\n\",$10}'", "r")) == NULL){
		DPRINT_ERR(WFA_ERR, "Couldn't get txframe stats\n");
		goto wfaStaGetStats_error;
	} else {
		fgets(cmdStr, sizeof(cmdStr), fd);	/* line 1: tx frame */
		statsResp.txFrames =  atoi(cmdStr);
		fgets(cmdStr, sizeof(cmdStr), fd);	/* line 2: rx frame */
		statsResp.rxFrames =  atoi(cmdStr);
		pclose(fd);
	}

	if ((fd = popen("/tmp/ASD/wl dump stats | grep txmulti | awk '{print $4, \"\\n\", $6 + $8}'", "r")) == NULL){
		DPRINT_ERR(WFA_ERR, "Couldn't get d11_txmulti stats\n");
		goto wfaStaGetStats_error;
	} else {
		fgets(cmdStr, sizeof(cmdStr), fd);	/* line 1: txmulti */
		statsResp.txMulticast = atoi(cmdStr);
		fgets(cmdStr, sizeof(cmdStr), fd);	/* line 2: d11_txretry + d11_txretrie */
		statsResp.txRetries = atoi(cmdStr);
		pclose(fd);
	}

	if ((fd = popen("/tmp/ASD/wl dump stats | grep rxdfrmmcast | awk '{print $6 + $8}'", "r")) == NULL){
		DPRINT_ERR(WFA_ERR, "Couldn't get rxdfrmmcast stats\n");
		goto wfaStaGetStats_error;
	} else {
		fgets(cmdStr, sizeof(cmdStr), fd);	/* data + mngment mcast frames */
		statsResp.rxMulticast = atoi(cmdStr);
		pclose(fd);
	}

	if ((fd = popen("/tmp/ASD/wl dump stats | grep rxbadfcs | awk '{print $8}'", "r")) == NULL){
		DPRINT_ERR(WFA_ERR, "Couldn't get rxbadfcs  stats\n");
		goto wfaStaGetStats_error;
	} else {
		fgets(cmdStr, sizeof(cmdStr), fd);
		statsResp.fcsErrors = atoi(cmdStr);
		pclose(fd);
	}

	statsResp.status = STATUS_COMPLETE;
	wfaEncodeTLV(WFA_STA_GET_STATS_RESP_TLV, sizeof(statsResp), (BYTE *)&statsResp, respBuf);   
	*respLen = WFA_TLV_HDR_LEN + sizeof(statsResp);
	return TRUE;

wfaStaGetStats_error:
	ret = STATUS_ERROR;
	wfaEncodeTLV(WFA_STA_GET_STATS_RESP_TLV, 4, (BYTE *)&ret, respBuf);   
	*respLen = WFA_TLV_HDR_LEN + 4;
	return FALSE;
}
/*
 * wfaStaGetMacAddress()
 *    This function is to retrieve the MAC address of a wireless I/F.
 */
int wfaStaGetMacAddress(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	dutCmdResponse_t getmacResp;
	FILE *tmpfd;

	DPRINT_INFO(WFA_OUT, "Entering wfaStaGetMacAddress ...\n");

	if ((tmpfd = popen("/tmp/ASD/wl dump | grep perm | awk '{print $4}'", "r")) == NULL){
		int status = STATUS_ERROR;
		wfaEncodeTLV(WFA_STA_GET_MAC_ADDRESS_RESP_TLV, 4, (BYTE *)&status, respBuf);   
		*respLen = WFA_TLV_HDR_LEN + 4;

		DPRINT_ERR(WFA_ERR, "Pipe open for wl dump failed\n");
		return FALSE;
	}
	fgets(getmacResp.cmdru.mac, sizeof(getmacResp.cmdru.mac), tmpfd);
	getmacResp.cmdru.mac[strlen(getmacResp.cmdru.mac) - 1] = 0;		/* Get rid of NL */
	printf("get_mac_addr: returning mac :%s:\n", getmacResp.cmdru.mac);
	pclose (tmpfd);
	getmacResp.status = STATUS_COMPLETE;
 
	wfaEncodeTLV(WFA_STA_GET_MAC_ADDRESS_RESP_TLV, sizeof(getmacResp), 
		(BYTE *)&getmacResp, respBuf);   

	*respLen = WFA_TLV_HDR_LEN + sizeof(getmacResp);
	return TRUE;
}
/*
 * tgStopPing(): Instruct Traffic Generator to stop ping packets
 *
 */
int wfaTGStopPing(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
    int streamid = *(int *)(caCmdBuf);
    dutCmdResponse_t *stpResp = &gGenericResp;
    tgStream_t *myStream;
    int i;

    stpResp->status = STATUS_COMPLETE;

    printf("CS: The length %d\n and the command buff is \n",len);

    for (i=0;i<8;i++)
       printf(" %x ",caCmdBuf[i]);

    printf("\nthe stream id is %d",streamid);

    if( gtgTransac == streamid&&gtgSend == streamid)
    {
        gtgTransac =0;
        gtgSend = 0;
//        gtimeOut = 0;
        gtgRecv = 0;
        alarm(0);

        myStream = findStreamProfile(streamid);
        if(myStream == NULL)
        {
            stpResp->status = STATUS_INVALID;
        }

        stpResp->cmdru.pingStp.sendCnt = myStream->stats.txFrames;
        stpResp->cmdru.pingStp.repliedCnt = myStream->stats.rxFrames;
    }
    else
    {
#if 0
        if(wfaStopPing(stpResp, streamid)== FALSE)
        {
            stpResp->status = STATUS_COMPLETE;

            wfaEncodeTLV(WFA_TRAFFIC_STOP_PING_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)stpResp, respBuf);
            *respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
        }
#endif

        if(cmd_traffic_stop_ping(sigma_dut_ptr(), streamid, stpResp) < 0){        
                       stpResp->status = STATUS_ERROR;  
                       *respLen = 0;
                        return FALSE;
        }        
        //wfaStopPing(stpResp, streamid);
     }

     wfaEncodeTLV(WFA_TRAFFIC_STOP_PING_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)stpResp, respBuf);
     *respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);

    return TRUE;
}
/*
 * wfaTGConfig: store the traffic profile setting that will be used to
 *           instruct traffic generation.
 * input: cmd -- not used
 * response: send success back to controller
 * return: success or fail
 * Note: the profile storage is a global space.
 */
int wfaTGConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
    int ret = FALSE;
    tgStream_t *myStream = NULL;
    dutCmdResponse_t *confResp = &gGenericResp;
    
    /* if the stream table over maximum, reset it */ 
    if(slotCnt == WFA_MAX_TRAFFIC_STREAMS)
       slotCnt = 0;

    if(slotCnt == 0)
    {
       printf("resetting stream table\n");
       wMEMSET(gStreams, 0, WFA_MAX_TRAFFIC_STREAMS*sizeof(tgStream_t));
    }
   
    DPRINT_INFO(WFA_OUT, "entering tcConfig ...\n");
    myStream = &gStreams[slotCnt++];
    wMEMSET(myStream, 0, sizeof(tgStream_t));
    wMEMCPY(&myStream->profile, caCmdBuf, len);
    myStream->id = ++streamId; /* the id start from 1 */ 
    myStream->tblidx = slotCnt-1;

#if 0
    DPRINT_INFO(WFA_OUT, "profile %i direction %i dest ip %s dport %i source %s sport %i rate %i duration %i size %i class %i delay %i\n", myStream->profile.profile, myStream->profile.direction, myStream->profile.dipaddr, myStream->profile.dport, myStream->profile.sipaddr, myStream->profile.sport, myStream->profile.rate, myStream->profile.duration, myStream->profile.pksize, myStream->profile.trafficClass, myStream->profile.startdelay);
#endif
 
    confResp->status = STATUS_COMPLETE; 
    confResp->streamId = myStream->id;
    wfaEncodeTLV(WFA_TRAFFIC_AGENT_CONFIG_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)confResp, respBuf);
    *respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t); 


    return ret;
}
int wfaDeviceGetInfo(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	caDeviceGetInfoResp_t dinfo;
	char cmdStr[WFA_CMD_STR_SZ];
	FILE *fd;

	if ((fd = popen("/tmp/ASD/wl ver | awk '{print $7}'", "r")) == NULL){
		printf("Couldn't open either /tmp/ASD/wl or awk\n");
		dinfo.status = STATUS_ERROR;
	} else {
		memset(&dinfo, 0, sizeof(dinfo));

		fgets(cmdStr, sizeof(cmdStr), fd);	/* Ignore first line */
		fgets(cmdStr, sizeof(cmdStr), fd);
		cmdStr[strlen(cmdStr) - 1] = 0;		/* Get rid of NL */
		pclose(fd);

	   dinfo.status = STATUS_COMPLETE;
	   sprintf(dinfo.vendor, "%.16s", "Broadcom");

	   sprintf(dinfo.version, "%.16s", cmdStr);
	   sprintf(dinfo.model, "%.8s", "BRCM");

	   DPRINT_INFO(WFA_OUT, "Entering wfaDeviceGetInfo ...\n");

	   DPRINT_INFO(WFA_OUT, "status %i vendor %s model %s version %s\n", dinfo.status, dinfo.vendor, dinfo.model, dinfo.version);

	   wfaEncodeTLV(WFA_DEVICE_GET_INFO_RESP_TLV, sizeof(dinfo), (BYTE *)&dinfo, respBuf);   
	   *respLen = WFA_TLV_HDR_LEN + sizeof(dinfo);

   }
   return TRUE;

}
/*
 * wfaStaSetUAPSD()
 *    This is to set
 *    1. maxSPLength - 0,1,2,or 4 
 *    2. acBE
 *    3. acBK
 *    4. acVI
 *    5. acVO
 */
int wfaStaSetUAPSD(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	int ret = 0;
	int retVal = TRUE;
	caStaSetUAPSD_t *uapsd = (caStaSetUAPSD_t *)caCmdBuf;
	bcmSsidObj_t *bso;
	char *ssidStr;

	DPRINT_INFO(WFA_OUT, "maxSPLength %d acBE %d acBK %d acVI %d acVO %d\n",
		uapsd->maxSPLength, uapsd->acBE, uapsd->acBK, uapsd->acVI, uapsd->acVO);

	ssidStr = uapsd->ssid;

	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
			retVal = FALSE;
			goto exit;
		}
	}

	bso->maxSPLength = uapsd->maxSPLength;
	bso->acBE = uapsd->acBE;
	bso->acBK = uapsd->acBK;
	bso->acVI = uapsd->acVI;
	bso->acVO = uapsd->acVO;

exit:
	ret = STATUS_COMPLETE;
	wfaEncodeTLV(WFA_STA_SET_UAPSD_RESP_TLV, 4, (BYTE *)&ret, respBuf);   
	*respLen = WFA_TLV_HDR_LEN + 4;

	return retVal;
}
/*
 *   wfaStaGetBSSID():
 *     This function is to retrieve BSSID of a specific wireless I/F.
 */ 
int wfaStaGetBSSID(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	char cmdStr[WFA_CMD_STR_SZ];
	FILE *tmpfd;
	dutCmdResponse_t bssidResp;

	/* Associated gets long response */
	if ((tmpfd = popen("/tmp/ASD/wl assoc | wc -l", "r")) == NULL){
		printf("wc -l failed\n");
	}
	fgets(cmdStr, sizeof(cmdStr), tmpfd);
	pclose(tmpfd);

	/* Short response means not associated */
	if (atoi(cmdStr) <= 2){
		strcpy(bssidResp.cmdru.bssid, "00:00:00:00:00:00");
	} else {
		if ((tmpfd = popen("/tmp/ASD/wl bssid", "r")) == NULL){
			printf("bassid failed\n");
		}
		fgets(cmdStr, sizeof(cmdStr), tmpfd);
		pclose(tmpfd);
		cmdStr[17] = 0;	/* Get rid of CR or NL */
		strcpy(bssidResp.cmdru.bssid, cmdStr);
	}
	bssidResp.status = STATUS_COMPLETE; 

	wfaEncodeTLV(WFA_STA_GET_BSSID_RESP_TLV, sizeof(bssidResp), 
		(BYTE *)&bssidResp, respBuf);   
	*respLen = WFA_TLV_HDR_LEN + sizeof(bssidResp);
	return TRUE;
}
/*
 * wfaStaSetEapTTLS():
 *   This is to set
 *   1. ssid
 *   2. username
 *   3. passwd
 *   4. encrypType - tkip or aes-ccmp
 *   5. keyManagementType - wpa or wpa2
 *   6. trustedRootCA
 */
int wfaStaSetEapTTLS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   int ret = 0;
   char cmdStr[WFA_CMD_STR_SZ];
   caStaSetEapTTLS_t *setTTLS = (caStaSetEapTTLS_t *)caCmdBuf;
   char *ifname = setTTLS->intf;

   sprintf(cmdStr, "wpa_cli -i %s disable_network 0", ifname);
   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ssid '\"%s\"'", ifname, setTTLS->ssid);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 identity '\"%s\"'", ifname, setTTLS->username);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 password '\"%s\"'", ifname, setTTLS->passwd);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 key_mgmt WPA-EAP", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

/* This may not need to set. if it is not set, default to take all */
//   sprintf(cmdStr, "wpa_cli -i %s set_network 0 pairwise '\"%s\"", ifname, setTTLS->encrptype);
//   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 eap TTLS", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ca_cert '\"%s/%s\"'", ifname, CERTIFICATES_PATH, setTTLS->trustedRootCA);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 proto WPA", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 anonymous_identity '\"anonymous\"'", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 phase2 '\"auth=MSCHAPV2\"'", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s enable_network 0", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   ret = STATUS_COMPLETE;
   wfaEncodeTLV(WFA_STA_SET_EAPTTLS_RESP_TLV, 4, (BYTE *)&ret, respBuf);
   *respLen = WFA_TLV_HDR_LEN + 4;

   return TRUE;
}
/*
 * wfaStaIsConnected():
 *    The function is to check whether the station's wireless I/F has 
 *    already connected to an AP.
 */
int wfaStaIsConnected(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	char cmdStr[WFA_CMD_STR_SZ];
	FILE *tmpfd;
	dutCmdResponse_t staConnectResp;

	DPRINT_INFO(WFA_OUT, "Entering isConnected ...\n"); 

	/* Associated gets long response */
	if ((tmpfd = popen("/tmp/ASD/wl assoc | wc -l", "r")) == NULL){
		printf("wc -l failed\n");
	}
	fgets(cmdStr, sizeof(cmdStr), tmpfd);
	pclose(tmpfd);

	/* Short response means not associated */
	if (atoi(cmdStr) <= 2)
		staConnectResp.cmdru.connected = 0;
	else
		staConnectResp.cmdru.connected = 1;

	/*
	 * Report back the status: Complete or Failed.
	 */
	staConnectResp.status = STATUS_COMPLETE;

	wfaEncodeTLV(WFA_STA_IS_CONNECTED_RESP_TLV, sizeof(staConnectResp), 
		(BYTE *)&staConnectResp, respBuf);   
	*respLen = WFA_TLV_HDR_LEN + sizeof(staConnectResp);
	return TRUE;
}
/*
 * wfaStaSetIpConfig():
 *   The function is to set the ip configuration to a wireless I/F.
 *   1. IP address
 *   2. Mac address
 *   3. default gateway
 *   4. dns nameserver (pri and sec).  
 */
int wfaStaSetIpConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   dutCommand_t *setIpConf = (dutCommand_t *)caCmdBuf;
   char cmds[128];
   int ret = 0;
   caStaSetIpConfig_t *ipconfig = &setIpConf->cmdsu.ipconfig;

   DPRINT_INFO(WFA_OUT, "entering wfaStaSetIpConfig ...\n");

   /*
    * Use command 'ifconfig' to configure the interface ip address, mask.
    * (Linux specific).
    */
   if (!strlen(ipconfig->intf) || !strlen(ipconfig->ipaddr)){
	   ret = STATUS_ERROR;
	   wfaEncodeTLV(WFA_STA_SET_IP_CONFIG_RESP_TLV, 4, (BYTE *)&ret, respBuf);   
	   *respLen = WFA_TLV_HDR_LEN + 4;
	   return TRUE;
   }
   sprintf(cmds, "%s %s %s ", IFCONFIG_PATH, ipconfig->intf, ipconfig->ipaddr);
   if (strlen(ipconfig->mask))
   	sprintf(&cmds[strlen(cmds)], "netmask %s ", ipconfig->mask);
   system(cmds);
   DPRINT_INFO(WFA_OUT, "%s\n", "doing ifconfig");

   /* use command 'route add' to set set gatewway (linux specific) */ 
   if(ipconfig->defGateway[0]) {
      sprintf(cmds, "%s add default gw %s > /dev/null 2>&1", ROUTE_PATH, ipconfig->defGateway);
      system(cmds);
      DPRINT_INFO(WFA_OUT, "%s\n", "doing route add");
   }

   /* set dns (linux specific) */
   if (ipconfig->pri_dns[0]){
	   sprintf(cmds, "cp /etc/resolv.conf /tmp/resolv.conf.bk");
	   system(cmds);
	   sprintf(cmds, "echo nameserv %s > /etc/resolv.conf", ipconfig->pri_dns);
	   system(cmds);
	   sprintf(cmds, "echo nameserv %s >> /etc/resolv.conf", ipconfig->sec_dns);
	   system(cmds);
   }

   ret = STATUS_COMPLETE;
   wfaEncodeTLV(WFA_STA_SET_IP_CONFIG_RESP_TLV, 4, (BYTE *)&ret, respBuf);   
   *respLen = WFA_TLV_HDR_LEN + 4;
   return TRUE;
}
/*
 * wfaStaVerifyIpConnection():
 * The function is to verify if the station has IP connection with an AP by
 * send ICMP/pings to the AP.
 */ 
int wfaStaVerifyIpConnection(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   dutCommand_t *verip = (dutCommand_t *)caCmdBuf;
   char cmdStr[WFA_CMD_STR_SZ];
   FILE *tmpfile;
   dutCmdResponse_t verifyIpResp;
   dutCommand_t vvv;

   
   DPRINT_INFO(WFA_OUT, "Entering wfaStaVerifyIpConnection ...\n");
   memcpy(&vvv, caCmdBuf, sizeof(dutCommand_t));

   /* set timeout value in case not set */
   if(verip->cmdsu.verifyIp.timeout <= 0)
        verip->cmdsu.verifyIp.timeout = 10;
   
   /* execute the ping command  and pipe the result to a tmp file */
   sprintf(cmdStr, "ping %s -c 3 -W %d | grep '100%%'", verip->cmdsu.verifyIp.dipaddr,  verip->cmdsu.verifyIp.timeout);

   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   if (strlen(verip->cmdsu.verifyIp.dipaddr) == 0 || ((tmpfile = popen(cmdStr, "r")) == NULL)){
      int status = STATUS_ERROR;
      wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV, 4, (BYTE *)&status, respBuf);   
      *respLen = WFA_TLV_HDR_LEN + 4;

      DPRINT_ERR(WFA_ERR, "Could not execute %s\n", cmdStr);
      return FALSE;
   }

   verifyIpResp.status = STATUS_COMPLETE;

   if (fgets(cmdStr, sizeof(cmdStr), tmpfile) == NULL){
      verifyIpResp.cmdru.connected = 1;
   } else{
      verifyIpResp.cmdru.connected = 0;
   }
   pclose(tmpfile);
   

   wfaEncodeTLV(WFA_STA_VERIFY_IP_CONNECTION_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)&verifyIpResp, respBuf);   

   *respLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);
   
   return TRUE;
}
/*
 * The function is to set 
 *   1. ssid
 *   2. passPhrase
 *   3. keyMangementType - wpa/wpa2
 *   4. encrypType - tkip or aes-ccmp
 */
int wfaStaSetPSK(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	int ret = 0;
	int retVal = TRUE;
	caStaSetPSK_t *setPSK = (caStaSetPSK_t *)caCmdBuf;
	bcmSsidObj_t *bso;
	char *ssidStr;

	DPRINT_INFO(WFA_OUT, "wfaStaSetPSK()");

	ssidStr = setPSK->ssid;
	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
			retVal = FALSE;
			goto exit;
		}
	}

	if (!strcmp(setPSK->keyMgmtType, "wpa")) {
		bso->wpa_auth = BCM_WPA_AUTH_PSK; /* WPA-PSK/WPA-Personal */
	} else if (!strcmp(setPSK->keyMgmtType, "wpa2")) {
		bso->wpa_auth = BCM_WPA2_AUTH_PSK; /* WPA2-PSK/WPA2-Personal */
	} else {
		DPRINT_ERR(WFA_OUT, "invalid key_mgmt %s", setPSK->keyMgmtType); 
		retVal = FALSE;
		goto exit;
	}

	DPRINT_INFO(WFA_OUT, "wpa_auth %d\n", bso->wpa_auth);

	if (setPSK->encpType == ENCRYPT_TKIP) {
		bso->wsec = 3;
	} else if (setPSK->encpType == ENCRYPT_AESCCMP) {
		bso->wsec = 7;
	} else {
		DPRINT_ERR(WFA_OUT, "invalid encpType %d", setPSK->encpType); 
		goto exit;
	}
	DPRINT_INFO(WFA_OUT, "encpType %d wsec %d\n", setPSK->encpType, bso->wsec);

	strcpy((char *)bso->passphrase, (char *)setPSK->passphrase);
	bso->auth = 0;

	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
		bcmWfaSsidObjPrint(bso);
	}

	retVal = TRUE;

exit:	
	ret = STATUS_COMPLETE;
	wfaEncodeTLV(WFA_STA_SET_PSK_RESP_TLV, 4, (BYTE *)&ret, respBuf);   
	*respLen = WFA_TLV_HDR_LEN + 4;
	
	return retVal; 
}
/* Not sure what the intention is, but I am using this routine
 * as storing info only, no action.  Action is taken when we actually associate */
int wfaStaSetIBSS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	int ret;
	int retVal = TRUE;
	caStaSetIBSS_t *setIBSS = (caStaSetIBSS_t *)caCmdBuf;
	bcmSsidObj_t *bso;
	int idx;
	char *ssidStr;
	
	DPRINT_INFO(WFA_OUT, "wfaStaSetIBSS()\n");

	/* Save the settings for when we need them */

	ssidStr = setIBSS->ssid;

	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
			retVal = FALSE;
			goto exit;
		}
	}

	bso->bssType = BCM_BSS_INDEPENDENT;

	if (setIBSS->channel) {
		bso->channel = setIBSS->channel;
	}

	bso->wsec = (!setIBSS->encpType) ? 0 : 1;

	for(idx = 0; idx < 4; idx++) {
		if(setIBSS->keys[idx][0] != '\0') {
			strcpy(bso->keys[idx], setIBSS->keys[idx]);
		} else {
			bzero(bso->keys[idx], BCM_WEP_KEY_SIZE_MAX);
		}
	}

	if ((setIBSS->activeKeyIdx > 0) && (setIBSS->activeKeyIdx < 5)) {
		/* move the index range from (1 to 4) to (0 to 3) */
		bso->primary_key = setIBSS->activeKeyIdx - 1;
	}

	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
		bcmWfaSsidObjPrint(bso);
	}

exit:
	ret = STATUS_COMPLETE;
	wfaEncodeTLV(WFA_STA_SET_IBSS_RESP_TLV, 4, (BYTE *)&ret, respBuf);   
	*respLen = WFA_TLV_HDR_LEN + 4;
	
	return retVal;
}
/*
 * collects the traffic statistics from other threads and
 * sends the collected information to CA
 */
void  wfaSentStatsResp(int sock, BYTE *buf)
{
    int i, total=0, pkLen;
    tgStream_t *allStreams = gStreams;
    dutCmdResponse_t *sendStatsResp = (dutCmdResponse_t *)buf, *first;
    char buff[WFA_RESP_BUF_SZ];

    if(sendStatsResp == NULL)
        return;

    first = sendStatsResp;

    for(i = 0; i < WFA_MAX_TRAFFIC_STREAMS; i++)
    {
        if((allStreams->id != 0) && (allStreams->profile.direction == DIRECT_SEND) && (allStreams->state == WFA_STREAM_ACTIVE))
        {
            sendStatsResp->status = STATUS_COMPLETE;
            sendStatsResp->streamId = allStreams->id;
            printf("stats stream id %i\n", allStreams->id);
            wMEMCPY(&sendStatsResp->cmdru.stats, &allStreams->stats, sizeof(tgStats_t));

            sendStatsResp++;
            total++;
        }
        allStreams->state = WFA_STREAM_INACTIVE;
        allStreams++;
    }

#if 1
    printf("%u %u %llu %llu\n", first->cmdru.stats.txFrames,
           first->cmdru.stats.rxFrames,
           first->cmdru.stats.txPayloadBytes,
           first->cmdru.stats.rxPayloadBytes);
#endif

    wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, total*sizeof(dutCmdResponse_t),
                 (BYTE *)first, (BYTE *)buff);

    pkLen = WFA_TLV_HDR_LEN + total*sizeof(dutCmdResponse_t);
    printf("pkLen %i\n", pkLen);

#if 0
    for(i = 0; i< pkLen; i++)
        printf("%x ", buff[i]);

    printf("\n");
#endif

    if(wfaCtrlSend(sock, (BYTE *)buff, pkLen) != pkLen)
    {
        DPRINT_WARNING(WFA_WNG, "wfaCtrlSend Error\n");
    }

    return;
}
/*
 * wfaSetEncryption():
 *   The function is to set the wireless interface with WEP or none.
 *   Input parameters: 
 *     1. I/F
 *     2. ssid
 *     3. encpType - wep or none
 *     Optional:
 *     4. key1
 *     5. key2
 *     6. key3
 *     7. key4
 *     8. activeKey Index : 1, 2, 3, or 4
 */
int wfaSetEncryption(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	int ret = 0;
	int retVal = TRUE;
	caStaSetEncryption_t *setEncryp = (caStaSetEncryption_t *)caCmdBuf;
	int idx;
	bcmSsidObj_t *bso;
	char * ssidStr;

	DPRINT_INFO(WFA_OUT, "wfaSetEncryption()\n");

	/* Save the settings for when we need them */

	ssidStr = setEncryp->ssid;

	if (!(bso = bcmWfaSsidTblSsidFind(ssidStr))) {
		if (!(bso = bcmWfaSsidObjTblAdd(ssidStr))) {
			DPRINT_INFO(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed.\n", ssidStr);
			retVal = FALSE;
			goto exit;
		}
	}

	/* set Key management to NONE (NO WPA) for plaintext or WEP */
	bso->wpa_auth = BCM_WPA_AUTH_DISABLED;

	for(idx = 0; idx < 4; idx++) {
		if(setEncryp->keys[idx][0] != '\0') {
			strcpy(bso->keys[idx], setEncryp->keys[idx]);
		} else {
			bzero(bso->keys[idx], BCM_WEP_KEY_SIZE_MAX);
		}
	}

	if ((setEncryp->activeKeyIdx > 0) && (setEncryp->activeKeyIdx < 5)) {
		/* move the index range from (1 to 4) to (0 to 3) */
		bso->primary_key = setEncryp->activeKeyIdx - 1;
	}

	bso->wsec = (!setEncryp->encpType) ? 0 : 1;

	if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
		bcmWfaSsidObjPrint(bso);
	}

exit:	
	ret = STATUS_COMPLETE;
	wfaEncodeTLV(WFA_STA_SET_ENCRYPTION_RESP_TLV, 4, (BYTE *)&ret, respBuf);
	*respLen = WFA_TLV_HDR_LEN + 4;
	
	return retVal;
}
/*
 * This funciton is to retrieve a list of interfaces and return
 * the list back to Agent control.
 * 
 */
int wfaDeviceListIF(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   int ret;
   dutCommand_t *ifList = (dutCommand_t *)caCmdBuf;
   caDeviceListIFResp_t ifListResp;

   switch(ifList->cmdsu.iftype)
   {
      case IF_80211:
      ifListResp.status = STATUS_COMPLETE;
      ifListResp.iftype = IF_80211; 
      strcpy(ifListResp.ifs[0], "eth1");
      strcpy(ifListResp.ifs[1], "NULL");
      strcpy(ifListResp.ifs[2], "NULL");
      break;
      case IF_ETH:
      ifListResp.status = STATUS_COMPLETE;
      ifListResp.iftype = IF_ETH; 
      strcpy(ifListResp.ifs[0], "eth0");
      strcpy(ifListResp.ifs[1], "NULL");
      strcpy(ifListResp.ifs[2], "NULL");
      break;
      default:
      {
         ret = STATUS_ERROR;
         wfaEncodeTLV(WFA_DEVICE_LIST_IF_RESP_TLV, 4, (BYTE *)&ret, respBuf);   
         *respLen = WFA_TLV_HDR_LEN + 4;

         return TRUE; 
      }
   }
   
   wfaEncodeTLV(WFA_DEVICE_LIST_IF_RESP_TLV, sizeof(ifListResp), (BYTE *)&ifListResp, respBuf);   
   *respLen = WFA_TLV_HDR_LEN + sizeof(ifListResp);

   return TRUE;
}
/*
 * agtCmdProcGetVersion(): response "ca_get_version" command to controller
 *  input:  cmd --- not used
 *          valLen -- not used
 *  output: parms -- a buffer to store the version info response.
 */
int agtCmdProcGetVersion(int len, BYTE *parms, int *respLen, BYTE *respBuf)
{
    dutCmdResponse_t getverResp;

    DPRINT_INFO(WFA_OUT, "entering agtCmdProcGetVersion ...\n");

    getverResp.status = STATUS_COMPLETE;
    strncpy(getverResp.cmdru.version, WFA_SYSTEM_VER, 8);

    wfaEncodeTLV(WFA_GET_VERSION_RESP_TLV, sizeof(getverResp), (BYTE *)&getverResp, respBuf);

    *respLen = WFA_TLV_HDR_LEN + sizeof(getverResp);

    return TRUE;
}
/*
 * wfaStaGetInfo(): 
 * Get vendor specific information in name/value pair by a wireless I/F.
 */
int wfaStaGetInfo(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   dutCmdResponse_t infoResp;
   dutCommand_t *getInfo = (dutCommand_t *)caCmdBuf;

   /*
    * Normally this is called to retrieve the vendor information
    * from a interface, no implement yet
    */
   sprintf(infoResp.cmdru.info, "interface,%s,vendor,XXX,cardtype,802.11a/b/g", getInfo->intf);
   
   infoResp.status = STATUS_COMPLETE;
   wfaEncodeTLV(WFA_STA_GET_INFO_RESP_TLV, sizeof(infoResp), (BYTE *)&infoResp, respBuf);   
   *respLen = WFA_TLV_HDR_LEN + sizeof(infoResp);

    DPRINT_INFO(WFA_OUT, "%s\n", infoResp.cmdru.info);

   return TRUE;
}
int wfaStaDebugSet(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   dutCmdResponse_t debugResp;
   dutCommand_t *debugSet = (dutCommand_t *)caCmdBuf;

   DPRINT_INFO(WFA_OUT, "Entering wfaStaDebugSet ...\n");

   if(debugSet->cmdsu.dbg.state == 1) /* enable */
      wfa_defined_debug |= debugSet->cmdsu.dbg.level;
   else
      wfa_defined_debug = (~debugSet->cmdsu.dbg.level & wfa_defined_debug);

   debugResp.status = STATUS_COMPLETE;
   wfaEncodeTLV(WFA_STA_GET_INFO_RESP_TLV, sizeof(debugResp), (BYTE *)&debugResp, respBuf);   
   *respLen = WFA_TLV_HDR_LEN + sizeof(debugResp);

    DPRINT_INFO(WFA_OUT, "%s\n", debugResp.cmdru.info);

   return TRUE;
}
/*
 * wfaStaSetEapSIM():
 *   This is to set
 *   1. ssid
 *   2. user name
 *   3. passwd
 *   4. encrypType - tkip or aes-ccmp
 *   5. keyMangementType - wpa or wpa2
 */
int wfaStaSetEapSIM(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   int ret = 0;
   char cmdStr[WFA_CMD_STR_SZ];
   caStaSetEapSIM_t *setSIM = (caStaSetEapSIM_t *)caCmdBuf;
   char *ifname = setSIM->intf;

   sprintf(cmdStr, "wpa_cli -i %s disable_network 0", ifname);
   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ssid '\"%s\"'", ifname, setSIM->ssid);
   system(cmdStr);


   sprintf(cmdStr, "wpa_cli -i %s set_network 0 identity '\"%s\"'", ifname, setSIM->username);
   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 key_mgmt WPA-EAP", ifname);
   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 pairwise '\"%s\"'", ifname, setSIM->encrptype);
   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 eap SIM", ifname);
   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 proto WPA", ifname);
   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s enable_network 0", ifname);
   system(cmdStr);

   ret = STATUS_COMPLETE;
   wfaEncodeTLV(WFA_STA_SET_EAPSIM_RESP_TLV, 4, (BYTE *)&ret, respBuf);
   *respLen = WFA_TLV_HDR_LEN + 4;

   return ret;
}
/* RecvStart: instruct traffic generator to start receiving 
 *                 based on a profile
 * input:      cmd -- not used
 * response:   inform controller for "running"
 * return:     success or failed 
 */
int wfaTGRecvStart(int len, BYTE *parms, int *respLen, BYTE *respBuf)
{
    int status = STATUS_COMPLETE, i;
    int numStreams = len/4;
    int streamid;
    tgProfile_t *theProfile;
    tgStream_t *myStream;

    DPRINT_INFO(WFA_OUT, "entering tgRecvStart\n");

    /*
     * The function wfaSetProcPriority called here is to enhance the real-time
     * performance for packet receiving. It is only for tuning and optional
     * to implement
     */
    //wfaSetProcPriority(60);

    for(i=0; i<numStreams; i++)
    {
        wMEMCPY(&streamid, parms+(4*i), 4); /* changed from 2 to 4, bug reported by n.ojanen */
        myStream = findStreamProfile(streamid); 
        if(myStream == NULL)
        {
            status = STATUS_INVALID;
            return status;    
        }

        theProfile = &myStream->profile;
        if(theProfile == NULL)
        {
           status = STATUS_INVALID;
           return status;
        }

        /* calculate the frame interval which is used to derive its jitter */
        if(theProfile->rate != 0 && theProfile->rate < 5000)
           myStream->fmInterval = 1000000/theProfile->rate; /* in ms */
        else
           myStream->fmInterval = 0;

        if(theProfile->direction != DIRECT_RECV)
        {
           status = STATUS_INVALID;
           return status;
        }

        wMEMSET(&myStream->stats, 0, sizeof(tgStats_t));

        // mark the stream active
        myStream->state = WFA_STREAM_ACTIVE;
       
        switch(theProfile->profile)
        {
#ifdef WFA_WPA2_SINGLE_THREAD  
           case PROF_MCAST:
           case PROF_FILE_TX:
//           case PROF_IPTV:
               btSockfd = wfaCreateUDPSock(theProfile->dipaddr, theProfile->dport);
               gtgRecv = streamid;

               if(btSockfd < 0)
                  status = STATUS_ERROR;
               else
               {
                  /* get current flags setting */
                  int ioflags = wFCNTL(btSockfd, F_GETFL, 0);

                  /* set only BLOCKING flag to non-blocking */
                  wFCNTL(btSockfd, F_SETFL, ioflags | O_NONBLOCK);
               }
           break;
#else

           case PROF_TRANSC:
	   case PROF_CALI_RTD:  /* Calibrate roundtrip delay */
              gtgTransac = streamid;
           case PROF_MCAST:
           case PROF_FILE_TX:
           case PROF_IPTV:
              gtgRecv = streamid;
              wmm_thr[usedThread].thr_flag = streamid;
              wPT_MUTEX_LOCK(&wmm_thr[usedThread].thr_flag_mutex);
              wPT_COND_SIGNAL(&wmm_thr[usedThread].thr_flag_cond);
              wPT_MUTEX_UNLOCK(&wmm_thr[usedThread].thr_flag_mutex);
              printf("Recv Start in thread %i for streamid %i\n", usedThread, streamid);
	      usedThread++;
           break;
#endif       
           case PROF_UAPSD:
#ifdef WFA_WMM_PS_EXT
           status = STATUS_COMPLETE;
           psSockfd = wfaCreateUDPSock(theProfile->dipaddr, WFA_WMMPS_UDP_PORT);

           wmmps_info.sta_state = 0;
           wmmps_info.wait_state = WFA_WAIT_STAUT_00;

           wMEMSET(&wmmps_info.psToAddr, 0, sizeof(wmmps_info.psToAddr));
           wmmps_info.psToAddr.sin_family = AF_INET;
           wmmps_info.psToAddr.sin_addr.s_addr = inet_addr(theProfile->sipaddr);
           wmmps_info.psToAddr.sin_port = htons(theProfile->sport);
	   wmmps_info.reset = 0;

           wmm_thr[usedThread].thr_flag = streamid;
           wmmps_info.streamid = streamid;
           wPT_MUTEX_LOCK(&wmm_thr[usedThread].thr_flag_mutex);
           wPT_COND_SIGNAL(&wmm_thr[usedThread].thr_flag_cond);
           gtgWmmPS = streamid;;
           wPT_MUTEX_UNLOCK(&wmm_thr[usedThread].thr_flag_mutex);
           usedThread++;
#endif   /* WFA_WMM_PS_EXT */
           break;
       }
    }

    /* encode a TLV for response for "complete/error ..." */
    wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_START_RESP_TLV, sizeof(int), 
                 (BYTE *)&status, respBuf);
    *respLen = WFA_TLV_HDR_LEN + sizeof(int); 

    return TRUE;
}
/*
 * tgRecvStop: instruct traffic generator to stop receiving based on a profile
 * input:      cmd -- not used
 * response:   inform controller for "complete"
 * return:     success or failed 
 */
int wfaTGRecvStop(int len, BYTE *parms, int *respLen, BYTE *respBuf)
{
    int status = STATUS_COMPLETE, i;
    int numStreams = len/4;
    unsigned int streamid;
    tgProfile_t *theProfile;
    tgStream_t *myStream=NULL;
    dutCmdResponse_t statResp;
    BYTE dutRspBuf[WFA_RESP_BUF_SZ];
    int id_cnt = 0;

    DPRINT_INFO(WFA_OUT, "entering tgRecvStop with length %d\n",len);

    /* in case that send-stream not done yet, an optional delay */
    while(sendThrId != 0)
      sleep(1);

    /*
     * After finishing the receiving command, it should lower itself back to 
     * normal level. It is optional implementation if it is not called 
     * while it starts receiving for raising priority level.
     */
    //wfaSetProcPriority(30);
    wMEMSET(dutRspBuf, 0, WFA_RESP_BUF_SZ);
    for(i=0; i<numStreams; i++)
    {
        wMEMCPY(&streamid, parms+(4*i), 4);
        printf(" stop stream id %i\n", streamid);
        myStream = findStreamProfile(streamid); 
        if(myStream == NULL)
        {
            status = STATUS_INVALID;
            wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV, 4, (BYTE *)&status, respBuf);
            *respLen = WFA_TLV_HDR_LEN + 4;
            printf("stream table empty\n");
            continue;    
        }

        theProfile = &myStream->profile;
        if(theProfile == NULL)
        {
           status = STATUS_INVALID;
           wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV, 4, (BYTE *)&status, respBuf);
           *respLen = WFA_TLV_HDR_LEN + 4;

           return TRUE;
        }

        if(theProfile->direction != DIRECT_RECV)
        {
           status = STATUS_INVALID;
           wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV, 4, (BYTE *)&status, respBuf);
           *respLen = WFA_TLV_HDR_LEN + 4;

           return TRUE;
        }

        /* reset its flags , close sockets */
        switch(theProfile->profile)
        {
         case PROF_TRANSC:
	 case PROF_CALI_RTD:
	     gtgTransac = 0;
         case PROF_MCAST:
         case PROF_FILE_TX:
         case PROF_IPTV:
             gtgRecv = 0;
             if(tgSockfds[myStream->tblidx] != -1)
             {
                wCLOSE(tgSockfds[myStream->tblidx]);
                tgSockfds[myStream->tblidx] = -1;
             }
         break;

	 case PROF_UAPSD:
#ifdef WFA_WMM_PS_EXT
         gtgWmmPS = 0;
         gtgPsPktRecvd = 0;

         if(psSockfd != -1)
         {
             wCLOSE(psSockfd);
             psSockfd = -1;
         }

         wMEMSET(&wmmps_info, 0, sizeof(wfaWmmPS_t));

         wfaSetDUTPwrMgmt(PS_OFF);
#endif /* WFA_WMM_PS_EXT */
         break;

         }
 
    	/* encode a TLV for response for "complete/error ..." */
    	statResp.status = STATUS_COMPLETE; 
    	statResp.streamId = streamid; 

#if 1
    	DPRINT_INFO(WFA_OUT, "stream Id %u rx %u total %llu\n", streamid, myStream->stats.rxFrames, myStream->stats.rxPayloadBytes);
#endif
    	wMEMCPY(&statResp.cmdru.stats, &myStream->stats, sizeof(tgStats_t));
     	wMEMCPY((dutRspBuf + i * sizeof(dutCmdResponse_t)), (BYTE *)&statResp, sizeof(dutCmdResponse_t));
	id_cnt++;

        // Not empty it but require to reset the entire table before test starts.
        //wMEMSET(myStream, 0, sizeof(tgStream_t));
    }

    // mark the stream inactive
    myStream->state = WFA_STREAM_INACTIVE;

    printf("Sending back the statistics at recvstop\n");
    wfaEncodeTLV(WFA_TRAFFIC_AGENT_RECV_STOP_RESP_TLV, id_cnt * sizeof(dutCmdResponse_t), dutRspBuf, respBuf);

    /* done here */
    *respLen = WFA_TLV_HDR_LEN + numStreams * sizeof(dutCmdResponse_t); 

    return TRUE;
}
/*
 * wfaStaSetEapTLS():
 *   This is to set
 *   1. ssid
 *   2. encrypType - tkip or aes-ccmp
 *   3. keyManagementType - wpa or wpa2
 *   4. trustedRootCA
 *   5. clientCertificate
 */
int wfaStaSetEapTLS(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   int ret = 0;
   caStaSetEapTLS_t *setTLS = (caStaSetEapTLS_t *)caCmdBuf;
   char cmdStr[WFA_CMD_STR_SZ];
   char *ifname = setTLS->intf;

   DPRINT_INFO(WFA_OUT, "Entering wfaStaSetEapTLS ...\n");

   /*
    * need to store the trustedROOTCA and clientCertificate into a file first.
    */
   sprintf(cmdStr, "wpa_cli -i %s disable_network 0", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   /* ssid */
   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ssid '\"%s\"'", ifname, setTLS->ssid);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   /* key management */
   sprintf(cmdStr, "wpa_cli -i %s set_network 0 key_mgmt WPA-EAP", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   /* protocol WPA */
   sprintf(cmdStr, "wpa_cli -i %s set_network 0 proto WPA", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 eap TLS", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ca_cert '\"%s\"'", ifname, setTLS->trustedRootCA);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 identity '\"[email protected]\"'", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 private_key '\"%s/%s\"'", ifname, CERTIFICATES_PATH, setTLS->clientCertificate);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 private_key_passwd '\"wifi\"'", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s enable_network 0", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   ret = STATUS_COMPLETE;
   wfaEncodeTLV(WFA_STA_SET_EAPTLS_RESP_TLV, 4, (BYTE *)&ret, respBuf);
   *respLen = WFA_TLV_HDR_LEN + 4;

   return TRUE;
}
/*
 * wfaTGSendStart: instruct traffic generator to start sending based on a profile
 * input:      cmd -- not used
 * response:   inform controller for "running"
 * return:     success or failed 
 */
int wfaTGSendStart(int len, BYTE *parms, int *respLen, BYTE *respBuf)
{
    int i=0, streamid=0;
    int numStreams = len/4;

    tgProfile_t *theProfile;
    tgStream_t *myStream = NULL;

    dutCmdResponse_t staSendResp;

    DPRINT_INFO(WFA_OUT, "Entering tgSendStart for %i streams ...\n", numStreams);
    for(i=0; i<numStreams; i++)
    {
        wMEMCPY(&streamid, parms+(4*i), 4);
        myStream = findStreamProfile(streamid); 
        if(myStream == NULL)
        {
           staSendResp.status = STATUS_INVALID;
           wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
           *respLen = WFA_TLV_HDR_LEN + 4;
           return TRUE;
        }

        theProfile = &myStream->profile;
        if(theProfile == NULL)
        {
           staSendResp.status = STATUS_INVALID;
           wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
           *respLen = WFA_TLV_HDR_LEN + 4;

           return TRUE;
        }
               
        if(theProfile->direction != DIRECT_SEND)
        {
           staSendResp.status = STATUS_INVALID;
           wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&staSendResp, respBuf);
           *respLen = WFA_TLV_HDR_LEN + 4;

           return TRUE;
        }

        /*
         * need to reset the stats
         */
        wMEMSET(&myStream->stats, 0, sizeof(tgStats_t));

        // mark the stream active;
        myStream->state = WFA_STREAM_ACTIVE;

        switch(theProfile->profile)
        {
        case PROF_FILE_TX:
        case PROF_MCAST:
        case PROF_TRANSC:
        gtgTransac = streamid;
        gtgSend = streamid;
        case PROF_CALI_RTD:
        gtgCaliRTD = streamid;
        case PROF_IPTV:
        gtgSend = streamid;
        /*
         * singal the thread to Sending WMM traffic 
         */
         
        //if(usedThread < 
        wmm_thr[usedThread].thr_flag = streamid;
        wPT_MUTEX_LOCK(&wmm_thr[usedThread].thr_flag_mutex);
        wPT_COND_SIGNAL(&wmm_thr[usedThread].thr_flag_cond);
        wPT_MUTEX_UNLOCK(&wmm_thr[usedThread].thr_flag_mutex);
        usedThread++;
        //wfaSetProcPriority(90);

        break;
        } 
    }

    *respLen = 0;
    return TRUE;
}
int wfaTGReset(int len, BYTE *parms, int *respLen, BYTE *respBuf)
{
    dutCmdResponse_t *resetResp = &gGenericResp;
    int i;

    /* need to reset all traffic socket fds */
    if(btSockfd != -1)
    {
       wCLOSE(btSockfd);
       btSockfd = -1;
    }

    for(i = 0; i<WFA_MAX_TRAFFIC_STREAMS; i++)
    {
        if(tgSockfds[i] != -1)
        {
            wCLOSE(tgSockfds[i]);
            tgSockfds[i] = -1;
        }
    }

    /* reset the timer alarm if it was armed */
    wALARM(0);

    /* just reset the flags for the command */
    gtgRecv = 0;
    gtgSend = 0;
    gtgTransac = 0;
#ifdef WFA_VOICE_EXT
    gtgCaliRTD = 0;
    min_rttime = 0xFFFFFFFF;
    gtgPktRTDelay = 0xFFFFFFFF;
#endif

    totalTranPkts = 0;
    //gtimeOut = 0;

    runLoop = 0;

    usedThread = 0;
#ifdef WFA_WMM_PS_EXT
    gtgWmmPS = 0;
    gtgPsPktRecvd = 0;

    if(psSockfd != -1)
    {
       wCLOSE(psSockfd);
       psSockfd = -1;
    }

    wMEMSET(&wmmps_info, 0, sizeof(wfaWmmPS_t));

//         wfaSetDUTPwrMgmt(PS_OFF);
#endif

    e2eResults[0] = '\0';

    /* Also need to clean up WMM streams NOT DONE YET!*/
    slotCnt = 0;             /* reset stream profile container */
    wMEMSET(gStreams, 0, WFA_MAX_TRAFFIC_STREAMS); 

    /*
     * After be asked to reset, it should lower itself back to 
     * normal level. It is optional implementation if it is not called 
     * while it starts sending/receiving for raising priority level.
     */
    //wfaSetProcPriority(20);

    /* encode a TLV for response for "complete ..." */
    resetResp->status = STATUS_COMPLETE; 
    wfaEncodeTLV(WFA_TRAFFIC_AGENT_RESET_RESP_TLV, 4, 
                 (BYTE *)resetResp, respBuf);
    *respLen = WFA_TLV_HDR_LEN + 4; 

    return TRUE;
}
/* This is going to be a blocking SEND till it finishes */
int wfaSendLongFile(int mySockfd, int streamid, BYTE *aRespBuf, int *aRespLen)
{
    tgProfile_t           *theProf = NULL;
    tgStream_t            *myStream = NULL;
    struct sockaddr_in    toAddr;
    char                  *packBuf; 
    int  packLen;
    int  bytesSent;
    dutCmdResponse_t sendResp;
    int sleepTime = 0;
    int throttledRate = 0;
    struct timeval before, after,af; 
    int difftime = 0, counter = 0;
    struct timeval stime;
    int throttled_est_cost;
    int act_sleep_time;
    gettimeofday(&af,0);
   
    DPRINT_INFO(WFA_OUT, "Entering sendLongFile %i\n", streamid);

    /* find the profile */
    myStream = findStreamProfile(streamid);
    if(myStream == NULL)
    {
        return FALSE;    
    }

    theProf = &myStream->profile;

    if(theProf == NULL)
    {
        return FALSE;
    }

    packLen = theProf->pksize;

    /* allocate a buf */
    packBuf = (char *)malloc(packLen);
    wMEMSET(packBuf, 1, packLen);

    /* fill in the header */
    wSTRNCPY(packBuf, "1345678", sizeof(tgHeader_t));

    /* initialize the destination address */
    wMEMSET(&toAddr, 0, sizeof(toAddr));
    toAddr.sin_family = AF_INET;
    toAddr.sin_addr.s_addr = inet_addr(theProf->dipaddr);
    toAddr.sin_port = htons(theProf->dport); 

    /* if a frame rate and duration are defined, then we know
     * interval for each packet and how many packets it needs to
     * send.
     */
    if(theProf->duration != 0)
    {
        printf("duration %i\n", theProf->duration);
        
        /* 
         *  use this to decide periodical interval sleep time and frames to send
         *  int the each interval.
         *  Each device should adopt a own algorithm for better performance
         */
        wfaTxSleepTime(theProf->profile, theProf->rate, &sleepTime, &throttledRate);
        /* 
         * alright, we need to raise the priority level of the process
         * to improve the real-time performance of packet sending.
         * Since this is for tuning purpose, it is optional implementation.
         */
        //wfaSetProcPriority(60);
	
	//interval = 1*1000000/theProf->rate ; // in usec;

	// Here assumes it takes 20 usec to send a packet
	throttled_est_cost = throttledRate * 20;  // MUST estimate the cost per ppk
	act_sleep_time = sleepTime - adj_latency;
	if (act_sleep_time <= 0)
	    act_sleep_time = sleepTime;  

        printf("sleep time %i act_sleep_time %i\n", sleepTime, act_sleep_time);

        runLoop=1;
        while(runLoop)
        {
	   counter++;
           /* fill in the counter */
           int2BuffBigEndian(counter, &((tgHeader_t *)packBuf)->hdr[8]);

           /*
            * the following code is only used to slow down
            * over fast traffic flooding the buffer and cause
            * packet drop or the other end not able to receive due to
            * some limitations, purely for experiment purpose.
            * each implementation needs some fine tune to it.
            */
	   if(counter ==1)
	   {
               wGETTIMEOFDAY(&before, NULL);

               before.tv_usec += sleepTime;
               if(before.tv_usec > 1000000)
               {
                   before.tv_usec -= 1000000;
                   before.tv_sec +=1;
               }
           }

           if(throttledRate != 0)
           {
              if(counter%throttledRate == 0)
              {
                 wGETTIMEOFDAY(&after, NULL);
	         difftime = wfa_itime_diff(&after, &before);

                 if(difftime > adj_latency)
                 {
                    // too much time left, go sleep
                    wUSLEEP(difftime-adj_latency);

                    wGETTIMEOFDAY(&after, NULL);
	            difftime = wfa_itime_diff(&after, &before);
                 }

		 // burn the rest to absort latency
	         if(difftime >0)
	             buzz_time(difftime);

	         before.tv_usec += sleepTime;
	         if(before.tv_usec > 1000000)
	         {
	             before.tv_usec -= 1000000;
		     before.tv_sec +=1;
	         }
              }
           } // otherwise, it floods 

	   /*
	    * Fill the timestamp to the header.
	    */
	   wGETTIMEOFDAY(&stime, NULL);

	   int2BuffBigEndian(stime.tv_sec, &((tgHeader_t *)packBuf)->hdr[12]);
	   int2BuffBigEndian(stime.tv_usec, &((tgHeader_t *)packBuf)->hdr[16]);

           bytesSent = wfaTrafficSendTo(mySockfd, packBuf, packLen, 
                            (struct sockaddr *)&toAddr);

           if(bytesSent != -1)
           {
              myStream->stats.txPayloadBytes += bytesSent; 
              myStream->stats.txFrames++ ;
           }
           else
           {
               int errsv = errno;
               switch(errsv)
               {
	           case EAGAIN:
                   case ENOBUFS:
                        DPRINT_ERR(WFA_ERR, "send error\n");
                        wUSLEEP(1000);             /* hold for 1 ms */
                        counter-- ;
                        myStream->stats.txFrames--;
                   break;
                   case ECONNRESET:
                        runLoop = 0;
                   break;
                   case EPIPE:
                        runLoop = 0;
                   break;
                   default:
                      perror("sendto: ");
                      DPRINT_ERR(WFA_ERR, "Packet sent error\n");
               }
           }

        }


        /*
         * lower back to an original level if the process is raised previously
         * It is optional.
         */
        //wfaSetProcPriority(30); 
    }
    else /* invalid parameters */
    {
        /* encode a TLV for response for "invalid ..." */
        sendResp.status = STATUS_INVALID;
        wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, 
                 (BYTE *)&sendResp, (BYTE *)aRespBuf);

        /* done here */
        *aRespLen = WFA_TLV_HDR_LEN + 4; 

        return DONE;
    }

    gtgSend = 0;

    /* free the buffer */
    wFREE(packBuf);

    //printf("done sending long\n");
    /* return statistics */
    sendResp.status = STATUS_COMPLETE;
    sendResp.streamId = myStream->id;
    wMEMCPY(&sendResp.cmdru.stats, &myStream->stats, sizeof(tgStats_t)); 

#if 0
    DPRINT_INFO(WFA_OUT, "stream Id %u tx %u total %llu\n", myStream->id, myStream->stats.txFrames, myStream->stats.txPayloadBytes);
#endif

    wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, sizeof(dutCmdResponse_t), 
                 (BYTE *)&sendResp, (BYTE *)aRespBuf);

    *aRespLen = WFA_TLV_HDR_LEN + sizeof(dutCmdResponse_t);

    return DONE;
}
void * wfa_wmm_thread(void *thr_param)
{
    int myId = ((tgThrData_t *)thr_param)->tid;
    tgWMM_t *my_wmm = &wmm_thr[myId];
    tgStream_t *myStream = NULL;
    int myStreamId, i=0,rttime=0,difftime=0, rcvCount=0,sendCount=0;
    int mySock = -1, status, respLen = 0, nbytes = 0, ret=0, j=0;
    tgProfile_t *myProfile;
    pthread_attr_t tattr;
#ifdef WFA_WMM_PS_EXT
    tgThrData_t *tdata =(tgThrData_t *) thr_param;
    StationProcStatetbl_t  curr_state;
#endif

//#ifdef WFA_VOICE_EXT
    struct timeval lstime, lrtime;
    int asn = 1;  /* everytime it starts from 1, and to ++ */
//#endif

    wPT_ATTR_INIT(&tattr);
    wPT_ATTR_SETSCH(&tattr, SCHED_RR);

    while(1)
    {
        int sleepTotal=0,sendFailCount=0;
        DPRINT_INFO(WFA_OUT, "wfa_wmm_thread::begin while loop for each send/rcv before mutex lock\n");
        pthread_mutex_lock(&my_wmm->thr_flag_mutex);
        /* it needs to reset the thr_flag to wait again */
        while(my_wmm->thr_flag == 0)
        {
            printf("Mutex wait\n");
            /*
             * in normal situation, the signal indicates the thr_flag changed to
             * a valid number (stream id), then it will go out the loop and do
             * work.
             */
            wPT_COND_WAIT(&my_wmm->thr_flag_cond, &my_wmm->thr_flag_mutex);
        }
        wPT_MUTEX_UNLOCK(&my_wmm->thr_flag_mutex);
        myStreamId = my_wmm->thr_flag;
        my_wmm->thr_flag=0;

        /* use the flag as a stream id to file the profile */
        myStream = findStreamProfile(myStreamId);
        myProfile = &myStream->profile;

        if(myProfile == NULL)
        {
            status = STATUS_INVALID;
            wfaEncodeTLV(WFA_TRAFFIC_AGENT_SEND_RESP_TLV, 4, (BYTE *)&status, respBuf);
            respLen = WFA_TLV_HDR_LEN+4;
            /*
             * send it back to control agent.
             */
            continue;
        }

        DPRINT_INFO(WFA_OUT, "wfa_wmm_thread::Mutex unlocked\n");
        switch(myProfile->direction)
        {
        case DIRECT_SEND:
            mySock = wfaCreateUDPSock(myProfile->sipaddr, myProfile->sport);
            if (mySock < 0)
            {
               DPRINT_INFO(WFA_OUT, "wfa_wmm_thread SEND ERROR failed create UDP socket! \n");
               break;
            }

            mySock = wfaConnectUDPPeer(mySock, myProfile->dipaddr, myProfile->dport);
            sendThrId = myId;
            /*
             * Set packet/socket priority TOS field
             */
            wfaTGSetPrio(mySock, myProfile->trafficClass);

            /*
             * set a proper priority
             */
            wfaSetThreadPrio(myId, myProfile->trafficClass);

            /* if delay is too long, it must be something wrong */
            if(myProfile->startdelay > 0 && myProfile->startdelay<100)
            {
                wSLEEP(myProfile->startdelay);
            }

            /*
             * set timer fire up
             */
            if(myProfile->maxcnt == 0)
            {
                wSIGNAL(SIGALRM, tmout_stop_send);
                wALARM(myProfile->duration );
                DPRINT_INFO(WFA_OUT, "wfa_wmm_thread SEND set stop alarm for %d sec \n", myProfile->duration);
            }

            if(myProfile->profile == PROF_MCAST)
            {
                wfaSetSockMcastSendOpt(mySock);
            }

            if (myProfile->profile == PROF_IPTV || myProfile->profile == PROF_FILE_TX || myProfile->profile == PROF_MCAST)
            {
                int iOptVal, iOptLen;

                getsockopt(mySock, SOL_SOCKET, SO_SNDBUF, (char *)&iOptVal, (socklen_t *)&iOptLen);
                iOptVal = iOptVal * 16;
                setsockopt(mySock, SOL_SOCKET, SO_SNDBUF, (char *)&iOptVal, (socklen_t )iOptLen);

              if ( (myProfile->rate != 0 ) /* WFA_SEND_FIX_BITRATE_MAX_FRAME_RATE)*/ && 
                   (myProfile->pksize * myProfile->rate * 8 < WFA_SEND_FIX_BITRATE_MAX) )
                 wfaSendBitrateData(mySock, myStreamId, respBuf, &respLen);
              else
              {
                 wfaSendLongFile(mySock, myStreamId, respBuf, &respLen);
              }

              /* wfaSendLongFile(mySock, myStreamId, respBuf, &respLen); */
                if(mySock != -1)
                {
                    wCLOSE(mySock);
                    mySock = -1;
                }
            }
            else if(myProfile->profile == PROF_TRANSC || myProfile->profile == PROF_START_SYNC || myProfile->profile == PROF_CALI_RTD)
            {
#if 0
                struct timeval nxtime, curtime;
                int ioflags = wFCNTL(mySock, F_GETFL, 0);
#endif
                struct timeval tmout;

                gtgTransac = myStreamId;
                sentTranPkts = 0;

#if 0
                gettimeofday(&nxtime, NULL);
                nxtime.tv_usec += 20000;   /* fixed 20 min sec timeout */
                if(nxtime.tv_usec >= 1000000)
                {
                    nxtime.tv_sec +=1;
                    nxtime.tv_usec -= 1000000;
                }
                wFCNTL(mySock, F_SETFL, ioflags | O_NONBLOCK);
#endif
                gettimeofday(&lstime,0);
                DPRINT_INFO(WFA_OUT, "Start sending traffic,at sec %d usec %d\n", (int )lstime.tv_sec, (int)lstime.tv_usec);


                tmout.tv_sec = 0;
                tmout.tv_usec = 15000;     // set for 15000 microsec timeout for rcv              
                ret = setsockopt(mySock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tmout, (socklen_t) sizeof(tmout)); 
                
                rcvCount=0; sendFailCount=0;
                j=0;  sendCount=0;
                sleepTotal = 0;
                while(gtgTransac != 0)
                {
					gettimeofday(&lstime, NULL);
#ifdef WFA_VOICE_EXT  					
                    /*
                     * If your device is BIG ENDIAN, you need to
                     * modify the the function calls
                     */
                    int2BuffBigEndian(asn++, &((tgHeader_t *)trafficBuf)->hdr[8]);
                    int2BuffBigEndian(lstime.tv_sec, &((tgHeader_t *)trafficBuf)->hdr[12]);
                    int2BuffBigEndian(lstime.tv_usec, &((tgHeader_t *)trafficBuf)->hdr[16]);
#else
                    j++;
                    i=0;
                    do
                    {

#endif /* WFA_VOICE_EXT */

                        if(gtgTransac != 0/* && nbytes <= 0 */)
                        {
                            if(respBuf == NULL)
                            {
                                DPRINT_INFO(WFA_OUT, "wfa_wmm_thread SEND,PROF_TRANSC::a Null respBuf\n");
                            }
                            memset(respBuf, 0, WFA_RESP_BUF_SZ);
                            respLen = 0;
                            memset(trafficBuf  ,0, MAX_UDP_LEN + 1);
                            if(wfaSendShortFile(mySock, myStreamId,
                                trafficBuf, 0, respBuf, &respLen) == DONE)
                            {
                                if(wfaCtrlSend(gxcSockfd, respBuf, respLen) != respLen)
                                {
                                    DPRINT_INFO(WFA_OUT, "wfa_wmm_thread SEND,PROF_TRANSC::wfaCtrlSend Error for wfaSendShortFile\n");
                                }
                                sendFailCount++;
                                i--;
                                usleep(1000);
                            }
                            else
                            {
                                i++;
                                sendCount++;
                            }

                            //sentTranPkts++; /* send routine already incresed this counter  */

                            if((myProfile->maxcnt>0) &&(sendCount == myProfile->maxcnt))
                            {
                                DPRINT_INFO(WFA_OUT, "wfa_wmm_thread SEND,PROF_TRANSC::meet maxcnt=%d; end loop\n",myProfile->maxcnt);
                                gtgTransac = 0; /* break snd/rcv wile loop  */
                                break;
                            }

                            nbytes = wfaRecvFile(mySock, myStreamId, (char  *)trafficBuf);
                            if(nbytes <= 0)
                            {/* Do not print any msg it will slow down process on snd/rcv  */
                            //setsockopt(mySock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tmout, (socklen_t) sizeof(tmout)); 
                            //printf("PROF_TRANSC::time out event, wfaRecvFile failed,resend a new packet ...\n");

                            //tmout.tv_sec = 0;
                            //tmout.tv_usec = 3000;    // set for 20 minlsec timeout              
                            //setsockopt(mySock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tmout, (socklen_t) sizeof(tmout)); 
#if 0  /* if your socket APIs does not support "recvfrom" timeout, this is the way to loop the descriptor */
                        gettimeofday(&curtime, NULL);
                        if(((curtime.tv_sec - nxtime.tv_sec) * 1000000 + (curtime.tv_usec -  nxtime.tv_usec)) < 20000)
                        {
                            continue;
                        }

                        nxtime.tv_usec = curtime.tv_usec += 20000;
                        if(nxtime.tv_usec >= 1000000)
                        {
                            nxtime.tv_sec = curtime.tv_sec +=1;
                            nxtime.tv_usec -= 1000000;
                        }
#endif
                              //continue;
                            }
                            else
                            {
                               rcvCount++;
                               nbytes = 0;
                            }
                        } /*  if gtgTransac != 0 */
#ifdef WFA_VOICE_EXT 
                        /*
                        * Roundtrip time delay:
                        *   1. retrieve the timestamp
                        *   2. calculate the Trt(1) roundtrip delay
                        *   3. store the minimum Trt(1)
                        *   4. store Cdut(t1) and Ctm(2)
                        */
                        gettimeofday(&lrtime, NULL);

                    /* get a round trip time */
                    rttime = wfa_ftime_diff(&lstime, &lrtime);

                    if(min_rttime > rttime)
                    {

                        min_rttime = rttime;
                        if(gtgCaliRTD != 0)
                        {
                            gtgPktRTDelay = min_rttime;
                        }
                    }

                        if(gtgCaliRTD != 0 )
                        {
                            usleep(20000); /* wait a few min seconds before retrying the next calibration */
                        }
#else
                        /*  not voice case  */ 
                        /*  for do-while loop for frame rate per sec */ 
 
                    }while ((i <= myProfile->rate + myProfile->rate/3) && (myProfile->rate !=0) && (gtgTransac != 0 )); 

					if(myProfile->maxcnt == 0)
                    {
	                    gettimeofday(&lrtime, NULL);
	                    rttime = wfa_itime_diff(&lstime, &lrtime);
	                    /*  we cover frame rate = 0 case without any sleep to continue push data */
	                    if (((difftime = 1000000 - rttime) > 0) && (myProfile->rate != 0))
	                    {
	                        if ( j < myProfile->duration)
	                        {
	                           usleep (difftime);
	                           sleepTotal = sleepTotal + difftime/1000;
	                        }
	                    }
	                    if (j > myProfile->duration + 2)
	                    {	/* avoid infinite loop  */
	                        DPRINT_INFO(WFA_OUT, "wfa_wmm_thread SEND over time %d sec, stop sending\n",myProfile->duration);
	                        break;
	                    }
					}
#endif /* WFA_VOICE_EXT */
                } /* while */

                if(mySock != -1)
                {
                    wCLOSE(mySock);
                    mySock = -1;
                }
                DPRINT_INFO(WFA_OUT, "wfa_wmm_thread SEND::Sending stats back, sendCount=%d rcvCount=%d sleepTotal in mil-sec=%d sendFailCount=%d frmRate=%d do count=%d\n", sendCount,rcvCount,sleepTotal,sendFailCount, myProfile->rate, j);

            }/* else if(myProfile->profile == PROF_TRANSC || myProfile->profile == PROF_START_SYNC || myProfile->profile == PROF_CALI_RTD) */

            wMEMSET(respBuf, 0, WFA_RESP_BUF_SZ);
            wSLEEP(1);

            /*
             * uses thread that is saved at last to pack the items and ships
             * it to CA.
             */

            if(myId == sendThrId)
            {
                wfaSentStatsResp(gxcSockfd, respBuf);
                printf("done stats\n");
                sendThrId = 0;
            }

            break;

        case DIRECT_RECV:
            /*
             * Test WMM-PS
             */
            if(myProfile->profile == PROF_UAPSD)
            {
#ifdef WFA_WMM_PS_EXT /* legacy code not used now  */
                wmmps_info.sta_test = B_D;
                wmmps_info.ps_thread = myId;
                wmmps_info.rcv_state = 0;
                wmmps_info.tdata = tdata;
                wmmps_info.dscp = wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
                tdata->state_num=0;
                /*
                 * default timer value
                 */

                while(gtgWmmPS>0)
                {
                    if(resetsnd)
                    {
                        tdata->state_num = 0;
                        resetsnd = 0;
                    }
                    if (wmmps_info.sta_test > LAST_TEST)
                        break;

                    tdata->state =  stationProcStatetbl[wmmps_info.sta_test];
                    curr_state = tdata->state[tdata->state_num];
                    curr_state.statefunc(curr_state.pw_offon,curr_state.sleep_period,&(tdata->state_num));
                }
#endif /* WFA_WMM_PS_EXT */
            }
            else if (myProfile->profile == PROF_IPTV || myProfile->profile == PROF_FILE_TX || myProfile->profile == PROF_MCAST)
            {
                char recvBuf[MAX_RCV_BUF_LEN+1];
                int iOptVal, iOptLen;
                struct timeval tmout;

#ifdef WFA_VOICE_EXT
                struct timeval currtime;
                FILE *e2eoutp = NULL;
                char e2eResults[124];
                int le2eCnt = 0;
#endif

                mySock = wfaCreateUDPSock(myProfile->dipaddr, myProfile->dport);
                if(mySock == -1)
                {
                    printf("Error open socket\n");
                    continue;
                }

                if (myProfile->profile == PROF_MCAST)
                {
                    int so = wfaSetSockMcastRecvOpt(mySock, myProfile->dipaddr);
                    if(so < 0)
                    {
                        DPRINT_ERR(WFA_ERR, "Join the multicast group failed\n");
                        wCLOSE(mySock);
                        continue;
                    }
                }

                tgSockfds[myStream->tblidx] = mySock;

#ifdef WFA_VOICE_EXT
                /* only for receive stream needs to create a stats storage */
                tgE2EStats_t *e2esp = NULL;
                int totalE2Cnt = 220 * WFA_G_CODEC_RATE;
                printf("init E2Cnt %i\n", totalE2Cnt);
                if(myProfile->profile == PROF_IPTV)
                {
                    e2esp = malloc(totalE2Cnt * sizeof(tgE2EStats_t));

                    if(e2esp == NULL)
                    {

                    }
                }
#endif

                /* increase the rec queue size */
                getsockopt(mySock, SOL_SOCKET, SO_RCVBUF, (char *)&iOptVal, (socklen_t *)&iOptLen);
                iOptVal = iOptVal * 10;
                setsockopt(mySock, SOL_SOCKET, SO_RCVBUF, (char *)&iOptVal, (socklen_t )iOptLen);

                /* set timeout for blocking receive */
                tmout.tv_sec = 0;
                tmout.tv_usec = 200000;   /* set the receive time out to 200 ms */
                setsockopt(mySock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tmout, (socklen_t) sizeof(tmout));

                wfaSetThreadPrio(myId, TG_WMM_AC_VO);   /* try to raise the receiver higher priority than sender */
                for(;;)
                {
                    nbytes = wfaRecvFile(mySock, myStreamId, (char *)recvBuf);
                    if(nbytes <= 0)
                    {
                        /* due to timeout */
                        if(tgSockfds[myStream->tblidx] >=0 )
                            continue;

                        break;
                    }

#ifdef WFA_VOICE_EXT
                    if(myProfile->profile == PROF_IPTV)
                    {
                        struct timeval ttval, currTimeVal;

                        int sn = bigEndianBuff2Int(&((tgHeader_t *)recvBuf)->hdr[8]);
                        ttval.tv_sec = bigEndianBuff2Int(&((tgHeader_t *)recvBuf)->hdr[12]);
                        ttval.tv_usec = bigEndianBuff2Int(&((tgHeader_t *)recvBuf)->hdr[16]);
                        gettimeofday(&currTimeVal, NULL);

                        /*
                         * take the end2end stats, limit to the max voice pkt number
                         */
                        if(le2eCnt < totalE2Cnt)
                        {
                            tgE2EStats_t *ep = e2esp + le2eCnt++;
                            ep->seqnum = sn;
                            ep->rsec = ttval.tv_sec;
                            ep->rusec = ttval.tv_usec;

                            ep->lsec = currTimeVal.tv_sec;
                            ep->lusec = currTimeVal.tv_usec;

                            if(ep->lusec  < 0)
                            {
                                ep->lsec -=1;
                                ep->lusec += 1000000;
                            }
                            else if(ep->lusec >= 1000000)
                            {
                                ep->lsec += 1;
                                ep->lusec -= 1000000;
                            }
                        }
                    }
#endif /* WFA_VOICE_EXT */
                    wfaSetThreadPrio(myId, TG_WMM_AC_BE); /* put it back down */
                } /* while */

                my_wmm->thr_flag = 0;

#ifdef WFA_VOICE_EXT
                if(myProfile->profile == PROF_IPTV)
                {
                    int j;

                    wGETTIMEOFDAY(&currtime, NULL);
                    sprintf(e2eResults, "/tmp/e2e%u-%i.txt", (unsigned int) currtime.tv_sec, myStreamId);
                    printf("file %s cnt %i\n", e2eResults, le2eCnt);
                    e2eoutp = fopen(e2eResults, "w+");
                    if(e2eoutp != NULL)
                    {
                        fprintf(e2eoutp, "roundtrip delay: %i\n", (int) (1000000*gtgPktRTDelay));
                        for(j = 0; j< le2eCnt; j++)
                        {
                            tgE2EStats_t *ep = e2esp+j;
                            fprintf(e2eoutp, "%i:%i:%i:%i:%i\n", ep->seqnum, ep->lsec, ep->lusec, ep->rsec, ep->rusec);
                        }
                        fclose(e2eoutp);
                    }

                    if(e2esp != NULL)
                        free(e2esp);
                }
#endif
            }
            else if(myProfile->profile == PROF_TRANSC || myProfile->profile == PROF_START_SYNC || myProfile->profile == PROF_CALI_RTD)
            {
                struct timeval tmout;

                mySock = wfaCreateUDPSock(myProfile->sipaddr, myProfile->sport);
                if(mySock < 0)
                {
                    /* return error */
                    my_wmm->thr_flag = 0;
                    continue;
                }

                tgSockfds[myStream->tblidx] = mySock;

                totalTranPkts = 0xFFFFFFF0;
                gtgTransac = myStreamId;

               /* set timeout for blocking receive */
               tmout.tv_sec = 0;
               tmout.tv_usec = 400000;   /* set the receive time out to 400 ms, 200ms is too short */
               setsockopt(mySock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tmout, (socklen_t) sizeof(tmout));

               while(gtgTransac != 0)
               {
                    memset(trafficBuf, 0, sizeof((char*)trafficBuf));

                    if(mySock != -1)
                    {
                        int i = gtgTransac;

                      nbytes = 0;

                      /* check for data as long as we are in a transaction */
                      while ((gtgTransac != 0) && (nbytes <= 0))
                      {
                          nbytes = wfaRecvFile(mySock, i, (char  *)trafficBuf);
                      }
                      /* It is the end of a transaction, go out of the loop */
                      if (gtgTransac == 0) break;
                   }
                    else
                    {
                        break;
                    }

#ifdef WFA_VOICE_EXT
                    /* for a transaction receiver, it just needs to send the local time back */
                    gettimeofday(&lstime, NULL);
                    int2BuffBigEndian(lstime.tv_sec, &((tgHeader_t *)trafficBuf)->hdr[12]);
                    int2BuffBigEndian(lstime.tv_usec, &((tgHeader_t *)trafficBuf)->hdr[16]);
#endif
                    memset(respBuf, 0, WFA_RESP_BUF_SZ);
                    respLen = 0;
                    if(wfaSendShortFile(mySock, gtgTransac, trafficBuf, nbytes, respBuf, &respLen) == DONE)
                    {
                        if(wfaCtrlSend(gxcSockfd, (BYTE *)respBuf, respLen)!=respLen)
                        {
                            DPRINT_WARNING(WFA_WNG, "wfaCtrlSend Error\n");
                        }
                    }
                }

                my_wmm->thr_flag = 0;
               //////////////////// Wifi Alliance Added
               if(mySock != -1)
               {
                   wCLOSE(mySock);
                   mySock = -1;
               }
               //////////////////// Wifi Alliance Added
           }
            break;

        default:
            DPRINT_ERR(WFA_ERR, "Unknown covered case\n");
        }

    }
}
/*
 * wfaStaSetPEAP()
 *   This is to set
 *   1. ssid
 *   2. user name
 *   3. passwd
 *   4. encryType - tkip or aes-ccmp
 *   5. keyMgmtType - wpa or wpa2
 *   6. trustedRootCA
 *   7. innerEAP
 *   8. peapVersion
 */
int wfaStaSetPEAP(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
   int ret = 0;
   char cmdStr[WFA_CMD_STR_SZ];
   caStaSetEapPEAP_t *setPEAP = (caStaSetEapPEAP_t *)caCmdBuf;
   char *ifname = setPEAP->intf;

   sprintf(cmdStr, "wpa_cli -i %s disable_network 0", ifname);
   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ssid '\"%s\"'", ifname, setPEAP->ssid);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 eap PEAP", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 anonymous_identity '\"anonymous\"' ", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 identity '\"%s\"'", ifname, setPEAP->username);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 password '\"%s\"'", ifname, setPEAP->passwd);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 ca_cert '\"%s/%s\"'", ifname, CERTIFICATES_PATH, setPEAP->trustedRootCA);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   /* if this not set, default to set support all */
   //sprintf(cmdStr, "wpa_cli -i %s set_network 0 pairwise '\"%s\"'", ifname, setPEAP->encrptype);
   //system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 key_mgmt WPA-EAP", ifname);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 phase1 '\"peaplabel=%i\"'", ifname, setPEAP->peapVersion);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s set_network 0 phase2 '\"auth=%s\"'", ifname, setPEAP->innerEAP);
   system(cmdStr);
   DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

//   sprintf(cmdStr, "wpa_cli -i %s set_network 0 proto WPA", ifname);
//   system(cmdStr);

   sprintf(cmdStr, "wpa_cli -i %s enable_network 0", ifname);
   system(cmdStr);

   ret = STATUS_COMPLETE;
   wfaEncodeTLV(WFA_STA_SET_PEAP_RESP_TLV, 4, (BYTE *)&ret, respBuf);
   *respLen = WFA_TLV_HDR_LEN + 4;

   return TRUE;
}
/*
 * wfaStaGetIpConfig():
 * This function is to retriev the ip info including
 *     1. dhcp enable
 *     2. ip address
 *     3. mask 
 *     4. primary-dns
 *     5. secondary-dns
 *
 *     The current implementation is to use a script to find these information
 *     and store them in a file. 
 */
int wfaStaGetIpConfig(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
    int i;
    dutCommand_t *getIpConf = (dutCommand_t *)caCmdBuf;
    dutCmdResponse_t ipconfigResp; 
    char *ifname = getIpConf->intf;
    caStaGetIpConfigResp_t *ifinfo = &ipconfigResp.cmdru.getIfconfig;

    FILE *tmpfd;
    char string[256];

    /* Dhcp */
    if ((tmpfd = popen("ps ax | grep -v grep | grep dhcli | wc -l", "r")) == NULL){
	printf("wc -l failed\n");
    }
    fgets(string, sizeof(string), tmpfd);
    pclose(tmpfd);
    if (atoi(string) >= 1)
       ifinfo->isDhcp = 1;
    else
       ifinfo->isDhcp = 0;

    /* ipaddr */
    sprintf(string, "ifconfig %s | grep 'inet addr' |  cut -d: -f2 | cut -d' ' -f1", ifname);
    if ((tmpfd = popen(string, "r")) == NULL){
	printf("ifconfig addr failed\n");
    }
    ifinfo->ipaddr[0] = 0;
    fgets(ifinfo->ipaddr, WFA_IP_ADDR_STR_LEN, tmpfd);
    ifinfo->ipaddr[strlen(ifinfo->ipaddr) - 1] = 0; /* Purge newline */
    pclose(tmpfd);
    if(ifinfo->ipaddr[0] == 0) 
       strncpy(ifinfo->ipaddr, "none", 15);

    /* mask */
    sprintf(string, "ifconfig %s | grep 'inet addr' |  cut -d: -f4", ifname);
    if ((tmpfd = popen(string, "r")) == NULL){
	printf("ifconfig mask failed\n");
    }
    ifinfo->mask[0] = 0;
    fgets(ifinfo->mask, WFA_IP_MASK_STR_LEN, tmpfd);
    ifinfo->mask[strlen(ifinfo->mask) - 1] = 0; /* Purge newline */
    pclose(tmpfd);

    if(ifinfo->mask[0] == 0) 
       strcpy(ifinfo->mask, "none");

    /* dns */
    if ((tmpfd = popen("cat /etc/resolv.conf | grep nameserver | awk '{print $2}'", "r")) == NULL){
	printf("resolve.conf failed\n");
    }
    for (i = 0; i < WFA_MAX_DNS_NUM; i++){
	    fgets(ifinfo->dns[i], WFA_MAC_ADDR_STR_LEN, tmpfd);
	    if (ifinfo->dns[i][0])
	        ifinfo->dns[i][strlen(ifinfo->dns[i]) - 1] = 0; /* Purge newline */
	    else
    		strcpy(ifinfo->dns[i], "NOTDEF");
    }
    pclose(tmpfd);

     /*
      * Report back the results
      */
     ipconfigResp.status = STATUS_COMPLETE;
     wfaEncodeTLV(WFA_STA_GET_IP_CONFIG_RESP_TLV, sizeof(dutCmdResponse_t), (BYTE *)&ipconfigResp, respBuf);   

     *respLen = WFA_TLV_HDR_LEN + sizeof(caStaGetIpConfigResp_t);

     DPRINT_INFO(WFA_OUT, "%i %i %s %s %s %s %i\n", ipconfigResp.status, 
        ifinfo->isDhcp, ifinfo->ipaddr, ifinfo->mask, 
            ifinfo->dns[0], ifinfo->dns[1], *respLen);

     return TRUE;
}
/*
 * wfaStaAssociate():
 *    The function is to force the station wireless I/F to re/associate 
 *    with the AP.
 */
int wfaStaAssociate(int len, BYTE *caCmdBuf, int *respLen, BYTE *respBuf)
{
	int ret = 0;
	int retVal = TRUE;
	dutCommand_t *assoc = (dutCommand_t *)caCmdBuf;
	char cmdStr[WFA_CMD_STR_SZ];
	int imode; /* 0 for ibss, 1 for infrastructure */
	char ssidTarget[WFA_SSID_NAME_LEN];
	bcmSsidObj_t *bso;
	int idx;

	bcopy(assoc->cmdsu.ssid, ssidTarget, WFA_SSID_NAME_LEN);

	bso = bcmWfaSsidTblSsidFind(ssidTarget);
	if (!bso) {
		if (!(bso = bcmWfaSsidObjTblAdd(ssidTarget))) {
			DPRINT_ERR(WFA_OUT, "bcmWfaSsidObjTblAdd(%s) failed\n", ssidTarget);
			retVal = FALSE;
			goto exit;
		}
		if (wfa_defined_debug & (WFA_DEBUG_ERR | WFA_DEBUG_INFO)) {
			bcmWfaSsidObjPrint(bso);
		}

	}
	imode = (bso->bssType == BCM_BSS_INDEPENDENT) ? 0 : 1;

	sprintf(cmdStr, "/tmp/ASD/wl disassoc");
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

	sprintf(cmdStr, "/tmp/ASD/wl down");
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

	/* handle WEP keys */
	for(idx = 0; idx < 4; idx++) {
		if(bso->keys[idx][0] != '\0') {
			sprintf(cmdStr, "/tmp/ASD/wl addwep %d %s", idx, bso->keys[idx]);
		} else {
			sprintf(cmdStr, "/tmp/ASD/wl rmwep %d", idx);
		}
		system(cmdStr);
		DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);
	}

	/* set primary key */
	if(bso->primary_key != BCM_PRI_KEY_BAD) {
		sprintf(cmdStr, "/tmp/ASD/wl primary_key %d", bso->primary_key);
		system(cmdStr);
		DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);
	}

	if ((!imode) && bso->channel){
		sprintf(cmdStr, "/tmp/ASD/wl channel %d", bso->channel);
		system(cmdStr);
		DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);
	}

	sprintf(cmdStr, "/tmp/ASD/wl infra %d", imode);
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

	/* security */
	sprintf(cmdStr, "/tmp/ASD/wl wsec %d", bso->wsec);
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

	if(bso->passphrase[0] != '\0') {
		sprintf(cmdStr, "/tmp/ASD/wl set_pmk %s", bso->passphrase); 
		system(cmdStr);
		DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);
	}

	sprintf(cmdStr, "/tmp/ASD/wl auth %d", bso->auth);
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

	sprintf(cmdStr, "/tmp/ASD/wl wpa_auth %d", bso->wpa_auth);
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

	/* Power Save */
	sprintf(cmdStr, "/tmp/ASD/wl wme_apsd_sta %d %d %d %d %d",
		bso->maxSPLength, bso->acBE, bso->acBK, bso->acVI, bso->acVO);
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

	sprintf(cmdStr, "/tmp/ASD/wl up");
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

	sprintf(cmdStr, "/tmp/ASD/wl ssid '%s'", ssidTarget);
	system(cmdStr);
	DPRINT_INFO(WFA_OUT, "%s\n", cmdStr);

exit:
	ret = STATUS_COMPLETE;
	wfaEncodeTLV(WFA_STA_ASSOCIATE_RESP_TLV, 4, (BYTE *)&ret, respBuf);   
	*respLen = WFA_TLV_HDR_LEN + 4;
	return retVal; 
}