| /* |
| * 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 */ |
| |
| |
| |