Home | History | Annotate | Download | only in Data_link
      1 /*
      2  * TxDataClsfr.c
      3  *
      4  * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  *  * Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *  * Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in
     15  *    the documentation and/or other materials provided with the
     16  *    distribution.
     17  *  * Neither the name Texas Instruments nor the names of its
     18  *    contributors may be used to endorse or promote products derived
     19  *    from this software without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 
     35 /** \file   txDataClsfr.c
     36  *  \brief  The Tx Data Classifier sub-module (under txDataQueue module).
     37  *
     38  *  \see    txDataQueue.h (the classifier uses the same object as txDataQueue)
     39  */
     40 
     41 #define __FILE_ID__  FILE_ID_59
     42 #include "paramOut.h"
     43 #include "osApi.h"
     44 #include "report.h"
     45 #include "context.h"
     46 #include "Ethernet.h"
     47 #include "TWDriver.h"
     48 #include "txDataQueue.h"
     49 
     50 
     51 
     52 /**
     53  * \fn     txDataClsfr_Config
     54  * \brief  Configure the classifier paramters
     55  *
     56  * Configure the classifier parameters according to the init parameters.
     57  * Called from the txDataQueue configuration function.
     58  *
     59  * \note
     60  * \param  hTxDataQ     - The object handle
     61  * \param  pClsfrInitParams - Pointer to the classifier init params
     62  * \return TI_OK on success or TI_NOK on failure
     63  * \sa
     64  */
     65 TI_STATUS txDataClsfr_Config (TI_HANDLE hTxDataQ, TClsfrParams *pClsfrInitParams)
     66 {
     67     TTxDataQ     *pTxDataQ = (TTxDataQ *)hTxDataQ;
     68     TClsfrParams *pParams  = &pTxDataQ->tClsfrParams; /* where to save the new params */
     69     TI_UINT32     uActualEntryCount;
     70     TI_UINT32     i, j;
     71     TI_BOOL       bConflictFound;
     72 
     73     /* Active classification algorithm */
     74     pParams->eClsfrType = pClsfrInitParams->eClsfrType;
     75 
     76     /* the number of active entries */
     77     if (pClsfrInitParams->uNumActiveEntries <= NUM_OF_CLSFR_TABLE_ENTRIES)
     78         pParams->uNumActiveEntries = pClsfrInitParams->uNumActiveEntries;
     79     else
     80         pParams->uNumActiveEntries = NUM_OF_CLSFR_TABLE_ENTRIES;
     81 
     82     /* Initialization of the classification table */
     83     switch (pParams->eClsfrType)
     84     {
     85         case D_TAG_CLSFR:
     86 			pParams->uNumActiveEntries = 0;
     87         break;
     88 
     89         case DSCP_CLSFR:
     90             uActualEntryCount=0;
     91             for (i = 0; i < pParams->uNumActiveEntries; i++)
     92             {
     93                bConflictFound = TI_FALSE;
     94                 /* check conflict */
     95                 for (j = 0; j < i; j++)
     96                 {
     97                    /* Detect both duplicate and conflicting entries */
     98                     if (pParams->ClsfrTable[j].Dscp.CodePoint == pClsfrInitParams->ClsfrTable[i].Dscp.CodePoint)
     99                     {
    100                         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING , "ERROR: txDataClsfr_Config(): duplicate/conflicting classifier entries\n");
    101                         bConflictFound = TI_TRUE;
    102                     }
    103                 }
    104                 if (bConflictFound == TI_FALSE)
    105                 {
    106                   pParams->ClsfrTable[uActualEntryCount].Dscp.CodePoint = pClsfrInitParams->ClsfrTable[i].Dscp.CodePoint;
    107                   pParams->ClsfrTable[uActualEntryCount].DTag = pClsfrInitParams->ClsfrTable[i].DTag;
    108                   uActualEntryCount++;
    109                 }
    110             }
    111             pParams->uNumActiveEntries = uActualEntryCount;
    112         break;
    113 
    114         case PORT_CLSFR:
    115            uActualEntryCount=0;
    116             for (i = 0; (i < pParams->uNumActiveEntries) ; i++)
    117             {
    118 				bConflictFound = TI_FALSE;
    119                 /* check conflict */
    120                 for (j = 0; j < i; j++)
    121                 {
    122                     /* Detect both duplicate and conflicting entries */
    123                     if (pParams->ClsfrTable[j].Dscp.DstPortNum == pClsfrInitParams->ClsfrTable[i].Dscp.DstPortNum)
    124                     {
    125                         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING , "ERROR: txDataClsfr_Config(): classifier entries conflict\n");
    126                         bConflictFound = TI_TRUE;
    127                     }
    128                 }
    129                 if (bConflictFound == TI_FALSE)
    130                 {
    131                   pParams->ClsfrTable[uActualEntryCount].Dscp.DstPortNum = pClsfrInitParams->ClsfrTable[i].Dscp.DstPortNum;
    132                   pParams->ClsfrTable[uActualEntryCount].DTag = pClsfrInitParams->ClsfrTable[i].DTag;
    133                   uActualEntryCount++;
    134                 }
    135             }
    136             pParams->uNumActiveEntries = uActualEntryCount;
    137         break;
    138 
    139         case IPPORT_CLSFR:
    140            uActualEntryCount=0;
    141             for (i=0; (i < pParams->uNumActiveEntries ) ; i++)
    142             {
    143 				bConflictFound = TI_FALSE;
    144                 /* check conflict */
    145                 for (j = 0; j < i; j++)
    146                 {
    147                    /* Detect both duplicate and conflicting entries */
    148                     if ((pParams->ClsfrTable[j].Dscp.DstIPPort.DstIPAddress == pClsfrInitParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress)&&
    149                     (pParams->ClsfrTable[j].Dscp.DstIPPort.DstPortNum == pClsfrInitParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum))
    150                     {
    151                         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING , "ERROR: txDataClsfr_Config(): classifier entries conflict\n");
    152                         bConflictFound = TI_TRUE;
    153                     }
    154                 }
    155                 if (bConflictFound == TI_FALSE)
    156                 {
    157                   pParams->ClsfrTable[uActualEntryCount].Dscp.DstIPPort.DstIPAddress = pClsfrInitParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress;
    158                   pParams->ClsfrTable[uActualEntryCount].Dscp.DstIPPort.DstPortNum = pClsfrInitParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum;
    159                   pParams->ClsfrTable[uActualEntryCount].DTag = pClsfrInitParams->ClsfrTable[i].DTag;
    160                   uActualEntryCount++;
    161                 }
    162             }
    163             pParams->uNumActiveEntries = uActualEntryCount;
    164         break;
    165 
    166         default:
    167             TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING , "ERROR: txDataClsfr_Config(): Classifier type -- unknown --> set to D-Tag\n");
    168             pParams->eClsfrType = D_TAG_CLSFR;
    169 			pParams->uNumActiveEntries = 0;
    170         break;
    171     }
    172 
    173     return TI_OK;
    174 }
    175 
    176 
    177 /**
    178  * \fn     getIpAndUdpHeader
    179  * \brief  Get IP & UDP headers addresses if exist
    180  *
    181  * This function gets the addresses of the IP and UDP headers
    182  *
    183  * \note   A local inline function!
    184  * \param  pTxDataQ    - The object handle
    185  * \param  pPktCtrlBlk - Pointer to the packet
    186  * \param  pIpHeader   - Pointer to pointer to IP header
    187  * \param  pUdpHeader  - Pointer to pointer to UDP header
    188  * \return TI_OK on success, TI_NOK if it's not an IP packet
    189  * \sa
    190  */
    191 static inline TI_STATUS getIpAndUdpHeader(TTxDataQ   *pTxDataQ,
    192                                           TTxCtrlBlk *pPktCtrlBlk,
    193                                           TI_UINT8  **pIpHeader,
    194                                           TI_UINT8  **pUdpHeader)
    195 {
    196     TI_UINT8 *pEthHead = pPktCtrlBlk->tTxnStruct.aBuf[0];
    197 	TI_UINT8  ipHeaderLen = 0;
    198 
    199 	/* check if frame is IP according to ether type */
    200     if( ( HTOWLANS(((TEthernetHeader *)pEthHead)->type) ) != ETHERTYPE_IP)
    201     {
    202         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION, " getIpAndUdpHeader: EthTypeLength is not 0x0800 \n");
    203         return TI_NOK;
    204     }
    205 
    206     /* set the pointer to the beginning of the IP header and calculate it's size */
    207     *pIpHeader  = pPktCtrlBlk->tTxnStruct.aBuf[1];
    208     ipHeaderLen = ((*(unsigned char*)(*pIpHeader) & 0x0f) * 4);
    209 
    210     /* Set the pointer to the beggining of the TCP/UDP header */
    211     if (ipHeaderLen == pPktCtrlBlk->tTxnStruct.aLen[1])
    212     {
    213         *pUdpHeader = pPktCtrlBlk->tTxnStruct.aBuf[2];
    214     }
    215     else
    216     {
    217         *pUdpHeader = *pIpHeader + ipHeaderLen;
    218     }
    219 
    220     return TI_OK;
    221 }
    222 
    223 
    224 /**
    225  * \fn     txDataClsfr_ClassifyTxPacket
    226  * \brief  Configure the classifier paramters
    227  *
    228  * This function classifies the given Tx packet according to the classifier parameters.
    229  * It sets the TID field with the classification result.
    230  * The classification is according to one of the following methods:
    231  * - D-Tag  - Transparent (TID = Dtag)
    232  * - DSCP   - According to the DSCP field in the IP header - the default method!
    233  * - Dest UDP-Port
    234  * - Dest IP-Addr & UDP-Port
    235  *
    236  * \note
    237  * \param  hTxDataQ    - The object handle
    238  * \param  pPktCtrlBlk - Pointer to the classified packet
    239  * \param  uPacketDtag - The packet priority optionaly set by the OAL
    240  * \return TI_OK on success, PARAM_VALUE_NOT_VALID in case of input parameters problems.
    241  * \sa
    242  */
    243 TI_STATUS txDataClsfr_ClassifyTxPacket (TI_HANDLE hTxDataQ, TTxCtrlBlk *pPktCtrlBlk, TI_UINT8 uPacketDtag)
    244 {
    245     TTxDataQ     *pTxDataQ = (TTxDataQ *)hTxDataQ;
    246     TClsfrParams *pClsfrParams = &pTxDataQ->tClsfrParams;
    247     TI_UINT8     *pUdpHeader = NULL;
    248     TI_UINT8     *pIpHeader = NULL;
    249     TI_UINT8   uDscp;
    250     TI_UINT16  uDstUdpPort;
    251     TI_UINT32  uDstIpAdd;
    252     TI_UINT32  i;
    253 
    254     pPktCtrlBlk->tTxDescriptor.tid = 0;
    255 
    256     switch(pClsfrParams->eClsfrType)
    257     {
    258             /* Trivial mapping D-tag to D-tag */
    259         case D_TAG_CLSFR:
    260             if (uPacketDtag > MAX_NUM_OF_802_1d_TAGS)
    261             {
    262                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR , "txDataClsfr_ClassifyTxPacket(): uPacketDtag error\n");
    263                 return PARAM_VALUE_NOT_VALID;
    264             }
    265             pPktCtrlBlk->tTxDescriptor.tid = uPacketDtag;
    266             TRACE1(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "Classifier D_TAG_CLSFR. uPacketDtag = %d\n", uPacketDtag);
    267         break;
    268 
    269         case DSCP_CLSFR:
    270             if( (getIpAndUdpHeader(pTxDataQ, pPktCtrlBlk, &pIpHeader, &pUdpHeader) != TI_OK)
    271                 || (pIpHeader == NULL) )
    272             {
    273                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "txDataClsfr_ClassifyTxPacket(): DSCP clsfr, getIpAndUdpHeader mismatch\n");
    274 				return PARAM_VALUE_NOT_VALID;
    275             }
    276 
    277             /* DSCP to D-tag mapping */
    278             uDscp =  *((TI_UINT8 *)(pIpHeader + 1)); /* Fetching the DSCP from the header */
    279             uDscp = (uDscp >> 2);
    280 
    281             /* looking for the specific DSCP, if found, its corresponding D-tag is set to the TID */
    282             for(i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    283             {
    284                 if (pClsfrParams->ClsfrTable[i].Dscp.CodePoint == uDscp)
    285 				{
    286                     pPktCtrlBlk->tTxDescriptor.tid = pClsfrParams->ClsfrTable[i].DTag;
    287                     TRACE2(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "Classifier DSCP_CLSFR found match - entry %d - Tid = %d\n",i,pPktCtrlBlk->tTxDescriptor.tid);
    288 					break;
    289 				}
    290             }
    291         break;
    292 
    293         case PORT_CLSFR:
    294             if( (getIpAndUdpHeader(pTxDataQ, pPktCtrlBlk, &pIpHeader, &pUdpHeader) != TI_OK) ||
    295                 (pUdpHeader == NULL) )
    296             {
    297                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION, " txDataClsfr_ClassifyTxPacket() : DstPort clsfr, getIpAndUdpHeader error\n");
    298                 return PARAM_VALUE_NOT_VALID;
    299             }
    300 
    301             uDstUdpPort = *((TI_UINT16 *)(pUdpHeader + 2));
    302             uDstUdpPort = HTOWLANS(uDstUdpPort);
    303 
    304             /* Looking for the specific port number. If found, its corresponding D-tag is set to the TID. */
    305             for(i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    306             {
    307                 if (pClsfrParams->ClsfrTable[i].Dscp.DstPortNum == uDstUdpPort)
    308 				{
    309                     pPktCtrlBlk->tTxDescriptor.tid = pClsfrParams->ClsfrTable[i].DTag;
    310                     TRACE2(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "Classifier PORT_CLSFR found match - entry %d - Tid = %d\n", i, pPktCtrlBlk->tTxDescriptor.tid);
    311 					break;
    312 				}
    313             }
    314         break;
    315 
    316         case IPPORT_CLSFR:
    317             if ( (getIpAndUdpHeader(pTxDataQ, pPktCtrlBlk, &pIpHeader, &pUdpHeader) != TI_OK)
    318                  || (pIpHeader == NULL) || (pUdpHeader == NULL) )
    319             {
    320                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION, "txDataClsfr_ClassifyTxPacket(): Dst IP&Port clsfr, getIpAndUdpHeader error\n");
    321                 return PARAM_VALUE_NOT_VALID;
    322             }
    323 
    324             uDstUdpPort = *((TI_UINT16 *)(pUdpHeader + 2));
    325             uDstUdpPort = HTOWLANS(uDstUdpPort);
    326             uDstIpAdd = *((TI_UINT32 *)(pIpHeader + 16));
    327 
    328             /*
    329              * Looking for the specific pair of dst IP address and dst port number.
    330              * If found, its corresponding D-tag is set to the TID.
    331              */
    332             for(i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    333             {
    334                 if ((pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress == uDstIpAdd) &&
    335                     (pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum == uDstUdpPort))
    336 				{
    337                     pPktCtrlBlk->tTxDescriptor.tid = pClsfrParams->ClsfrTable[i].DTag;
    338                     TRACE2(pTxDataQ->hReport, REPORT_SEVERITY_INFORMATION , "Classifier IPPORT_CLSFR found match - entry %d - Tid = %d\n", i, pPktCtrlBlk->tTxDescriptor.tid);
    339 					break;
    340 				}
    341             }
    342         break;
    343 
    344         default:
    345             TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "txDataClsfr_ClassifyTxPacket(): eClsfrType error\n");
    346     }
    347 
    348     return TI_OK;
    349 }
    350 
    351 
    352 /**
    353  * \fn     txDataClsfr_InsertClsfrEntry
    354  * \brief  Insert a new entry to classifier table
    355  *
    356  * Add a new entry to the classification table.
    357  * If the new entry is invalid or conflicts with existing entries, the operation is canceled.
    358  *
    359  * \note
    360  * \param  hTxDataQ - The object handle
    361  * \param  pNewEntry    - Pointer to the new entry to insert
    362  * \return TI_OK on success, PARAM_VALUE_NOT_VALID in case of input parameters problems.
    363  * \sa     txDataClsfr_RemoveClsfrEntry
    364  */
    365 TI_STATUS txDataClsfr_InsertClsfrEntry(TI_HANDLE hTxDataQ, TClsfrTableEntry *pNewEntry)
    366 {
    367     TTxDataQ      *pTxDataQ     = (TTxDataQ *)hTxDataQ;
    368     TClsfrParams  *pClsfrParams = &pTxDataQ->tClsfrParams;
    369     TI_UINT32     i;
    370 
    371 	if(pNewEntry == NULL)
    372     {
    373         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): NULL ConfigBuffer pointer Error - Aborting\n");
    374 		return PARAM_VALUE_NOT_VALID;
    375     }
    376 
    377     /* If no available entries, exit */
    378     if (pClsfrParams->uNumActiveEntries == NUM_OF_CLSFR_TABLE_ENTRIES)
    379     {
    380         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): Bad Number Of Entries - Aborting\n");
    381         return PARAM_VALUE_NOT_VALID;
    382     }
    383 
    384     if (pClsfrParams->eClsfrType == D_TAG_CLSFR)
    385     {
    386         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): D-Tag classifier - Aborting\n");
    387         return PARAM_VALUE_NOT_VALID;
    388     }
    389 
    390     /* Check new entry and conflict with existing entries and if OK, insert to classifier table */
    391     switch (pClsfrParams->eClsfrType)
    392     {
    393         case DSCP_CLSFR:
    394 
    395             /* Check entry */
    396             if ( (pNewEntry->Dscp.CodePoint > CLASSIFIER_CODE_POINT_MAX) ||
    397                  (pNewEntry->DTag > CLASSIFIER_DTAG_MAX) )
    398             {
    399                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): bad parameter - Aborting\n");
    400                 return PARAM_VALUE_NOT_VALID;
    401             }
    402 
    403             /* Check conflict*/
    404             for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    405             {
    406                /* Detect both duplicate and conflicting entries */
    407                 if (pClsfrParams->ClsfrTable[i].Dscp.CodePoint == pNewEntry->Dscp.CodePoint)
    408                 {
    409                     TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): classifier entries conflict - Aborting\n");
    410                     return PARAM_VALUE_NOT_VALID;
    411                 }
    412             }
    413 
    414             /* Insert new entry to classifier table. */
    415             /* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
    416             context_EnterCriticalSection (pTxDataQ->hContext);
    417             pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].Dscp.CodePoint = pNewEntry->Dscp.CodePoint;
    418             pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].DTag = pNewEntry->DTag;
    419             context_LeaveCriticalSection (pTxDataQ->hContext);
    420 
    421         break;
    422 
    423         case PORT_CLSFR:
    424 
    425             /* Check entry */
    426             if ((pNewEntry->DTag > CLASSIFIER_DTAG_MAX) ||
    427                 (pNewEntry->Dscp.DstPortNum > CLASSIFIER_PORT_MAX-1) ||
    428                 (pNewEntry->Dscp.DstPortNum < CLASSIFIER_PORT_MIN) )
    429             {
    430                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): bad parameter - Aborting\n");
    431                 return PARAM_VALUE_NOT_VALID;
    432             }
    433 
    434             /* Check conflict*/
    435             for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    436             {
    437                /* Detect both duplicate and conflicting entries */
    438                 if ((pClsfrParams->ClsfrTable[i].Dscp.DstPortNum == pNewEntry->Dscp.DstPortNum))
    439                 {
    440                     TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): classifier entries conflict - Aborting\n");
    441                      return PARAM_VALUE_NOT_VALID;
    442                 }
    443             }
    444 
    445             /* Insert new entry to classifier table. */
    446             /* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
    447             context_EnterCriticalSection (pTxDataQ->hContext);
    448             pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].Dscp.DstPortNum = pNewEntry->Dscp.DstPortNum;
    449             pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].DTag = pNewEntry->DTag;
    450             context_LeaveCriticalSection (pTxDataQ->hContext);
    451 
    452         break;
    453 
    454         case IPPORT_CLSFR:
    455 
    456             /* Check entry */
    457             if ( (pNewEntry->DTag > CLASSIFIER_DTAG_MAX) ||
    458                  (pNewEntry->Dscp.DstIPPort.DstPortNum > CLASSIFIER_PORT_MAX-1) ||
    459                  (pNewEntry->Dscp.DstIPPort.DstPortNum < CLASSIFIER_PORT_MIN) ||
    460                  (pNewEntry->Dscp.DstIPPort.DstIPAddress > CLASSIFIER_IPADDRESS_MAX-1) ||
    461                  (pNewEntry->Dscp.DstIPPort.DstIPAddress < CLASSIFIER_IPADDRESS_MIN+1) )
    462             {
    463                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): bad parameter - Aborting\n");
    464                 return PARAM_VALUE_NOT_VALID;
    465             }
    466 
    467             /* Check conflict*/
    468             for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    469             {
    470                /* Detect both duplicate and conflicting entries */
    471                 if ( (pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress == pNewEntry->Dscp.DstIPPort.DstIPAddress) &&
    472                      (pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum == pNewEntry->Dscp.DstIPPort.DstPortNum))
    473                 {
    474                     TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): classifier entries conflict - Aborting\n");
    475                      return PARAM_VALUE_NOT_VALID;
    476                 }
    477             }
    478 
    479             /* Insert new entry to classifier table */
    480             /* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
    481             context_EnterCriticalSection (pTxDataQ->hContext);
    482             pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].Dscp.DstIPPort.DstIPAddress = pNewEntry->Dscp.DstIPPort.DstIPAddress;
    483             pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].Dscp.DstIPPort.DstPortNum = pNewEntry->Dscp.DstIPPort.DstPortNum;
    484             pClsfrParams->ClsfrTable[pClsfrParams->uNumActiveEntries].DTag = pNewEntry->DTag;
    485             context_LeaveCriticalSection (pTxDataQ->hContext);
    486 
    487         break;
    488 
    489         default:
    490 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): Classifier type -- unknown - Aborting\n");
    491 
    492     }
    493 
    494     /* Increment the number of classifier active entries */
    495     pClsfrParams->uNumActiveEntries++;
    496 
    497     return TI_OK;
    498 }
    499 
    500 
    501 /**
    502  * \fn     txDataClsfr_RemoveClsfrEntry
    503  * \brief  Remove an entry from classifier table
    504  *
    505  * Remove an entry from classifier table.
    506  *
    507  * \note
    508  * \param  hTxDataQ - The object handle
    509  * \param  pRemEntry    - Pointer to the entry to remove
    510  * \return TI_OK on success, PARAM_VALUE_NOT_VALID in case of input parameters problems.
    511  * \sa     txDataClsfr_InsertClsfrEntry
    512  */
    513 TI_STATUS txDataClsfr_RemoveClsfrEntry(TI_HANDLE hTxDataQ, TClsfrTableEntry *pRemEntry)
    514 {
    515     TTxDataQ      *pTxDataQ     = (TTxDataQ *)hTxDataQ;
    516     TClsfrParams  *pClsfrParams = &pTxDataQ->tClsfrParams;
    517     TI_UINT32     i, j;
    518 
    519 	if(pRemEntry == NULL)
    520     {
    521         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): NULL ConfigBuffer pointer Error - Aborting\n");
    522 		return PARAM_VALUE_NOT_VALID;
    523     }
    524 
    525     if (pClsfrParams->uNumActiveEntries == 0)
    526     {
    527         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Classifier table is empty - Aborting\n");
    528 		return PARAM_VALUE_NOT_VALID;
    529     }
    530 
    531     if (pClsfrParams->eClsfrType == D_TAG_CLSFR)
    532     {
    533         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): D-Tag classifier - Aborting\n");
    534         return PARAM_VALUE_NOT_VALID;
    535     }
    536 
    537     /* Check conflicts with classifier table entries */
    538     /* check all conflicts, if all entries are TI_OK --> insert to classifier table*/
    539 
    540     switch (pClsfrParams->eClsfrType)
    541     {
    542         case DSCP_CLSFR:
    543 
    544            /* Find the classifier entry */
    545            i = 0;
    546             while ((i < pClsfrParams->uNumActiveEntries) &&
    547                   ((pClsfrParams->ClsfrTable[i].Dscp.CodePoint != pRemEntry->Dscp.CodePoint) ||
    548                   (pClsfrParams->ClsfrTable[i].DTag != pRemEntry->DTag)))
    549             {
    550               i++;
    551             }
    552 
    553            /* If we have reached the number of active entries, it means we couldn't find the requested entry */
    554             if (i == pClsfrParams->uNumActiveEntries)
    555            {
    556                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Entry not found - Aborting\n");
    557                return PARAM_VALUE_NOT_VALID;
    558            }
    559 
    560             /* Shift all entries above the removed one downward */
    561             /* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
    562             context_EnterCriticalSection (pTxDataQ->hContext);
    563             for (j = i; j < pClsfrParams->uNumActiveEntries - 1; j++)
    564                 {
    565                    /* Move entries */
    566                 pClsfrParams->ClsfrTable[j].Dscp.CodePoint = pClsfrParams->ClsfrTable[j+1].Dscp.CodePoint;
    567                 pClsfrParams->ClsfrTable[j].DTag = pClsfrParams->ClsfrTable[j+1].DTag;
    568                 }
    569             context_LeaveCriticalSection (pTxDataQ->hContext);
    570 
    571         break;
    572 
    573         case PORT_CLSFR:
    574 
    575            /* Find the classifier entry */
    576            i = 0;
    577             while ((i < pClsfrParams->uNumActiveEntries) &&
    578                   ((pClsfrParams->ClsfrTable[i].Dscp.DstPortNum != pRemEntry->Dscp.DstPortNum) ||
    579                   (pClsfrParams->ClsfrTable[i].DTag != pRemEntry->DTag)))
    580             {
    581               i++;
    582             }
    583 
    584            /* If we have reached the number of active entries, it means we couldn't find the requested entry */
    585             if (i == pClsfrParams->uNumActiveEntries)
    586            {
    587                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Entry not found - Aborting\n");
    588                return PARAM_VALUE_NOT_VALID;
    589            }
    590 
    591             /* Shift all entries above the removed one downward */
    592             /* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
    593             context_EnterCriticalSection (pTxDataQ->hContext);
    594 			for (j = i; j < pClsfrParams->uNumActiveEntries - 1; j++)
    595                 {
    596                 pClsfrParams->ClsfrTable[j].Dscp.DstPortNum = pClsfrParams->ClsfrTable[j+1].Dscp.DstPortNum;
    597                 pClsfrParams->ClsfrTable[j].DTag = pClsfrParams->ClsfrTable[j+1].DTag;
    598             }
    599             context_LeaveCriticalSection (pTxDataQ->hContext);
    600 
    601         break;
    602 
    603         case IPPORT_CLSFR:
    604 
    605             /* Find the classifier entry */
    606             i = 0;
    607             while ((i < pClsfrParams->uNumActiveEntries) &&
    608                   ((pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress != pRemEntry->Dscp.DstIPPort.DstIPAddress) ||
    609                   (pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum != pRemEntry->Dscp.DstIPPort.DstPortNum) ||
    610                   (pClsfrParams->ClsfrTable[i].DTag != pRemEntry->DTag)))
    611             {
    612                 i++;
    613             }
    614 
    615             /* If we have reached the number of active entries, it means we couldn't find the requested entry */
    616             if (i == pClsfrParams->uNumActiveEntries)
    617             {
    618                 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Entry not found - Aborting\n");
    619                 return PARAM_VALUE_NOT_VALID;
    620             }
    621 
    622             /* Shift all entries above the removed one downward. */
    623             /* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
    624             context_EnterCriticalSection (pTxDataQ->hContext);
    625 			for (j = i; j < pClsfrParams->uNumActiveEntries - 1; j++)
    626             {
    627                 pClsfrParams->ClsfrTable[j].Dscp.DstIPPort.DstIPAddress = pClsfrParams->ClsfrTable[j+1].Dscp.DstIPPort.DstIPAddress;
    628                 pClsfrParams->ClsfrTable[j].Dscp.DstIPPort.DstPortNum = pClsfrParams->ClsfrTable[j+1].Dscp.DstIPPort.DstPortNum;
    629                 pClsfrParams->ClsfrTable[j].DTag = pClsfrParams->ClsfrTable[j+1].DTag;
    630             }
    631             context_LeaveCriticalSection (pTxDataQ->hContext);
    632 
    633         break;
    634 
    635         default:
    636 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "classifier_RemoveClsfrEntry(): Classifier type -- unknown - Aborting\n");
    637     }
    638 
    639     /* Decrement the number of classifier active entries */
    640     pClsfrParams->uNumActiveEntries--;
    641 
    642     return TI_OK;
    643 }
    644 
    645 
    646 /**
    647  * \fn     txDataClsfr_SetClsfrType & txDataClsfr_GetClsfrType
    648  * \brief  Set / Get classifier type
    649  *
    650  * Set / Get classifier type.
    651  * When setting type, the table is emptied!
    652  *
    653  * \note
    654  * \param  hTxDataQ  - The object handle
    655  * \param  eNewClsfrType - New type
    656  * \return TI_OK on success, PARAM_VALUE_NOT_VALID in case of input parameters problems.
    657  * \sa
    658  */
    659 TI_STATUS txDataClsfr_SetClsfrType (TI_HANDLE hTxDataQ, EClsfrType eNewClsfrType)
    660 {
    661     TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    662 
    663 	if (eNewClsfrType > CLSFR_TYPE_MAX)
    664 	{
    665 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_setClsfrType(): classifier type exceed its MAX \n");
    666 		return PARAM_VALUE_NOT_VALID;
    667     }
    668 
    669 	if (pTxDataQ->tClsfrParams.eClsfrType == eNewClsfrType)
    670 	{
    671 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING, "Classifier_setClsfrType(): equal classifier type --> will empty classifier table \n");
    672     }
    673 
    674 	/* Update type and empty table. */
    675     /* Note: Protect from txDataClsfr_ClassifyTxPacket context preemption. */
    676     context_EnterCriticalSection (pTxDataQ->hContext);
    677     pTxDataQ->tClsfrParams.eClsfrType = eNewClsfrType;
    678 	pTxDataQ->tClsfrParams.uNumActiveEntries = 0;
    679     context_LeaveCriticalSection (pTxDataQ->hContext);
    680 
    681     return TI_OK;
    682 }
    683 
    684 TI_STATUS txDataClsfr_GetClsfrType (TI_HANDLE hTxDataQ, EClsfrType *pClsfrType)
    685 {
    686     TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    687 
    688 	*pClsfrType = pTxDataQ->tClsfrParams.eClsfrType;
    689 	return TI_OK;
    690 }
    691 
    692 
    693 
    694 #ifdef TI_DBG
    695 
    696 /**
    697  * \fn     txDataClsfr_PrintClsfrTable
    698  * \brief  Print classifier table
    699  *
    700  * Print the classifier table for debug
    701  *
    702  * \note
    703  * \param  hTxDataQ  - The object handle
    704  * \return void
    705  * \sa
    706  */
    707 void txDataClsfr_PrintClsfrTable (TI_HANDLE hTxDataQ)
    708 {
    709     TTxDataQ      *pTxDataQ     = (TTxDataQ *)hTxDataQ;
    710     TClsfrParams  *pClsfrParams = &pTxDataQ->tClsfrParams;
    711 	TI_UINT32      uIpAddr, i;
    712 
    713 	if (pClsfrParams->eClsfrType == D_TAG_CLSFR)
    714 	{
    715 		WLAN_OS_REPORT (("D_TAG classifier type selected...Nothing to print...\n"));
    716 		return;
    717 	}
    718 
    719 	WLAN_OS_REPORT (("Number of active entries in classifier table : %d\n",pClsfrParams->uNumActiveEntries));
    720 
    721 	switch (pClsfrParams->eClsfrType)
    722 	{
    723 		case DSCP_CLSFR:
    724 			WLAN_OS_REPORT (("+------+-------+\n"));
    725 			WLAN_OS_REPORT (("| Code | D-Tag |\n"));
    726 			WLAN_OS_REPORT (("+------+-------+\n"));
    727 
    728 			for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    729             {
    730 				WLAN_OS_REPORT (("| %5d | %5d |\n",
    731                     pClsfrParams->ClsfrTable[i].Dscp.CodePoint,pClsfrParams->ClsfrTable[i].DTag));
    732 			}
    733 
    734 			WLAN_OS_REPORT (("+-------+-------+\n"));
    735 			break;
    736 
    737 		case PORT_CLSFR:
    738 			WLAN_OS_REPORT (("+-------+-------+\n"));
    739 			WLAN_OS_REPORT (("| Port  | D-Tag |\n"));
    740 			WLAN_OS_REPORT (("+-------+-------+\n"));
    741 
    742 			for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    743             {
    744 				WLAN_OS_REPORT (("| %5d | %5d |\n",
    745                     pClsfrParams->ClsfrTable[i].Dscp.DstPortNum,pClsfrParams->ClsfrTable[i].DTag));
    746 			}
    747 
    748 			WLAN_OS_REPORT (("+-------+-------+\n"));
    749 			break;
    750 
    751 		case IPPORT_CLSFR:
    752 
    753 			WLAN_OS_REPORT (("+-------------+-------+-------+\n"));
    754 			WLAN_OS_REPORT (("| IP Address  | Port  | D-Tag |\n"));
    755 			WLAN_OS_REPORT (("+-------------+-------+-------+\n"));
    756 
    757 			for (i = 0; i < pClsfrParams->uNumActiveEntries; i++)
    758             {
    759 				uIpAddr = pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstIPAddress;
    760 				WLAN_OS_REPORT (("| %02x.%02x.%02x.%02x | %5d | %5d |\n",
    761                     (uIpAddr & 0xFF),((uIpAddr >> 8) & (0xFF)),((uIpAddr >> 16) & (0xFF)),((uIpAddr >> 24) & (0xFF)),
    762                     pClsfrParams->ClsfrTable[i].Dscp.DstIPPort.DstPortNum, pClsfrParams->ClsfrTable[i].DTag));
    763 			}
    764 
    765 			WLAN_OS_REPORT (("+-------------+-------+-------+\n"));
    766 			break;
    767 
    768 		default:
    769 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "Classifier_InsertClsfrEntry(): Classifier type -- unknown - Aborting\n");
    770 			break;
    771 	}
    772 }
    773 
    774 #endif  /* TI_DBG */
    775 
    776 
    777 
    778