blob: 1d19c7ffadd7d5d9c6d4cb917ed290f5b93065e4 [file] [log] [blame]
/*
* TxDataClsfr.c
*
* Copyright(c) 1998 - 2009 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.
*/
/** \file txDataClsfr.c
* \brief The Tx Data Classifier sub-module (under txDataQueue module).
*
* \see txDataQueue.h (the classifier uses the same object as txDataQueue)
*/
#define __FILE_ID__ FILE_ID_59
#include "paramOut.h"
#include "osApi.h"
#include "report.h"
#include "context.h"
#include "Ethernet.h"
#include "TWDriver.h"
#include "txDataQueue.h"
/**
* \fn txDataClsfr_Config
* \brief Configure the classifier paramters
*
* Configure the classifier parameters according to the init parameters.
* Called from the txDataQueue configuration function.
*
* \note
* \param hTxDataQ - The object handle
* \param pClsfrInitParams - Pointer to the classifier init params
* \return TI_OK on success or TI_NOK on failure
* \sa
*/
TI_STATUS txDataClsfr_Config (TI_HANDLE hTxDataQ, TClsfrParams *pClsfrInitParams)
{
TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
TClsfrParams *pParams = &pTxDataQ->tClsfrParams; /* where to save the new params */
TI_UINT32 uActualEntryCount;
TI_UINT32 i, j;
TI_BOOL bConflictFound;
/* Active classification algorithm */
pParams->eClsfrType = pClsfrInitParams->eClsfrType;
/* the number of active entries */
if (pClsfrInitParams->uNumActiveEntries <= NUM_OF_CLSFR_TABLE_ENTRIES)
pParams->uNumActiveEntries = pClsfrInitParams->uNumActiveEntries;
else
pParams->uNumActiveEntries = NUM_OF_CLSFR_TABLE_ENTRIES;
/* Initialization of the classification table */
switch (pParams->eClsfrType)
{
case D_TAG_CLSFR:
pParams->uNumActiveEntries = 0;
break;
case DSCP_CLSFR:
uActualEntryCount=0;
for (i = 0; i < pParams->uNumActiveEntries; i++)
{
bConflictFound = TI_FALSE;
/* check conflict */
for (j = 0; j < i; j++)
{
/* Detect both duplicate and conflicting entries */
if (pParams->ClsfrTable[j].Dscp.CodePoint == pClsfrInitParams->ClsfrTable[i].Dscp.CodePoint)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING , "ERROR: txDataClsfr_Config(): duplicate/conflicting classifier entries\n");
bConflictFound = TI_TRUE;
}
}
if (bConflictFound == TI_FALSE)
{
pParams->ClsfrTable[uActualEntryCount].Dscp.CodePoint = pClsfrInitParams->ClsfrTable[i].Dscp.CodePoint;
pParams->ClsfrTable[uActualEntryCount].DTag = pClsfrInitParams->ClsfrTable[i].DTag;
uActualEntryCount++;
}
}
pParams->uNumActiveEntries = uActualEntryCount;
break;
case PORT_CLSFR:
uActualEntryCount=0;
for (i = 0; (i < pParams->uNumActiveEntries) ; i++)
{
bConflictFound = TI_FALSE;
/* check conflict */
for (j = 0; j < i; j++)
{
/* Detect both duplicate and conflicting entries */
if (pParams->ClsfrTable[j].Dscp.DstPortNum == pClsfrInitParams->ClsfrTable[i].Dscp.DstPortNum)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING , "ERROR: txDataClsfr_Config(): classifier entries conflict\n");
bConflictFound = TI_TRUE;
}
}
if (bConflictFound == TI_FALSE)
{
pParams->ClsfrTable[uActualEntryCount].Dscp.DstPortNum = pClsfrInitParams->ClsfrTable[i].Dscp.DstPortNum;
pParams->ClsfrTable[uActualEntryCount].DTag = pClsfrInitParams->ClsfrTable[i].DTag;
uActualEntryCount++;
}
}
pParams->uNumActiveEntries = uActualEntryCount;
break;
case IPPORT_CLSFR:
uActualEntryCount=0;
for (i=0; (i < pParams->uNumActiveEntries ) ; i++)
{
bConflictFound = TI_FALSE;
/* check conflict */
for (j = 0; j < i; j++)
{
/* Detect both duplicate and conflicting entries */
if ((pParams->ClsfrTable[j].Dscp.DstIPPort.DstIPAddress == pClsfrInitParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress)&&
(pParams->ClsfrTable[j].Dscp.DstIPPort.DstPortNum == pClsfrInitParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum))
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING , "ERROR: txDataClsfr_Config(): classifier entries conflict\n");
bConflictFound = TI_TRUE;
}
}
if (bConflictFound == TI_FALSE)
{
pParams->ClsfrTable[uActualEntryCount].Dscp.DstIPPort.DstIPAddress = pClsfrInitParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress;
pParams->ClsfrTable[uActualEntryCount].Dscp.DstIPPort.DstPortNum = pClsfrInitParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum;
pParams->ClsfrTable[uActualEntryCount].DTag = pClsfrInitParams->ClsfrTable[i].DTag;
uActualEntryCount++;
}
}
pParams->uNumActiveEntries = uActualEntryCount;
break;
default:
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING , "ERROR: txDataClsfr_Config(): Classifier type -- unknown --> set to D-Tag\n");
pParams->eClsfrType = D_TAG_CLSFR;
pParams->uNumActiveEntries = 0;
break;
}
return TI_OK;
}
/**
* \fn getIpAndUdpHeader
* \brief Get IP & UDP headers addresses if exist
*
* This function gets the addresses of the IP and UDP headers
*
* \note A local inline function!
* \param pTxDataQ - The object handle
* \param pPktCtrlBlk - Pointer to the packet
* \param pIpHeader - Pointer to pointer to IP header
* \param pUdpHeader - Pointer to pointer to UDP header
* \return TI_OK on success, TI_NOK if it's not an IP packet
* \sa
*/
static inline TI_STATUS getIpAndUdpHeader(TTxDataQ *pTxDataQ,
TTxCtrlBlk *pPktCtrlBlk,
TI_UINT8 **pIpHeader,
TI_UINT8 **pUdpHeader)
{
TI_UINT8 *pEthHead = pPktCtrlBlk->tTxnStruct.aBuf[0];
TI_UINT8 ipHeaderLen = 0;
/* check if frame is IP according to ether type */
if( ( HTOWLANS(((TEthernetHeader *)pEthHead)->type) ) != ETHERTYPE_IP)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION, " getIpAndUdpHeader: EthTypeLength is not 0x0800 \n");
return TI_NOK;
}
/* set the pointer to the beginning of the IP header and calculate it's size */
*pIpHeader = pPktCtrlBlk->tTxnStruct.aBuf[1];
ipHeaderLen = ((*(unsigned char*)(*pIpHeader) & 0x0f) * 4);
/* Set the pointer to the beggining of the TCP/UDP header */
if (ipHeaderLen == pPktCtrlBlk->tTxnStruct.aLen[1])
{
*pUdpHeader = pPktCtrlBlk->tTxnStruct.aBuf[2];
}
else
{
*pUdpHeader = *pIpHeader + ipHeaderLen;
}
return TI_OK;
}
/**
* \fn txDataClsfr_ClassifyTxPacket
* \brief Configure the classifier paramters
*
* This function classifies the given Tx packet according to the classifier parameters.
* It sets the TID field with the classification result.
* The classification is according to one of the following methods:
* - D-Tag - Transparent (TID = Dtag)
* - DSCP - According to the DSCP field in the IP header - the default method!
* - Dest UDP-Port
* - Dest IP-Addr & UDP-Port
*
* \note
* \param hTxDataQ - The object handle
* \param pPktCtrlBlk - Pointer to the classified packet
* \param uPacketDtag - The packet priority optionaly set by the OAL
* \return TI_OK on success, PARAM_VALUE_NOT_VALID in case of input parameters problems.
* \sa
*/
TI_STATUS txDataClsfr_ClassifyTxPacket (TI_HANDLE hTxDataQ, TTxCtrlBlk *pPktCtrlBlk, TI_UINT8 uPacketDtag)
{
TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
TClsfrParams *pClsfrParams = &pTxDataQ->tClsfrParams;
TI_UINT8 *pUdpHeader = NULL;
TI_UINT8 *pIpHeader = NULL;
TI_UINT8 uDscp;
TI_UINT16 uDstUdpPort;
TI_UINT32 uDstIpAdd;
TI_UINT32 i;
pPktCtrlBlk->tTxDescriptor.tid = 0;
switch(pClsfrParams->eClsfrType)
{
/* Trivial mapping D-tag to D-tag */
case D_TAG_CLSFR:
if (uPacketDtag > MAX_NUM_OF_802_1d_TAGS)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR , "txDataClsfr_ClassifyTxPacket(): uPacketDtag error\n");
return PARAM_VALUE_NOT_VALID;
}
pPktCtrlBlk->tTxDescriptor.tid = uPacketDtag;
TRACE1(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "Classifier D_TAG_CLSFR. uPacketDtag = %d\n", uPacketDtag);
break;
case DSCP_CLSFR:
if( (getIpAndUdpHeader(pTxDataQ, pPktCtrlBlk, &pIpHeader, &pUdpHeader) != TI_OK)
|| (pIpHeader == NULL) )
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "txDataClsfr_ClassifyTxPacket(): DSCP clsfr, getIpAndUdpHeader mismatch\n");
return PARAM_VALUE_NOT_VALID;
}
/* DSCP to D-tag mapping */
uDscp = *((TI_UINT8 *)(pIpHeader + 1)); /* Fetching the DSCP from the header */
uDscp = (uDscp >> 2);
/* looking for the specific DSCP, if found, its corresponding D-tag is set to the TID */
for(i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
if (pClsfrParams->ClsfrTable[i].Dscp.CodePoint == uDscp)
{
pPktCtrlBlk->tTxDescriptor.tid = pClsfrParams->ClsfrTable[i].DTag;
TRACE2(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "Classifier DSCP_CLSFR found match - entry %d - Tid = %d\n",i,pPktCtrlBlk->tTxDescriptor.tid);
break;
}
}
break;
case PORT_CLSFR:
if( (getIpAndUdpHeader(pTxDataQ, pPktCtrlBlk, &pIpHeader, &pUdpHeader) != TI_OK) ||
(pUdpHeader == NULL) )
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION, " txDataClsfr_ClassifyTxPacket() : DstPort clsfr, getIpAndUdpHeader error\n");
return PARAM_VALUE_NOT_VALID;
}
uDstUdpPort = *((TI_UINT16 *)(pUdpHeader + 2));
uDstUdpPort = HTOWLANS(uDstUdpPort);
/* Looking for the specific port number. If found, its corresponding D-tag is set to the TID. */
for(i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
if (pClsfrParams->ClsfrTable[i].Dscp.DstPortNum == uDstUdpPort)
{
pPktCtrlBlk->tTxDescriptor.tid = pClsfrParams->ClsfrTable[i].DTag;
TRACE2(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "Classifier PORT_CLSFR found match - entry %d - Tid = %d\n", i, pPktCtrlBlk->tTxDescriptor.tid);
break;
}
}
break;
case IPPORT_CLSFR:
if ( (getIpAndUdpHeader(pTxDataQ, pPktCtrlBlk, &pIpHeader, &pUdpHeader) != TI_OK)
|| (pIpHeader == NULL) || (pUdpHeader == NULL) )
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION, "txDataClsfr_ClassifyTxPacket(): Dst IP&Port clsfr, getIpAndUdpHeader error\n");
return PARAM_VALUE_NOT_VALID;
}
uDstUdpPort = *((TI_UINT16 *)(pUdpHeader + 2));
uDstUdpPort = HTOWLANS(uDstUdpPort);
uDstIpAdd = *((TI_UINT32 *)(pIpHeader + 16));
/*
* Looking for the specific pair of dst IP address and dst port number.
* If found, its corresponding D-tag is set to the TID.
*/
for(i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
if ((pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress == uDstIpAdd) &&
(pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum == uDstUdpPort))
{
pPktCtrlBlk->tTxDescriptor.tid = pClsfrParams->ClsfrTable[i].DTag;
TRACE2(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "Classifier IPPORT_CLSFR found match - entry %d - Tid = %d\n", i, pPktCtrlBlk->tTxDescriptor.tid);
break;
}
}
break;
default:
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "txDataClsfr_ClassifyTxPacket(): eClsfrType error\n");
}
return TI_OK;
}
/**
* \fn txDataClsfr_InsertClsfrEntry
* \brief Insert a new entry to classifier table
*
* Add a new entry to the classification table.
* If the new entry is invalid or conflicts with existing entries, the operation is canceled.
*
* \note
* \param hTxDataQ - The object handle
* \param pNewEntry - Pointer to the new entry to insert
* \return TI_OK on success, PARAM_VALUE_NOT_VALID in case of input parameters problems.
* \sa txDataClsfr_RemoveClsfrEntry
*/
TI_STATUS txDataClsfr_InsertClsfrEntry(TI_HANDLE hTxDataQ, TClsfrTableEntry *pNewEntry)
{
TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
TClsfrParams *pClsfrParams = &pTxDataQ->tClsfrParams;
TI_UINT32 i;
if(pNewEntry == NULL)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): NULL ConfigBuffer pointer Error - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* If no available entries, exit */
if (pClsfrParams->uNumActiveEntries == NUM_OF_CLSFR_TABLE_ENTRIES)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): Bad Number Of Entries - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
if (pClsfrParams->eClsfrType == D_TAG_CLSFR)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): D-Tag classifier - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* Check new entry and conflict with existing entries and if OK, insert to classifier table */
switch (pClsfrParams->eClsfrType)
{
case DSCP_CLSFR:
/* Check entry */
if ( (pNewEntry->Dscp.CodePoint > CLASSIFIER_CODE_POINT_MAX) ||
(pNewEntry->DTag > CLASSIFIER_DTAG_MAX) )
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): bad parameter - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* Check conflict*/
for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
/* Detect both duplicate and conflicting entries */
if (pClsfrParams->ClsfrTable[i].Dscp.CodePoint == pNewEntry->Dscp.CodePoint)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): classifier entries conflict - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
}
/* Insert new entry to classifier table. */
/* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
context_EnterCriticalSection (pTxDataQ->hContext);
pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].Dscp.CodePoint = pNewEntry->Dscp.CodePoint;
pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].DTag = pNewEntry->DTag;
context_LeaveCriticalSection (pTxDataQ->hContext);
break;
case PORT_CLSFR:
/* Check entry */
if ((pNewEntry->DTag > CLASSIFIER_DTAG_MAX) ||
(pNewEntry->Dscp.DstPortNum > CLASSIFIER_PORT_MAX-1) ||
(pNewEntry->Dscp.DstPortNum < CLASSIFIER_PORT_MIN) )
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): bad parameter - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* Check conflict*/
for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
/* Detect both duplicate and conflicting entries */
if ((pClsfrParams->ClsfrTable[i].Dscp.DstPortNum == pNewEntry->Dscp.DstPortNum))
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): classifier entries conflict - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
}
/* Insert new entry to classifier table. */
/* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
context_EnterCriticalSection (pTxDataQ->hContext);
pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].Dscp.DstPortNum = pNewEntry->Dscp.DstPortNum;
pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].DTag = pNewEntry->DTag;
context_LeaveCriticalSection (pTxDataQ->hContext);
break;
case IPPORT_CLSFR:
/* Check entry */
if ( (pNewEntry->DTag > CLASSIFIER_DTAG_MAX) ||
(pNewEntry->Dscp.DstIPPort.DstPortNum > CLASSIFIER_PORT_MAX-1) ||
(pNewEntry->Dscp.DstIPPort.DstPortNum < CLASSIFIER_PORT_MIN) ||
(pNewEntry->Dscp.DstIPPort.DstIPAddress > CLASSIFIER_IPADDRESS_MAX-1) ||
(pNewEntry->Dscp.DstIPPort.DstIPAddress < CLASSIFIER_IPADDRESS_MIN+1) )
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): bad parameter - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* Check conflict*/
for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
/* Detect both duplicate and conflicting entries */
if ( (pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress == pNewEntry->Dscp.DstIPPort.DstIPAddress) &&
(pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum == pNewEntry->Dscp.DstIPPort.DstPortNum))
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): classifier entries conflict - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
}
/* Insert new entry to classifier table */
/* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
context_EnterCriticalSection (pTxDataQ->hContext);
pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].Dscp.DstIPPort.DstIPAddress = pNewEntry->Dscp.DstIPPort.DstIPAddress;
pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].Dscp.DstIPPort.DstPortNum = pNewEntry->Dscp.DstIPPort.DstPortNum;
pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].DTag = pNewEntry->DTag;
context_LeaveCriticalSection (pTxDataQ->hContext);
break;
default:
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): Classifier type -- unknown - Aborting\n");
}
/* Increment the number of classifier active entries */
pClsfrParams->uNumActiveEntries++;
return TI_OK;
}
/**
* \fn txDataClsfr_RemoveClsfrEntry
* \brief Remove an entry from classifier table
*
* Remove an entry from classifier table.
*
* \note
* \param hTxDataQ - The object handle
* \param pRemEntry - Pointer to the entry to remove
* \return TI_OK on success, PARAM_VALUE_NOT_VALID in case of input parameters problems.
* \sa txDataClsfr_InsertClsfrEntry
*/
TI_STATUS txDataClsfr_RemoveClsfrEntry(TI_HANDLE hTxDataQ, TClsfrTableEntry *pRemEntry)
{
TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
TClsfrParams *pClsfrParams = &pTxDataQ->tClsfrParams;
TI_UINT32 i, j;
if(pRemEntry == NULL)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): NULL ConfigBuffer pointer Error - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
if (pClsfrParams->uNumActiveEntries == 0)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Classifier table is empty - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
if (pClsfrParams->eClsfrType == D_TAG_CLSFR)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): D-Tag classifier - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* Check conflicts with classifier table entries */
/* check all conflicts, if all entries are TI_OK --> insert to classifier table*/
switch (pClsfrParams->eClsfrType)
{
case DSCP_CLSFR:
/* Find the classifier entry */
i = 0;
while ((i < pClsfrParams->uNumActiveEntries) &&
((pClsfrParams->ClsfrTable[i].Dscp.CodePoint != pRemEntry->Dscp.CodePoint) ||
(pClsfrParams->ClsfrTable[i].DTag != pRemEntry->DTag)))
{
i++;
}
/* If we have reached the number of active entries, it means we couldn't find the requested entry */
if (i == pClsfrParams->uNumActiveEntries)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Entry not found - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* Shift all entries above the removed one downward */
/* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
context_EnterCriticalSection (pTxDataQ->hContext);
for (j = i; j < pClsfrParams->uNumActiveEntries - 1; j++)
{
/* Move entries */
pClsfrParams->ClsfrTable[j].Dscp.CodePoint = pClsfrParams->ClsfrTable[j+1].Dscp.CodePoint;
pClsfrParams->ClsfrTable[j].DTag = pClsfrParams->ClsfrTable[j+1].DTag;
}
context_LeaveCriticalSection (pTxDataQ->hContext);
break;
case PORT_CLSFR:
/* Find the classifier entry */
i = 0;
while ((i < pClsfrParams->uNumActiveEntries) &&
((pClsfrParams->ClsfrTable[i].Dscp.DstPortNum != pRemEntry->Dscp.DstPortNum) ||
(pClsfrParams->ClsfrTable[i].DTag != pRemEntry->DTag)))
{
i++;
}
/* If we have reached the number of active entries, it means we couldn't find the requested entry */
if (i == pClsfrParams->uNumActiveEntries)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Entry not found - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* Shift all entries above the removed one downward */
/* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
context_EnterCriticalSection (pTxDataQ->hContext);
for (j = i; j < pClsfrParams->uNumActiveEntries - 1; j++)
{
pClsfrParams->ClsfrTable[j].Dscp.DstPortNum = pClsfrParams->ClsfrTable[j+1].Dscp.DstPortNum;
pClsfrParams->ClsfrTable[j].DTag = pClsfrParams->ClsfrTable[j+1].DTag;
}
context_LeaveCriticalSection (pTxDataQ->hContext);
break;
case IPPORT_CLSFR:
/* Find the classifier entry */
i = 0;
while ((i < pClsfrParams->uNumActiveEntries) &&
((pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress != pRemEntry->Dscp.DstIPPort.DstIPAddress) ||
(pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum != pRemEntry->Dscp.DstIPPort.DstPortNum) ||
(pClsfrParams->ClsfrTable[i].DTag != pRemEntry->DTag)))
{
i++;
}
/* If we have reached the number of active entries, it means we couldn't find the requested entry */
if (i == pClsfrParams->uNumActiveEntries)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Entry not found - Aborting\n");
return PARAM_VALUE_NOT_VALID;
}
/* Shift all entries above the removed one downward. */
/* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
context_EnterCriticalSection (pTxDataQ->hContext);
for (j = i; j < pClsfrParams->uNumActiveEntries - 1; j++)
{
pClsfrParams->ClsfrTable[j].Dscp.DstIPPort.DstIPAddress = pClsfrParams->ClsfrTable[j+1].Dscp.DstIPPort.DstIPAddress;
pClsfrParams->ClsfrTable[j].Dscp.DstIPPort.DstPortNum = pClsfrParams->ClsfrTable[j+1].Dscp.DstIPPort.DstPortNum;
pClsfrParams->ClsfrTable[j].DTag = pClsfrParams->ClsfrTable[j+1].DTag;
}
context_LeaveCriticalSection (pTxDataQ->hContext);
break;
default:
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Classifier type -- unknown - Aborting\n");
}
/* Decrement the number of classifier active entries */
pClsfrParams->uNumActiveEntries--;
return TI_OK;
}
/**
* \fn txDataClsfr_SetClsfrType & txDataClsfr_GetClsfrType
* \brief Set / Get classifier type
*
* Set / Get classifier type.
* When setting type, the table is emptied!
*
* \note
* \param hTxDataQ - The object handle
* \param eNewClsfrType - New type
* \return TI_OK on success, PARAM_VALUE_NOT_VALID in case of input parameters problems.
* \sa
*/
TI_STATUS txDataClsfr_SetClsfrType (TI_HANDLE hTxDataQ, EClsfrType eNewClsfrType)
{
TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
if (eNewClsfrType > CLSFR_TYPE_MAX)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_setClsfrType(): classifier type exceed its MAX \n");
return PARAM_VALUE_NOT_VALID;
}
if (pTxDataQ->tClsfrParams.eClsfrType == eNewClsfrType)
{
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING, "Classifier_setClsfrType(): equal classifier type --> will empty classifier table \n");
}
/* Update type and empty table. */
/* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
context_EnterCriticalSection (pTxDataQ->hContext);
pTxDataQ->tClsfrParams.eClsfrType = eNewClsfrType;
pTxDataQ->tClsfrParams.uNumActiveEntries = 0;
context_LeaveCriticalSection (pTxDataQ->hContext);
return TI_OK;
}
TI_STATUS txDataClsfr_GetClsfrType (TI_HANDLE hTxDataQ, EClsfrType *pClsfrType)
{
TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
*pClsfrType = pTxDataQ->tClsfrParams.eClsfrType;
return TI_OK;
}
#ifdef TI_DBG
/**
* \fn txDataClsfr_PrintClsfrTable
* \brief Print classifier table
*
* Print the classifier table for debug
*
* \note
* \param hTxDataQ - The object handle
* \return void
* \sa
*/
void txDataClsfr_PrintClsfrTable (TI_HANDLE hTxDataQ)
{
TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
TClsfrParams *pClsfrParams = &pTxDataQ->tClsfrParams;
TI_UINT32 uIpAddr, i;
if (pClsfrParams->eClsfrType == D_TAG_CLSFR)
{
WLAN_OS_REPORT (("D_TAG classifier type selected...Nothing to print...\n"));
return;
}
WLAN_OS_REPORT (("Number of active entries in classifier table : %d\n",pClsfrParams->uNumActiveEntries));
switch (pClsfrParams->eClsfrType)
{
case DSCP_CLSFR:
WLAN_OS_REPORT (("+------+-------+\n"));
WLAN_OS_REPORT (("| Code | D-Tag |\n"));
WLAN_OS_REPORT (("+------+-------+\n"));
for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
WLAN_OS_REPORT (("| %5d | %5d |\n",
pClsfrParams->ClsfrTable[i].Dscp.CodePoint,pClsfrParams->ClsfrTable[i].DTag));
}
WLAN_OS_REPORT (("+-------+-------+\n"));
break;
case PORT_CLSFR:
WLAN_OS_REPORT (("+-------+-------+\n"));
WLAN_OS_REPORT (("| Port | D-Tag |\n"));
WLAN_OS_REPORT (("+-------+-------+\n"));
for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
WLAN_OS_REPORT (("| %5d | %5d |\n",
pClsfrParams->ClsfrTable[i].Dscp.DstPortNum,pClsfrParams->ClsfrTable[i].DTag));
}
WLAN_OS_REPORT (("+-------+-------+\n"));
break;
case IPPORT_CLSFR:
WLAN_OS_REPORT (("+-------------+-------+-------+\n"));
WLAN_OS_REPORT (("| IP Address | Port | D-Tag |\n"));
WLAN_OS_REPORT (("+-------------+-------+-------+\n"));
for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
{
uIpAddr = pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress;
WLAN_OS_REPORT (("| %02x.%02x.%02x.%02x | %5d | %5d |\n",
(uIpAddr & 0xFF),((uIpAddr >> 8) & (0xFF)),((uIpAddr >> 16) & (0xFF)),((uIpAddr >> 24) & (0xFF)),
pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum, pClsfrParams->ClsfrTable[i].DTag));
}
WLAN_OS_REPORT (("+-------------+-------+-------+\n"));
break;
default:
TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): Classifier type -- unknown - Aborting\n");
break;
}
}
#endif /* TI_DBG */