/*
* trafficAdmControl.c
*
* Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Texas Instruments nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/***************************************************************************/
/* */
/* MODULE: admCtrlQos.c */
/* PURPOSE: WSM/WME admission Control */
/* */
/***************************************************************************/
#define __FILE_ID__ FILE_ID_89
#include "osApi.h"
#include "paramOut.h"
#include "timer.h"
#include "fsm.h"
#include "report.h"
#include "DataCtrl_Api.h"
#include "trafficAdmControl.h"
#include "qosMngr_API.h"
#include "TWDriver.h"
#ifdef XCC_MODULE_INCLUDED
#include "XCCMngr.h"
#endif
/* Constants */
/** number of states in the state machine */
#define TRAFFIC_ADM_CTRL_SM_NUM_STATES 2
/** number of events in the state machine */
#define TRAFFIC_ADM_CTRL_SM_NUM_EVENTS 5
extern int WMEQosTagToACTable[MAX_NUM_OF_802_1d_TAGS];
typedef struct
{
TI_HANDLE hTrafficAdmCtrl;
tspecInfo_t *pTSpecInfo;
TI_UINT8 acID;
}fsmTSpecInfo_t;
/* Timer functions */
void trafficAdmCtrl_timeoutAcBE(TI_HANDLE hTrafficAdmCtrl, TI_BOOL bTwdInitOccured);
void trafficAdmCtrl_timeoutAcBK(TI_HANDLE hTrafficAdmCtrl, TI_BOOL bTwdInitOccured);
void trafficAdmCtrl_timeoutAcVI(TI_HANDLE hTrafficAdmCtrl, TI_BOOL bTwdInitOccured);
void trafficAdmCtrl_timeoutAcVO(TI_HANDLE hTrafficAdmCtrl, TI_BOOL bTwdInitOccured);
/* SM Functions */
TI_STATUS trafficAdmCtrl_smEvent(trafficAdmCtrl_t *pAdmCtrlQos, TI_UINT8 event, void *pData);
TI_STATUS trafficAdmCtrl_smActionUnexpectedTspecResponse(fsmTSpecInfo_t *fsmTSpecInfo); /*unxcepted*/
TI_STATUS trafficAdmCtrl_smActionUnexpected(fsmTSpecInfo_t *fsmTSpecInfo); /*unxcepted*/
TI_STATUS trafficAdmCtrl_smActionNop(fsmTSpecInfo_t *fsmTSpecInfo); /*NOP*/
TI_STATUS trafficAdmCtrl_smStart(fsmTSpecInfo_t *fsmTSpecInfo); /*EVENT_START*/
TI_STATUS trafficAdmCtrl_smWaitStop(fsmTSpecInfo_t *fsmTSpecInfo); /*EVENT_STOP*/
TI_STATUS trafficAdmCtrl_smWaitAccept(fsmTSpecInfo_t *fsmTSpecInfo); /*EVENT_ACCEPT*/
TI_STATUS trafficAdmCtrl_smWaitReject(fsmTSpecInfo_t *fsmTSpecInfo); /*EVENT_REJECT*/
TI_STATUS trafficAdmCtrl_smWaitTimeout(fsmTSpecInfo_t *fsmTSpecInfo); /*EVENT_TIMEOUT*/
TI_STATUS trafficAdmCtrl_sendAdmissionReq(TI_HANDLE hTrafficAdmCtrl, tspecInfo_t *pTSpecInfo);
TI_STATUS trafficAdmCtrl_startTimer(trafficAdmCtrl_t* pTrafficAdmCtrl, TI_UINT8 acID);
TI_STATUS trafficAdmCtrl_stopTimer(trafficAdmCtrl_t* pTrafficAdmCtrl, TI_UINT8 acID);
TI_STATUS trafficAdmCtrl_buildFrameHeader(trafficAdmCtrl_t *pTrafficAdmCtrl, TTxCtrlBlk *pPktCtrlBlk);
static TI_STATUS trafficAdmCtrl_tokenToAc (TI_HANDLE hTrafficAdmCtrl, TI_UINT8 token, TI_UINT8 *acID);
/********************************************************************************
* trafficAdmCtrl_create *
********************************************************************************
DESCRIPTION: trafficAdmCtrl module creation function
INPUT: hOs - Handle to OS
OUTPUT:
RETURN: Handle to the trafficAdmCtrl module on success, NULL otherwise
************************************************************************/
TI_HANDLE trafficAdmCtrl_create(TI_HANDLE hOs)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
TI_STATUS status;
/* allocate admission control context memory */
pTrafficAdmCtrl = (trafficAdmCtrl_t*)os_memoryAlloc(hOs, sizeof(trafficAdmCtrl_t));
if (pTrafficAdmCtrl == NULL)
{
return NULL;
}
os_memoryZero(hOs, pTrafficAdmCtrl, sizeof(trafficAdmCtrl_t));
pTrafficAdmCtrl->hOs = hOs;
/* allocate memory for admCtrlQos state machine */
status = fsm_Create(hOs, &pTrafficAdmCtrl->pTrafficAdmCtrlSm, TRAFFIC_ADM_CTRL_SM_NUM_STATES, TRAFFIC_ADM_CTRL_SM_NUM_EVENTS);
if (status != TI_OK)
{
os_memoryFree(hOs, pTrafficAdmCtrl, sizeof(trafficAdmCtrl_t));
return NULL;
}
return pTrafficAdmCtrl;
}
/************************************************************************
* trafficAdmCtrl_unload *
************************************************************************
DESCRIPTION: trafficAdmCtrl module destroy function,
- Free all memory alocated by the module
INPUT: hTrafficAdmCtrl - trafficAdmCtrl handle.
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_unload(TI_HANDLE hTrafficAdmCtrl)
{
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
TI_UINT32 uAcId;
if (pTrafficAdmCtrl->pTrafficAdmCtrlSm)
{
fsm_Unload (pTrafficAdmCtrl->hOs, pTrafficAdmCtrl->pTrafficAdmCtrlSm);
}
/* free timers */
for (uAcId = 0; uAcId < MAX_NUM_OF_AC; uAcId++)
{
if (pTrafficAdmCtrl->hAdmCtrlTimer[uAcId])
{
tmr_DestroyTimer (pTrafficAdmCtrl->hAdmCtrlTimer[uAcId]);
}
}
os_memoryFree(pTrafficAdmCtrl->hOs, pTrafficAdmCtrl, sizeof(trafficAdmCtrl_t));
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_config *
************************************************************************
DESCRIPTION: trafficAdmCtrl module configuration function,
performs the following:
- Reset & initiailzes local variables
- Init the handles to be used by the module
INPUT: hTrafficAdmCtrl - trafficAdmCtrl handle.
List of handles to be used by the module
pTrafficAdmCtrlInitParams - init parameters.
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_config (TI_HANDLE hTrafficAdmCtrl,
TI_HANDLE hTxMgmtQ,
TI_HANDLE hReport,
TI_HANDLE hOs,
TI_HANDLE hQosMngr,
TI_HANDLE hCtrlData,
TI_HANDLE hXCCMgr,
TI_HANDLE hTimer,
TI_HANDLE hTWD,
TI_HANDLE hTxCtrl,
trafficAdmCtrlInitParams_t *pTrafficAdmCtrlInitParams)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
TI_STATUS status;
TI_UINT32 uAcId;
fsm_actionCell_t trafficAdmCtrl_smMatrix[TRAFFIC_ADM_CTRL_SM_NUM_STATES][TRAFFIC_ADM_CTRL_SM_NUM_EVENTS] =
{
/* next state and actions for IDLE state */
{{TRAFFIC_ADM_CTRL_SM_STATE_WAIT, (fsm_Action_t)trafficAdmCtrl_smStart}, /*EVENT_START*/
{TRAFFIC_ADM_CTRL_SM_STATE_IDLE, (fsm_Action_t)trafficAdmCtrl_smActionNop}, /*EVENT_STOP*/
{TRAFFIC_ADM_CTRL_SM_STATE_IDLE, (fsm_Action_t)trafficAdmCtrl_smActionUnexpectedTspecResponse}, /*EVENT_ACCEPT*/
{TRAFFIC_ADM_CTRL_SM_STATE_IDLE, (fsm_Action_t)trafficAdmCtrl_smActionUnexpectedTspecResponse}, /*EVENT_REJECT*/
{TRAFFIC_ADM_CTRL_SM_STATE_IDLE, (fsm_Action_t)trafficAdmCtrl_smActionUnexpected}, /*EVENT_TIMEOUT*/
},
/* next state and actions for WAIT state */
{{TRAFFIC_ADM_CTRL_SM_STATE_WAIT, (fsm_Action_t)trafficAdmCtrl_smActionUnexpected}, /*EVENT_START*/
{TRAFFIC_ADM_CTRL_SM_STATE_IDLE, (fsm_Action_t)trafficAdmCtrl_smWaitStop}, /*EVENT_STOP*/
{TRAFFIC_ADM_CTRL_SM_STATE_IDLE, (fsm_Action_t)trafficAdmCtrl_smWaitAccept}, /*EVENT_ACCEPT*/
{TRAFFIC_ADM_CTRL_SM_STATE_IDLE, (fsm_Action_t)trafficAdmCtrl_smWaitReject}, /*EVENT_REJECT*/
{TRAFFIC_ADM_CTRL_SM_STATE_IDLE, (fsm_Action_t)trafficAdmCtrl_smWaitTimeout}, /*EVENT_TIMEOUT*/
},
};
pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
pTrafficAdmCtrl->hTxMgmtQ = hTxMgmtQ;
pTrafficAdmCtrl->hReport = hReport;
pTrafficAdmCtrl->hOs = hOs;
pTrafficAdmCtrl->hQosMngr = hQosMngr;
pTrafficAdmCtrl->hCtrlData = hCtrlData;
pTrafficAdmCtrl->hXCCMgr = hXCCMgr;
pTrafficAdmCtrl->hTimer = hTimer;
pTrafficAdmCtrl->hTWD = hTWD;
pTrafficAdmCtrl->hTxCtrl = hTxCtrl;
for (uAcId = 0; uAcId < MAX_NUM_OF_AC; uAcId++)
{
pTrafficAdmCtrl->dialogToken[uAcId] = 0;
/* Create per AC timers */
pTrafficAdmCtrl->hAdmCtrlTimer[uAcId] = tmr_CreateTimer (pTrafficAdmCtrl->hTimer);
if (pTrafficAdmCtrl->hAdmCtrlTimer[uAcId] == NULL)
{
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_ERROR, "trafficAdmCtrl_config(): Failed to create hAssocSmTimer!\n");
return TI_NOK;
}
}
/* configure state machine */
status = fsm_Config(pTrafficAdmCtrl->pTrafficAdmCtrlSm, &trafficAdmCtrl_smMatrix[0][0],
TRAFFIC_ADM_CTRL_SM_NUM_STATES, TRAFFIC_ADM_CTRL_SM_NUM_EVENTS, NULL, hOs);
if (status != TI_OK)
{
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_ERROR, "TRAFFIC_ADM_CTRL_SM: fsm_Config - Error \n");
return TI_NOK;
}
pTrafficAdmCtrl->timeout = pTrafficAdmCtrlInitParams->trafficAdmCtrlResponseTimeout;
pTrafficAdmCtrl->useFixedMsduSize = pTrafficAdmCtrlInitParams->trafficAdmCtrlUseFixedMsduSize;
pTrafficAdmCtrl->dialogTokenCounter = INITIAL_DIALOG_TOKEN;
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "TRAFFIC ADM CTRL - configuration completed ..... \n");
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_smEvent *
************************************************************************
DESCRIPTION: trafficAdmCtrl SM general function
INPUT: pTrafficAdmCtrl - trafficAdmCtr handle.
event - the event to the SM.
pData - handle to passing parameter
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smEvent(trafficAdmCtrl_t *pTrafficAdmCtrl, TI_UINT8 event, void *pData)
{
TI_STATUS status;
TI_UINT8 nextState;
fsmTSpecInfo_t *fsmTSpecInfo = (fsmTSpecInfo_t*)pData;
TI_UINT8 acID = fsmTSpecInfo->acID;
/* It looks like it never happens. Anyway decided to check */
if ( acID >= MAX_NUM_OF_AC )
{
TRACE2( pTrafficAdmCtrl->hReport, REPORT_SEVERITY_ERROR,
"trafficAdmCtrl_smEvent. fsmTSpecInfo->acID=%d exceeds the limit %d\n",
acID, MAX_NUM_OF_AC-1);
handleRunProblem(PROBLEM_BUF_SIZE_VIOLATION);
return TI_NOK;
}
status = fsm_GetNextState(pTrafficAdmCtrl->pTrafficAdmCtrlSm, pTrafficAdmCtrl->currentState[acID], event, &nextState);
if (status != TI_OK)
{
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_ERROR, "ADM_CTRL: ERROR - failed getting next state \n");
return(TI_NOK);
}
TRACE3(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "trafficAdmCtrl_smEvent: <currentState = %d, event = %d> --> nextState = %d\n", pTrafficAdmCtrl->currentState[acID], event, nextState);
status = fsm_Event(pTrafficAdmCtrl->pTrafficAdmCtrlSm, &pTrafficAdmCtrl->currentState[acID], event, pData);
return(status);
}
/************************************************************************
* state machine functions *
************************************************************************/
/************************************************************************
* trafficAdmCtrl_smStart *
************************************************************************
DESCRIPTION: the action function when event start ocuured on idle state
performs the following:
- send admision requestReset
- start timer for the response.
INPUT: fsmTSpecInfo - parameters for the request
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smStart(fsmTSpecInfo_t *fsmTSpecInfo)
{
TI_STATUS status;
trafficAdmCtrl_t *pTrafficAdmCtrl;
tspecInfo_t *pTSpecInfo;
pTrafficAdmCtrl = (trafficAdmCtrl_t*)(fsmTSpecInfo->hTrafficAdmCtrl);
pTSpecInfo = fsmTSpecInfo->pTSpecInfo;
/* send adm request frame */
status = trafficAdmCtrl_sendAdmissionReq(pTrafficAdmCtrl, pTSpecInfo);
if(status != TI_OK)
return status;
/* init timer */
trafficAdmCtrl_startTimer(pTrafficAdmCtrl, pTSpecInfo->AC);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_smWaitStop *
************************************************************************
DESCRIPTION: the action function when event stop ocuured on wait state
performs the following:
- stop timer.
INPUT: fsmTSpecInfo - parameters of the request
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smWaitStop(fsmTSpecInfo_t *fsmTSpecInfo)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
tspecInfo_t *pTSpecInfo;
pTrafficAdmCtrl = (trafficAdmCtrl_t*)(fsmTSpecInfo->hTrafficAdmCtrl);
pTSpecInfo = fsmTSpecInfo->pTSpecInfo;
/* stop timer */
trafficAdmCtrl_stopTimer(pTrafficAdmCtrl,fsmTSpecInfo->pTSpecInfo->AC);
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "TRAFFIC ADM CTRL - AC = %d, Stoped ..... \n", pTSpecInfo->AC);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_smWaitAccept *
************************************************************************
DESCRIPTION: the action function when event accept ocuured on wait state
performs the following:
- update the Qos Mngr of the status and the parameters
INPUT: fsmTSpecInfo - parameters of the response
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smWaitAccept(fsmTSpecInfo_t *fsmTSpecInfo)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
tspecInfo_t *pTSpecInfo;
pTrafficAdmCtrl = (trafficAdmCtrl_t*)(fsmTSpecInfo->hTrafficAdmCtrl);
pTSpecInfo = fsmTSpecInfo->pTSpecInfo;
/* update the QosMngr */
qosMngr_setAdmissionInfo(pTrafficAdmCtrl->hQosMngr, pTSpecInfo->AC, pTSpecInfo, STATUS_TRAFFIC_ADM_REQUEST_ACCEPT);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_smWaitReject *
************************************************************************
DESCRIPTION: the action function when event reject ocuured on wait state
performs the following:
- update the Qos Mngr of the status and the parameters
INPUT: fsmTSpecInfo - parameters of the response
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smWaitReject(fsmTSpecInfo_t *fsmTSpecInfo)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
tspecInfo_t *pTSpecInfo;
pTrafficAdmCtrl = (trafficAdmCtrl_t*)(fsmTSpecInfo->hTrafficAdmCtrl);
pTSpecInfo = fsmTSpecInfo->pTSpecInfo;
/* update the QosMngr */
qosMngr_setAdmissionInfo(pTrafficAdmCtrl->hQosMngr, pTSpecInfo->AC, pTSpecInfo, STATUS_TRAFFIC_ADM_REQUEST_REJECT);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_smWaitTimeout *
************************************************************************
DESCRIPTION: the action function when event timeout ocuured on wait state
performs the following:
- update the Qos Mngr of the status and the parameters
INPUT: fsmTSpecInfo - parameters of the request
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smWaitTimeout(fsmTSpecInfo_t *fsmTSpecInfo)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
pTrafficAdmCtrl = (trafficAdmCtrl_t*)(fsmTSpecInfo->hTrafficAdmCtrl);
/* update the QosMngr */
qosMngr_setAdmissionInfo(pTrafficAdmCtrl->hQosMngr, fsmTSpecInfo->acID, NULL, STATUS_TRAFFIC_ADM_REQUEST_TIMEOUT);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_smActionUnexpected *
************************************************************************
DESCRIPTION:
INPUT: fsmTSpecInfo - tspec parameters
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smActionUnexpected(fsmTSpecInfo_t *fsmTSpecInfo)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
pTrafficAdmCtrl = (trafficAdmCtrl_t*)(fsmTSpecInfo->hTrafficAdmCtrl);
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_ERROR, "TRAFFIC ADM CTRL - AC = %d, ActionUnexpected ..... \n", fsmTSpecInfo->acID);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_smActionUnexpectedTspecResponse *
************************************************************************
DESCRIPTION:
INPUT: fsmTSpecInfo - tspec parameters
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smActionUnexpectedTspecResponse(fsmTSpecInfo_t *fsmTSpecInfo)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
tspecInfo_t *pTSpecInfo;
pTrafficAdmCtrl = (trafficAdmCtrl_t*)(fsmTSpecInfo->hTrafficAdmCtrl);
pTSpecInfo = fsmTSpecInfo->pTSpecInfo;
/* Send event to user application - how come TSPEC response arrives without request ? */
qosMngr_sendUnexpectedTSPECResponseEvent (pTrafficAdmCtrl->hQosMngr,pTSpecInfo);
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_WARNING, "TRAFFIC ADM CTRL - AC = %d, ActionUnexpected ..... \n", fsmTSpecInfo->acID);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_smActionNop *
************************************************************************
DESCRIPTION:
INPUT: fsmTSpecInfo - tspec parameters
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_smActionNop(fsmTSpecInfo_t *fsmTSpecInfo)
{
trafficAdmCtrl_t *pTrafficAdmCtrl;
tspecInfo_t *pTSpecInfo;
pTrafficAdmCtrl = (trafficAdmCtrl_t*)(fsmTSpecInfo->hTrafficAdmCtrl);
pTSpecInfo = fsmTSpecInfo->pTSpecInfo;
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "TRAFFIC ADM CTRL - AC = %d, Action NOP..... \n", pTSpecInfo->AC);
return TI_OK;
}
/************************************************************************
* API FUNCTIONS *
************************************************************************
************************************************************************/
/************************************************************************
* trafficAdmCtrl_startAdmRequest *
************************************************************************
DESCRIPTION: start TSPEC signaling
INPUT: pTrafficAdmCtrl - trafficAdmCtr handle.
pTSpecInfo - the TSPEC parameters
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_startAdmRequest(TI_HANDLE hTrafficAdmCtrl, tspecInfo_t *pTSpecInfo)
{
TI_STATUS status;
fsmTSpecInfo_t fsmTSpecInfo;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
if (pTrafficAdmCtrl == NULL)
return TI_NOK;
fsmTSpecInfo.hTrafficAdmCtrl = hTrafficAdmCtrl;
fsmTSpecInfo.pTSpecInfo = pTSpecInfo;
fsmTSpecInfo.acID = pTSpecInfo->AC;
/* send event START to SM */
status = trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_START, &fsmTSpecInfo);
return status;
}
/************************************************************************
* trafficAdmCtrl_stopAdmRequest *
************************************************************************
DESCRIPTION: stop specific tspec signaling
INPUT: pTrafficAdmCtrl - trafficAdmCtr handle.
acID - the AC of the tspec to stop
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_stopAdmRequest(TI_HANDLE hTrafficAdmCtrl, TI_UINT8 acID)
{
TI_STATUS status;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
tspecInfo_t pTSpecInfo;
fsmTSpecInfo_t fsmTSpecInfo;
fsmTSpecInfo.hTrafficAdmCtrl = hTrafficAdmCtrl;
fsmTSpecInfo.pTSpecInfo = &pTSpecInfo;
fsmTSpecInfo.pTSpecInfo->AC = (EAcTrfcType)acID;
fsmTSpecInfo.acID = acID;
/* send event STOP to SM */
status = trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_STOP, &fsmTSpecInfo);
return status;
}
/************************************************************************
* trafficAdmCtrl_stop *
************************************************************************
DESCRIPTION: stop all tspecs and reset SM
called on disconnect
INPUT: pTrafficAdmCtrl - trafficAdmCtr handle.
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_stop(TI_HANDLE hTrafficAdmCtrl)
{
TI_UINT32 uAcId;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
tspecInfo_t pTSpecInfo;
fsmTSpecInfo_t fsmTSpecInfo;
fsmTSpecInfo.hTrafficAdmCtrl = hTrafficAdmCtrl;
fsmTSpecInfo.pTSpecInfo = &pTSpecInfo;
/* clean all AC SM */
for (uAcId = 0; uAcId < MAX_NUM_OF_AC; uAcId++)
{
fsmTSpecInfo.pTSpecInfo->AC = (EAcTrfcType)uAcId;
fsmTSpecInfo.acID = uAcId;
trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_STOP, &fsmTSpecInfo);
pTrafficAdmCtrl->dialogToken[uAcId] = 0;
}
pTrafficAdmCtrl->dialogTokenCounter = INITIAL_DIALOG_TOKEN;
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_recv *
************************************************************************
DESCRIPTION:
INPUT: pTrafficAdmCtrl - trafficAdmCtr handle.
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_recv(TI_HANDLE hTrafficAdmCtrl, TI_UINT8* pData, TI_UINT8 action)
{
TI_STATUS status = TI_OK;
TI_UINT8 statusCode;
TI_UINT8 dialogToken;
TI_UINT8 tacID;
tspecInfo_t tspecInfo;
fsmTSpecInfo_t fsmTSpecInfo;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
if (action == ADDTS_RESPONSE_ACTION)
{
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "action = 1 - ADDTS RESPONSE ACTION........!! \n");
/* parsing the dialog token */
dialogToken = *pData;
pData++;
/* in WME status code is 1 byte, in WSM is 2 bytes */
statusCode = *pData;
pData++;
tspecInfo.statusCode = statusCode;
TRACE2(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "dialogToken = %d , statusCode = %d \n",dialogToken, statusCode);
trafficAdmCtrl_parseTspecIE(&tspecInfo, pData);
if (trafficAdmCtrl_tokenToAc (pTrafficAdmCtrl, dialogToken, &tacID) == TI_NOK)
{
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_WARNING, "dialog token Not found, dialogToken = %d , \n",dialogToken);
qosMngr_sendUnexpectedTSPECResponseEvent(pTrafficAdmCtrl->hQosMngr, &tspecInfo);
return TI_NOK;
}
/* validate dialog token matching */
if(pTrafficAdmCtrl->dialogToken[tspecInfo.AC] != dialogToken)
{
TRACE2(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_WARNING, "dialog token mismatch, dialogToken = %d , acID = %d \n",dialogToken, tspecInfo.AC);
qosMngr_sendUnexpectedTSPECResponseEvent(pTrafficAdmCtrl->hQosMngr, &tspecInfo);
return TI_NOK;
}
/* Stop the relevant Timer */
trafficAdmCtrl_stopTimer(pTrafficAdmCtrl, tspecInfo.AC);
fsmTSpecInfo.hTrafficAdmCtrl = hTrafficAdmCtrl;
fsmTSpecInfo.pTSpecInfo = &tspecInfo;
fsmTSpecInfo.acID = tspecInfo.AC;
if(statusCode != ADDTS_STATUS_CODE_SUCCESS)
{
/* admission reject */
/********************/
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "***** admCtrlQos_recv: admission reject [ statusCode = %d ]\n",statusCode);
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "ADDTS Response (reject) userPriority = %d , \n", tspecInfo.userPriority);
trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_REJECT, &fsmTSpecInfo);
}
else
{
/* admission accept */
/********************/
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "***** admCtrlQos_recv: admission accept [ statusCode = %d ]\n",statusCode);
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "ADDTS Response (accepted) userPriority = %d , \n", tspecInfo.userPriority);
TRACE2(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "mediumTime = %d , surplusBandwidthAllowance = %d \n", tspecInfo.mediumTime, tspecInfo.surplausBwAllowance);
trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_ACCEPT, &fsmTSpecInfo);
}
}
else
{
status = TI_NOK;
TRACE1(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "trafficAdmCtrl_recv: unknown action code = %d , \n",action);
}
return status;
}
/************************************************************************
* trafficAdmCtrl_sendDeltsFrame *
************************************************************************
DESCRIPTION:
INPUT: pTrafficAdmCtrl - trafficAdmCtr handle.
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_sendDeltsFrame(TI_HANDLE hTrafficAdmCtrl, tspecInfo_t *pTSpecInfo, TI_UINT8 reasonCode)
{
TI_STATUS status = TI_OK;
TTxCtrlBlk *pPktCtrlBlk;
TI_UINT8 *pPktBuffer;
TI_UINT32 totalLen = 0;
tsInfo_t tsInfo;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t *)hTrafficAdmCtrl;
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "admCtrlQos_sendDeltsFrame: Enter....!! \n");
/* Allocate a TxCtrlBlk and data buffer (large enough for the max packet) */
pPktCtrlBlk = TWD_txCtrlBlk_Alloc (pTrafficAdmCtrl->hTWD);
pPktBuffer = txCtrl_AllocPacketBuffer (pTrafficAdmCtrl->hTxCtrl, pPktCtrlBlk, 2000);
if (pPktBuffer == NULL)
{
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_ERROR , ": No memory\n");
TWD_txCtrlBlk_Free (pTrafficAdmCtrl->hTWD, pPktCtrlBlk);
return TI_NOK;
}
status = trafficAdmCtrl_buildFrameHeader (pTrafficAdmCtrl, pPktCtrlBlk);
if (status != TI_OK)
{
TWD_txCtrlBlk_Free (pTrafficAdmCtrl->hTWD, pPktCtrlBlk);
return TI_NOK;
}
*(pPktBuffer + totalLen) = WME_CATAGORY_QOS; /* CATEGORY_QOS in WME = 17*/
totalLen++;
*(pPktBuffer + totalLen) = DELTS_ACTION; /* DELTS ACTION */
totalLen++;
*(pPktBuffer + totalLen) = 0; /* DIALOG_TOKEN is 0 in DELTS */
totalLen++;
*(pPktBuffer + totalLen) = 0; /* STATUS CODE is 0 in DELTS */
totalLen++;
/*
* Build tsInfo fields
*/
tsInfo.tsInfoArr[0] = 0;
tsInfo.tsInfoArr[1] = 0;
tsInfo.tsInfoArr[2] = 0;
tsInfo.tsInfoArr[0] |= ( (pTSpecInfo->userPriority) << TSID_SHIFT);
tsInfo.tsInfoArr[0] |= (BI_DIRECTIONAL << DIRECTION_SHIFT); /* bidirectional */
tsInfo.tsInfoArr[0] |= (TS_INFO_0_ACCESS_POLICY_EDCA << ACCESS_POLICY_SHIFT); /* EDCA */
tsInfo.tsInfoArr[1] |= (0 << AGGREGATION_SHIFT);
tsInfo.tsInfoArr[1] |= (pTSpecInfo->UPSDFlag << APSD_SHIFT);
tsInfo.tsInfoArr[1] |= (pTSpecInfo->userPriority << USER_PRIORITY_SHIFT);
tsInfo.tsInfoArr[1] |= (NORMAL_ACKNOWLEDGEMENT << TSINFO_ACK_POLICY_SHIFT);
tsInfo.tsInfoArr[2] |= (NO_SCHEDULE << SCHEDULE_SHIFT);
/*
* Build TSpec IE for DELTS
*/
*(pPktBuffer + totalLen ) = WME_TSPEC_IE_ID;
*(pPktBuffer + totalLen + 1) = WME_TSPEC_IE_TSINFO_LEN;
*(pPktBuffer + totalLen + 2) = 0x00;
*(pPktBuffer + totalLen + 3) = 0x50;
*(pPktBuffer + totalLen + 4) = 0xf2;
*(pPktBuffer + totalLen + 5) = WME_TSPEC_IE_OUI_TYPE;
*(pPktBuffer + totalLen + 6) = WME_TSPEC_IE_OUI_SUB_TYPE;
*(pPktBuffer + totalLen + 7) = WME_TSPEC_IE_VERSION;
*(pPktBuffer + totalLen + 8) = tsInfo.tsInfoArr[0];
*(pPktBuffer + totalLen + 9) = tsInfo.tsInfoArr[1];
*(pPktBuffer + totalLen +10) = tsInfo.tsInfoArr[2];
totalLen += WME_TSPEC_IE_TSINFO_LEN + 2;
/* Update packet parameters (start-time, pkt-type and BDL) */
pPktCtrlBlk->tTxDescriptor.startTime = os_timeStampMs (pTrafficAdmCtrl->hOs);
pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_MGMT;
BUILD_TX_TWO_BUF_PKT_BDL (pPktCtrlBlk, pPktCtrlBlk->aPktHdr, WLAN_HDR_LEN, pPktBuffer, totalLen)
/* Enqueue packet in the mgmt-queues and run the scheduler. */
status = txMgmtQ_Xmit (pTrafficAdmCtrl->hTxMgmtQ, pPktCtrlBlk, TI_FALSE);
return TI_OK;
}
/************************************************************************
* INTERNAL FUNCTIONS *
************************************************************************/
/************************************************************************
* trafficAdmCtrl_startTimer *
************************************************************************
DESCRIPTION: start a specific ac timer
INPUT: pTrafficAdmCtrl - trafficAdmCtr handle.
acID - the AC of the timer
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_startTimer(trafficAdmCtrl_t* pTrafficAdmCtrl, TI_UINT8 acID)
{
TTimerCbFunc fTimerExpiryFunc = NULL;
if (pTrafficAdmCtrl == NULL)
{
return TI_NOK;
}
switch (acID)
{
case QOS_AC_BE: fTimerExpiryFunc = trafficAdmCtrl_timeoutAcBE; break;
case QOS_AC_BK: fTimerExpiryFunc = trafficAdmCtrl_timeoutAcBK; break;
case QOS_AC_VI: fTimerExpiryFunc = trafficAdmCtrl_timeoutAcVI; break;
case QOS_AC_VO: fTimerExpiryFunc = trafficAdmCtrl_timeoutAcVO; break;
}
tmr_StartTimer (pTrafficAdmCtrl->hAdmCtrlTimer[acID],
fTimerExpiryFunc,
(TI_HANDLE)pTrafficAdmCtrl,
pTrafficAdmCtrl->timeout,
TI_FALSE);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_stopTimer *
************************************************************************
DESCRIPTION: stop a specific ac timer
INPUT: pTrafficAdmCtrl - trafficAdmCtr handle.
acID - the AC of the timer
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_stopTimer(trafficAdmCtrl_t* pTrafficAdmCtrl, TI_UINT8 acID)
{
if (pTrafficAdmCtrl == NULL)
return TI_NOK;
tmr_StopTimer (pTrafficAdmCtrl->hAdmCtrlTimer[acID]);
return TI_OK;
}
/************************************************************************
* AC timers functionc *
************************************************************************/
/* QOS_AC_BE */
/*********/
void trafficAdmCtrl_timeoutAcBE (TI_HANDLE hTrafficAdmCtrl, TI_BOOL bTwdInitOccured)
{
fsmTSpecInfo_t fsmTSpecInfo;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
/* FSM Tspec Info Structure */
fsmTSpecInfo.acID = QOS_AC_BE;
fsmTSpecInfo.hTrafficAdmCtrl = hTrafficAdmCtrl;
fsmTSpecInfo.pTSpecInfo = NULL;
trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_TIMEOUT, &fsmTSpecInfo);
}
/* QOS_AC_BK */
/*********/
void trafficAdmCtrl_timeoutAcBK(TI_HANDLE hTrafficAdmCtrl, TI_BOOL bTwdInitOccured)
{
fsmTSpecInfo_t fsmTSpecInfo;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
/* FSM Tspec Info Structure */
fsmTSpecInfo.acID = QOS_AC_BK;
fsmTSpecInfo.hTrafficAdmCtrl = hTrafficAdmCtrl;
fsmTSpecInfo.pTSpecInfo = NULL;
trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_TIMEOUT, &fsmTSpecInfo);
}
/* QOS_AC_VI */
/*********/
void trafficAdmCtrl_timeoutAcVI(TI_HANDLE hTrafficAdmCtrl, TI_BOOL bTwdInitOccured)
{
fsmTSpecInfo_t fsmTSpecInfo;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
/* FSM Tspec Info Structure */
fsmTSpecInfo.acID = QOS_AC_VI;
fsmTSpecInfo.hTrafficAdmCtrl = hTrafficAdmCtrl;
fsmTSpecInfo.pTSpecInfo = NULL;
trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_TIMEOUT, &fsmTSpecInfo);
}
/* QOS_AC_VO */
/*********/
void trafficAdmCtrl_timeoutAcVO(TI_HANDLE hTrafficAdmCtrl, TI_BOOL bTwdInitOccured)
{
fsmTSpecInfo_t fsmTSpecInfo;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
/* FSM Tspec Info Structure */
fsmTSpecInfo.acID = QOS_AC_VO;
fsmTSpecInfo.hTrafficAdmCtrl = hTrafficAdmCtrl;
fsmTSpecInfo.pTSpecInfo = NULL;
trafficAdmCtrl_smEvent(pTrafficAdmCtrl, TRAFFIC_ADM_CTRL_SM_EVENT_TIMEOUT, &fsmTSpecInfo);
}
static TI_STATUS trafficAdmCtrl_tokenToAc (TI_HANDLE hTrafficAdmCtrl, TI_UINT8 token, TI_UINT8 *acID)
{
TI_UINT8 idx;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
for (idx=0; idx<MAX_NUM_OF_AC; idx++)
{
if (pTrafficAdmCtrl->dialogToken[idx] == token)
{
*acID = idx;
return (TI_OK);
}
}
return (TI_NOK);
}
/************************************************************************
* trafficAdmCtrl_buildFrameHeader *
************************************************************************
DESCRIPTION: build frame header
INPUT:
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_buildFrameHeader(trafficAdmCtrl_t *pTrafficAdmCtrl, TTxCtrlBlk *pPktCtrlBlk)
{
TI_STATUS status;
TMacAddr daBssid, saBssid;
dot11_mgmtHeader_t *pdot11Header;
ScanBssType_e currBssType;
TMacAddr currBssId;
pdot11Header = (dot11_mgmtHeader_t *)(pPktCtrlBlk->aPktHdr);
/* Get the Destination MAC address */
status = ctrlData_getParamBssid(pTrafficAdmCtrl->hCtrlData, CTRL_DATA_CURRENT_BSSID_PARAM, daBssid);
if (status != TI_OK)
{
return TI_NOK;
}
/* Get the Source MAC address */
status = ctrlData_getParamBssid(pTrafficAdmCtrl->hCtrlData, CTRL_DATA_MAC_ADDRESS, saBssid);
if (status != TI_OK)
{
return TI_NOK;
}
/* receive BssId and Bss Type from control module */
ctrlData_getCurrBssTypeAndCurrBssId(pTrafficAdmCtrl->hCtrlData, &currBssId, &currBssType);
if (currBssType != BSS_INFRASTRUCTURE)
{
/* report failure but don't stop... */
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_ERROR, "trafficAdmCtrl_buildFrameHeader: Error !! currBssType = BSS_INFRASTRUCTURE \n");
return TI_NOK;
}
/* infrastructure BSS */
/* copy BSSID */
MAC_COPY (pdot11Header->BSSID, currBssId);
/* copy source mac address */
MAC_COPY (pdot11Header->SA, saBssid);
/* copy destination mac address */
MAC_COPY (pdot11Header->DA, daBssid);
/* set frame ctrl to mgmt action frame an to DS */
pdot11Header->fc = ENDIAN_HANDLE_WORD(DOT11_FC_ACTION | DOT11_FC_TO_DS);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_sendAdmissionReq *
************************************************************************
DESCRIPTION: send admision request frame
INPUT: hTrafficAdmCtrl - Qos Manager handle.
pTSpecInfo - tspec parameters
OUTPUT:
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
TI_STATUS trafficAdmCtrl_sendAdmissionReq(TI_HANDLE hTrafficAdmCtrl, tspecInfo_t *pTSpecInfo)
{
TI_STATUS status = TI_OK;
TTxCtrlBlk *pPktCtrlBlk;
TI_UINT8 *pPktBuffer;
TI_UINT32 len;
TI_UINT32 totalLen = 0;
trafficAdmCtrl_t *pTrafficAdmCtrl = (trafficAdmCtrl_t*)hTrafficAdmCtrl;
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_INFORMATION, "admCtrlQos_smAdmissionReq: Enter....!! \n");
/* Allocate a TxCtrlBlk and data buffer (large enough for the max packet) */
pPktCtrlBlk = TWD_txCtrlBlk_Alloc (pTrafficAdmCtrl->hTWD);
pPktBuffer = txCtrl_AllocPacketBuffer (pTrafficAdmCtrl->hTxCtrl, pPktCtrlBlk, 2000);
if (pPktBuffer == NULL)
{
TRACE0(pTrafficAdmCtrl->hReport, REPORT_SEVERITY_ERROR , ": No memory\n");
TWD_txCtrlBlk_Free (pTrafficAdmCtrl->hTWD, pPktCtrlBlk);
return TI_NOK;
}
status = trafficAdmCtrl_buildFrameHeader (pTrafficAdmCtrl, pPktCtrlBlk);
if (status != TI_OK)
{
TWD_txCtrlBlk_Free (pTrafficAdmCtrl->hTWD, pPktCtrlBlk);
return TI_NOK;
}
*(pPktBuffer + totalLen) = WME_CATAGORY_QOS; /* CATEGORY_QOS WME = 17*/
totalLen++;
*(pPktBuffer + totalLen) = ADDTS_REQUEST_ACTION; /* ADDTS request ACTION */
totalLen++;
/* storing the dialog token for response validation */
pTrafficAdmCtrl->dialogToken[pTSpecInfo->AC] = pTrafficAdmCtrl->dialogTokenCounter++; /* DIALOG_TOKEN */
*(pPktBuffer + totalLen) = pTrafficAdmCtrl->dialogToken[pTSpecInfo->AC];
totalLen++;
*(pPktBuffer + totalLen) = 0; /* STATUS CODE is 0 for ADDTS */
totalLen++;
trafficAdmCtrl_buildTSPec (pTrafficAdmCtrl, pTSpecInfo, pPktBuffer + totalLen, (TI_UINT32*)&len);
totalLen += len;
/* Update packet parameters (start-time, length, pkt-type) */
pPktCtrlBlk->tTxDescriptor.startTime = os_timeStampMs (pTrafficAdmCtrl->hOs);
pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_MGMT;
BUILD_TX_TWO_BUF_PKT_BDL (pPktCtrlBlk, pPktCtrlBlk->aPktHdr, WLAN_HDR_LEN, pPktBuffer, totalLen)
/* Enqueue packet in the mgmt-queues and run the scheduler. */
status = txMgmtQ_Xmit (pTrafficAdmCtrl->hTxMgmtQ, pPktCtrlBlk, TI_FALSE);
return TI_OK;
}
/************************************************************************
* trafficAdmCtrl_buildTSPec *
************************************************************************
DESCRIPTION: build a tspec according to the tspec parameters
INPUT: hTrafficAdmCtrl - Qos Manager handle.
pTSpecInfo - tspec parameters
OUTPUT: pPktBuffer - the Tspec IE to send
len - the tspec frame len
RETURN: TI_OK on success, TI_NOK otherwise
************************************************************************/
void trafficAdmCtrl_buildTSPec(trafficAdmCtrl_t *pTrafficAdmCtrl,
tspecInfo_t *pTSpecInfo,
TI_UINT8 *pDataBuf,
TI_UINT32 *len)
{
tsInfo_t tsInfo;
TI_UINT16 nominalMSDUSize, maxMSDUSize;
TI_UINT32 suspensionInterval = 0; /* disable */
os_memoryZero(pTrafficAdmCtrl->hOs, (void *)pDataBuf, WME_TSPEC_IE_LEN + 2);
*pDataBuf = WME_TSPEC_IE_ID;
*(pDataBuf + 1) = WME_TSPEC_IE_LEN;
*(pDataBuf + 2) = 0x00;
*(pDataBuf + 3) = 0x50;
*(pDataBuf + 4) = 0xf2;
*(pDataBuf + 5) = WME_TSPEC_IE_OUI_TYPE;
*(pDataBuf + 6) = WME_TSPEC_IE_OUI_SUB_TYPE;
*(pDataBuf + 7) = WME_TSPEC_IE_VERSION;
/*
* Build tsInfo fields
*/
tsInfo.tsInfoArr[0] = 0;
tsInfo.tsInfoArr[1] = 0;
tsInfo.tsInfoArr[2] = 0;
tsInfo.tsInfoArr[0] |= ( (pTSpecInfo->userPriority) << TSID_SHIFT);
tsInfo.tsInfoArr[0] |= (pTSpecInfo->streamDirection << DIRECTION_SHIFT); /* bidirectional */
tsInfo.tsInfoArr[0] |= (TS_INFO_0_ACCESS_POLICY_EDCA << ACCESS_POLICY_SHIFT); /* EDCA */
tsInfo.tsInfoArr[1] |= (0 << AGGREGATION_SHIFT);
tsInfo.tsInfoArr[1] |= (pTSpecInfo->UPSDFlag << APSD_SHIFT);
tsInfo.tsInfoArr[1] |= (pTSpecInfo->userPriority << USER_PRIORITY_SHIFT);
tsInfo.tsInfoArr[1] |= (NORMAL_ACKNOWLEDGEMENT << TSINFO_ACK_POLICY_SHIFT);
tsInfo.tsInfoArr[2] |= (NO_SCHEDULE << SCHEDULE_SHIFT);
*(pDataBuf + 8) = tsInfo.tsInfoArr[0];
*(pDataBuf + 9) = tsInfo.tsInfoArr[1];
*(pDataBuf +10) = tsInfo.tsInfoArr[2];
pDataBuf += 11; /* Progress the data pointer to the next IE parameters. */
/*
* Set all remained parameters
*/
nominalMSDUSize = pTSpecInfo->nominalMsduSize;
if (pTrafficAdmCtrl->useFixedMsduSize)
nominalMSDUSize |= FIX_MSDU_SIZE;
maxMSDUSize = (nominalMSDUSize & (~FIX_MSDU_SIZE));
COPY_WLAN_WORD(pDataBuf, &nominalMSDUSize); /* Nominal-MSDU-size. */
COPY_WLAN_WORD(pDataBuf + 2, &maxMSDUSize); /* Maximum-MSDU-size. */
COPY_WLAN_LONG(pDataBuf + 4, &pTSpecInfo->uMinimumServiceInterval); /* Minimum service interval */
COPY_WLAN_LONG(pDataBuf + 8, &pTSpecInfo->uMaximumServiceInterval); /* Maximum service interval */
COPY_WLAN_LONG(pDataBuf + 16, &suspensionInterval);
COPY_WLAN_LONG(pDataBuf + 24, &pTSpecInfo->meanDataRate); /* Minimum-data-rate. */
COPY_WLAN_LONG(pDataBuf + 28, &pTSpecInfo->meanDataRate); /* Mean-data-rate. */
COPY_WLAN_LONG(pDataBuf + 32, &pTSpecInfo->meanDataRate); /* Peak-data-rate. */
COPY_WLAN_LONG(pDataBuf + 44, &pTSpecInfo->minimumPHYRate);
COPY_WLAN_WORD(pDataBuf + 48, &pTSpecInfo->surplausBwAllowance);
*len = WME_TSPEC_IE_LEN + 2;
}
/************************************************************************
* trafficAdmCtrl_parseTspecIE *
************************************************************************
DESCRIPTION: parses a tspec IE according to the tspec parameters
INPUT: pData - tspec IE from received frame
OUTPUT: pTSpecInfo - parsed tspec parameters
RETURN: None
************************************************************************/
void trafficAdmCtrl_parseTspecIE(tspecInfo_t *pTSpecInfo, TI_UINT8 *pData)
{
tsInfo_t tsInfo;
TI_UINT8 userPriority;
TI_UINT8 acID;
TI_UINT8 tid;
TI_UINT8 direction;
TI_UINT8 APSDbit;
pData += 8; /* Skip the WME_TSPEC_IE header */
/* Get the TS-Info (3 bytes) and parse its fields */
tsInfo.tsInfoArr[0] = *pData;
tsInfo.tsInfoArr[1] = *(pData + 1);
tsInfo.tsInfoArr[2] = *(pData + 2);
pData += 3;
userPriority = (((tsInfo.tsInfoArr[1]) & TS_INFO_1_USER_PRIORITY_MASK) >> USER_PRIORITY_SHIFT);
acID = WMEQosTagToACTable[userPriority];
tid = (((tsInfo.tsInfoArr[0]) & TS_INFO_0_TSID_MASK) >> TSID_SHIFT);
APSDbit = (((tsInfo.tsInfoArr[1]) & TS_INFO_1_APSD_MASK) >> APSD_SHIFT);
direction = (((tsInfo.tsInfoArr[0]) & TS_INFO_0_DIRECTION_MASK) >> DIRECTION_SHIFT);
pTSpecInfo->AC = (EAcTrfcType)acID;
pTSpecInfo->userPriority = userPriority;
pTSpecInfo->UPSDFlag = APSDbit;
pTSpecInfo->streamDirection = (EStreamDirection)direction;
pTSpecInfo->tid = tid;
/* Get the other Tspec IE parameters (handle WLAN fram endianess if required) */
COPY_WLAN_WORD(&pTSpecInfo->nominalMsduSize, pData);
COPY_WLAN_LONG(&pTSpecInfo->uMinimumServiceInterval, pData + 4);
COPY_WLAN_LONG(&pTSpecInfo->uMaximumServiceInterval, pData + 8);
COPY_WLAN_LONG(&pTSpecInfo->meanDataRate, pData + 28);
COPY_WLAN_LONG(&pTSpecInfo->minimumPHYRate, pData + 44);
COPY_WLAN_WORD(&pTSpecInfo->surplausBwAllowance, pData + 48);
pTSpecInfo->surplausBwAllowance >>= SURPLUS_BANDWIDTH_ALLOW; /* Surplus is in 3 MSBits of TI_UINT16 */
COPY_WLAN_WORD(&pTSpecInfo->mediumTime, pData + 50);
}
/*************************************************************************
* *
* DEBUG FUNCTIONS *
* *
*************************************************************************/
void trafficAdmCtrl_print(trafficAdmCtrl_t *pTrafficAdmCtr)
{
TI_UINT32 acID;
WLAN_OS_REPORT((" traffic Adm Ctrl \n"));
WLAN_OS_REPORT(("-----------------------------------\n\n"));
WLAN_OS_REPORT(("timeout = %d\n",pTrafficAdmCtr->timeout));
WLAN_OS_REPORT(("dialogTokenCounter = %d\n",pTrafficAdmCtr->dialogTokenCounter));
for (acID = 0 ; acID < MAX_NUM_OF_AC ; acID++)
{
WLAN_OS_REPORT((" AC = %d \n",acID));
WLAN_OS_REPORT(("----------------------\n"));
WLAN_OS_REPORT(("currentState = %d \n",pTrafficAdmCtr->currentState[acID]));
WLAN_OS_REPORT(("dialogToken = %d \n",pTrafficAdmCtr->dialogToken[acID]));
}
}