blob: b810e0745d9155686ecf7bb200518f4818b7ee84 [file] [log] [blame]
/*
* Windows port of asd command line utility
*
* Copyright 2002, Broadcom Corporation
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Broadcom Corporation.
*
*/
#include <netdb.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include "wfa_sock.h"
#include "wfa_types.h"
#include "wfa_tg.h"
#include "wfa_ca.h"
#include "wfa_wmmps.h"
#include "wfa_miscs.h"
#include "wfa_main.h"
#include "wfa_debug.h"
#include "wfa_tlv.h"
extern int psSockfd;
extern int msgsize;
extern int resetsnd;
extern int gtgWmmPS;
extern int num_stops;
extern int num_hello;
extern tgWMM_t wmm_thr[];
extern wfaWmmPS_t wmmps_info;
extern unsigned int psTxMsg[512];
tgThrData_t tdata[WFA_THREADS_NUM];
extern void tmout_stop_send(int num);
extern void wfaSetDUTPwrMgmt(int mode);
extern void wfaSetThreadPrio(int tid, int class);
extern void mpx(char *m, void *buf_v, int len);
extern int wfaTGSetPrio(int sockfd, int tgClass);
extern tgStream_t *findStreamProfile(int id);
extern StationProcStatetbl_t stationProcStatetbl[LAST_TEST+1][11];
extern int receiver(unsigned int *rmsg,int length,int tos,unsigned int type);
/* WfaRcvVOCyclic: This is meant for the L1 test case. The function
** receives the VO packets from the console */
int WfaRcvVOCyclic(unsigned int *rmsg,int length,int *state)
{
int r;
tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
if(rmsg[10] != APTS_STOP)
{
if ((r=receiver(rmsg,length,TOS_VO,APTS_DEFAULT))>=0);
else
PRINTF("\nBAD REC in VO%d\n",r);
}
else
{
pthread_mutex_lock(&my_wmm->thr_stop_mutex);
while(!my_wmm->stop_flag)
{
pthread_cond_wait(&my_wmm->thr_stop_cond, &my_wmm->thr_stop_mutex);
}
pthread_mutex_unlock(&my_wmm->thr_stop_mutex);
my_wmm->stop_flag = 0;
gtgWmmPS = 0;
asd_closeSocket(psSockfd);
psSockfd = -1;
signal(SIGALRM, SIG_IGN);
wfaSetDUTPwrMgmt(PS_OFF);
uapsd_sleep(1);
}
return 0;
}
/* WfaRcvStop: This function receives the stop message from the
** console, it waits for the sending thread to have sent the stop before
** quitting*/
int WfaRcvStop(unsigned int *rmsg,int length,int *state)
{
tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
my_wmm->stop_flag = 0;
PRINTF("\r\nEnterring Wfarcvstop\n");
if(rmsg[10] != APTS_STOP)
{
//PRINTF("\nBAD REC in rcvstop%d\n",r);
//WfaStaResetAll();
}
else
{
pthread_mutex_lock(&my_wmm->thr_stop_mutex);
while(!my_wmm->stop_flag)
{
printf("\r\n stuck\n");
pthread_cond_wait(&my_wmm->thr_stop_cond, &my_wmm->thr_stop_mutex);
}
num_stops=0;
pthread_mutex_unlock(&my_wmm->thr_stop_mutex);
my_wmm->stop_flag = 0;
gtgWmmPS = 0;
asd_closeSocket(psSockfd);
psSockfd = -1;
signal(SIGALRM, SIG_IGN);
wfaSetDUTPwrMgmt(PS_OFF);
uapsd_sleep(1);
}
return 0;
}
/*
* wfaStaSndHello(): This function sends a Hello packet
* and sleeps for sleep_period, the idea is
* to keep sending hello packets till the console
* responds, the function keeps a check on the MAX
* Hellos and if number of Hellos exceed that it quits
*/
int WfaStaSndHello(char psave,int sleep_period,int *state)
{
int r;
tgWMM_t *my_wmm = &wmm_thr[wmmps_info.ps_thread];
if(!(num_hello++))
create_apts_msg(APTS_HELLO, psTxMsg,0);
r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
uapsd_sleep(sleep_period);
pthread_mutex_lock(&my_wmm->thr_flag_mutex);
if(my_wmm->thr_flag)
{
(*state)++;
num_hello=0;
my_wmm->thr_flag=0;
}
pthread_mutex_unlock(&my_wmm->thr_flag_mutex);
if(num_hello > MAXHELLO)
{
DPRINT_ERR(WFA_ERR, "Too many Hellos sent\n");
gtgWmmPS = 0;
num_hello=0;
asd_closeSocket(psSockfd);
psSockfd = -1;
signal(SIGALRM, SIG_IGN);
}
return 0;
}
/*
* WfaStaWaitStop(): This function sends the stop packet on behalf of the
* station, the idea is to keep sending the Stop
* till a stop is recd from the console,the functions
* quits after stop threshold reaches.
*/
int WfaStaWaitStop(char psave,int sleep_period,int *state)
{
int r;
int myid=wmmps_info.ps_thread;
PRINTF("\n Entering Sendwait");
uapsd_sleep(sleep_period);
if(!num_stops)
{
wfaSetDUTPwrMgmt(psave);
wfaTGSetPrio(psSockfd, TG_WMM_AC_BE);
}
num_stops++;
create_apts_msg(APTS_STOP, psTxMsg,wmmps_info.my_sta_id);
r = wfaTrafficSendTo(psSockfd, (char *)psTxMsg, msgsize, (struct sockaddr *)&wmmps_info.psToAddr);
mpx("STA msg",psTxMsg,64);
wmm_thr[myid].stop_flag = 1;
pthread_mutex_lock(&wmm_thr[myid].thr_stop_mutex);
pthread_cond_signal(&wmm_thr[myid].thr_stop_cond);
pthread_mutex_unlock(&wmm_thr[myid].thr_stop_mutex);
if(num_stops > MAX_STOPS)
{
DPRINT_ERR(WFA_ERR, "Too many stops sent\n");
gtgWmmPS = 0;
asd_closeSocket(psSockfd);
psSockfd = -1;
signal(SIGALRM, SIG_IGN);
}
wfaSetDUTPwrMgmt(PS_OFF);
return 0;
}
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;
tgThrData_t *tdata =(tgThrData_t *) thr_param;
int myStreamId;
int mySock = -1;
int status, respLen;
tgProfile_t *myProfile;
StationProcStatetbl_t curr_state;
BYTE respBuf[WFA_BUFF_1K];
pthread_attr_t tattr;
pthread_attr_init(&tattr);
pthread_attr_setschedpolicy(&tattr, SCHED_RR);
while(1)
{
pthread_mutex_lock(&my_wmm->thr_flag_mutex);
/* it needs to reset the thr_flag to wait again */
while(!my_wmm->thr_flag)
{
/*
* 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.
*/
pthread_cond_wait(&my_wmm->thr_flag_cond, &my_wmm->thr_flag_mutex);
}
sleep(2);
pthread_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;
}
switch(myProfile->direction)
{
case DIRECT_SEND:
mySock = wfaCreateUDPSock(myProfile->sipaddr, myProfile->sport);
mySock = wfaConnectUDPPeer(mySock, myProfile->dipaddr, myProfile->dport);
/*
* Set packet/socket priority TOS field
*/
wfaTGSetPrio(mySock, myProfile->trafficClass);
/*
* set a proper priority
*/
wfaSetThreadPrio(myId, myProfile->trafficClass);
#ifdef DEBUG
printf("wfa_wmm_thread: myProfile->startdelay %i\n", myProfile->startdelay);
#endif /* DEBUG */
/* if delay is too long, it must be something wrong */
if(myProfile->startdelay > 0 && myProfile->startdelay < 50)
{
asd_sleep(myProfile->startdelay);
}
/*
* set timer fire up
*/
signal(SIGALRM, tmout_stop_send);
alarm(myProfile->duration);
/* Whenever frameRate is 0,sending data at the maximum possible rate */
if (myProfile->rate != 0)
wfaSendLongFile(mySock, myStreamId, respBuf, &respLen );
else
wfaImprovePerfSendLongFile(mySock, myStreamId, respBuf, &respLen );
memset(respBuf, 0, WFA_BUFF_1K);
if (mySock != -1) {
asd_closeSocket(mySock);
mySock = -1;
}
/*
* uses thread 0 to pack the items and ships it to CA.
*/
if(myId == 0) {
// wfaSentStatsResp(gxcSockfd, respBuf);
printf("respBuf = %s sent from thr\n", respBuf);
}
break;
case DIRECT_RECV:
#ifdef WFA_WMM_PS_EXT
if(myProfile->profile == PROF_UAPSD)
{
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;
}
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));
}
}
break;
#endif /* WFA_WMM_PS_EXT */
default:
DPRINT_ERR(WFA_ERR, "Unknown covered case\n");
}
}
}
void init_thr_flag()
{
int cntThr = 0;
pthread_attr_t ptAttr;
int ptPolicy;
struct sched_param ptSchedParam;
pthread_attr_init(&ptAttr);
ptSchedParam.sched_priority = 10;
pthread_attr_setschedparam(&ptAttr, &ptSchedParam);
pthread_attr_getschedpolicy(&ptAttr, &ptPolicy);
pthread_attr_setschedpolicy(&ptAttr, SCHED_RR);
pthread_attr_getschedpolicy(&ptAttr, &ptPolicy);
/*
* Create multiple threads for WMM Stream processing.
*/
for(cntThr = 0; cntThr< WFA_THREADS_NUM; cntThr++)
{
tdata[cntThr].tid = cntThr;
pthread_mutex_init(&wmm_thr[cntThr].thr_flag_mutex, NULL);
pthread_cond_init(&wmm_thr[cntThr].thr_flag_cond, NULL);
wmm_thr[cntThr].thr_id = pthread_create(&wmm_thr[cntThr].thr,
&ptAttr, wfa_wmm_thread, &tdata[cntThr]);
sleep(1);
wmm_thr[cntThr].thr_flag = 0;
}
}
/*
* wfaSetThreadPrio():
* Set thread priorities
* It is an optional experiment if you decide not necessary.
*/
void wfaSetThreadPrio(int tid, int class)
{
struct sched_param tschedParam;
pthread_attr_t tattr;
pthread_attr_init(&tattr);
pthread_attr_setschedpolicy(&tattr, SCHED_RR);
switch(class)
{
case TG_WMM_AC_BK:
tschedParam.sched_priority = 70-3;
break;
case TG_WMM_AC_VI:
tschedParam.sched_priority = 70-1;
break;
case TG_WMM_AC_VO:
tschedParam.sched_priority = 70;
break;
case TG_WMM_AC_BE:
tschedParam.sched_priority = 70-2;
default:
/* default */
;
}
pthread_attr_setschedparam(&tattr, &tschedParam);
}
int WmmpsTrafficRecv(int sock, char *buf, struct sockaddr *from)
{
int bytesRecvd;
socklen_t addrLen;
bytesRecvd = recvfrom(sock, buf, MAX_UDP_LEN, 0, from, &addrLen);
return bytesRecvd;
}