/* * 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])); } }