From 605d2ad9a561593fa1187b72568fc9b353815a2f Mon Sep 17 00:00:00 2001 From: Mandy Lavi Date: Tue, 30 Jul 2013 14:26:03 +0300 Subject: fmd: support retrieval of more statistics counters - miss entry in a CC Node - miss entry in the hash table Signed-off-by: Mandy Lavi Change-Id: Iacbebff6f8f7ef1fa9c97b24d1072515f5098860 Reviewed-on: http://git.am.freescale.net:8181/3828 Reviewed-by: Lavi Mandy-R52568 Reviewed-by: Chereji Marian-Cornel-R27762 Reviewed-by: Schmitt Richard-B43082 Tested-by: Schmitt Richard-B43082 diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c index a68ff12..a8a52b2 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c @@ -1192,6 +1192,10 @@ static void DeleteNode(t_FmPcdCcNode *p_CcNode) p_CcNode->h_Spinlock = NULL; } + /* Restore the original counters pointer instead of the mutual pointer (mutual to all hash buckets) */ + if (p_CcNode->isHashBucket && (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE)) + p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].p_StatsObj->h_StatsCounters = p_CcNode->h_PrivMissStatsCounters; + /* Releasing all currently used statistics objects, including 'miss' entry */ for (i = 0; i < p_CcNode->numOfKeys + 1; i++) if (p_CcNode->keyAndNextEngineParams[i].p_StatsObj) @@ -1200,7 +1204,6 @@ static void DeleteNode(t_FmPcdCcNode *p_CcNode) if (!LIST_IsEmpty(&p_CcNode->availableStatsLst)) { t_Handle h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd); - ASSERT_COND(h_FmMuram); FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); @@ -1490,7 +1493,7 @@ t_Error ValidateNextEngineParams(t_Handle h_FmPcd, (p_FmPcdCcNextEngineParams->statisticsEn)) RETURN_ERROR(MAJOR, E_CONFLICT, ("Statistics are requested for a key, but statistics mode was set" - "to 'NONE' upon initialization of this match table")); + "to 'NONE' upon initialization")); switch (p_FmPcdCcNextEngineParams->nextEngine) { @@ -3397,13 +3400,18 @@ static t_Error ValidateAndCalcStatsParams(t_FmPcdCcNode *p_CcNode, uint32_t *p_NumOfRanges, uint32_t *p_CountersArraySize) { - e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode; + e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode; + uint32_t i; UNUSED(p_CcNodeParam); switch (statisticsMode) { case e_FM_PCD_CC_STATS_MODE_NONE: + for (i = 0; i < p_CcNode->numOfKeys; i++) + if (p_CcNodeParam->keysParams.keyParams[i].ccNextEngineParams.statisticsEn) + RETURN_ERROR(MAJOR, E_INVALID_VALUE, + ("Statistics cannot be enabled for key %d when statistics mode was set to 'NONE'", i)); return E_OK; case e_FM_PCD_CC_STATS_MODE_FRAME: @@ -3983,9 +3991,6 @@ static t_Error MatchTableGetKeyStatistics(t_FmPcdCcNode *p_CcNode, if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table")); - if (keyIndex >= p_CcNode->numOfKeys) - RETURN_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table")); - if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key")); @@ -5014,927 +5019,949 @@ void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node, ASSERT_COND(i != p_CurrentNode->numOfKeys); } #endif /* (DPAA_VERSION >= 11) */ -/*********************** End of inter-module routines ************************/ - -/****************************************/ -/* API Init unit functions */ -/****************************************/ - -t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, t_FmPcdCcTreeParams *p_PcdGroupsParam) +t_Error FmPcdCcMatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, t_FmPcdCcNodeParams *p_CcNodeParam) { - t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; - t_Error err = E_OK; - int i = 0, j = 0, k = 0; - t_FmPcdCcTree *p_FmPcdCcTree; - uint8_t numOfEntries; - t_Handle p_CcTreeTmp; - t_FmPcdCcGrpParams *p_FmPcdCcGroupParams; - t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams; - t_NetEnvParams netEnvParams; - uint8_t lastOne = 0; - uint32_t requiredAction = 0; - t_FmPcdCcNode *p_FmPcdCcNextNode; - t_CcNodeInformation ccNodeInfo, *p_CcInformation; + t_FmPcd *p_FmPcd = (t_FmPcd *) h_FmPcd; + t_FmPcdCcNode *p_FmPcdCcNextNode; + t_Error err = E_OK; + uint32_t tmp, keySize; + bool glblMask = FALSE; + t_FmPcdCcKeyParams *p_KeyParams; + t_Handle h_FmMuram, p_KeysMatchTblTmp, p_AdTableTmp; +#if (DPAA_VERSION >= 11) + t_Handle h_StatsFLRs; +#endif /* (DPAA_VERSION >= 11) */ + bool fullField = FALSE; + ccPrivateInfo_t icCode = CC_PRIVATE_INFO_NONE; + bool isKeyTblAlloc, fromIc = FALSE; + uint32_t matchTableSize, adTableSize; + t_CcNodeInformation ccNodeInfo, *p_CcInformation; + t_FmPcdStatsObj *p_StatsObj; + t_FmPcdCcStatsParams statsParams = {0}; + t_Handle h_Manip; - SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, NULL); - SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam,E_INVALID_HANDLE, NULL); + ASSERT_COND(h_FmPcd); + ASSERT_COND(p_CcNode); + ASSERT_COND(p_CcNodeParam); - if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS) - { - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); - return NULL; - } + p_CcNode->p_GlblMask = (t_Handle)XX_Malloc(CC_GLBL_MASK_SIZE * sizeof(uint8_t)); + memset(p_CcNode->p_GlblMask, 0, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); - p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree)); - if (!p_FmPcdCcTree) - { - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure")); - return NULL; - } - memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree)); - p_FmPcdCcTree->h_FmPcd = h_FmPcd; + p_CcNode->h_FmPcd = h_FmPcd; + p_CcNode->numOfKeys = p_CcNodeParam->keysParams.numOfKeys; + p_CcNode->maxNumOfKeys = p_CcNodeParam->keysParams.maxNumOfKeys; + p_CcNode->maskSupport = p_CcNodeParam->keysParams.maskSupport; + p_CcNode->statisticsMode = p_CcNodeParam->keysParams.statisticsMode; - p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc(FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); - memset(p_Params, 0, FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); + /* For backward compatibility - even if statistics mode is nullified, + we'll fix it to frame mode so we can support per-key request for + statistics using 'statisticsEn' in next engine parameters */ + if (!p_CcNode->maxNumOfKeys && + (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)) + p_CcNode->statisticsMode = e_FM_PCD_CC_STATS_MODE_FRAME; - INIT_LIST(&p_FmPcdCcTree->fmPortsLst); + h_FmMuram = FmPcdGetMuramHandle(h_FmPcd); + if (!h_FmMuram) + RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM")); -#ifdef FM_CAPWAP_SUPPORT - if ((p_PcdGroupsParam->numOfGrps == 1) && - (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) && - (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) && - p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode && - IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode)) + INIT_LIST(&p_CcNode->ccPrevNodesLst); + INIT_LIST(&p_CcNode->ccTreeIdLst); + INIT_LIST(&p_CcNode->ccTreesLst); + INIT_LIST(&p_CcNode->availableStatsLst); + + p_CcNode->h_Spinlock = XX_InitSpinlock(); + if (!p_CcNode->h_Spinlock) { - p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild(); - if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); - return NULL; - } + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock")); } -#endif /* FM_CAPWAP_SUPPORT */ - - numOfEntries = 0; - p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv); - for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++) + if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_BY_HDR) && + ((p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv4) || + (p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv6)) && + (p_CcNodeParam->extractCcParams.extractByHdr.type == e_FM_PCD_EXTRACT_FULL_FIELD) && + ((p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv6 == NET_HEADER_FIELD_IPv6_HOP_LIMIT) || + (p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv4 == NET_HEADER_FIELD_IPv4_TTL))) { - p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i]; - - if (p_FmPcdCcGroupParams->numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_CC_UNITS) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, - ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS)); - return NULL; - } - - p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries; - p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup =(uint8_t)( 0x01 << p_FmPcdCcGroupParams->numOfDistinctionUnits); - numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; - if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS) + err = Ipv4TtlOrIpv6HopLimitCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); + glblMask = FALSE; + } + else if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_NON_HDR) && + ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_KEY) || + (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_HASH) || + (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID))) + { + if ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID) && + (p_CcNodeParam->extractCcParams.extractNonHdr.offset != 0)) { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); - return NULL; + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_VALUE, + ("In the case of the extraction from e_FM_PCD_EXTRACT_FROM_FLOW_ID offset has to be 0")); } - if (lastOne) + icCode = IcDefineCode(p_CcNodeParam); + fromIc = TRUE; + if (icCode == CC_PRIVATE_INFO_NONE) { - if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order")); - return NULL; - } + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_STATE, + ("user asked extraction from IC and field in internal context or action wasn't initialized in the right way")); } - lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; - - netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId; - netEnvParams.numOfDistinctionUnits = p_FmPcdCcGroupParams->numOfDistinctionUnits; - - memcpy(netEnvParams.unitIds, - &p_FmPcdCcGroupParams->unitIds, - (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits); - - err = PcdGetUnitsVector(p_FmPcd, &netEnvParams); - if (err) + if ((icCode == CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP) || + (icCode == CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP)) { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; + err = IcHashIndexedCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); + glblMask = TRUE; } - - p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector; - for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; j++) + else { - err = ValidateNextEngineParams(h_FmPcd, - &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], - e_FM_PCD_CC_STATS_MODE_NONE); - if (err) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, err, (NO_MSG)); - return NULL; - } - - if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip) - { - err = FmPcdManipCheckParamsForCcNextEngine(&p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], &requiredAction); - if (err) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); - return NULL; - } - } - p_KeyAndNextEngineParams = p_Params+k; - - memcpy(&p_KeyAndNextEngineParams->nextEngineParams, - &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], - sizeof(t_FmPcdCcNextEngineParams)); - - if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine == e_FM_PCD_CC) - && p_KeyAndNextEngineParams->nextEngineParams.h_Manip) - { - err = AllocAndFillAdForContLookupManip(p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode); - if (err) - { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); - return NULL; - } - } - - requiredAction |= UPDATE_CC_WITH_TREE; - p_KeyAndNextEngineParams->requiredAction = requiredAction; - - k++; + err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); + if (p_CcNode->glblMaskSize) + glblMask = TRUE; } } - - p_FmPcdCcTree->numOfEntries = (uint8_t)k; - p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps; - - p_FmPcdCcTree->ccTreeBaseAddr = - PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd), - (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE), - FM_PCD_CC_TREE_ADDR_ALIGN)); - if (!p_FmPcdCcTree->ccTreeBaseAddr) + else { - DeleteTree(p_FmPcdCcTree,p_FmPcd); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); - return NULL; + err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); + if (p_CcNode->glblMaskSize) + glblMask = TRUE; } - IOMemSet32(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE)); - - p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); - j = 0; - for (i = 0; i < numOfEntries; i++) + if (err) { - p_KeyAndNextEngineParams = p_Params + i; + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, err, NO_MSG); + } - NextStepAd(p_CcTreeTmp, - NULL, - &p_KeyAndNextEngineParams->nextEngineParams, - p_FmPcd); + switch (p_CcNodeParam->extractCcParams.type) + { + case (e_FM_PCD_EXTRACT_BY_HDR): + switch (p_CcNodeParam->extractCcParams.extractByHdr.type) + { + case (e_FM_PCD_EXTRACT_FULL_FIELD): + p_CcNode->parseCode = + GetFullFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, + p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, + p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField); + GetSizeHeaderField(p_CcNodeParam->extractCcParams.extractByHdr.hdr, + p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, + p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField, + &p_CcNode->sizeOfExtraction); + fullField = TRUE; + if ((p_CcNode->parseCode != CC_PC_FF_TCI1) && + (p_CcNode->parseCode != CC_PC_FF_TCI2) && + (p_CcNode->parseCode != CC_PC_FF_MPLS1) && + (p_CcNode->parseCode != CC_PC_FF_MPLS1) && + (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1) && + (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2) && + (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1) && + (p_CcNode->parseCode != CC_PC_FF_IPDSCP) && + (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2) && + glblMask) + { + glblMask = FALSE; + p_CcNode->glblMaskSize = 4; + p_CcNode->lclMask = TRUE; + } + break; - p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); + case (e_FM_PCD_EXTRACT_FROM_HDR): + p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.size; + p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset; + p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset; + p_CcNode->parseCode = + GetPrParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, + p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, + p_CcNode->offset,glblMask, + &p_CcNode->prsArrayOffset); + break; - memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i], - p_KeyAndNextEngineParams, - sizeof(t_FmPcdCcKeyAndNextEngineParams)); + case (e_FM_PCD_EXTRACT_FROM_FIELD): + p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset; + p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset; + p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.size; + p_CcNode->parseCode = + GetFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, + p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.field, + p_CcNode->offset, + &p_CcNode->prsArrayOffset, + p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex); + break; - if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine== e_FM_PCD_CC) - { - p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; - p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccTreeIdLst, - (t_Handle)p_FmPcdCcTree, - p_FmPcdCcNextNode->h_Spinlock); + default: + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); + } + break; - if (!p_CcInformation) + case (e_FM_PCD_EXTRACT_NON_HDR): + /* get the field code for the generic extract */ + p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractNonHdr.size; + p_CcNode->offset = p_CcNodeParam->extractCcParams.extractNonHdr.offset; + p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractNonHdr.offset; + p_CcNode->parseCode = + GetGenParseCode(h_FmPcd, + p_CcNodeParam->extractCcParams.extractNonHdr.src, + p_CcNode->offset, + glblMask, + &p_CcNode->prsArrayOffset, + fromIc,icCode); + + if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED) { - memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); - ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree; - ccNodeInfo.index = 1; - EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst, - &ccNodeInfo, - p_FmPcdCcNextNode->h_Spinlock); + if ((p_CcNode->offset + p_CcNode->sizeOfExtraction) > 8) + { + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_SELECTION,("when node of the type CC_PC_GENERIC_IC_HASH_INDEXED offset + size can not be bigger then size of HASH 64 bits (8 bytes)")); + } } - else - p_CcInformation->index++; - } - } + if ((p_CcNode->parseCode == CC_PC_GENERIC_IC_GMASK) || + (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)) + { + p_CcNode->offset += p_CcNode->prsArrayOffset; + p_CcNode->prsArrayOffset = 0; + } + break; - FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId); - p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); + default: + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); + } - if (!FmPcdLockTryLockAll(p_FmPcd)) + if (p_CcNode->parseCode == CC_PC_ILLEGAL) { - FM_PCD_CcRootDelete(p_FmPcdCcTree); - XX_Free(p_Params); - DBG(TRACE, ("FmPcdLockTryLockAll failed")); - return NULL; + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type")); } - for (i = 0; i < numOfEntries; i++) + if ((p_CcNode->sizeOfExtraction > FM_PCD_MAX_SIZE_OF_KEY) || + !p_CcNode->sizeOfExtraction) { - if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction) - { - err = SetRequiredAction(h_FmPcd, - p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction, - &p_FmPcdCcTree->keyAndNextEngineParams[i], - p_CcTreeTmp, - 1, - p_FmPcdCcTree); - if (err) - { - FmPcdLockUnlockAll(p_FmPcd); - FM_PCD_CcRootDelete(p_FmPcdCcTree); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); - return NULL; - } - p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); - } + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("sizeOfExatrction can not be greater than 56 and not 0")); } - FmPcdLockUnlockAll(p_FmPcd); - p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd); - if (!p_FmPcdCcTree->p_Lock) + if (p_CcNodeParam->keysParams.keySize != p_CcNode->sizeOfExtraction) { - FM_PCD_CcRootDelete(p_FmPcdCcTree); - XX_Free(p_Params); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock")); - return NULL; + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); } - XX_Free(p_Params); - - return p_FmPcdCcTree; -} + p_CcNode->userSizeOfExtraction = p_CcNode->sizeOfExtraction; -t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree) -{ - t_FmPcd *p_FmPcd; - t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; - int i= 0; + if (!glblMask) + memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); - SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); - p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; - SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); + err = CheckAndSetManipParamsWithCcNodeParams(p_CcNode); + if (err != E_OK) + { + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); + } - FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId); + /* Calculating matching table entry size by rounding up the user-defined size of extraction to valid entry size */ + GetCcExtractKeySize(p_CcNode->sizeOfExtraction, &p_CcNode->ccKeySizeAccExtraction); - if (p_CcTree->owners) - RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree")); + /* If local mask is used, it is stored next to each key in the keys match table */ + if (p_CcNode->lclMask) + keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction); + else + keySize = p_CcNode->ccKeySizeAccExtraction; - /* Delete reassembly schemes if exist */ - if (p_CcTree->h_IpReassemblyManip) + /* Update CC shadow with maximal size required by this node */ + if (p_CcNode->maxNumOfKeys) { - FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip); - FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE); - } + err = CalcAndUpdateCcShadow(p_CcNode, + isKeyTblAlloc, + &matchTableSize, + &adTableSize); + if (err != E_OK) + { + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, err, NO_MSG); + } - for (i = 0; i numOfEntries; i++) - { - if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) - UpdateNodeOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE); + p_CcNode->keysMatchTableMaxSize = matchTableSize; - if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip) - FmPcdManipUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE); + if (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE) + { + err = AllocStatsObjs(p_CcNode); + if (err != E_OK) + { + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, err, NO_MSG); + } + } -#ifdef FM_CAPWAP_SUPPORT - if ((p_CcTree->numOfGrps == 1) && - (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) && - (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) && - p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode && - IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode)) + /* If manipulation will be initialized before this node, it will use the table + descriptor in the AD table of previous node and this node will need an extra + AD as his table descriptor. */ + p_CcNode->h_TmpAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, + FM_PCD_CC_AD_ENTRY_SIZE, + FM_PCD_CC_AD_TABLE_ALIGN); + if (!p_CcNode->h_TmpAd) { - if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK) - return E_INVALID_STATE; + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor")); } -#endif /* FM_CAPWAP_SUPPORT */ + } + else + { + matchTableSize = (uint32_t)(keySize * sizeof(uint8_t) * (p_CcNode->numOfKeys + 1)); + adTableSize = (uint32_t)(FM_PCD_CC_AD_ENTRY_SIZE * (p_CcNode->numOfKeys + 1)); + } #if (DPAA_VERSION >= 11) - if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) && - (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic)) - FrmReplicGroupUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic, - FALSE); -#endif /* (DPAA_VERSION >= 11) */ - } + switch (p_CcNode->statisticsMode) + { - if (p_CcTree->p_Lock) - FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock); + case e_FM_PCD_CC_STATS_MODE_RMON: + /* If RMON statistics or RMON conditional statistics modes are requested, + allocate frame length ranges array */ + p_CcNode->h_StatsFLRs = + FM_MURAM_AllocMem(h_FmMuram, + (uint32_t)(p_CcNode->numOfStatsFLRs) * FM_PCD_CC_STATS_FLR_SIZE, + FM_PCD_CC_AD_TABLE_ALIGN); - DeleteTree(p_CcTree, p_FmPcd); + if (!p_CcNode->h_StatsFLRs) + { + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC frame length ranges array")); + } - return E_OK; -} + /* Initialize using value received from the user */ + for (tmp = 0; tmp < p_CcNode->numOfStatsFLRs; tmp++) + { + h_StatsFLRs = PTR_MOVE(p_CcNode->h_StatsFLRs, tmp * FM_PCD_CC_STATS_FLR_SIZE); -t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree, - uint8_t grpId, - uint8_t index, - t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) -{ - t_FmPcd *p_FmPcd; - t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; - t_Error err = E_OK; + Mem2IOCpy32(h_StatsFLRs, + &(p_CcNodeParam->keysParams.frameLengthRanges[tmp]), + FM_PCD_CC_STATS_FLR_SIZE); + } + break; - SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); - SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); - p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; - SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); + default: + break; + } +#endif /* (DPAA_VERSION >= 11) */ - if (!FmPcdLockTryLockAll(p_FmPcd)) + + /* Allocate keys match table. Not required for some CC nodes, for example for IPv4 TTL + identification, IPv6 hop count identification, etc. */ + if (isKeyTblAlloc) { - DBG(TRACE, ("FmPcdLockTryLockAll failed")); - return ERROR_CODE(E_BUSY); + p_CcNode->h_KeysMatchTable = + (t_Handle)FM_MURAM_AllocMem(h_FmMuram, + matchTableSize, + FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN); + if (!p_CcNode->h_KeysMatchTable) + { + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table")); + } + IOMemSet32((uint8_t *)p_CcNode->h_KeysMatchTable, + 0, + matchTableSize); } - err = FmPcdCcModifyNextEngineParamTree(p_FmPcd, - p_CcTree, - grpId, - index, - p_FmPcdCcNextEngineParams); - FmPcdLockUnlockAll(p_FmPcd); - - if (err) + /* Allocate action descriptors table */ + p_CcNode->h_AdTable = + (t_Handle)FM_MURAM_AllocMem(h_FmMuram, + adTableSize, + FM_PCD_CC_AD_TABLE_ALIGN); + if (!p_CcNode->h_AdTable) { - RETURN_ERROR(MAJOR, err, NO_MSG); + DeleteNode(p_CcNode); + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table")); } + IOMemSet32((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize); - return E_OK; -} + p_KeysMatchTblTmp = p_CcNode->h_KeysMatchTable; + p_AdTableTmp = p_CcNode->h_AdTable; -t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam) -{ - t_FmPcd *p_FmPcd = (t_FmPcd *) h_FmPcd; - t_FmPcdCcNode *p_CcNode, *p_FmPcdCcNextNode; - t_Error err = E_OK; - uint32_t tmp, keySize; - bool glblMask = FALSE; - t_FmPcdCcKeyParams *p_KeyParams; - t_Handle h_FmMuram, p_KeysMatchTblTmp, p_AdTableTmp; -#if (DPAA_VERSION >= 11) - t_Handle h_StatsFLRs; -#endif /* (DPAA_VERSION >= 11) */ - bool fullField = FALSE; - ccPrivateInfo_t icCode = CC_PRIVATE_INFO_NONE; - bool isKeyTblAlloc, fromIc = FALSE; - uint32_t matchTableSize, adTableSize; - t_CcNodeInformation ccNodeInfo, *p_CcInformation; - t_FmPcdStatsObj *p_StatsObj; - t_FmPcdCcStatsParams statsParams = {0}; - t_Handle h_Manip; + /* For each key, create the key and the next step AD */ + for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) + { + p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; - SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL); + if (p_KeysMatchTblTmp) + { + /* Copy the key */ + Mem2IOCpy32((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key, p_CcNode->sizeOfExtraction); - p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode)); - if (!p_CcNode) - { - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); - return NULL; - } - memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); + /* Copy the key mask or initialize it to 0xFF..F */ + if (p_CcNode->lclMask && p_KeyParams->p_Mask) + { + Mem2IOCpy32(PTR_MOVE(p_KeysMatchTblTmp, + p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ + p_KeyParams->p_Mask, + p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ + } + else if (p_CcNode->lclMask) + { + IOMemSet32(PTR_MOVE(p_KeysMatchTblTmp, + p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ + 0xff, + p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ + } - p_CcNode->p_GlblMask = (t_Handle)XX_Malloc(CC_GLBL_MASK_SIZE * sizeof(uint8_t)); - memset(p_CcNode->p_GlblMask, 0, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); + p_KeysMatchTblTmp = PTR_MOVE(p_KeysMatchTblTmp, keySize * sizeof(uint8_t)); + } - p_CcNode->h_FmPcd = h_FmPcd; - p_CcNode->numOfKeys = p_CcNodeParam->keysParams.numOfKeys; - p_CcNode->maxNumOfKeys = p_CcNodeParam->keysParams.maxNumOfKeys; - p_CcNode->maskSupport = p_CcNodeParam->keysParams.maskSupport; - p_CcNode->statisticsMode = p_CcNodeParam->keysParams.statisticsMode; + /* Create the next action descriptor in the match table */ + if (p_KeyParams->ccNextEngineParams.statisticsEn) + { + p_StatsObj = GetStatsObj(p_CcNode); + ASSERT_COND(p_StatsObj); - /* For backward compatibility - even if statistics mode is nullified, - we'll fix it to frame mode so we can support per-key request for - statistics using 'statisticsEn' in next engine parameters */ - if (!p_CcNode->maxNumOfKeys && - (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)) - p_CcNode->statisticsMode = e_FM_PCD_CC_STATS_MODE_FRAME; + statsParams.h_StatsAd = p_StatsObj->h_StatsAd; + statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; +#if (DPAA_VERSION >= 11) + statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; - h_FmMuram = FmPcdGetMuramHandle(h_FmPcd); - if (!h_FmMuram) - { - REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM")); - return NULL; - } +#endif /* (DPAA_VERSION >= 11) */ + NextStepAd(p_AdTableTmp, + &statsParams, + &p_KeyParams->ccNextEngineParams, + p_FmPcd); - INIT_LIST(&p_CcNode->ccPrevNodesLst); - INIT_LIST(&p_CcNode->ccTreeIdLst); - INIT_LIST(&p_CcNode->ccTreesLst); - INIT_LIST(&p_CcNode->availableStatsLst); + p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj; + } + else + { + NextStepAd(p_AdTableTmp, + NULL, + &p_KeyParams->ccNextEngineParams, + p_FmPcd); - p_CcNode->h_Spinlock = XX_InitSpinlock(); - if (!p_CcNode->h_Spinlock) - { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock")); - return NULL; - } + p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL; + } - if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_BY_HDR) && - ((p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv4) || - (p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv6)) && - (p_CcNodeParam->extractCcParams.extractByHdr.type == e_FM_PCD_EXTRACT_FULL_FIELD) && - ((p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv6 == NET_HEADER_FIELD_IPv6_HOP_LIMIT) || - (p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv4 == NET_HEADER_FIELD_IPv4_TTL))) - { - err = Ipv4TtlOrIpv6HopLimitCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); - glblMask = FALSE; + p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); } - else if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_NON_HDR) && - ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_KEY) || - (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_HASH) || - (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID))) + + /* Update next engine for the 'miss' entry */ + if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.statisticsEn) { - if ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID) && - (p_CcNodeParam->extractCcParams.extractNonHdr.offset != 0)) - { - REPORT_ERROR(MAJOR, E_INVALID_VALUE, - ("In the case of the extraction from e_FM_PCD_EXTRACT_FROM_FLOW_ID offset has to be 0")); - return NULL; - } + p_StatsObj = GetStatsObj(p_CcNode); + ASSERT_COND(p_StatsObj); - icCode = IcDefineCode(p_CcNodeParam); - fromIc = TRUE; - if (icCode == CC_PRIVATE_INFO_NONE) + /* All 'bucket' nodes of a hash table should share the same statistics counters, + allocated by the hash table. So, if this node is a bucket of a hash table, + we'll replace the locally allocated counters with the shared counters. */ + if (p_CcNode->isHashBucket) { - REPORT_ERROR(MAJOR, E_INVALID_STATE, - ("user asked extraction from IC and field in internal context or action wasn't initialized in the right way")); - return NULL; - } + ASSERT_COND(p_CcNode->h_MissStatsCounters); - if ((icCode == CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP) || - (icCode == CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP)) - { - err = IcHashIndexedCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); - glblMask = TRUE; - } - else - { - err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); - if (p_CcNode->glblMaskSize) - glblMask = TRUE; + /* Store original counters pointer and replace it with mutual preallocated pointer */ + p_CcNode->h_PrivMissStatsCounters = p_StatsObj->h_StatsCounters; + p_StatsObj->h_StatsCounters = p_CcNode->h_MissStatsCounters; } + + statsParams.h_StatsAd = p_StatsObj->h_StatsAd; + statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; +#if (DPAA_VERSION >= 11) + statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; + +#endif /* (DPAA_VERSION >= 11) */ + + NextStepAd(p_AdTableTmp, + &statsParams, + &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, + p_FmPcd); + + p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj; } else { - err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); - if (p_CcNode->glblMaskSize) - glblMask = TRUE; - } + NextStepAd(p_AdTableTmp, + NULL, + &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, + p_FmPcd); - if (err) - { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; + p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL; } - switch (p_CcNodeParam->extractCcParams.type) + /* This parameter will be used to initialize the "key length" field in the action descriptor + that points to this node and it should be 0 for full field extraction */ + if (fullField == TRUE) + p_CcNode->sizeOfExtraction = 0; + + for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++) { - case (e_FM_PCD_EXTRACT_BY_HDR): - switch (p_CcNodeParam->extractCcParams.extractByHdr.type) + if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC) + { + p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode; + p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccPrevNodesLst, + (t_Handle)p_CcNode, + p_FmPcdCcNextNode->h_Spinlock); + if (!p_CcInformation) { - case (e_FM_PCD_EXTRACT_FULL_FIELD): - p_CcNode->parseCode = - GetFullFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, - p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, - p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField); - GetSizeHeaderField(p_CcNodeParam->extractCcParams.extractByHdr.hdr, - p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, - p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField, - &p_CcNode->sizeOfExtraction); - fullField = TRUE; - if ((p_CcNode->parseCode != CC_PC_FF_TCI1) && - (p_CcNode->parseCode != CC_PC_FF_TCI2) && - (p_CcNode->parseCode != CC_PC_FF_MPLS1) && - (p_CcNode->parseCode != CC_PC_FF_MPLS1) && - (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1) && - (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2) && - (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1) && - (p_CcNode->parseCode != CC_PC_FF_IPDSCP) && - (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2) && - glblMask) - { - glblMask = FALSE; - p_CcNode->glblMaskSize = 4; - p_CcNode->lclMask = TRUE; - } - break; - - case (e_FM_PCD_EXTRACT_FROM_HDR): - p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.size; - p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset; - p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset; - p_CcNode->parseCode = - GetPrParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, - p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, - p_CcNode->offset,glblMask, - &p_CcNode->prsArrayOffset); - break; - - case (e_FM_PCD_EXTRACT_FROM_FIELD): - p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset; - p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset; - p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.size; - p_CcNode->parseCode = - GetFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr, - p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.field, - p_CcNode->offset, - &p_CcNode->prsArrayOffset, - p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex); - break; - - default: - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); - return NULL; + memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); + ccNodeInfo.h_CcNode = (t_Handle)p_CcNode; + ccNodeInfo.index = 1; + EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccPrevNodesLst, + &ccNodeInfo, + p_FmPcdCcNextNode->h_Spinlock); } - break; - - case (e_FM_PCD_EXTRACT_NON_HDR): - /* get the field code for the generic extract */ - p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractNonHdr.size; - p_CcNode->offset = p_CcNodeParam->extractCcParams.extractNonHdr.offset; - p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractNonHdr.offset; - p_CcNode->parseCode = - GetGenParseCode(h_FmPcd, - p_CcNodeParam->extractCcParams.extractNonHdr.src, - p_CcNode->offset, - glblMask, - &p_CcNode->prsArrayOffset, - fromIc,icCode); + else + p_CcInformation->index++; - if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED) + if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) { - if ((p_CcNode->offset + p_CcNode->sizeOfExtraction) > 8) + h_Manip = p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip; + p_CcInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip), + (t_Handle)p_CcNode, + FmPcdManipGetSpinlock(h_Manip)); + if (!p_CcInformation) { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_SELECTION,("when node of the type CC_PC_GENERIC_IC_HASH_INDEXED offset + size can not be bigger then size of HASH 64 bits (8 bytes)")); - return NULL; + memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); + ccNodeInfo.h_CcNode = (t_Handle)p_CcNode; + ccNodeInfo.index = 1; + EnqueueNodeInfoToRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip), + &ccNodeInfo, + FmPcdManipGetSpinlock(h_Manip)); } + else + p_CcInformation->index++; } - if ((p_CcNode->parseCode == CC_PC_GENERIC_IC_GMASK) || - (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)) - { - p_CcNode->offset += p_CcNode->prsArrayOffset; - p_CcNode->prsArrayOffset = 0; - } - break; - - default: - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); - return NULL; + } } - if (p_CcNode->parseCode == CC_PC_ILLEGAL) - { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type")); - return NULL; - } + p_AdTableTmp = p_CcNode->h_AdTable; - if ((p_CcNode->sizeOfExtraction > FM_PCD_MAX_SIZE_OF_KEY) || - !p_CcNode->sizeOfExtraction) + if (!FmPcdLockTryLockAll(h_FmPcd)) { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("sizeOfExatrction can not be greater than 56 and not 0")); - return NULL; + FM_PCD_MatchTableDelete((t_Handle)p_CcNode); + DBG(TRACE, ("FmPcdLockTryLockAll failed")); + return ERROR_CODE(E_BUSY); } - if (p_CcNodeParam->keysParams.keySize != p_CcNode->sizeOfExtraction) + /* Required action for each next engine */ + for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++) { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); - return NULL; + if (p_CcNode->keyAndNextEngineParams[tmp].requiredAction) + { + err = SetRequiredAction(h_FmPcd, + p_CcNode->keyAndNextEngineParams[tmp].requiredAction, + &p_CcNode->keyAndNextEngineParams[tmp], + p_AdTableTmp, + 1, + NULL); + if (err) + { + FmPcdLockUnlockAll(h_FmPcd); + FM_PCD_MatchTableDelete((t_Handle)p_CcNode); + RETURN_ERROR(MAJOR, err, NO_MSG); + } + p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); + } } - p_CcNode->userSizeOfExtraction = p_CcNode->sizeOfExtraction; + FmPcdLockUnlockAll(h_FmPcd); - if (!glblMask) - memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); + return E_OK; +} +/*********************** End of inter-module routines ************************/ - err = CheckAndSetManipParamsWithCcNodeParams(p_CcNode); - if (err != E_OK) + +/****************************************/ +/* API Init unit functions */ +/****************************************/ + +t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, t_FmPcdCcTreeParams *p_PcdGroupsParam) +{ + t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; + t_Error err = E_OK; + int i = 0, j = 0, k = 0; + t_FmPcdCcTree *p_FmPcdCcTree; + uint8_t numOfEntries; + t_Handle p_CcTreeTmp; + t_FmPcdCcGrpParams *p_FmPcdCcGroupParams; + t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams; + t_NetEnvParams netEnvParams; + uint8_t lastOne = 0; + uint32_t requiredAction = 0; + t_FmPcdCcNode *p_FmPcdCcNextNode; + t_CcNodeInformation ccNodeInfo, *p_CcInformation; + + SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, NULL); + SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam,E_INVALID_HANDLE, NULL); + + if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS) { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction")); + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); return NULL; } - /* Calculating matching table entry size by rounding up the user-defined size of extraction to valid entry size */ - GetCcExtractKeySize(p_CcNode->sizeOfExtraction, &p_CcNode->ccKeySizeAccExtraction); - - /* If local mask is used, it is stored next to each key in the keys match table */ - if (p_CcNode->lclMask) - keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction); - else - keySize = p_CcNode->ccKeySizeAccExtraction; - - /* Update CC shadow with maximal size required by this node */ - if (p_CcNode->maxNumOfKeys) + p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree)); + if (!p_FmPcdCcTree) { - err = CalcAndUpdateCcShadow(p_CcNode, - isKeyTblAlloc, - &matchTableSize, - &adTableSize); - if (err != E_OK) - { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; - } + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure")); + return NULL; + } + memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree)); + p_FmPcdCcTree->h_FmPcd = h_FmPcd; - p_CcNode->keysMatchTableMaxSize = matchTableSize; + p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc(FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); + memset(p_Params, 0, FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams)); - if (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE) - { - err = AllocStatsObjs(p_CcNode); - if (err != E_OK) - { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, err, NO_MSG); - return NULL; - } - } + INIT_LIST(&p_FmPcdCcTree->fmPortsLst); - /* If manipulation will be initialized before this node, it will use the table - descriptor in the AD table of previous node and this node will need an extra - AD as his table descriptor. */ - p_CcNode->h_TmpAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, - FM_PCD_CC_AD_ENTRY_SIZE, - FM_PCD_CC_AD_TABLE_ALIGN); - if (!p_CcNode->h_TmpAd) +#ifdef FM_CAPWAP_SUPPORT + if ((p_PcdGroupsParam->numOfGrps == 1) && + (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) && + (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) && + p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode && + IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode)) + { + p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild(); + if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip) { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor")); + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); return NULL; } } - else - { - matchTableSize = (uint32_t)(keySize * sizeof(uint8_t) * (p_CcNode->numOfKeys + 1)); - adTableSize = (uint32_t)(FM_PCD_CC_AD_ENTRY_SIZE * (p_CcNode->numOfKeys + 1)); - } +#endif /* FM_CAPWAP_SUPPORT */ -#if (DPAA_VERSION >= 11) - switch (p_CcNode->statisticsMode) + numOfEntries = 0; + p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv); + + for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++) { + p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i]; - case e_FM_PCD_CC_STATS_MODE_RMON: - /* If RMON statistics or RMON conditional statistics modes are requested, - allocate frame length ranges array */ - p_CcNode->h_StatsFLRs = - FM_MURAM_AllocMem(h_FmMuram, - (uint32_t)(p_CcNode->numOfStatsFLRs) * FM_PCD_CC_STATS_FLR_SIZE, - FM_PCD_CC_AD_TABLE_ALIGN); + if (p_FmPcdCcGroupParams->numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_CC_UNITS) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS)); + return NULL; + } - if (!p_CcNode->h_StatsFLRs) + p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries; + p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup =(uint8_t)( 0x01 << p_FmPcdCcGroupParams->numOfDistinctionUnits); + numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; + if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); + return NULL; + } + + if (lastOne) + { + if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne) { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC frame length ranges array")); + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order")); return NULL; } + } - /* Initialize using value received from the user */ - for (tmp = 0; tmp < p_CcNode->numOfStatsFLRs; tmp++) - { - h_StatsFLRs = PTR_MOVE(p_CcNode->h_StatsFLRs, tmp * FM_PCD_CC_STATS_FLR_SIZE); - - Mem2IOCpy32(h_StatsFLRs, - &(p_CcNodeParam->keysParams.frameLengthRanges[tmp]), - FM_PCD_CC_STATS_FLR_SIZE); - } - break; + lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; - default: - break; - } -#endif /* (DPAA_VERSION >= 11) */ + netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId; + netEnvParams.numOfDistinctionUnits = p_FmPcdCcGroupParams->numOfDistinctionUnits; + memcpy(netEnvParams.unitIds, + &p_FmPcdCcGroupParams->unitIds, + (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits); - /* Allocate keys match table. Not required for some CC nodes, for example for IPv4 TTL - identification, IPv6 hop count identification, etc. */ - if (isKeyTblAlloc) - { - p_CcNode->h_KeysMatchTable = - (t_Handle)FM_MURAM_AllocMem(h_FmMuram, - matchTableSize, - FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN); - if (!p_CcNode->h_KeysMatchTable) + err = PcdGetUnitsVector(p_FmPcd, &netEnvParams); + if (err) { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table")); + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, err, NO_MSG); return NULL; } - IOMemSet32((uint8_t *)p_CcNode->h_KeysMatchTable, - 0, - matchTableSize); - } - - /* Allocate action descriptors table */ - p_CcNode->h_AdTable = - (t_Handle)FM_MURAM_AllocMem(h_FmMuram, - adTableSize, - FM_PCD_CC_AD_TABLE_ALIGN); - if (!p_CcNode->h_AdTable) - { - DeleteNode(p_CcNode); - REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table")); - return NULL; - } - IOMemSet32((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize); - - p_KeysMatchTblTmp = p_CcNode->h_KeysMatchTable; - p_AdTableTmp = p_CcNode->h_AdTable; - - /* For each key, create the key and the next step AD */ - for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) - { - p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; - if (p_KeysMatchTblTmp) + p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector; + for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; j++) { - /* Copy the key */ - Mem2IOCpy32((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key, p_CcNode->sizeOfExtraction); - - /* Copy the key mask or initialize it to 0xFF..F */ - if (p_CcNode->lclMask && p_KeyParams->p_Mask) + err = ValidateNextEngineParams(h_FmPcd, + &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], + e_FM_PCD_CC_STATS_MODE_NONE); + if (err) { - Mem2IOCpy32(PTR_MOVE(p_KeysMatchTblTmp, - p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ - p_KeyParams->p_Mask, - p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, err, (NO_MSG)); + return NULL; } - else if (p_CcNode->lclMask) + + if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip) { - IOMemSet32(PTR_MOVE(p_KeysMatchTblTmp, - p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ - 0xff, - p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ + err = FmPcdManipCheckParamsForCcNextEngine(&p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], &requiredAction); + if (err) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); + return NULL; + } } + p_KeyAndNextEngineParams = p_Params+k; - p_KeysMatchTblTmp = PTR_MOVE(p_KeysMatchTblTmp, keySize * sizeof(uint8_t)); - } - - /* Create the next action descriptor in the match table */ - if (p_KeyParams->ccNextEngineParams.statisticsEn) - { - p_StatsObj = GetStatsObj(p_CcNode); - ASSERT_COND(p_StatsObj); - - statsParams.h_StatsAd = p_StatsObj->h_StatsAd; - statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; -#if (DPAA_VERSION >= 11) - statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; + memcpy(&p_KeyAndNextEngineParams->nextEngineParams, + &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], + sizeof(t_FmPcdCcNextEngineParams)); -#endif /* (DPAA_VERSION >= 11) */ - NextStepAd(p_AdTableTmp, - &statsParams, - &p_KeyParams->ccNextEngineParams, - p_FmPcd); + if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine == e_FM_PCD_CC) + && p_KeyAndNextEngineParams->nextEngineParams.h_Manip) + { + err = AllocAndFillAdForContLookupManip(p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode); + if (err) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); + return NULL; + } + } - p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj; - } - else - { - NextStepAd(p_AdTableTmp, - NULL, - &p_KeyParams->ccNextEngineParams, - p_FmPcd); + requiredAction |= UPDATE_CC_WITH_TREE; + p_KeyAndNextEngineParams->requiredAction = requiredAction; - p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL; + k++; } - - p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); } - /* Update next engine for the 'miss' entry */ - if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.statisticsEn) - { - p_StatsObj = GetStatsObj(p_CcNode); - ASSERT_COND(p_StatsObj); - - statsParams.h_StatsAd = p_StatsObj->h_StatsAd; - statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; -#if (DPAA_VERSION >= 11) - statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; + p_FmPcdCcTree->numOfEntries = (uint8_t)k; + p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps; -#endif /* (DPAA_VERSION >= 11) */ + p_FmPcdCcTree->ccTreeBaseAddr = + PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd), + (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE), + FM_PCD_CC_TREE_ADDR_ALIGN)); + if (!p_FmPcdCcTree->ccTreeBaseAddr) + { + DeleteTree(p_FmPcdCcTree,p_FmPcd); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); + return NULL; + } + IOMemSet32(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE)); - NextStepAd(p_AdTableTmp, - &statsParams, - &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, - p_FmPcd); + p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); - p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj; - } - else + j = 0; + for (i = 0; i < numOfEntries; i++) { - NextStepAd(p_AdTableTmp, + p_KeyAndNextEngineParams = p_Params + i; + + NextStepAd(p_CcTreeTmp, NULL, - &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, + &p_KeyAndNextEngineParams->nextEngineParams, p_FmPcd); - p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL; - } + p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); - /* This parameter will be used to initialize the "key length" field in the action descriptor - that points to this node and it should be 0 for full field extraction */ - if (fullField == TRUE) - p_CcNode->sizeOfExtraction = 0; + memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i], + p_KeyAndNextEngineParams, + sizeof(t_FmPcdCcKeyAndNextEngineParams)); - for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++) - { - if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC) + if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine== e_FM_PCD_CC) { - p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode; - p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccPrevNodesLst, - (t_Handle)p_CcNode, + p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; + p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccTreeIdLst, + (t_Handle)p_FmPcdCcTree, p_FmPcdCcNextNode->h_Spinlock); + if (!p_CcInformation) { memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); - ccNodeInfo.h_CcNode = (t_Handle)p_CcNode; + ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree; ccNodeInfo.index = 1; - EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccPrevNodesLst, + EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst, &ccNodeInfo, p_FmPcdCcNextNode->h_Spinlock); } else p_CcInformation->index++; - - if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) - { - h_Manip = p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip; - p_CcInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip), - (t_Handle)p_CcNode, - FmPcdManipGetSpinlock(h_Manip)); - if (!p_CcInformation) - { - memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); - ccNodeInfo.h_CcNode = (t_Handle)p_CcNode; - ccNodeInfo.index = 1; - EnqueueNodeInfoToRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip), - &ccNodeInfo, - FmPcdManipGetSpinlock(h_Manip)); - } - else - p_CcInformation->index++; - } } } - p_AdTableTmp = p_CcNode->h_AdTable; + FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId); + p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); - if (!FmPcdLockTryLockAll(h_FmPcd)) + if (!FmPcdLockTryLockAll(p_FmPcd)) { - FM_PCD_MatchTableDelete((t_Handle)p_CcNode); - DBG(TRACE, ("FmPcdLockTryLockAll failed")); - return NULL; + FM_PCD_CcRootDelete(p_FmPcdCcTree); + XX_Free(p_Params); + DBG(TRACE, ("FmPcdLockTryLockAll failed")); + return NULL; } - /* Required action for each next engine */ - for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++) + for (i = 0; i < numOfEntries; i++) { - if (p_CcNode->keyAndNextEngineParams[tmp].requiredAction) + if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction) { err = SetRequiredAction(h_FmPcd, - p_CcNode->keyAndNextEngineParams[tmp].requiredAction, - &p_CcNode->keyAndNextEngineParams[tmp], - p_AdTableTmp, + p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction, + &p_FmPcdCcTree->keyAndNextEngineParams[i], + p_CcTreeTmp, 1, - NULL); + p_FmPcdCcTree); if (err) { - FmPcdLockUnlockAll(h_FmPcd); - FM_PCD_MatchTableDelete((t_Handle)p_CcNode); - REPORT_ERROR(MAJOR, err, NO_MSG); + FmPcdLockUnlockAll(p_FmPcd); + FM_PCD_CcRootDelete(p_FmPcdCcTree); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); return NULL; } - p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); + p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); } } - FmPcdLockUnlockAll(h_FmPcd); + FmPcdLockUnlockAll(p_FmPcd); + p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd); + if (!p_FmPcdCcTree->p_Lock) + { + FM_PCD_CcRootDelete(p_FmPcdCcTree); + XX_Free(p_Params); + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock")); + return NULL; + } + + XX_Free(p_Params); + + return p_FmPcdCcTree; +} + +t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree) +{ + t_FmPcd *p_FmPcd; + t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; + int i= 0; + + SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); + p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; + SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); + + FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId); + + if (p_CcTree->owners) + RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree")); + + /* Delete reassembly schemes if exist */ + if (p_CcTree->h_IpReassemblyManip) + { + FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip); + FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE); + } + + for (i = 0; i numOfEntries; i++) + { + if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) + UpdateNodeOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE); + + if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip) + FmPcdManipUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE); + +#ifdef FM_CAPWAP_SUPPORT + if ((p_CcTree->numOfGrps == 1) && + (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) && + (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) && + p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode && + IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode)) + { + if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK) + return E_INVALID_STATE; + } +#endif /* FM_CAPWAP_SUPPORT */ + +#if (DPAA_VERSION >= 11) + if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) && + (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic)) + FrmReplicGroupUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic, + FALSE); +#endif /* (DPAA_VERSION >= 11) */ + } + + if (p_CcTree->p_Lock) + FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock); + + DeleteTree(p_CcTree, p_FmPcd); + + return E_OK; +} + +t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree, + uint8_t grpId, + uint8_t index, + t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) +{ + t_FmPcd *p_FmPcd; + t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; + t_Error err = E_OK; + + SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); + SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE); + p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; + SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); + + if (!FmPcdLockTryLockAll(p_FmPcd)) + { + DBG(TRACE, ("FmPcdLockTryLockAll failed")); + return ERROR_CODE(E_BUSY); + } + + err = FmPcdCcModifyNextEngineParamTree(p_FmPcd, + p_CcTree, + grpId, + index, + p_FmPcdCcNextEngineParams); + FmPcdLockUnlockAll(p_FmPcd); + + if (err) + { + RETURN_ERROR(MAJOR, err, NO_MSG); + } + + return E_OK; +} + +t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam) +{ + t_FmPcdCcNode *p_CcNode; + t_Error err; + + SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); + SANITY_CHECK_RETURN_VALUE(p_CcNodeParam, E_NULL_POINTER, NULL); + + p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode)); + if (!p_CcNode) + { + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); + return NULL; + } + memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); + + err = FmPcdCcMatchTableSet(h_FmPcd, p_CcNode, p_CcNodeParam); + + switch (GET_ERROR_TYPE(err)) + { + case E_OK: + break; + + case E_BUSY: + DBG(TRACE, ("E_BUSY error")); + return NULL; + + default: + REPORT_ERROR(MAJOR, err, NO_MSG); + return NULL; + } return p_CcNode; } @@ -6536,6 +6563,9 @@ t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); + if (keyIndex >= p_CcNode->numOfKeys) + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table")); + err = MatchTableGetKeyStatistics(p_CcNode, keyIndex, p_KeyStatistics); @@ -6548,6 +6578,30 @@ t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, return E_OK; } +t_Error FM_PCD_MatchTableGetMissStatistics(t_Handle h_CcNode, + t_FmPcdCcKeyStatistics *p_MissStatistics) +{ + t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; + uint32_t intFlags; + t_Error err; + + SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE); + SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER); + + intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); + + err = MatchTableGetKeyStatistics(p_CcNode, + p_CcNode->numOfKeys, + p_MissStatistics); + + XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); + + if (err != E_OK) + RETURN_ERROR(MAJOR, err, NO_MSG); + + return E_OK; +} + t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, @@ -6572,6 +6626,8 @@ t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode "match table of the provided node")); } + ASSERT_COND(keyIndex < p_CcNode->numOfKeys); + err = MatchTableGetKeyStatistics(p_CcNode, keyIndex, p_KeyStatistics); @@ -6624,10 +6680,13 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) { t_FmPcdCcNode *p_CcNodeHashTbl; t_FmPcdCcNodeParams *p_IndxHashCcNodeParam, *p_ExactMatchCcNodeParam; - t_Handle h_CcNode; + t_FmPcdCcNode *p_CcNode; + t_Handle h_MissStatsCounters = NULL; t_FmPcdCcKeyParams *p_HashKeyParams; int i; uint16_t numOfSets, numOfWays, countMask, onesCount = 0; + bool statsEnForMiss = FALSE; + t_Error err; SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); SANITY_CHECK_RETURN_VALUE(p_Param, E_NULL_POINTER, NULL); @@ -6684,6 +6743,28 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) if (p_Param->maxNumOfKeys % numOfSets) DBG(INFO, ("'maxNumOfKeys' is not a multiple of hash number of ways, so number of ways will be rounded up")); + if ((p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_FRAME) || + (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME)) + { + /* Allocating a statistics counters table that will be used by all + 'miss' entries of the hash table */ + h_MissStatsCounters = (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd), + 2 * FM_PCD_CC_STATS_COUNTER_SIZE, + FM_PCD_CC_AD_TABLE_ALIGN); + if (!h_MissStatsCounters) + { + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics table for hash miss")); + return NULL; + } + memset(h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); + + /* Always enable statistics for 'miss', so that a statistics AD will be + initialized from the start. We'll store the requested 'statistics enable' + value and it will be used when statistics are read by the user. */ + statsEnForMiss = p_Param->ccNextEngineParamsForMiss.statisticsEn; + p_Param->ccNextEngineParamsForMiss.statisticsEn = TRUE; + } + /* Building exact-match node params, will be used to create the hash buckets */ p_ExactMatchCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR; @@ -6703,13 +6784,23 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) for (i = 0; i < numOfSets; i++) { - h_CcNode = FM_PCD_MatchTableSet(h_FmPcd, p_ExactMatchCcNodeParam); - if (!h_CcNode) + /* Each exact-match node will be marked as a 'bucket' and provided with a pointer to statistics counters, + to be used for 'miss' entry statistics */ + p_CcNode = (t_FmPcdCcNode *)XX_Malloc(sizeof(t_FmPcdCcNode)); + if (!p_CcNode) + break; + memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); + + p_CcNode->isHashBucket = TRUE; + p_CcNode->h_MissStatsCounters = h_MissStatsCounters; + + err = FmPcdCcMatchTableSet(h_FmPcd, p_CcNode, p_ExactMatchCcNodeParam); + if (err) break; p_HashKeyParams[i].ccNextEngineParams.nextEngine = e_FM_PCD_CC; p_HashKeyParams[i].ccNextEngineParams.statisticsEn = FALSE; - p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode = h_CcNode; + p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode = p_CcNode; } if (i < numOfSets) @@ -6717,6 +6808,8 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) for (i = i-1; i >=0; i--) FM_PCD_MatchTableDelete(p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode); + FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters); + REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG); XX_Free(p_IndxHashCcNodeParam); XX_Free(p_ExactMatchCcNodeParam); @@ -6738,10 +6831,17 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) p_IndxHashCcNodeParam->keysParams.keySize = 2; p_CcNodeHashTbl = FM_PCD_MatchTableSet(h_FmPcd, p_IndxHashCcNodeParam); - + if (p_CcNodeHashTbl) p_CcNodeHashTbl->kgHashShift = p_Param->kgHashShift; - + + /* Storing the allocated counters for buckets 'miss' in the hash table + and is statistics for miss wre enabled. */ + p_CcNodeHashTbl->h_MissStatsCounters = h_MissStatsCounters; + p_CcNodeHashTbl->statsEnForMiss = statsEnForMiss; + + XX_Print("Hash 0x%x: 0x%x\n", p_CcNodeHashTbl, h_MissStatsCounters); + XX_Free(p_IndxHashCcNodeParam); XX_Free(p_ExactMatchCcNodeParam); @@ -6751,12 +6851,14 @@ t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl) { t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; - t_Handle *p_HashBuckets; + t_Handle h_FmPcd; + t_Handle *p_HashBuckets, h_MissStatsCounters; uint16_t i, numOfBuckets; t_Error err; SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); + /* Store all hash buckets before the hash is freed */ numOfBuckets = p_HashTbl->numOfKeys; p_HashBuckets = (t_Handle *)XX_Malloc(numOfBuckets * sizeof(t_Handle)); @@ -6766,14 +6868,23 @@ t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl) for (i = 0; i < numOfBuckets; i++) p_HashBuckets[i] = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; + h_FmPcd = p_HashTbl->h_FmPcd; + h_MissStatsCounters = p_HashTbl->h_MissStatsCounters; + + /* Free the hash */ err = FM_PCD_MatchTableDelete(p_HashTbl); + /* Free each hash bucket */ for (i = 0; i < numOfBuckets; i++) err |= FM_PCD_MatchTableDelete(p_HashBuckets[i]); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); + /* Free statistics counters for 'miss', id these were allocated */ + if (h_MissStatsCounters) + FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters); + XX_Free(p_HashBuckets); return E_OK; @@ -6879,11 +6990,29 @@ t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; t_Handle h_HashBucket; uint8_t i; + bool nullifyMissStats = FALSE; t_Error err; SANITY_CHECK_RETURN_ERROR(h_HashTbl, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); + if ((!p_HashTbl->h_MissStatsCounters) && (p_FmPcdCcNextEngineParams->statisticsEn)) + RETURN_ERROR(MAJOR, E_CONFLICT, + ("Statistics are requested for a key, but statistics mode was set" + "to 'NONE' upon initialization")); + + if (p_HashTbl->h_MissStatsCounters) + { + if ((!p_HashTbl->statsEnForMiss) && (p_FmPcdCcNextEngineParams->statisticsEn)) + nullifyMissStats = TRUE; + + if ((p_HashTbl->statsEnForMiss) && (!p_FmPcdCcNextEngineParams->statisticsEn)) + { + p_HashTbl->statsEnForMiss = FALSE; + p_FmPcdCcNextEngineParams->statisticsEn = TRUE; + } + } + for (i = 0; i < p_HashTbl->numOfKeys; i++) { h_HashBucket = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; @@ -6894,6 +7023,13 @@ t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl RETURN_ERROR(MAJOR, err, NO_MSG); } + if (nullifyMissStats) + { + memset(p_HashTbl->h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); + memset(p_HashTbl->h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); + p_HashTbl->statsEnForMiss = TRUE; + } + return E_OK; } @@ -6947,3 +7083,21 @@ t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl NULL, p_KeyStatistics); } + +t_Error FM_PCD_HashTableGetMissStatistics(t_Handle h_HashTbl, + t_FmPcdCcKeyStatistics *p_MissStatistics) +{ + t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; + t_Handle h_HashBucket; + + SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); + SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER); + + if (!p_HashTbl->statsEnForMiss) + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for miss")); + + h_HashBucket = p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode; + + return FM_PCD_MatchTableGetMissStatistics(h_HashBucket, + p_MissStatistics); +} diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h index eeb43a2..997eb5d 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h @@ -310,6 +310,17 @@ typedef struct uint32_t numOfStatsFLRs; uint32_t countersArraySize; + bool isHashBucket; /**< Valid for match table node that is a bucket of a hash table only */ + t_Handle h_MissStatsCounters; /**< Valid for hash table node and match table that is a bucket; + Holds the statistics counters allocated by the hash table and + are shared by all hash table buckets; */ + t_Handle h_PrivMissStatsCounters; /**< Valid for match table node that is a bucket of a hash table only; + Holds the statistics counters that were allocated for this node + and replaced by the shared counters (allocated by the hash table); */ + bool statsEnForMiss; /**< Valid for hash table node only; TRUE is statistics are currently + enabled for hash 'miss', FALSE otherwise; This parameter effects the + returned statistics count to user, statistics AD always present for 'miss' + for all hash buckets; */ bool glblMaskUpdated; t_Handle p_GlblMask; bool lclMask; diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h index 60edfd2..d9bea95 100644 --- a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h +++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h @@ -1068,7 +1068,9 @@ typedef enum e_FmPcdPlcrRateMode { *//***************************************************************************/ typedef enum e_FmPcdDoneAction { e_FM_PCD_ENQ_FRAME = 0, /**< Enqueue frame */ - e_FM_PCD_DROP_FRAME /**< Drop frame */ + e_FM_PCD_DROP_FRAME /**< Mark this frame as error frame and continue + to error flow; 'FM_PORT_FRM_ERR_CLS_DISCARD' + flag will be set for this frame. */ } e_FmPcdDoneAction; /**************************************************************************//** @@ -2080,8 +2082,7 @@ typedef struct t_FmPcdPlcrProfileParams { /**************************************************************************//** @Description Parameters for selecting a location for requested manipulation *//***************************************************************************/ -typedef struct t_FmManipHdrInfo -{ +typedef struct t_FmManipHdrInfo { e_NetHeaderType hdr; /**< Header selection */ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled IP. Otherwise should be cleared. */ bool byField; /**< TRUE if the location of manipulation is according to some field in the specific header*/ @@ -2575,7 +2576,7 @@ typedef struct t_FmPcdManipParams { *//***************************************************************************/ typedef struct t_FmPcdManipReassemIpStats { /* common counters for both IPv4 and IPv6 */ - uint32_t timeout; /**< Counts the number of TimeOut occurrences */ + uint32_t timeout; /**< Counts the number of timeout occurrences */ uint32_t rfdPoolBusy; /**< Counts the number of failed attempts to allocate a Reassembly Frame Descriptor */ uint32_t internalBufferBusy; /**< Counts the number of times an internal buffer busy occurred */ @@ -2942,7 +2943,8 @@ t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode); @Return E_OK on success; Error code otherwise. - @Cautions Allowed only following FM_PCD_MatchTableSet(). + @Cautions Allowed only following FM_PCD_MatchTableSet(); + Not relevant in the case the node is of type 'INDEXED_LOOKUP'. *//***************************************************************************/ t_Error FM_PCD_MatchTableModifyMissNextEngine(t_Handle h_CcNode, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); @@ -3195,6 +3197,29 @@ t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, t_FmPcdCcKeyStatistics *p_KeyStatistics); /**************************************************************************//** + @Function FM_PCD_MatchTableGetMissStatistics + + @Description This routine may be used to get statistics counters of miss entry + in a CC Node. + + If 'e_FM_PCD_CC_STATS_MODE_FRAME' and + 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, + these counters reflect how many frames were not matched to any + existing key and therefore passed through the miss entry; The + total frames count will be returned in the counter of the + first range (as only one frame length range was defined). + + @Param[in] h_CcNode A handle to the node + @Param[out] p_MissStatistics Statistics counters for 'miss' + + @Return The statistics for 'miss'. + + @Cautions Allowed only following FM_PCD_MatchTableSet(). +*//***************************************************************************/ +t_Error FM_PCD_MatchTableGetMissStatistics(t_Handle h_CcNode, + t_FmPcdCcKeyStatistics *p_MissStatistics); + +/**************************************************************************//** @Function FM_PCD_MatchTableFindNGetKeyStatistics @Description This routine may be used to get statistics counters of specific key @@ -3446,6 +3471,27 @@ t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl t_FmPcdCcKeyStatistics *p_KeyStatistics); /**************************************************************************//** + @Function FM_PCD_HashTableGetMissStatistics + + @Description This routine may be used to get statistics counters of 'miss' + entry of the a hash table. + + If 'e_FM_PCD_CC_STATS_MODE_FRAME' and + 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, + these counters reflect how many frames were not matched to any + existing key and therefore passed through the miss entry; + + @Param[in] h_HashTbl A handle to a hash table + @Param[out] p_MissStatistics Statistics counters for 'miss' + + @Return The statistics for 'miss'. + + @Cautions Allowed only following FM_PCD_HashTableSet(). +*//***************************************************************************/ +t_Error FM_PCD_HashTableGetMissStatistics(t_Handle h_HashTbl, + t_FmPcdCcKeyStatistics *p_MissStatistics); + +/**************************************************************************//** @Function FM_PCD_ManipNodeSet @Description This routine should be called for defining a manipulation diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h index 4c60893..13c61d2 100644 --- a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h +++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h @@ -88,6 +88,8 @@ EXPORT_SYMBOL(FM_PCD_MatchTableGetNextEngine); EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyCounter); EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyStatistics); EXPORT_SYMBOL(FM_PCD_MatchTableFindNGetKeyStatistics); +EXPORT_SYMBOL(FM_PCD_MatchTableGetMissStatistics); +EXPORT_SYMBOL(FM_PCD_HashTableGetMissStatistics); EXPORT_SYMBOL(FM_PCD_HashTableSet); EXPORT_SYMBOL(FM_PCD_HashTableDelete); EXPORT_SYMBOL(FM_PCD_HashTableAddKey); -- cgit v0.10.2