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