• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
txDataClsfr_Config(TI_HANDLE hTxDataQ,TClsfrParams * pClsfrInitParams)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  */
getIpAndUdpHeader(TTxDataQ * pTxDataQ,TTxCtrlBlk * pPktCtrlBlk,TI_UINT8 ** pIpHeader,TI_UINT8 ** pUdpHeader)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  */
txDataClsfr_ClassifyTxPacket(TI_HANDLE hTxDataQ,TTxCtrlBlk * pPktCtrlBlk,TI_UINT8 uPacketDtag)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  */
txDataClsfr_InsertClsfrEntry(TI_HANDLE hTxDataQ,TClsfrTableEntry * pNewEntry)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  */
txDataClsfr_RemoveClsfrEntry(TI_HANDLE hTxDataQ,TClsfrTableEntry * pRemEntry)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  */
txDataClsfr_SetClsfrType(TI_HANDLE hTxDataQ,EClsfrType eNewClsfrType)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 
txDataClsfr_GetClsfrType(TI_HANDLE hTxDataQ,EClsfrType * pClsfrType)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  */
txDataClsfr_PrintClsfrTable(TI_HANDLE hTxDataQ)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