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