/* * Copyright 2008-2012 Freescale Semiconductor Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Freescale Semiconductor nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any * later version. * * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /****************************************************************************** @File fm_manip.c @Description FM PCD manip ... *//***************************************************************************/ #include "std_ext.h" #include "error_ext.h" #include "string_ext.h" #include "debug_ext.h" #include "fm_pcd_ext.h" #include "fm_port_ext.h" #include "fm_muram_ext.h" #include "memcpy_ext.h" #include "fm_common.h" #include "fm_hc.h" #include "fm_manip.h" /****************************************/ /* static functions */ /****************************************/ static t_Handle GetManipInfo(t_FmPcdManip *p_Manip, e_ManipInfo manipInfo) { t_FmPcdManip *p_CurManip = p_Manip; if (!MANIP_IS_UNIFIED(p_Manip)) p_CurManip = p_Manip; else { /* go to first unified */ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) p_CurManip = p_CurManip->h_PrevManip; } switch (manipInfo) { case (e_MANIP_HMCT): return p_CurManip->p_Hmct; case (e_MANIP_HMTD): return p_CurManip->h_Ad; case (e_MANIP_HANDLER_TABLE_OWNER): return (t_Handle)p_CurManip; default: return NULL; } } static uint16_t GetHmctSize(t_FmPcdManip *p_Manip) { uint16_t size = 0; t_FmPcdManip *p_CurManip = p_Manip; if (!MANIP_IS_UNIFIED(p_Manip)) return p_Manip->tableSize; /* accumulate sizes, starting with the first node */ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) p_CurManip = p_CurManip->h_PrevManip; while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) { size += p_CurManip->tableSize; p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip; } size += p_CurManip->tableSize; /* add last size */ return (size); } static uint16_t GetDataSize(t_FmPcdManip *p_Manip) { uint16_t size = 0; t_FmPcdManip *p_CurManip = p_Manip; if (!MANIP_IS_UNIFIED(p_Manip)) return p_Manip->dataSize; /* accumulate sizes, starting with the first node */ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) p_CurManip = p_CurManip->h_PrevManip; while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) { size += p_CurManip->dataSize; p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip; } size += p_CurManip->dataSize; /* add last size */ return (size); } static t_Error CalculateTableSize(t_FmPcdManipParams *p_FmPcdManipParams, uint16_t *p_TableSize, uint8_t *p_DataSize) { uint8_t localDataSize, remain, tableSize = 0, dataSize = 0; if (p_FmPcdManipParams->u.hdr.rmv) { switch (p_FmPcdManipParams->u.hdr.rmvParams.type) { case (e_FM_PCD_MANIP_RMV_GENERIC): tableSize += HMCD_BASIC_SIZE; break; case (e_FM_PCD_MANIP_RMV_BY_HDR): switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.type) { case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2): #if (DPAA_VERSION >= 11) case (e_FM_PCD_MANIP_RMV_BY_HDR_CAPWAP): case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START): #endif /* (DPAA_VERSION >= 11) */ tableSize += HMCD_BASIC_SIZE; break; default: RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown byHdr.type")); } break; default: RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown rmvParams.type")); } } if (p_FmPcdManipParams->u.hdr.insrt) { switch (p_FmPcdManipParams->u.hdr.insrtParams.type) { case (e_FM_PCD_MANIP_INSRT_GENERIC): remain = (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size % 4); if (remain) localDataSize = (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size + 4 - remain); else localDataSize = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size; tableSize += (uint8_t)(HMCD_BASIC_SIZE + localDataSize); break; case (e_FM_PCD_MANIP_INSRT_BY_HDR): { switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type) { case (e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2): tableSize += HMCD_BASIC_SIZE + HMCD_PTR_SIZE; switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2) { case (e_FM_PCD_MANIP_HDR_INSRT_MPLS): dataSize += p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size; break; default: RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); } break; #if (DPAA_VERSION >= 11) case (e_FM_PCD_MANIP_INSRT_BY_HDR_IP): tableSize += (HMCD_BASIC_SIZE + HMCD_PTR_SIZE + HMCD_PARAM_SIZE + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size); dataSize += 2; break; case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP): case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE): tableSize += (HMCD_BASIC_SIZE + HMCD_L4_HDR_SIZE); break; case (e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP): tableSize += (HMCD_BASIC_SIZE + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size); break; #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown byHdr.type")); } } break; default: RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown insrtParams.type")); } } if (p_FmPcdManipParams->u.hdr.fieldUpdate) { switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type) { case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN): tableSize += HMCD_BASIC_SIZE; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) { tableSize += HMCD_PTR_SIZE; dataSize += DSCP_TO_VLAN_TABLE_SIZE; } break; case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4): tableSize += HMCD_BASIC_SIZE; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID) { tableSize += HMCD_PARAM_SIZE; dataSize += 2; } if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC) tableSize += HMCD_IPV4_ADDR_SIZE; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST) tableSize += HMCD_IPV4_ADDR_SIZE; break; case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6): tableSize += HMCD_BASIC_SIZE; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV6_SRC) tableSize += HMCD_IPV6_ADDR_SIZE; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV6_DST) tableSize += HMCD_IPV6_ADDR_SIZE; break; case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP): if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates == HDR_MANIP_TCP_UDP_CHECKSUM) /* we implement this case with the update-checksum descriptor */ tableSize += HMCD_BASIC_SIZE; else /* we implement this case with the TCP/UDP-update descriptor */ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE; break; default: RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown fieldUpdateParams.type")); } } if (p_FmPcdManipParams->u.hdr.custom) { switch (p_FmPcdManipParams->u.hdr.customParams.type) { case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE): { tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE + HMCD_PARAM_SIZE; dataSize += p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize; if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) && (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id)) dataSize += 2; } break; case (e_FM_PCD_MANIP_HDR_CUSTOM_GEN_FIELD_REPLACE): tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE; break; default: RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown customParams.type")); } } *p_TableSize = tableSize; *p_DataSize = dataSize; return E_OK; } static t_Error GetPrOffsetByHeaderOrField(t_FmManipHdrInfo *p_HdrInfo, uint8_t *parseArrayOffset) { e_NetHeaderType hdr = p_HdrInfo->hdr; e_FmPcdHdrIndex hdrIndex = p_HdrInfo->hdrIndex; bool byField = p_HdrInfo->byField; t_FmPcdFields field; if (byField) field = p_HdrInfo->fullField; if (byField) { switch (hdr) { case (HEADER_TYPE_ETH): switch (field.eth) { case (NET_HEADER_FIELD_ETH_TYPE): *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET; break; default: RETURN_ERROR( MAJOR, E_NOT_SUPPORTED, ("Header manipulation of the type Ethernet with this field not supported")); } break; case (HEADER_TYPE_VLAN): switch (field.vlan) { case (NET_HEADER_FIELD_VLAN_TCI): if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET; else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET; break; default: RETURN_ERROR( MAJOR, E_NOT_SUPPORTED, ("Header manipulation of the type VLAN with this field not supported")); } break; default: RETURN_ERROR( MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header by field not supported")); } } else { switch (hdr) { case (HEADER_TYPE_ETH): *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET; break; case (HEADER_TYPE_USER_DEFINED_SHIM1): *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET; break; case (HEADER_TYPE_USER_DEFINED_SHIM2): *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET; break; case (HEADER_TYPE_LLC_SNAP): *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET; break; case (HEADER_TYPE_PPPoE): *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET; break; case (HEADER_TYPE_MPLS): if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET; else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET; break; case (HEADER_TYPE_IPv4): case (HEADER_TYPE_IPv6): if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) *parseArrayOffset = CC_PC_PR_IP1_OFFSET; else if (hdrIndex == e_FM_PCD_HDR_INDEX_2) *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET; break; case (HEADER_TYPE_MINENCAP): *parseArrayOffset = CC_PC_PR_MINENC_OFFSET; break; case (HEADER_TYPE_GRE): *parseArrayOffset = CC_PC_PR_GRE_OFFSET; break; case (HEADER_TYPE_TCP): case (HEADER_TYPE_UDP): case (HEADER_TYPE_IPSEC_AH): case (HEADER_TYPE_IPSEC_ESP): case (HEADER_TYPE_DCCP): case (HEADER_TYPE_SCTP): *parseArrayOffset = CC_PC_PR_L4_OFFSET; break; case (HEADER_TYPE_CAPWAP): case (HEADER_TYPE_CAPWAP_DTLS): *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET; break; default: RETURN_ERROR( MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header is not supported")); } } return E_OK; } static t_Error BuildHmct(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams, uint8_t *p_DestHmct, uint8_t *p_DestData, bool new) { uint32_t *p_TmpHmct = (uint32_t*)p_DestHmct, *p_LocalData; uint32_t tmpReg = 0, *p_Last = NULL, tmp_ipv6_addr; uint8_t remain, i, size = 0, origSize, *p_UsrData = NULL, *p_TmpData = p_DestData; t_Handle h_FmPcd = p_Manip->h_FmPcd; uint8_t j = 0; if (p_FmPcdManipParams->u.hdr.rmv) { if (p_FmPcdManipParams->u.hdr.rmvParams.type == e_FM_PCD_MANIP_RMV_GENERIC) { /* initialize HMCD */ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_RMV) << HMCD_OC_SHIFT; /* tmp, should be conditional */ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.offset << HMCD_RMV_OFFSET_SHIFT; tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.size << HMCD_RMV_SIZE_SHIFT; } else if (p_FmPcdManipParams->u.hdr.rmvParams.type == e_FM_PCD_MANIP_RMV_BY_HDR) { switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.type) { case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2): { uint8_t hmcdOpt; /* initialize HMCD */ tmpReg = (uint32_t)(HMCD_OPCODE_L2_RMV) << HMCD_OC_SHIFT; switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.u.specificL2) { case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET): hmcdOpt = HMCD_RMV_L2_ETHERNET; break; case (e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS): hmcdOpt = HMCD_RMV_L2_STACKED_QTAGS; break; case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS): hmcdOpt = HMCD_RMV_L2_ETHERNET_AND_MPLS; break; case (e_FM_PCD_MANIP_HDR_RMV_MPLS): hmcdOpt = HMCD_RMV_L2_MPLS; break; default: RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); } tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT; break; } #if (DPAA_VERSION >= 11) case (e_FM_PCD_MANIP_RMV_BY_HDR_CAPWAP): tmpReg = (uint32_t)(HMCD_OPCODE_CAPWAP_RMV) << HMCD_OC_SHIFT; break; case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START): { uint8_t prsArrayOffset; t_Error err = E_OK; tmpReg = (uint32_t)(HMCD_OPCODE_RMV_TILL) << HMCD_OC_SHIFT; err = GetPrOffsetByHeaderOrField( &p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.u.hdrInfo, &prsArrayOffset); ASSERT_COND(!err); /* was previously checked */ tmpReg |= ((uint32_t)prsArrayOffset << 16); } break; #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("manip header remove by hdr type!")); } } WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; /* advance to next command */ p_TmpHmct += HMCD_BASIC_SIZE / 4; } if (p_FmPcdManipParams->u.hdr.insrt) { if (p_FmPcdManipParams->u.hdr.insrtParams.type == e_FM_PCD_MANIP_INSRT_GENERIC) { /* initialize HMCD */ if (p_FmPcdManipParams->u.hdr.insrtParams.u.generic.replace) tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_REPLACE) << HMCD_OC_SHIFT; else tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_INSRT) << HMCD_OC_SHIFT; tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.offset << HMCD_INSRT_OFFSET_SHIFT; tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size << HMCD_INSRT_SIZE_SHIFT; size = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size; p_UsrData = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.p_Data; WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; /* initialize data to be inserted */ /* if size is not a multiple of 4, padd with 0's */ origSize = size; remain = (uint8_t)(size % 4); if (remain) { size += (uint8_t)(4 - remain); p_LocalData = (uint32_t *)XX_Malloc(size); memset((uint8_t *)p_LocalData, 0, size); memcpy((uint8_t *)p_LocalData, p_UsrData, origSize); } else p_LocalData = (uint32_t*)p_UsrData; /* initialize data and advance pointer to next command */ for (i = 0; i < size / 4; i++, p_TmpHmct += HMCD_BASIC_SIZE / 4) WRITE_UINT32(*p_TmpHmct, *(p_LocalData+i)); if (remain) XX_Free(p_LocalData); } else if (p_FmPcdManipParams->u.hdr.insrtParams.type == e_FM_PCD_MANIP_INSRT_BY_HDR) { switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type) { case (e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2): { uint8_t hmcdOpt; /* initialize HMCD */ tmpReg = (uint32_t)(HMCD_OPCODE_L2_INSRT) << HMCD_OC_SHIFT; switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2) { case (e_FM_PCD_MANIP_HDR_INSRT_MPLS): if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.update) hmcdOpt = HMCD_INSRT_N_UPDATE_L2_MPLS; else hmcdOpt = HMCD_INSRT_L2_MPLS; break; default: RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); } tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT; WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; /* set size and pointer of user's data */ size = (uint8_t)p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size; ASSERT_COND(p_TmpData); Mem2IOCpy32( p_TmpData, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.p_Data, size); tmpReg = (size << HMCD_INSRT_L2_SIZE_SHIFT) | (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)); WRITE_UINT32(*p_TmpHmct, tmpReg); p_TmpHmct += HMCD_PTR_SIZE / 4; p_TmpData += size; } break; #if (DPAA_VERSION >= 11) case (e_FM_PCD_MANIP_INSRT_BY_HDR_IP): tmpReg = (uint32_t)(HMCD_OPCODE_IP_INSRT) << HMCD_OC_SHIFT; if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.calcL4Checksum) tmpReg |= HMCD_IP_L4_CS_CALC; if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.mappingMode == e_FM_PCD_MANIP_HDR_QOS_MAPPING_AS_IS) tmpReg |= HMCD_IP_OR_QOS; tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.lastPidOffset & HMCD_IP_LAST_PID_MASK; tmpReg |= ((p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size << HMCD_IP_SIZE_SHIFT) & HMCD_IP_SIZE_MASK); if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.dontFragOverwrite) tmpReg |= HMCD_IP_DF_MODE; WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; /* set IP id */ ASSERT_COND(p_TmpData); WRITE_UINT16( *(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.id); WRITE_UINT32( *p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase))); p_TmpData += 2; p_TmpHmct += HMCD_PTR_SIZE / 4; WRITE_UINT8(*p_TmpHmct, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.lastDstOffset); p_TmpHmct += HMCD_PARAM_SIZE / 4; Mem2IOCpy32( p_TmpHmct, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.p_Data, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size); p_TmpHmct += p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size / 4; break; case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE): tmpReg = HMCD_INSRT_UDP_LITE; case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP): tmpReg |= (uint32_t)(HMCD_OPCODE_UDP_INSRT) << HMCD_OC_SHIFT; WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; Mem2IOCpy32( p_TmpHmct, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.p_Data, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size); p_TmpHmct += p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size / 4; break; case (e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP): tmpReg = (uint32_t)(HMCD_OPCODE_CAPWAP_INSRT) << HMCD_OC_SHIFT; tmpReg |= HMCD_CAPWAP_INSRT; WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; Mem2IOCpy32( p_TmpHmct, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.p_Data, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size); p_TmpHmct += p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size / 4; break; #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("manip header insert by header type!")); } } } if (p_FmPcdManipParams->u.hdr.fieldUpdate) { switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type) { case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN): /* set opcode */ tmpReg = (uint32_t)(HMCD_OPCODE_VLAN_PRI_UPDATE) << HMCD_OC_SHIFT; /* set mode & table pointer */ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) { /* set Mode */ tmpReg |= (uint32_t)(HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI) << HMCD_VLAN_PRI_REP_MODE_SHIFT; /* set VPRI default */ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal; WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; /* write the table pointer into the Manip descriptor */ p_TmpHmct += HMCD_BASIC_SIZE / 4; tmpReg = 0; ASSERT_COND(p_TmpData); for (i = 0; i < HMCD_DSCP_VALUES; i++) { /* first we build from each 8 values a 32bit register */ tmpReg |= (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i]) << (32 - 4 * (j + 1)); j++; /* Than we write this register to the next table word * (i=7-->word 0, i=15-->word 1,... i=63-->word 7) */ if ((i % 8) == 7) { WRITE_UINT32(*((uint32_t*)p_TmpData + (i+1)/8-1), tmpReg); tmpReg = 0; j = 0; } } WRITE_UINT32( *p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase))); p_TmpHmct += HMCD_PTR_SIZE / 4; p_TmpData += DSCP_TO_VLAN_TABLE_SIZE; } else if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI) { /* set Mode */ /* line commented out as it has no-side-effect ('0' value). */ /*tmpReg |= HMCD_VLAN_PRI_UPDATE << HMCD_VLAN_PRI_REP_MODE_SHIFT*/; /* set VPRI parameter */ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri; WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; } break; case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4): /* set opcode */ tmpReg = (uint32_t)(HMCD_OPCODE_IPV4_UPDATE) << HMCD_OC_SHIFT; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_TTL) tmpReg |= HMCD_IPV4_UPDATE_TTL; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_TOS) { tmpReg |= HMCD_IPV4_UPDATE_TOS; tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.tos << HMCD_IPV4_UPDATE_TOS_SHIFT; } if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID) tmpReg |= HMCD_IPV4_UPDATE_ID; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC) tmpReg |= HMCD_IPV4_UPDATE_SRC; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST) tmpReg |= HMCD_IPV4_UPDATE_DST; /* write the first 4 bytes of the descriptor */ WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID) { ASSERT_COND(p_TmpData); WRITE_UINT16( *(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.id); WRITE_UINT32( *p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase))); p_TmpData += 2; p_TmpHmct += HMCD_PTR_SIZE / 4; } if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC) { WRITE_UINT32( *p_TmpHmct, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.src); p_TmpHmct += HMCD_IPV4_ADDR_SIZE / 4; } if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST) { WRITE_UINT32( *p_TmpHmct, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.dst); p_TmpHmct += HMCD_IPV4_ADDR_SIZE / 4; } break; case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6): /* set opcode */ tmpReg = (uint32_t)(HMCD_OPCODE_IPV6_UPDATE) << HMCD_OC_SHIFT; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_HL) tmpReg |= HMCD_IPV6_UPDATE_HL; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_TC) { tmpReg |= HMCD_IPV6_UPDATE_TC; tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.trafficClass << HMCD_IPV6_UPDATE_TC_SHIFT; } if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_SRC) tmpReg |= HMCD_IPV6_UPDATE_SRC; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_DST) tmpReg |= HMCD_IPV6_UPDATE_DST; /* write the first 4 bytes of the descriptor */ WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_SRC) { for (i = 0; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE; i += 4) { memcpy(&tmp_ipv6_addr, &p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.src[i], sizeof(uint32_t)); WRITE_UINT32(*p_TmpHmct, tmp_ipv6_addr); p_TmpHmct += HMCD_PTR_SIZE / 4; } } if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_DST) { for (i = 0; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE; i += 4) { memcpy(&tmp_ipv6_addr, &p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.dst[i], sizeof(uint32_t)); WRITE_UINT32(*p_TmpHmct, tmp_ipv6_addr); p_TmpHmct += HMCD_PTR_SIZE / 4; } } break; case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP): if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates == HDR_MANIP_TCP_UDP_CHECKSUM) { /* we implement this case with the update-checksum descriptor */ /* set opcode */ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_CHECKSUM) << HMCD_OC_SHIFT; /* write the first 4 bytes of the descriptor */ WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; } else { /* we implement this case with the TCP/UDP update descriptor */ /* set opcode */ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_UPDATE) << HMCD_OC_SHIFT; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_DST) tmpReg |= HMCD_TCP_UDP_UPDATE_DST; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_SRC) tmpReg |= HMCD_TCP_UDP_UPDATE_SRC; /* write the first 4 bytes of the descriptor */ WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; tmpReg = 0; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_SRC) tmpReg |= ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.src) << HMCD_TCP_UDP_UPDATE_SRC_SHIFT; if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_DST) tmpReg |= ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.dst); WRITE_UINT32(*p_TmpHmct, tmpReg); p_TmpHmct += HMCD_PTR_SIZE / 4; } break; default: RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown fieldUpdateParams.type")); } } if (p_FmPcdManipParams->u.hdr.custom) { switch (p_FmPcdManipParams->u.hdr.customParams.type) { case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE): /* set opcode */ tmpReg = (uint32_t)(HMCD_OPCODE_REPLACE_IP) << HMCD_OC_SHIFT; if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.decTtlHl) tmpReg |= HMCD_IP_REPLACE_TTL_HL; if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6) /* line commented out as it has no-side-effect ('0' value). */ /*tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV4*/; else if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) { tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV6; if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id) tmpReg |= HMCD_IP_REPLACE_ID; } else RETURN_ERROR( MINOR, E_NOT_SUPPORTED, ("One flag out of HDR_MANIP_IP_REPLACE_IPV4, HDR_MANIP_IP_REPLACE_IPV6 - must be set.")); /* write the first 4 bytes of the descriptor */ WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE / 4; size = p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize; ASSERT_COND(p_TmpData); Mem2IOCpy32( p_TmpData, p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdr, size); tmpReg = (uint32_t)(size << HMCD_IP_REPLACE_L3HDRSIZE_SHIFT); tmpReg |= (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)); WRITE_UINT32(*p_TmpHmct, tmpReg); p_TmpHmct += HMCD_PTR_SIZE / 4; p_TmpData += size; if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) && (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id)) { WRITE_UINT16( *(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.id); WRITE_UINT32( *p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase))); p_TmpData += 2; } p_TmpHmct += HMCD_PTR_SIZE / 4; break; case (e_FM_PCD_MANIP_HDR_CUSTOM_GEN_FIELD_REPLACE): /* set opcode */ tmpReg = (uint32_t)(HMCD_OPCODE_GEN_FIELD_REPLACE) << HMCD_OC_SHIFT; tmpReg |= p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.size << HMCD_GEN_FIELD_SIZE_SHIFT; tmpReg |= p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.srcOffset << HMCD_GEN_FIELD_SRC_OFF_SHIFT; tmpReg |= p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.dstOffset << HMCD_GEN_FIELD_DST_OFF_SHIFT; if (p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.mask) tmpReg |= HMCD_GEN_FIELD_MASK_EN; /* write the first 4 bytes of the descriptor */ WRITE_UINT32(*p_TmpHmct, tmpReg); /* save a pointer to the "last" indication word */ p_Last = p_TmpHmct; p_TmpHmct += HMCD_BASIC_SIZE/4; if (p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.mask) { tmpReg = p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.mask << HMCD_GEN_FIELD_MASK_SHIFT; tmpReg |= p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.maskOffset << HMCD_GEN_FIELD_MASK_OFF_SHIFT; /* write the next 4 bytes of the descriptor */ WRITE_UINT32(*p_TmpHmct, tmpReg); } p_TmpHmct += HMCD_PARAM_SIZE/4; break; default: RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown customParams.type")); } } /* If this node has a nextManip, and no parsing is required, the old table must be copied to the new table the old table and should be freed */ if (p_FmPcdManipParams->h_NextManip && (p_Manip->nextManipType == e_FM_PCD_MANIP_HDR) && (MANIP_DONT_REPARSE(p_Manip))) { if (new) { /* If this is the first time this manip is created we need to free unused memory. If it * is a dynamic changes case, the memory used is either the CC shadow or the existing * table - no allocation, no free */ MANIP_UPDATE_UNIFIED_POSITION(p_FmPcdManipParams->h_NextManip); p_Manip->unifiedPosition = e_MANIP_UNIFIED_FIRST; } } else { ASSERT_COND(p_Last); /* set the "last" indication on the last command of the current table */ WRITE_UINT32(*p_Last, GET_UINT32(*p_Last) | HMCD_LAST); } return E_OK; } static t_Error CreateManipActionNew(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams) { t_FmPcdManip *p_CurManip; t_Error err; uint32_t nextSize = 0, totalSize; uint16_t tmpReg; uint8_t *p_OldHmct, *p_TmpHmctPtr, *p_TmpDataPtr; /* set Manip structure */ p_Manip->dontParseAfterManip = p_FmPcdManipParams->u.hdr.dontParseAfterManip; if (p_FmPcdManipParams->h_NextManip) { /* Next Header manipulation exists */ p_Manip->nextManipType = MANIP_GET_TYPE(p_FmPcdManipParams->h_NextManip); if ((p_Manip->nextManipType == e_FM_PCD_MANIP_HDR) && p_Manip->dontParseAfterManip) nextSize = (uint32_t)(GetHmctSize(p_FmPcdManipParams->h_NextManip) + GetDataSize(p_FmPcdManipParams->h_NextManip)); else /* either parsing is required or next manip is Frag; no table merging. */ p_Manip->cascaded = TRUE; /* pass up the "cascaded" attribute. The whole chain is cascaded * if something is cascaded along the way. */ if (MANIP_IS_CASCADED(p_FmPcdManipParams->h_NextManip)) p_Manip->cascaded = TRUE; } /* Allocate new table */ /* calculate table size according to manip parameters */ err = CalculateTableSize(p_FmPcdManipParams, &p_Manip->tableSize, &p_Manip->dataSize); if (err) RETURN_ERROR(MINOR, err, NO_MSG); totalSize = (uint16_t)(p_Manip->tableSize + p_Manip->dataSize + nextSize); p_Manip->p_Hmct = (uint8_t*)FM_MURAM_AllocMem( ((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, totalSize, 4); if (!p_Manip->p_Hmct) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc failed")); if (p_Manip->dataSize) p_Manip->p_Data = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, (p_Manip->tableSize + nextSize)); /* update shadow size to allow runtime replacement of Header manipulation */ /* The allocated shadow is divided as follows: 0 . . . 16 . . . -------------------------------- | Shadow | Shadow HMTD | | HMTD | Match Table | | (16 bytes) | (maximal size) | -------------------------------- */ err = FmPcdUpdateCcShadow(p_Manip->h_FmPcd, (uint32_t)(totalSize + 16), (uint16_t)FM_PCD_CC_AD_TABLE_ALIGN); if (err != E_OK) { FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct); RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for HdrManip node shadow")); } if (p_FmPcdManipParams->h_NextManip && (p_Manip->nextManipType == e_FM_PCD_MANIP_HDR) && (MANIP_DONT_REPARSE(p_Manip))) { p_OldHmct = (uint8_t *)GetManipInfo(p_FmPcdManipParams->h_NextManip, e_MANIP_HMCT); p_CurManip = p_FmPcdManipParams->h_NextManip; /* Run till the last Manip (which is the first to configure) */ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) p_CurManip = p_CurManip->h_NextManip; while (p_CurManip) { /* If this is a unified table, point to the part of the table * which is the relative offset in HMCT. */ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, (p_Manip->tableSize + (PTR_TO_UINT(p_CurManip->p_Hmct) - PTR_TO_UINT(p_OldHmct)))); if (p_CurManip->p_Data) p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, (p_Manip->tableSize + (PTR_TO_UINT(p_CurManip->p_Data) - PTR_TO_UINT(p_OldHmct)))); else p_TmpDataPtr = NULL; BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE); /* update old manip table pointer */ MANIP_SET_HMCT_PTR(p_CurManip, p_TmpHmctPtr); MANIP_SET_DATA_PTR(p_CurManip, p_TmpDataPtr); p_CurManip = p_CurManip->h_PrevManip; } /* We copied the HMCT to create a new large HMCT so we can free the old one */ FM_MURAM_FreeMem(MANIP_GET_MURAM(p_FmPcdManipParams->h_NextManip), p_OldHmct); } /* Fill table */ err = BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, TRUE); if (err) { FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct); RETURN_ERROR(MINOR, err, NO_MSG); } /* Build HMTD (table descriptor) */ tmpReg = HMTD_CFG_TYPE; /* NADEN = 0 */ /* add parseAfterManip */ if (!p_Manip->dontParseAfterManip) tmpReg |= HMTD_CFG_PRS_AFTER_HM; /* create cascade */ /*if (p_FmPcdManipParams->h_NextManip && (!MANIP_DONT_REPARSE(p_Manip) || (p_Manip->nextManipType != e_FM_PCD_MANIP_HDR)))*/ if (p_Manip->cascaded) { uint16_t nextAd; /* indicate that there's another HM table descriptor */ tmpReg |= HMTD_CFG_NEXT_AD_EN; /* get address of next HMTD (table descriptor; h_Ad). * If the next HMTD was removed due to table unifing, get the address * of the "next next" as written in the h_Ad of the next h_Manip node. */ if (p_Manip->unifiedPosition != e_MANIP_UNIFIED_FIRST) nextAd = (uint16_t)((uint32_t)(XX_VirtToPhys(MANIP_GET_HMTD_PTR(p_FmPcdManipParams->h_NextManip)) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4); else nextAd = ((t_Hmtd *)((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad)->nextAdIdx; WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->nextAdIdx, nextAd); } WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->cfg, tmpReg); WRITE_UINT32( ((t_Hmtd *)p_Manip->h_Ad)->hmcdBasePtr, (uint32_t)(XX_VirtToPhys(p_Manip->p_Hmct) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase))); WRITE_UINT8(((t_Hmtd *)p_Manip->h_Ad)->opCode, HMAN_OC); if (p_Manip->unifiedPosition == e_MANIP_UNIFIED_FIRST) { /* The HMTD of the next Manip is never going to be used */ if (((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->muramAllocate) FM_MURAM_FreeMem( ((t_FmPcd *)((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_FmPcd)->h_FmMuram, ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad); else XX_Free(((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad); ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad = NULL; } return E_OK; } static t_Error CreateManipActionShadow(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams) { uint8_t *p_WholeHmct, *p_TmpHmctPtr, newDataSize, *p_TmpDataPtr = NULL; uint16_t newSize; t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; t_Error err; t_FmPcdManip *p_CurManip = p_Manip; err = CalculateTableSize(p_FmPcdManipParams, &newSize, &newDataSize); if (err) RETURN_ERROR(MINOR, err, NO_MSG); /* check coherency of new table parameters */ if (newSize > p_Manip->tableSize) RETURN_ERROR( MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration requires larger size than current one (command table).")); if (newDataSize > p_Manip->dataSize) RETURN_ERROR( MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration requires larger size than current one (data).")); if (p_FmPcdManipParams->h_NextManip) RETURN_ERROR( MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration can not contain h_NextManip.")); if (MANIP_IS_UNIFIED(p_Manip) && (newSize != p_Manip->tableSize)) RETURN_ERROR( MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration in a chained manipulation requires different size than current one.")); if (p_Manip->dontParseAfterManip != p_FmPcdManipParams->u.hdr.dontParseAfterManip) RETURN_ERROR( MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration differs in dontParseAfterManip value.")); p_Manip->tableSize = newSize; p_Manip->dataSize = newDataSize; /* Build the new table in the shadow */ if (!MANIP_IS_UNIFIED(p_Manip)) { p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16); if (p_Manip->p_Data) p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_TmpHmctPtr, (PTR_TO_UINT(p_Manip->p_Data) - PTR_TO_UINT(p_Manip->p_Hmct))); BuildHmct(p_Manip, p_FmPcdManipParams, p_TmpHmctPtr, p_Manip->p_Data, FALSE); } else { p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ASSERT_COND(p_WholeHmct); /* Run till the last Manip (which is the first to configure) */ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) p_CurManip = p_CurManip->h_NextManip; while (p_CurManip) { /* If this is a non-head node in a unified table, point to the part of the shadow * which is the relative offset in HMCT. * else, point to the beginning of the * shadow table (we save 16 for the HMTD. */ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, (16 + PTR_TO_UINT(p_CurManip->p_Hmct) - PTR_TO_UINT(p_WholeHmct))); if (p_CurManip->p_Data) p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, (16 + PTR_TO_UINT(p_CurManip->p_Data) - PTR_TO_UINT(p_WholeHmct))); BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE); p_CurManip = p_CurManip->h_PrevManip; } } return E_OK; } static t_Error CreateManipActionBackToOrig( t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams) { uint8_t *p_WholeHmct = NULL, *p_TmpHmctPtr, *p_TmpDataPtr; t_FmPcdManip *p_CurManip = p_Manip; /* Build the new table in the shadow */ if (!MANIP_IS_UNIFIED(p_Manip)) BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, FALSE); else { p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ASSERT_COND(p_WholeHmct); /* Run till the last Manip (which is the first to configure) */ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) p_CurManip = p_CurManip->h_NextManip; while (p_CurManip) { /* If this is a unified table, point to the part of the table * which is the relative offset in HMCT. */ p_TmpHmctPtr = p_CurManip->p_Hmct; /*- (uint32_t)p_WholeHmct*/ p_TmpDataPtr = p_CurManip->p_Data; /*- (uint32_t)p_WholeHmct*/ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE); p_CurManip = p_CurManip->h_PrevManip; } } return E_OK; } #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) static t_Error UpdateManipIc(t_Handle h_Manip, uint8_t icOffset) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; t_Handle p_Ad; uint32_t tmpReg32 = 0; SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); switch (p_Manip->opcode) { case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET) { tmpReg32 = *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets; tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16); *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets = tmpReg32; p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET; p_Manip->icOffset = icOffset; } else { if (p_Manip->icOffset != icOffset) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("this manipulation was updated previously by different value");); } break; case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): if (p_Manip->h_Frag) { if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET) { p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; tmpReg32 |= GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets); tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16); WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, tmpReg32); p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET; p_Manip->icOffset = icOffset; } else { if (p_Manip->icOffset != icOffset) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("this manipulation was updated previousely by different value");); } } break; } return E_OK; } static t_Error UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix( t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate) { t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad; t_FmPortGetSetCcParams fmPortGetSetCcParams; t_Error err; uint32_t tmpReg32; memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR( (p_Manip->opcode & HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX), E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR(!p_Manip->muramAllocate, E_INVALID_STATE); if (p_Manip->updateParams) { if ((!(p_Manip->updateParams & OFFSET_OF_PR)) || (p_Manip->shadowUpdateParams & OFFSET_OF_PR)) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO; fmPortGetSetCcParams.setCcParams.psoSize = 16; err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("Parser result offset wasn't configured previousely")); #ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ASSERT_COND(!(fmPortGetSetCcParams.getCcParams.prOffset % 16)); #endif } else if (validate) { if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_PR)) || (p_Manip->updateParams & OFFSET_OF_PR)) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO; fmPortGetSetCcParams.setCcParams.psoSize = 16; err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("Parser result offset wasn't configured previousely")); } ASSERT_COND(p_Ad); if (p_Manip->updateParams & OFFSET_OF_PR) { tmpReg32 = 0; tmpReg32 |= fmPortGetSetCcParams.getCcParams.prOffset; WRITE_UINT32(p_Ad->matchTblPtr, (GET_UINT32(p_Ad->matchTblPtr) | tmpReg32)); p_Manip->updateParams &= ~OFFSET_OF_PR; p_Manip->shadowUpdateParams |= OFFSET_OF_PR; } else if (validate) { tmpReg32 = GET_UINT32(p_Ad->matchTblPtr); if ((uint8_t)tmpReg32 != fmPortGetSetCcParams.getCcParams.prOffset) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value");); } return E_OK; } static t_Error UpdateModifyCapwapFragmenation(t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate,t_Handle h_FmTree) { t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad; t_FmPcdCcSavedManipParams *p_SavedManipParams = NULL; uint32_t tmpReg32 = 0; SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; if (p_Manip->updateParams) { if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) || ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA))) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree); if (!p_SavedManipParams) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type")); p_Manip->capwapFragParams.dataOffset = p_SavedManipParams->capwapParams.dataOffset; tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets); tmpReg32 |= ((uint32_t)p_Manip->capwapFragParams.dataOffset<< 16); WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32); p_Manip->updateParams &= ~OFFSET_OF_DATA; p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; } else if (validate) { p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree); if (!p_SavedManipParams) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type")); if (p_Manip->capwapFragParams.dataOffset != p_SavedManipParams->capwapParams.dataOffset) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value")); } return E_OK; } static t_Error UpdateInitCapwapFragmentation(t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate, t_Handle h_FmTree) { t_AdOfTypeContLookup *p_Ad; t_FmPortGetSetCcParams fmPortGetSetCcParams; t_Error err; uint32_t tmpReg32 = 0; t_FmPcdCcSavedManipParams *p_SavedManipParams; UNUSED(h_Ad); SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; if (p_Manip->updateParams) { if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) || ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA))) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY; fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; /* For CAPWAP Rassembly used FMAN_CTRL2 hardcoded - so for fragmentation its better to use FMAN_CTRL1 */ fmPortGetSetCcParams.setCcParams.orFmanCtrl = FPM_PORT_FM_CTL1; err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely")); p_SavedManipParams = (t_FmPcdCcSavedManipParams *)XX_Malloc(sizeof(t_FmPcdCcSavedManipParams)); p_SavedManipParams->capwapParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; #ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ASSERT_COND(!(p_SavedManipParams->capwapParams.dataOffset % 16)); #endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */ FmPcdCcTreeSetSavedManipParams(h_FmTree, (t_Handle)p_SavedManipParams); } else if (validate) { if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_DATA)) || ((p_Manip->updateParams & OFFSET_OF_DATA))) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY; fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely")); } if (p_Manip->updateParams) { tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets); tmpReg32 |= ((uint32_t)fmPortGetSetCcParams.getCcParams.dataOffset<< 16); WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32); p_Manip->updateParams &= ~OFFSET_OF_DATA; p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; p_Manip->capwapFragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; } else if (validate) { if (p_Manip->capwapFragParams.dataOffset != fmPortGetSetCcParams.getCcParams.dataOffset) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value")); } return E_OK; } static t_Error UpdateInitCapwapReasm(t_Handle h_FmPcd, t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate) { t_CapwapReasmPram *p_ReassmTbl; t_Error err; t_FmPortGetSetCcParams fmPortGetSetCcParams; uint8_t i = 0; uint16_t size; uint32_t tmpReg32; t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeoutParams; SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Manip->frag,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST), E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc,E_INVALID_HANDLE); if (p_Manip->h_FmPcd != h_FmPcd) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("handler of PCD previously was initiated by different value")); UNUSED(h_Ad); memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); p_ReassmTbl = (t_CapwapReasmPram *)p_Manip->h_Frag; if (p_Manip->updateParams) { if ((!(p_Manip->updateParams & NUM_OF_TASKS) && !(p_Manip->updateParams & OFFSET_OF_DATA) && !(p_Manip->updateParams & OFFSET_OF_PR) && !(p_Manip->updateParams & HW_PORT_ID)) || ((p_Manip->shadowUpdateParams & NUM_OF_TASKS) || (p_Manip->shadowUpdateParams & OFFSET_OF_DATA) || (p_Manip->shadowUpdateParams & OFFSET_OF_PR) || (p_Manip->shadowUpdateParams & HW_PORT_ID))) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN; fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Num of tasks wasn't configured previousely")); if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previousely")); if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated")); #ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ASSERT_COND((fmPortGetSetCcParams.getCcParams.dataOffset % 16) == 0); #endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */ } else if (validate) { if ((!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) && !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) && !(p_Manip->shadowUpdateParams & OFFSET_OF_PR) && !(p_Manip->shadowUpdateParams & HW_PORT_ID)) && ((p_Manip->updateParams & NUM_OF_TASKS) || (p_Manip->updateParams & OFFSET_OF_DATA) || (p_Manip->updateParams & OFFSET_OF_PR) || (p_Manip->updateParams & HW_PORT_ID))) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN; fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("NumOfTasks wasn't configured previously")); if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously")); if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated")); } if (p_Manip->updateParams) { if (p_Manip->updateParams & NUM_OF_TASKS) { /*recommendation of Microcode team - (maxNumFramesInProcess * 2) */ size = (uint16_t)(p_Manip->capwapFragParams.maxNumFramesInProcess*2 + fmPortGetSetCcParams.getCcParams.numOfTasks); if (size > 255) RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("numOfOpenReassmEntries + numOfTasks per port can not be greater than 256")); p_Manip->capwapFragParams.numOfTasks = fmPortGetSetCcParams.getCcParams.numOfTasks; /*p_ReassmFrmDescrIndxPoolTbl*/ p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(size + 1), 4); if (!p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer index pool table")); IOMemSet32(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size + 1)); for ( i = 0; i < size; i++) WRITE_UINT8(*(uint8_t *)PTR_MOVE(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl, i), (uint8_t)(i+1)); tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl) - p_FmPcd->physicalMuramBase); WRITE_UINT32(p_ReassmTbl->reasmFrmDescIndexPoolTblPtr, tmpReg32); /*p_ReassmFrmDescrPoolTbl*/ p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)((size + 1) * FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE), 4); if (!p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer pool table")); IOMemSet32(p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl, 0, (uint32_t)((size +1)* FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE)); tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl) - p_FmPcd->physicalMuramBase); WRITE_UINT32(p_ReassmTbl->reasmFrmDescPoolTblPtr, tmpReg32); /*p_TimeOutTbl*/ p_Manip->capwapFragParams.p_TimeOutTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)((size + 1)* FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE), 4); if (!p_Manip->capwapFragParams.p_TimeOutTbl) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly timeout table")); IOMemSet32(p_Manip->capwapFragParams.p_TimeOutTbl, 0, (uint16_t)((size + 1)*FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE)); tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_TimeOutTbl) - p_FmPcd->physicalMuramBase); WRITE_UINT32(p_ReassmTbl->timeOutTblPtr, tmpReg32); p_Manip->updateParams &= ~NUM_OF_TASKS; p_Manip->shadowUpdateParams |= NUM_OF_TASKS; } if (p_Manip->updateParams & OFFSET_OF_DATA) { p_Manip->capwapFragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; tmpReg32 = GET_UINT32(p_ReassmTbl->mode); tmpReg32|= p_Manip->capwapFragParams.dataOffset; WRITE_UINT32(p_ReassmTbl->mode, tmpReg32); p_Manip->updateParams &= ~OFFSET_OF_DATA; p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; } if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)) { p_Manip->capwapFragParams.prOffset = fmPortGetSetCcParams.getCcParams.prOffset; tmpReg32 = GET_UINT32(p_ReassmTbl->mode); tmpReg32|= FM_PCD_MANIP_CAPWAP_REASM_PR_COPY; WRITE_UINT32(p_ReassmTbl->mode, tmpReg32); tmpReg32 = GET_UINT32(p_ReassmTbl->intStatsTblPtr); tmpReg32 |= (uint32_t)p_Manip->capwapFragParams.prOffset << 24; WRITE_UINT32(p_ReassmTbl->intStatsTblPtr, tmpReg32); p_Manip->updateParams &= ~OFFSET_OF_PR; p_Manip->shadowUpdateParams |= OFFSET_OF_PR; } else { p_Manip->capwapFragParams.prOffset = 0xff; p_Manip->updateParams &= ~OFFSET_OF_PR; p_Manip->shadowUpdateParams |= OFFSET_OF_PR; } p_Manip->capwapFragParams.hwPortId = fmPortGetSetCcParams.getCcParams.hardwarePortId; p_Manip->updateParams &= ~HW_PORT_ID; p_Manip->shadowUpdateParams |= HW_PORT_ID; /*timeout hc */ ccCapwapReassmTimeoutParams.fqidForTimeOutFrames = p_Manip->capwapFragParams.fqidForTimeOutFrames; ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl = (uint32_t)p_Manip->capwapFragParams.hwPortId << 24; ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl |= (uint32_t)((XX_VirtToPhys(p_ReassmTbl) - p_FmPcd->physicalMuramBase)); ccCapwapReassmTimeoutParams.timeoutRequestTime = (((uint32_t)1<capwapFragParams.bitFor1Micro) * p_Manip->capwapFragParams.timeoutRoutineRequestTime)/2; return FmHcPcdCcCapwapTimeoutReassm(p_FmPcd->h_Hc,&ccCapwapReassmTimeoutParams); } else if (validate) { if (fmPortGetSetCcParams.getCcParams.hardwarePortId != p_Manip->capwapFragParams.hwPortId) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Reassembly manipulation previously was assigned to another port")); if (fmPortGetSetCcParams.getCcParams.numOfTasks != p_Manip->capwapFragParams.numOfTasks) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfTasks for this manipulation previously was defined by another value ")); if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)) { if (p_Manip->capwapFragParams.prOffset != fmPortGetSetCcParams.getCcParams.prOffset) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value ")); } else { if (p_Manip->capwapFragParams.prOffset != 0xff) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value ")); } if (fmPortGetSetCcParams.getCcParams.dataOffset != p_Manip->capwapFragParams.dataOffset) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Data offset previously was defined by another value ")); } return E_OK; } #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_ReasmCommonPramTbl) { t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; t_FmPcdCcReassmTimeoutParams ccReassmTimeoutParams = { 0 }; t_Error err = E_OK; uint8_t result; uint32_t bitFor1Micro, tsbs, log2num; ASSERT_COND(p_FmPcd); ASSERT_COND(h_ReasmCommonPramTbl); bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); if (bitFor1Micro == 0) RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale")); bitFor1Micro = 32 - bitFor1Micro; LOG2(FM_PCD_MANIP_REASM_TIMEOUT_THREAD_THRESH, log2num); tsbs = bitFor1Micro - log2num; ccReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys( h_ReasmCommonPramTbl) - p_FmPcd->physicalMuramBase); ccReassmTimeoutParams.tsbs = (uint8_t)tsbs; ccReassmTimeoutParams.activate = TRUE; if ((err = FmHcPcdCcTimeoutReassm(p_FmPcd->h_Hc, &ccReassmTimeoutParams, &result)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); switch (result) { case (0): return E_OK; case (1): RETURN_ERROR(MAJOR, E_NO_MEMORY, ("failed to allocate TNUM")); case (2): RETURN_ERROR( MAJOR, E_NO_MEMORY, ("failed to allocate internal buffer from the HC-Port")); case (3): RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("'Disable Timeout Task' with invalid IPRCPT")); case (4): RETURN_ERROR(MAJOR, E_FULL, ("too many timeout tasks")); case (5): RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("invalid sub command")); default: RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); } return E_OK; } static t_Error CreateReassCommonTable(t_FmPcdManip *p_Manip) { uint32_t tmpReg32 = 0, i, bitFor1Micro; uint64_t tmpReg64, size; t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; t_Error err = E_OK; bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); if (bitFor1Micro == 0) RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale")); /* Allocation of the Reassembly Common Parameters table. This table is located in the MURAM. Its size is 64 bytes and its base address should be 8-byte aligned. */ p_Manip->reassmParams.p_ReassCommonTbl = (t_ReassCommonTbl *)FM_MURAM_AllocMem( p_FmPcd->h_FmMuram, FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_SIZE, FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_ALIGN); if (!p_Manip->reassmParams.p_ReassCommonTbl) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly common parameters table")); IOMemSet32(p_Manip->reassmParams.p_ReassCommonTbl, 0, FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_SIZE); /* Setting the TimeOut Mode.*/ tmpReg32 = 0; if (p_Manip->reassmParams.timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES) tmpReg32 |= FM_PCD_MANIP_REASM_TIME_OUT_BETWEEN_FRAMES; /* Setting TimeOut FQID - Frames that time out are enqueued to this FQID. In order to cause TimeOut frames to be discarded, this queue should be configured accordingly*/ tmpReg32 |= p_Manip->reassmParams.fqidForTimeOutFrames; WRITE_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->timeoutModeAndFqid, tmpReg32); /* Calculation the size of IP Reassembly Frame Descriptor - number of frames that are allowed to be reassembled simultaneously + 129.*/ size = p_Manip->reassmParams.maxNumFramesInProcess + 129; /*Allocation of IP Reassembly Frame Descriptor Indexes Pool - This pool resides in the MURAM */ p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(size * 2), 256)); if (!p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr) RETURN_ERROR( MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly frame descriptor indexes pool")); IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr), 0, (uint32_t)(size * 2)); /* The entries in IP Reassembly Frame Descriptor Indexes Pool contains indexes starting with 1 up to the maximum number of frames that are allowed to be reassembled simultaneously + 128. The last entry in this pool must contain the index zero*/ for (i = 0; i < (size - 1); i++) WRITE_UINT16( *(uint16_t *)PTR_MOVE(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr), (i<<1)), (uint16_t)(i+1)); /* Sets the IP Reassembly Frame Descriptor Indexes Pool offset from MURAM */ tmpReg32 = (uint32_t)(XX_VirtToPhys( UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr)) - p_FmPcd->physicalMuramBase); WRITE_UINT32( p_Manip->reassmParams.p_ReassCommonTbl->reassFrmDescIndexPoolTblPtr, tmpReg32); /* Allocation of the Reassembly Frame Descriptors Pool - This pool resides in external memory. The number of entries in this pool should be equal to the number of entries in IP Reassembly Frame Descriptor Indexes Pool.*/ p_Manip->reassmParams.reassFrmDescrPoolTblAddr = PTR_TO_UINT(XX_MallocSmart((uint32_t)(size * 64), p_Manip->reassmParams.dataMemId, 64)); if (!p_Manip->reassmParams.reassFrmDescrPoolTblAddr) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrPoolTblAddr), 0, (uint32_t)(size * 64)); /* Sets the Reassembly Frame Descriptors Pool and liodn offset*/ tmpReg64 = (uint64_t)(XX_VirtToPhys( UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrPoolTblAddr))); tmpReg64 |= ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset & FM_PCD_MANIP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_REASM_LIODN_SHIFT); tmpReg64 |= ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset & FM_PCD_MANIP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_REASM_ELIODN_SHIFT); WRITE_UINT32( p_Manip->reassmParams.p_ReassCommonTbl->liodnAndReassFrmDescPoolPtrHi, (uint32_t)(tmpReg64 >> 32)); WRITE_UINT32( p_Manip->reassmParams.p_ReassCommonTbl->reassFrmDescPoolPtrLow, (uint32_t)tmpReg64); /*Allocation of the TimeOut table - This table resides in the MURAM. The number of entries in this table is identical to the number of entries in the Reassembly Frame Descriptors Pool*/ p_Manip->reassmParams.timeOutTblAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(size * 8),8)); if (!p_Manip->reassmParams.timeOutTblAddr) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly timeout table")); IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.timeOutTblAddr), 0, (uint16_t)(size * 8)); /* Sets the TimeOut table offset from MURAM */ tmpReg32 = (uint32_t)(XX_VirtToPhys( UINT_TO_PTR(p_Manip->reassmParams.timeOutTblAddr)) - p_FmPcd->physicalMuramBase); WRITE_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->timeOutTblPtr, tmpReg32); /* Sets the Expiration Delay */ tmpReg32 = 0; tmpReg32 |= (((uint32_t)(1 << bitFor1Micro)) * p_Manip->reassmParams.timeoutThresholdForReassmProcess); WRITE_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->expirationDelay, tmpReg32); err = FmPcdRegisterReassmPort(p_FmPcd, p_Manip->reassmParams.p_ReassCommonTbl); if (err != E_OK) { FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->reassmParams.p_ReassCommonTbl); RETURN_ERROR(MAJOR, err, ("port registration")); } return err; } static t_Error CreateReassTable(t_FmPcdManip *p_Manip, e_NetHeaderType hdr) { t_FmPcd *p_FmPcd = p_Manip->h_FmPcd; uint32_t tmpReg32, autoLearnHashTblSize; uint32_t numOfWays, setSize, setSizeCode, keySize; uint32_t waySize, numOfSets, numOfEntries; uint64_t tmpReg64; uint16_t minFragSize; uint16_t maxReassemSize; uintptr_t *p_AutoLearnHashTblAddr, *p_AutoLearnSetLockTblAddr; t_ReassTbl **p_ReassTbl; switch (hdr) { case HEADER_TYPE_IPv4: p_ReassTbl = &p_Manip->reassmParams.ip.p_Ipv4ReassTbl; p_AutoLearnHashTblAddr = &p_Manip->reassmParams.ip.ipv4AutoLearnHashTblAddr; p_AutoLearnSetLockTblAddr = &p_Manip->reassmParams.ip.ipv4AutoLearnSetLockTblAddr; minFragSize = p_Manip->reassmParams.ip.minFragSize[0]; maxReassemSize = 0; numOfWays = p_Manip->reassmParams.ip.numOfFramesPerHashEntry[0]; keySize = 4 + 4 + 1 + 2; /* 3-tuple + IP-Id */ break; case HEADER_TYPE_IPv6: p_ReassTbl = &p_Manip->reassmParams.ip.p_Ipv6ReassTbl; p_AutoLearnHashTblAddr = &p_Manip->reassmParams.ip.ipv6AutoLearnHashTblAddr; p_AutoLearnSetLockTblAddr = &p_Manip->reassmParams.ip.ipv6AutoLearnSetLockTblAddr; minFragSize = p_Manip->reassmParams.ip.minFragSize[1]; maxReassemSize = 0; numOfWays = p_Manip->reassmParams.ip.numOfFramesPerHashEntry[1]; keySize = 16 + 16 + 4; /* 2-tuple + IP-Id */ if (numOfWays > e_FM_PCD_MANIP_SIX_WAYS_HASH) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("num of ways")); break; case HEADER_TYPE_CAPWAP: p_ReassTbl = &p_Manip->reassmParams.capwap.p_ReassTbl; p_AutoLearnHashTblAddr = &p_Manip->reassmParams.capwap.autoLearnHashTblAddr; p_AutoLearnSetLockTblAddr = &p_Manip->reassmParams.capwap.autoLearnSetLockTblAddr; minFragSize = 0; maxReassemSize = p_Manip->reassmParams.capwap.maxRessembledsSize; numOfWays = p_Manip->reassmParams.capwap.numOfFramesPerHashEntry; keySize = 4; break; default: RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header type")); } keySize += 2; /* 2 bytes reserved for RFDIndex */ #if (DPAA_VERSION >= 11) keySize += 2; /* 2 bytes reserved */ #endif /* (DPAA_VERSION >= 11) */ waySize = ROUND_UP(keySize, 8); /* Allocates the Reassembly Parameters Table - This table is located in the MURAM.*/ *p_ReassTbl = (t_ReassTbl *)FM_MURAM_AllocMem( p_FmPcd->h_FmMuram, FM_PCD_MANIP_REASM_TABLE_SIZE, FM_PCD_MANIP_REASM_TABLE_ALIGN); if (!*p_ReassTbl) RETURN_ERROR( MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly specific parameters table")); memset(*p_ReassTbl, 0, sizeof(t_ReassTbl)); /* Sets the Reassembly common Parameters table offset from MURAM in the Reassembly Table descriptor*/ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->reassmParams.p_ReassCommonTbl) - p_FmPcd->physicalMuramBase); WRITE_UINT32((*p_ReassTbl)->reassCommonPrmTblPtr, tmpReg32); /* Calculate set size (set size is rounded-up to next power of 2) */ NEXT_POWER_OF_2(numOfWays * waySize, setSize); /* Get set size code */ LOG2(setSize, setSizeCode); /* Sets ways number and set size code */ WRITE_UINT16((*p_ReassTbl)->waysNumAndSetSize, (uint16_t)((numOfWays << 8) | setSizeCode)); /* It is recommended that the total number of entries in this table (number of sets * number of ways) will be twice the number of frames that are expected to be reassembled simultaneously.*/ numOfEntries = (uint32_t)(p_Manip->reassmParams.maxNumFramesInProcess * 2); /* sets number calculation - number of entries = number of sets * number of ways */ numOfSets = numOfEntries / numOfWays; /* Sets AutoLearnHashKeyMask*/ NEXT_POWER_OF_2(numOfSets, numOfSets); WRITE_UINT16((*p_ReassTbl)->autoLearnHashKeyMask, (uint16_t)(numOfSets - 1)); /* Allocation of Reassembly Automatic Learning Hash Table - This table resides in external memory. The size of this table is determined by the number of sets and the set size. Table size = set size * number of sets This table base address should be aligned to SetSize.*/ autoLearnHashTblSize = numOfSets * setSize; *p_AutoLearnHashTblAddr = PTR_TO_UINT(XX_MallocSmart(autoLearnHashTblSize, p_Manip->reassmParams.dataMemId, setSize)); if (!*p_AutoLearnHashTblAddr) { FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_ReassTbl); *p_ReassTbl = NULL; RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); } IOMemSet32(UINT_TO_PTR(*p_AutoLearnHashTblAddr), 0, autoLearnHashTblSize); /* Sets the Reassembly Automatic Learning Hash Table and liodn offset */ tmpReg64 = ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset & FM_PCD_MANIP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_REASM_LIODN_SHIFT); tmpReg64 |= ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset & FM_PCD_MANIP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_REASM_ELIODN_SHIFT); tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnHashTblAddr)); WRITE_UINT32( (*p_ReassTbl)->liodnAlAndAutoLearnHashTblPtrHi, (uint32_t)(tmpReg64 >> 32)); WRITE_UINT32((*p_ReassTbl)->autoLearnHashTblPtrLow, (uint32_t)tmpReg64); /* Allocation of the Set Lock table - This table resides in external memory The size of this table is (number of sets in the Reassembly Automatic Learning Hash table)*4 bytes. This table resides in external memory and its base address should be 4-byte aligned */ *p_AutoLearnSetLockTblAddr = PTR_TO_UINT(XX_MallocSmart((uint32_t)(numOfSets * 4), p_Manip->reassmParams.dataMemId, 4)); if (!*p_AutoLearnSetLockTblAddr) { FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_ReassTbl); *p_ReassTbl = NULL; XX_FreeSmart(UINT_TO_PTR(*p_AutoLearnHashTblAddr)); *p_AutoLearnHashTblAddr = 0; RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); } IOMemSet32(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr), 0, (numOfSets * 4)); /* sets Set Lock table pointer and liodn offset*/ tmpReg64 = ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset & FM_PCD_MANIP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_REASM_LIODN_SHIFT); tmpReg64 |= ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset & FM_PCD_MANIP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_REASM_ELIODN_SHIFT); tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr)); WRITE_UINT32( (*p_ReassTbl)->liodnSlAndAutoLearnSetLockTblPtrHi, (uint32_t)(tmpReg64 >> 32)); WRITE_UINT32((*p_ReassTbl)->autoLearnSetLockTblPtrLow, (uint32_t)tmpReg64); /* Sets user's requested minimum fragment size (in Bytes) for First/Middle fragment */ WRITE_UINT16((*p_ReassTbl)->minFragSize, minFragSize); WRITE_UINT16((*p_ReassTbl)->maxReassemblySize, maxReassemSize); return E_OK; } static t_Error UpdateInitReasm(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate) { t_FmPortGetSetCcParams fmPortGetSetCcParams; uint32_t tmpReg32; t_Error err; t_FmPortPcdParams *p_PcdParams = (t_FmPortPcdParams *)h_PcdParams; #if (DPAA_VERSION >= 11) t_FmPcdCtrlParamsPage *p_ParamsPage; #endif /* (DPAA_VERSION >= 11) */ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Manip->frag, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR( (p_Manip->opcode == HMAN_OC_IP_REASSEMBLY) || (p_Manip->opcode == HMAN_OC_CAPWAP_REASSEMBLY), E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Manip->updateParams || h_PcdParams, E_INVALID_HANDLE); UNUSED(h_Ad); if (!p_Manip->updateParams) return E_OK; if (p_Manip->h_FmPcd != h_FmPcd) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("handler of PCD previously was initiated by different value")); if (p_Manip->updateParams) { if ((!(p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK))) || ((p_Manip->shadowUpdateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK)))) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); fmPortGetSetCcParams.setCcParams.type = 0; if (p_Manip->opcode == HMAN_OC_CAPWAP_REASSEMBLY) { fmPortGetSetCcParams.setCcParams.type |= UPDATE_OFP_DPTE; fmPortGetSetCcParams.setCcParams.ofpDpde = 0xF; } fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams | FM_REV; if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); if (fmPortGetSetCcParams.getCcParams.type & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK | FM_REV)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously")); if (p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK)) { t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; uint8_t *p_Ptr, i, totalNumOfTnums; totalNumOfTnums = (uint8_t)(fmPortGetSetCcParams.getCcParams.numOfTasks + fmPortGetSetCcParams.getCcParams.numOfExtraTasks); p_Manip->reassmParams.internalBufferPoolAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS), BMI_FIFO_UNITS)); if (!p_Manip->reassmParams.internalBufferPoolAddr) RETURN_ERROR( MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly internal buffers pool")); IOMemSet32( UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolAddr), 0, (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS)); p_Manip->reassmParams.internalBufferPoolManagementIndexAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(5 + totalNumOfTnums), 4)); if (!p_Manip->reassmParams.internalBufferPoolManagementIndexAddr) RETURN_ERROR( MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly internal buffers management")); p_Ptr = (uint8_t*)UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolManagementIndexAddr); WRITE_UINT32( *(uint32_t*)p_Ptr, (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolAddr)) - p_FmPcd->physicalMuramBase)); for (i = 0, p_Ptr += 4; i < totalNumOfTnums; i++, p_Ptr++) WRITE_UINT8(*p_Ptr, i); WRITE_UINT8(*p_Ptr, 0xFF); tmpReg32 = (4 << FM_PCD_MANIP_REASM_COMMON_INT_BUFFER_IDX_SHIFT) | ((uint32_t)(XX_VirtToPhys( UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolManagementIndexAddr)) - p_FmPcd->physicalMuramBase)); WRITE_UINT32( p_Manip->reassmParams.p_ReassCommonTbl->internalBufferManagement, tmpReg32); p_Manip->updateParams &= ~(NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK); p_Manip->shadowUpdateParams |= (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK); } } if (p_Manip->opcode == HMAN_OC_CAPWAP_REASSEMBLY) { if (p_Manip->reassmParams.capwap.h_Scheme) { p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->reassmParams.capwap.h_Scheme; p_PcdParams->p_KgParams->numOfSchemes++; } } else { if (p_Manip->reassmParams.ip.h_Ipv4Scheme) { p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->reassmParams.ip.h_Ipv4Scheme; p_PcdParams->p_KgParams->numOfSchemes++; } if (p_Manip->reassmParams.ip.h_Ipv6Scheme) { p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->reassmParams.ip.h_Ipv6Scheme; p_PcdParams->p_KgParams->numOfSchemes++; } #if (DPAA_VERSION >= 11) if (fmPortGetSetCcParams.getCcParams.revInfo.majorRev >= 6) { if ((err = FmPortSetGprFunc(h_FmPort, e_FM_PORT_GPR_MURAM_PAGE, (void**)&p_ParamsPage)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); tmpReg32 = NIA_ENG_KG; if (p_Manip->reassmParams.ip.h_Ipv4Scheme) { tmpReg32 |= NIA_KG_DIRECT; tmpReg32 |= NIA_KG_CC_EN; tmpReg32 |= FmPcdKgGetSchemeId( p_Manip->reassmParams.ip.h_Ipv4Scheme); WRITE_UINT32(p_ParamsPage->iprIpv4Nia, tmpReg32); } if (p_Manip->reassmParams.ip.h_Ipv6Scheme) { tmpReg32 &= ~NIA_AC_MASK; tmpReg32 |= NIA_KG_DIRECT; tmpReg32 |= NIA_KG_CC_EN; tmpReg32 |= FmPcdKgGetSchemeId( p_Manip->reassmParams.ip.h_Ipv6Scheme); WRITE_UINT32(p_ParamsPage->iprIpv6Nia, tmpReg32); } } #else if (fmPortGetSetCcParams.getCcParams.revInfo.majorRev < 6) { WRITE_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->discardMask, fmPortGetSetCcParams.getCcParams.discardMask); } #endif /* (DPAA_VERSION >= 11) */ } return E_OK; } #if (DPAA_VERSION == 10) static t_Error FmPcdFragHcScratchPoolFill(t_Handle h_FmPcd, uint8_t scratchBpid) { t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams; t_Error err; SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams)); fmPcdCcFragScratchPoolCmdParams.numOfBuffers = NUM_OF_SCRATCH_POOL_BUFFERS; fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid; if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, TRUE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); if (fmPcdCcFragScratchPoolCmdParams.numOfBuffers != 0) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Fill scratch pool failed," "Failed to release %d buffers to the BM (missing FBPRs)", fmPcdCcFragScratchPoolCmdParams.numOfBuffers)); return E_OK; } static t_Error FmPcdFragHcScratchPoolEmpty(t_Handle h_FmPcd, uint8_t scratchBpid) { t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams; t_Error err; SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams)); fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid; if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, FALSE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); return E_OK; } #endif /* (DPAA_VERSION == 10) */ static void ReleaseManipHandler(t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd) { if (p_Manip->h_Ad) { if (p_Manip->muramAllocate) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Ad); else XX_Free(p_Manip->h_Ad); p_Manip->h_Ad = NULL; } if (p_Manip->p_Template) { FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_Template); p_Manip->p_Template = NULL; } #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) if (p_Manip->h_Frag) { if (p_Manip->capwapFragParams.p_AutoLearnHashTbl) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->capwapFragParams.p_AutoLearnHashTbl); if (p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl); if (p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl); if (p_Manip->capwapFragParams.p_TimeOutTbl) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->capwapFragParams.p_TimeOutTbl); FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Frag); } #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ if (p_Manip->frag) { if (p_Manip->fragParams.p_Frag) { #if (DPAA_VERSION == 10) FmPcdFragHcScratchPoolEmpty((t_Handle)p_FmPcd, p_Manip->fragParams.scratchBpid); #endif /* (DPAA_VERSION == 10) */ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_Frag); } } else if (p_Manip->reassm) { FmPcdUnregisterReassmPort(p_FmPcd, p_Manip->reassmParams.p_ReassCommonTbl); if (p_Manip->reassmParams.timeOutTblAddr) FM_MURAM_FreeMem( p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->reassmParams.timeOutTblAddr)); if (p_Manip->reassmParams.reassFrmDescrPoolTblAddr) XX_FreeSmart( UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrPoolTblAddr)); if (p_Manip->reassmParams.p_ReassCommonTbl) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->reassmParams.p_ReassCommonTbl); if (p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr) FM_MURAM_FreeMem( p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr)); if (p_Manip->reassmParams.internalBufferPoolManagementIndexAddr) FM_MURAM_FreeMem( p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolManagementIndexAddr)); if (p_Manip->reassmParams.internalBufferPoolAddr) FM_MURAM_FreeMem( p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolAddr)); if (p_Manip->reassmParams.hdr == HEADER_TYPE_CAPWAP) { } else { if (p_Manip->reassmParams.ip.ipv4AutoLearnHashTblAddr) XX_FreeSmart( UINT_TO_PTR(p_Manip->reassmParams.ip.ipv4AutoLearnHashTblAddr)); if (p_Manip->reassmParams.ip.ipv6AutoLearnHashTblAddr) XX_FreeSmart( UINT_TO_PTR(p_Manip->reassmParams.ip.ipv6AutoLearnHashTblAddr)); if (p_Manip->reassmParams.ip.ipv4AutoLearnSetLockTblAddr) XX_FreeSmart( UINT_TO_PTR(p_Manip->reassmParams.ip.ipv4AutoLearnSetLockTblAddr)); if (p_Manip->reassmParams.ip.ipv6AutoLearnSetLockTblAddr) XX_FreeSmart( UINT_TO_PTR(p_Manip->reassmParams.ip.ipv6AutoLearnSetLockTblAddr)); if (p_Manip->reassmParams.ip.p_Ipv4ReassTbl) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->reassmParams.ip.p_Ipv4ReassTbl); if (p_Manip->reassmParams.ip.p_Ipv6ReassTbl) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->reassmParams.ip.p_Ipv6ReassTbl); if (p_Manip->reassmParams.ip.h_Ipv6Ad) XX_FreeSmart(p_Manip->reassmParams.ip.h_Ipv6Ad); if (p_Manip->reassmParams.ip.h_Ipv4Ad) XX_FreeSmart(p_Manip->reassmParams.ip.h_Ipv4Ad); } } if (p_Manip->p_StatsTbl) FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_StatsTbl); } #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams) { if (p_ManipParams->u.hdr.rmv) { switch (p_ManipParams->u.hdr.rmvParams.type) { case (e_FM_PCD_MANIP_RMV_BY_HDR): switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type) { case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START) : if (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.include) { switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr) { case (HEADER_TYPE_CAPWAP_DTLS) : p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; p_Manip->muramAllocate = TRUE; if (p_ManipParams->u.hdr.insrt) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for CAPWAP_DTLS_HDR remove can not be insrt manipualtion after")); if (p_ManipParams->fragOrReasm) { if (!p_ManipParams->fragOrReasmParams.frag) { switch (p_ManipParams->fragOrReasmParams.hdr) { case (HEADER_TYPE_CAPWAP): p_Manip->opcode = HMAN_OC_CAPWAP_REASSEMBLY; break; default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("unsupported header for Reassembly")); } } else RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for this type of manipulation frag can not be TRUE")); } break; default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("non valid net header of remove location")); } } else { switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr) { case (HEADER_TYPE_CAPWAP_DTLS) : case (HEADER_TYPE_CAPWAP) : if (p_ManipParams->fragOrReasm || p_ManipParams->u.hdr.insrt) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for the type of remove e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_TILL_CAPWAP can not be insert or fragOrReasm TRUE")); p_Manip->opcode = HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR; p_Manip->muramAllocate = TRUE; p_ManipParams->u.hdr.insrt = TRUE; //internal frame header break; default : RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); } } break; default : RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); } break; default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); } } else if (p_ManipParams->u.hdr.insrt) { switch (p_ManipParams->u.hdr.insrtParams.type) { case (e_FM_PCD_MANIP_INSRT_BY_TEMPLATE) : p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; p_Manip->muramAllocate = FALSE; if (p_ManipParams->fragOrReasm) { if (p_ManipParams->fragOrReasmParams.frag) { switch (p_ManipParams->fragOrReasmParams.hdr) { case (HEADER_TYPE_CAPWAP): p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION; break; default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header for fragmentation")); } } else RETURN_ERROR(MAJOR, E_INVALID_STATE,("can not reach this point")); } break; default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for only isert manipulation unsupported type")); } } else if (p_ManipParams->fragOrReasm) { if (p_ManipParams->fragOrReasmParams.frag) { switch (p_ManipParams->fragOrReasmParams.hdr) { case (HEADER_TYPE_CAPWAP): p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION; p_Manip->muramAllocate = FALSE; break; default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for fragmentation")); } } else { switch (p_ManipParams->fragOrReasmParams.hdr) { case (HEADER_TYPE_CAPWAP): RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Reassembly has to be with additional operation - rmv = TRUE, type of remove - e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_INCLUDE_SPECIFIC_LOCATION,type = e_FM_PCD_MANIP_LOC_BY_HDR, hdr = HEADER_TYPE_CAPWAP_DTLS")); default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for reassembly")); } } } else RETURN_ERROR(MAJOR, E_INVALID_STATE, ("User didn't ask for any manipulation")); p_Manip->insrt = p_ManipParams->u.hdr.insrt; p_Manip->rmv = p_ManipParams->u.hdr.rmv; return E_OK; } #else /* not (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams) { switch (p_ManipParams->type) { case e_FM_PCD_MANIP_HDR: /* Check that next-manip is not already used */ if (p_ManipParams->h_NextManip) { if (!MANIP_IS_FIRST(p_ManipParams->h_NextManip)) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("h_NextManip is already a part of another chain")); if ((MANIP_GET_TYPE(p_ManipParams->h_NextManip) != e_FM_PCD_MANIP_HDR) && (MANIP_GET_TYPE(p_ManipParams->h_NextManip) != e_FM_PCD_MANIP_FRAG)) RETURN_ERROR( MAJOR, E_NOT_SUPPORTED, ("For a Header Manipulation node - no support of h_NextManip of type other than Header Manipulation or Fragmentation.")); } if (p_ManipParams->u.hdr.rmv) { switch (p_ManipParams->u.hdr.rmvParams.type) { case (e_FM_PCD_MANIP_RMV_BY_HDR): switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type) { case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2): break; #if (DPAA_VERSION >= 11) case (e_FM_PCD_MANIP_RMV_BY_HDR_CAPWAP): break; case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START): { t_Error err; uint8_t prsArrayOffset; err = GetPrOffsetByHeaderOrField( &p_ManipParams->u.hdr.rmvParams.u.byHdr.u.hdrInfo, &prsArrayOffset); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); break; } #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR( MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); } break; case (e_FM_PCD_MANIP_RMV_GENERIC): break; default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); } p_Manip->opcode = HMAN_OC; p_Manip->muramAllocate = TRUE; p_Manip->rmv = TRUE; } else if (p_ManipParams->u.hdr.insrt) { switch (p_ManipParams->u.hdr.insrtParams.type) { case (e_FM_PCD_MANIP_INSRT_BY_HDR): { switch (p_ManipParams->u.hdr.insrtParams.u.byHdr.type) { case (e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2): /* nothing to check */ break; #if (DPAA_VERSION >= 11) case (e_FM_PCD_MANIP_INSRT_BY_HDR_IP): if (p_ManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size % 4) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("IP inserted header must be of size which is a multiple of four bytes")); break; case (e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP): if (p_ManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size % 4) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("CAPWAP inserted header must be of size which is a multiple of four bytes")); break; case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP): case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE): if (p_ManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size != 8) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("Inserted header must be of size 8")); break; #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR( MAJOR, E_INVALID_STATE, ("unsupported insert by header type")); } } case (e_FM_PCD_MANIP_INSRT_GENERIC): break; default: RETURN_ERROR( MAJOR, E_INVALID_STATE, ("for only insert manipulation unsupported type")); } p_Manip->opcode = HMAN_OC; p_Manip->muramAllocate = TRUE; p_Manip->insrt = TRUE; } else if (p_ManipParams->u.hdr.fieldUpdate) { /* Check parameters */ if (p_ManipParams->u.hdr.fieldUpdateParams.type == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN) { if ((p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI) && (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri > 7)) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("vpri should get values of 0-7 ")); if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) { int i; if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal > 7) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("vpriDefVal should get values of 0-7 ")); for (i = 0; i < FM_PCD_MANIP_DSCP_TO_VLAN_TRANS; i++) if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i] & 0xf0) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("dscpToVpriTabl value out of range (0-15)")); } } p_Manip->opcode = HMAN_OC; p_Manip->muramAllocate = TRUE; p_Manip->fieldUpdate = TRUE; } else if (p_ManipParams->u.hdr.custom) { if (p_ManipParams->u.hdr.customParams.type == e_FM_PCD_MANIP_HDR_CUSTOM_GEN_FIELD_REPLACE) { if ((p_ManipParams->u.hdr.customParams.u.genFieldReplace.size == 0) || (p_ManipParams->u.hdr.customParams.u.genFieldReplace.size > 8)) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("size should get values of 1-8 ")); if (p_ManipParams->u.hdr.customParams.u.genFieldReplace.srcOffset > 7) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("srcOffset should be <= 7")); if ((p_ManipParams->u.hdr.customParams.u.genFieldReplace.srcOffset + p_ManipParams->u.hdr.customParams.u.genFieldReplace.size) > 8) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("(srcOffset + size) should be <= 8")); if ((p_ManipParams->u.hdr.customParams.u.genFieldReplace.dstOffset + p_ManipParams->u.hdr.customParams.u.genFieldReplace.size) > 256) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("(dstOffset + size) should be <= 256")); } p_Manip->opcode = HMAN_OC; p_Manip->muramAllocate = TRUE; p_Manip->custom = TRUE; } break; case e_FM_PCD_MANIP_REASSEM: if (p_ManipParams->h_NextManip) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("next manip with reassembly")); switch (p_ManipParams->u.reassem.hdr) { case (HEADER_TYPE_IPv4): p_Manip->reassmParams.hdr = HEADER_TYPE_IPv4; p_Manip->opcode = HMAN_OC_IP_REASSEMBLY; break; case (HEADER_TYPE_IPv6): p_Manip->reassmParams.hdr = HEADER_TYPE_IPv6; p_Manip->opcode = HMAN_OC_IP_REASSEMBLY; break; #if (DPAA_VERSION >= 11) case (HEADER_TYPE_CAPWAP): p_Manip->reassmParams.hdr = HEADER_TYPE_CAPWAP; p_Manip->opcode = HMAN_OC_CAPWAP_REASSEMBLY; break; #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header for reassembly")); } break; case e_FM_PCD_MANIP_FRAG: if (p_ManipParams->h_NextManip) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("next manip with fragmentation")); switch (p_ManipParams->u.frag.hdr) { case (HEADER_TYPE_IPv4): case (HEADER_TYPE_IPv6): p_Manip->opcode = HMAN_OC_IP_FRAGMENTATION; break; #if (DPAA_VERSION >= 11) case (HEADER_TYPE_CAPWAP): p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION; break; #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header for fragmentation")); } p_Manip->muramAllocate = TRUE; break; case e_FM_PCD_MANIP_SPECIAL_OFFLOAD: switch (p_ManipParams->u.specialOffload.type) { case (e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC): p_Manip->opcode = HMAN_OC_IPSEC_MANIP; p_Manip->muramAllocate = TRUE; break; #if (DPAA_VERSION >= 11) case (e_FM_PCD_MANIP_SPECIAL_OFFLOAD_CAPWAP): p_Manip->opcode = HMAN_OC_CAPWAP_MANIP; p_Manip->muramAllocate = TRUE; break; #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("special offload type")); } break; default: RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("manip type")); } return E_OK; } #endif /* not (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) static t_Error UpdateIndxStats(t_Handle h_FmPcd, t_Handle h_FmPort, t_FmPcdManip *p_Manip) { t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; uint32_t tmpReg32 = 0; t_AdOfTypeContLookup *p_Ad; t_FmPortGetSetCcParams fmPortGetSetCcParams; t_Error err; SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; if (p_Manip->h_FmPcd != h_FmPcd) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("handler of PCD previously was initiated by different value")); memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); if (!p_Manip->p_StatsTbl) { fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN; fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC; err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); tmpReg32 = GET_UINT32(p_Ad->ccAdBase); p_Manip->p_StatsTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)p_Manip->owner * FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE, 4); if (!p_Manip->p_StatsTbl) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation indexed statistics table")); IOMemSet32(p_Manip->p_StatsTbl, 0, (uint32_t)(p_Manip->owner * 4)); tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->p_StatsTbl) - p_FmPcd->physicalMuramBase); if (p_Manip->cnia) tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_CNIA; tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_DPD; WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); } else { fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN; fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC; err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); } return E_OK; } static t_Error RmvHdrTillSpecLocNOrInsrtIntFrmHdr(t_FmPcdManipHdrRmvParams *p_ManipParams, t_FmPcdManip *p_Manip) { t_AdOfTypeContLookup *p_Ad; uint32_t tmpReg32 = 0; uint8_t prsArrayOffset = 0; t_Error err; SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER); SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER); SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; if (p_Manip->rmv) { err = GetPrOffsetByHeaderOrField(&p_ManipParams->u.byHdr.u.fromStartByHdr.hdrInfo, &prsArrayOffset); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); tmpReg32 |= (uint32_t)prsArrayOffset << 24; tmpReg32 |= HMAN_RMV_HDR; } if (p_Manip->insrt) tmpReg32 |= HMAN_INSRT_INT_FRM_HDR; tmpReg32 |= (uint32_t)HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR; WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); tmpReg32 = 0; tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); return E_OK; } static t_Error MvIntFrameHeaderFromFrameToBufferPrefix(t_FmPcdManip *p_Manip, bool caamUsed) { t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; uint32_t tmpReg32 = 0; SANITY_CHECK_RETURN_ERROR(p_Ad, E_INVALID_HANDLE); p_Manip->updateParams |= OFFSET_OF_PR | INTERNAL_CONTEXT_OFFSET; tmpReg32 = 0; tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; *(uint32_t *)&p_Ad->ccAdBase = tmpReg32; tmpReg32 = 0; tmpReg32 |= HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX; tmpReg32 |= (uint32_t)0x16 << 16; *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32; if (caamUsed) *(uint32_t *)&p_Ad->gmask = 0xf0000000; return E_OK; } static t_Error CapwapRmvDtlsHdr(t_FmPcd *p_FmPcd, t_FmPcdManip *p_Manip) { t_AdOfTypeContLookup *p_Ad; uint32_t tmpReg32 = 0; t_Error err = E_OK; SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; tmpReg32 = 0; tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); tmpReg32 = 0; tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; if (p_Manip->h_Frag) { p_Manip->updateParams |= INTERNAL_CONTEXT_OFFSET; tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase)); } WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); return err; } static t_Error CapwapReassembly(t_CapwapReassemblyParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd, uint8_t poolId) { t_Handle p_Table; uint32_t tmpReg32 = 0; int i = 0; uint8_t log2Num; uint8_t numOfSets; uint32_t j = 0; uint32_t bitFor1Micro; SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); if (!p_FmPcd->h_Hc) RETURN_ERROR(MAJOR, E_INVALID_VALUE,("hc port has to be initialized in this mode")); if (!POWER_OF_2(p_ManipParams->timeoutRoutineRequestTime)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("timeoutRoutineRequestTime has to be power of 2")); if (!POWER_OF_2(p_ManipParams->maxNumFramesInProcess)) RETURN_ERROR(MAJOR, E_INVALID_VALUE,("maxNumFramesInProcess has to be power of 2")); if (!p_ManipParams->timeoutRoutineRequestTime && p_ManipParams->timeoutThresholdForReassmProcess) DBG(WARNING, ("if timeoutRoutineRequestTime 0, timeoutThresholdForReassmProcess is uselessly")); if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH) { if ((p_ManipParams->maxNumFramesInProcess < 4) || (p_ManipParams->maxNumFramesInProcess > 512)) RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_EIGHT_WAYS_HASH maxNumFramesInProcess has to be in the range 4-512")); } else { if ((p_ManipParams->maxNumFramesInProcess < 8) || (p_ManipParams->maxNumFramesInProcess > 2048)) RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_FOUR_WAYS_HASH maxNumFramesInProcess has to be in the range 8-2048")); } bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); if (bitFor1Micro == 0) RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale")); p_Manip->updateParams |= (NUM_OF_TASKS | OFFSET_OF_PR | OFFSET_OF_DATA | HW_PORT_ID); p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE, FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN); if (!p_Manip->h_Frag) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc CAPWAP reassembly parameters table")); IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE); p_Table = (t_CapwapReasmPram *)p_Manip->h_Frag; p_Manip->capwapFragParams.p_AutoLearnHashTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN); if (!p_Manip->capwapFragParams.p_AutoLearnHashTbl) RETURN_ERROR(MAJOR, E_NO_MEMORY,("MURAM alloc for CAPWAP automatic learning hash table")); IOMemSet32(p_Manip->capwapFragParams.p_AutoLearnHashTbl, 0, (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE)); tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_AutoLearnHashTbl) - p_FmPcd->physicalMuramBase); WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->autoLearnHashTblPtr, tmpReg32); tmpReg32 = 0; if (p_ManipParams->timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES) tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES; if (p_ManipParams->haltOnDuplicationFrag) tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG; if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH) { i = 8; tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS; } else i = 4; numOfSets = (uint8_t)((p_ManipParams->maxNumFramesInProcess * 2) / i); LOG2(numOfSets, log2Num); tmpReg32 |= (uint32_t)(log2Num - 1) << 24; WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->mode, tmpReg32); for (j=0; jmaxNumFramesInProcess*2; j++) if (((j / i) % 2)== 0) WRITE_UINT32(*(uint32_t *)PTR_MOVE(p_Manip->capwapFragParams.p_AutoLearnHashTbl, j * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), 0x80000000); tmpReg32 = 0x00008000; tmpReg32 |= (uint32_t)poolId << 16; WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->bufferPoolIdAndRisc1SetIndexes, tmpReg32); WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc23SetIndexes, 0x80008000); WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc4SetIndexesAndExtendedStatsTblPtr, 0x80000000); p_Manip->capwapFragParams.maxNumFramesInProcess = p_ManipParams->maxNumFramesInProcess; p_Manip->capwapFragParams.sgBpid = poolId; p_Manip->capwapFragParams.fqidForTimeOutFrames = p_ManipParams->fqidForTimeOutFrames; p_Manip->capwapFragParams.timeoutRoutineRequestTime = p_ManipParams->timeoutRoutineRequestTime; p_Manip->capwapFragParams.bitFor1Micro = bitFor1Micro; tmpReg32 = 0; tmpReg32 |= (((uint32_t)1<capwapFragParams.bitFor1Micro) * p_ManipParams->timeoutThresholdForReassmProcess); WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->expirationDelay, tmpReg32); return E_OK; } static t_Error CapwapFragmentation(t_CapwapFragmentationParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd, uint8_t poolId) { t_AdOfTypeContLookup *p_Ad; uint32_t tmpReg32 = 0; SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); p_Manip->updateParams |= OFFSET_OF_DATA; p_Manip->frag = TRUE; p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN); if (!p_Manip->h_Frag) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP fragmentation table descriptor")); IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; tmpReg32 = 0; tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_FRAGMENTATION; if (p_ManipParams->headerOptionsCompr) tmpReg32 |= FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN; tmpReg32 |= ((uint32_t)poolId << 8); WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); tmpReg32 = 0; tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation; p_Manip->capwapFragParams.sgBpid = poolId; return E_OK; } static t_Error IndxStats(t_FmPcdStatsParams *p_StatsParams,t_FmPcdManip *p_Manip,t_FmPcd *p_FmPcd) { t_AdOfTypeContLookup *p_Ad; uint32_t tmpReg32 = 0; SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); UNUSED(p_FmPcd); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; tmpReg32 = 0; tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_INDEXED_STATS; if (p_StatsParams->type == e_FM_PCD_STATS_PER_FLOWID) tmpReg32 |= (uint32_t)0x16 << 16; WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); tmpReg32 = 0; tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); return E_OK; } static t_Error InsrtHdrByTempl(t_FmPcdManipHdrInsrtParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd) { t_FmPcdManipHdrInsrtByTemplateParams *p_InsrtByTemplate = &p_ManipParams->u.byTemplate; uint8_t tmpReg8 = 0xff; t_AdOfTypeContLookup *p_Ad; bool ipModify = FALSE; uint32_t tmpReg32 = 0, tmpRegNia = 0; uint16_t tmpReg16 = 0; t_Error err = E_OK; uint8_t extraAddedBytes = 0, blockSize = 0, extraAddedBytesAlignedToBlockSize = 0, log2Num = 0; uint8_t *p_Template = NULL; SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER); SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER); SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_NULL_POINTER); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; if (p_Manip->insrt) { if ((!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp) || (!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterVlan)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : asking for header template modifications with no template for insertion (template size)")); if (p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp && (p_InsrtByTemplate->size <= p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : size of template < ipOuterOffset")); if (p_InsrtByTemplate->size > 128) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size of header template for insertion can not be more than 128")); if (p_InsrtByTemplate->size) { p_Manip->p_Template = (uint8_t *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, p_InsrtByTemplate->size, FM_PCD_CC_AD_TABLE_ALIGN); if(!p_Manip->p_Template) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED")); tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->p_Template) - (p_FmPcd->physicalMuramBase)); tmpReg32 |= (uint32_t)p_InsrtByTemplate->size << 24; *(uint32_t *)&p_Ad->matchTblPtr = tmpReg32; } tmpReg32 = 0; p_Template = (uint8_t *)XX_Malloc(p_InsrtByTemplate->size * sizeof(uint8_t)); if (!p_Template) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("XX_Malloc allocation FAILED")); memcpy(p_Template, p_InsrtByTemplate->hdrTemplate, p_InsrtByTemplate->size * sizeof(uint8_t)); if (p_InsrtByTemplate->modifyOuterIp) { ipModify = TRUE; tmpReg8 = (uint8_t)p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset]; if((tmpReg8 & 0xf0) == 0x40) tmpReg8 = 4; else if((tmpReg8 & 0xf0) == 0x60) tmpReg8 = 6; else tmpReg8 = 0xff; if (tmpReg8 != 0xff) { if(p_InsrtByTemplate->modifyOuterIpParams.dscpEcn & 0xff00) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IPV4 present in header template, dscpEcn has to be only 1 byte")); if(p_InsrtByTemplate->modifyOuterIpParams.recalculateLength) { if((p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize) > 255) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("extra Byte added can not be more than 256 bytes")); extraAddedBytes = (uint8_t) (p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize); blockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.blockSize; extraAddedBytesAlignedToBlockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize; /*IP header template - IP totalLength - (1 byte) extraByteForIp = headerTemplateSize - ipOffset + insertedBytesAfterThisStage , in the case of SEC insertedBytesAfterThisStage - SEC trailer (21/31) + header(13) second byte - extraByteForIp = headerTemplate - ipOffset + insertedBytesAfterThisStage*/ } if (blockSize) { if (!POWER_OF_2(blockSize)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("inputFrmPaddingUpToBlockSize has to be power of 2")); } } if (tmpReg8 == 4) { if ((IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset) > p_InsrtByTemplate->size) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IP present in header template, user asked for IP modifications but ipOffset + ipTotalLengthFieldOffset in header template bigger than template size")); p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_DSCECN_FIELD_OFFSET_FROM_IP] = (uint8_t)p_InsrtByTemplate->modifyOuterIpParams.dscpEcn; if (blockSize) blockSize -= 1; if ((p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes) > 255) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes has to be less than 255")); p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP + 1] = blockSize; // IPV6 - in AD instead of SEQ IND p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes);// for IPV6 decrement additional 40 bytes of IPV6 heade size p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP] = 0x00; p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize; /*IP header template - relevant only for ipv4 CheckSum = 0*/ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP] = 0x00; p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + 1] = 0x00; /*UDP checksum has to be 0*/ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent) { if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template")); p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP ] = 0x00; p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00; } if (p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId > 7) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("ipIdentGenId has to be one out of 8 sequence number generators (0 - 7) for IP identification field")); tmpRegNia |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId<<24; } else if (tmpReg8 == 6) { /*TODO - add check for maximum value of blockSize;*/ if (blockSize) LOG2(blockSize, log2Num); tmpRegNia |= (uint32_t)log2Num << 24; // for IPV6 decrement additional 40 bytes of IPV6 heade size - because IPV6 header size is not included in payloadLength p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes - 40); p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize; if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent) { if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template")); if (p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_NEXT_HEADER_OFFSET_FROM_IP] != 0x88) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("OUr suppport is only IPv6/UDPLite")); p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP] = 0x00; p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP + 1] = 0x08; p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP] = 0x00; p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00; } } else RETURN_ERROR(MAJOR, E_INVALID_STATE, ("IP version supported only IPV4")); } tmpReg32 = tmpReg16 = tmpReg8 = 0; /*TODO - check it*/ if (p_InsrtByTemplate->modifyOuterVlan) { if (p_InsrtByTemplate->modifyOuterVlanParams.vpri & ~0x07) RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but VPRI more than 3 bits")); memcpy(&tmpReg16, &p_Template[VLAN_TAG_FIELD_OFFSET_FROM_ETH], 2*(sizeof(uint8_t))); if ((tmpReg16 != 0x9100) && (tmpReg16!= 0x9200) && (tmpReg16 != 0x8100)) RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but Tag Protocol identifier is not VLAN ")); memcpy(&tmpReg8, &p_Template[14],1*(sizeof(uint8_t))); tmpReg8 &= 0x1f; tmpReg8 |= (uint8_t)(p_InsrtByTemplate->modifyOuterVlanParams.vpri << 5); p_Template[14] = tmpReg8; } Mem2IOCpy32(p_Manip->p_Template, p_Template, p_InsrtByTemplate->size); XX_Free(p_Template); } tmpReg32 = 0; if (p_Manip->h_Frag) { tmpRegNia |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase)); tmpReg32 |= (uint32_t)p_Manip->sizeForFragmentation << 16; } else tmpReg32 = 0xffff0000; if (ipModify) tmpReg32 |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset << 8; else tmpReg32 |= (uint32_t)0x0000ff00; tmpReg32 |= (uint32_t)HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32; tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE; *(uint32_t *)&p_Ad->ccAdBase = tmpRegNia; return err; } static t_Error CheckStatsParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdStatsParams *p_StatsParams) { switch (p_StatsParams->type) { case (e_FM_PCD_STATS_PER_FLOWID): p_Manip->opcode = HMAN_OC_CAPWAP_INDEXED_STATS; p_Manip->muramAllocate = TRUE; break; default: RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported statistics type")); } return E_OK; } #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ static t_Error FillReassmManipParams(t_FmPcdManip *p_Manip, e_NetHeaderType hdr) { t_AdOfTypeContLookup *p_Ad; t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; uint32_t tmpReg32; t_Error err = E_OK; /* Creates the Reassembly Parameters table. It contains parameters that are specific to either the IPv4 reassembly function or to the IPv6 reassembly function. If both IPv4 reassembly and IPv6 reassembly are required, then two separate IP Reassembly Parameter tables are required.*/ if ((err = CreateReassTable(p_Manip, hdr)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); /* Sets the first Ad register (ccAdBase) - Action Descriptor Type and Pointer to the Reassembly Parameters Table offset from MURAM*/ tmpReg32 = 0; tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; /* Gets the required Action descriptor table pointer */ switch (hdr) { case HEADER_TYPE_IPv4: p_Ad = (t_AdOfTypeContLookup *)p_Manip->reassmParams.ip.h_Ipv4Ad; tmpReg32 |= (uint32_t)(XX_VirtToPhys( p_Manip->reassmParams.ip.p_Ipv4ReassTbl) - (p_FmPcd->physicalMuramBase)); break; case HEADER_TYPE_IPv6: p_Ad = (t_AdOfTypeContLookup *)p_Manip->reassmParams.ip.h_Ipv6Ad; tmpReg32 |= (uint32_t)(XX_VirtToPhys( p_Manip->reassmParams.ip.p_Ipv6ReassTbl) - (p_FmPcd->physicalMuramBase)); break; case HEADER_TYPE_CAPWAP: p_Ad = (t_AdOfTypeContLookup *)p_Manip->reassmParams.capwap.h_Ad; tmpReg32 |= (uint32_t)(XX_VirtToPhys( p_Manip->reassmParams.capwap.p_ReassTbl) - (p_FmPcd->physicalMuramBase)); break; default: RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header type")); } WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); /* Sets the second Ad register (matchTblPtr) - Buffer pool ID (BPID for V2) and Scatter/Gather table offset*/ /* mark the Scatter/Gather table offset to be set later on when the port will be known */ p_Manip->updateParams = (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK); if ((hdr == HEADER_TYPE_IPv6) || (hdr == HEADER_TYPE_IPv4)) { #if (DPAA_VERSION == 10) tmpReg32 = (uint32_t)(p_Manip->reassmParams.sgBpid << 8); WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32); #endif /* (DPAA_VERSION == 10) */ #if (DPAA_VERSION >= 11) if (p_Manip->reassmParams.ip.nonConsistentSpFqid != 0) { tmpReg32 = FM_PCD_AD_NCSPFQIDM_MASK | (uint32_t)(p_Manip->reassmParams.ip.nonConsistentSpFqid); WRITE_UINT32(p_Ad->gmask, tmpReg32); } #endif /* (DPAA_VERSION >= 11) */ /* Sets the third Ad register (pcAndOffsets)- IP Reassemble Operation Code*/ tmpReg32 = 0; tmpReg32 |= (uint32_t)HMAN_OC_IP_REASSEMBLY; } #if (DPAA_VERSION >= 11) else if (hdr == HEADER_TYPE_CAPWAP) { tmpReg32 = 0; tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_REASSEMBLY; } #endif /* (DPAA_VERSION >= 11) */ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); p_Manip->reassm = TRUE; return E_OK; } static t_Error SetIpv4ReassmManip(t_FmPcdManip *p_Manip) { t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; /* Allocation if IPv4 Action descriptor */ p_Manip->reassmParams.ip.h_Ipv4Ad = (t_Handle)XX_MallocSmart( FM_PCD_CC_AD_ENTRY_SIZE, p_Manip->reassmParams.dataMemId, FM_PCD_CC_AD_TABLE_ALIGN); if (!p_Manip->reassmParams.ip.h_Ipv4Ad) { ReleaseManipHandler(p_Manip, p_FmPcd); RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of IPv4 table descriptor")); } memset(p_Manip->reassmParams.ip.h_Ipv4Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */ return FillReassmManipParams(p_Manip, HEADER_TYPE_IPv4); } static t_Error SetIpv6ReassmManip(t_FmPcdManip *p_Manip) { t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; /* Allocation if IPv6 Action descriptor */ p_Manip->reassmParams.ip.h_Ipv6Ad = (t_Handle)XX_MallocSmart( FM_PCD_CC_AD_ENTRY_SIZE, p_Manip->reassmParams.dataMemId, FM_PCD_CC_AD_TABLE_ALIGN); if (!p_Manip->reassmParams.ip.h_Ipv6Ad) { ReleaseManipHandler(p_Manip, p_FmPcd); RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of IPv6 table descriptor")); } memset(p_Manip->reassmParams.ip.h_Ipv6Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */ return FillReassmManipParams(p_Manip, HEADER_TYPE_IPv6); } static t_Error IpReassembly(t_FmPcdManipReassemParams *p_ManipReassmParams, t_FmPcdManip *p_Manip) { uint32_t maxSetNumber = 10000; t_FmPcdManipReassemIpParams reassmManipParams = p_ManipReassmParams->u.ipReassem; t_Error res; SANITY_CHECK_RETURN_ERROR(p_Manip->h_FmPcd, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(((t_FmPcd *)p_Manip->h_FmPcd)->h_Hc, E_INVALID_HANDLE); /* Check validation of user's parameter.*/ if ((reassmManipParams.timeoutThresholdForReassmProcess < 1000) || (reassmManipParams.timeoutThresholdForReassmProcess > 8000000)) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("timeoutThresholdForReassmProcess should be 1msec - 8sec")); /* It is recommended that the total number of entries in this table (number of sets * number of ways) will be twice the number of frames that are expected to be reassembled simultaneously.*/ if (reassmManipParams.maxNumFramesInProcess > (reassmManipParams.maxNumFramesInProcess * maxSetNumber / 2)) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("maxNumFramesInProcess has to be less than (maximun set number * number of ways / 2)")); if ((p_ManipReassmParams->hdr == HEADER_TYPE_IPv6) && (reassmManipParams.minFragSize[1] < 256)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("minFragSize[1] must be >= 256")); /* Saves user's reassembly manipulation parameters */ p_Manip->reassmParams.ip.relativeSchemeId[0] = reassmManipParams.relativeSchemeId[0]; p_Manip->reassmParams.ip.relativeSchemeId[1] = reassmManipParams.relativeSchemeId[1]; p_Manip->reassmParams.ip.numOfFramesPerHashEntry[0] = reassmManipParams.numOfFramesPerHashEntry[0]; p_Manip->reassmParams.ip.numOfFramesPerHashEntry[1] = reassmManipParams.numOfFramesPerHashEntry[1]; p_Manip->reassmParams.ip.minFragSize[0] = reassmManipParams.minFragSize[0]; p_Manip->reassmParams.ip.minFragSize[1] = reassmManipParams.minFragSize[1]; p_Manip->reassmParams.maxNumFramesInProcess = reassmManipParams.maxNumFramesInProcess; p_Manip->reassmParams.timeOutMode = reassmManipParams.timeOutMode; p_Manip->reassmParams.fqidForTimeOutFrames = reassmManipParams.fqidForTimeOutFrames; p_Manip->reassmParams.timeoutThresholdForReassmProcess = reassmManipParams.timeoutThresholdForReassmProcess; p_Manip->reassmParams.dataMemId = reassmManipParams.dataMemId; p_Manip->reassmParams.dataLiodnOffset = reassmManipParams.dataLiodnOffset; #if (DPAA_VERSION == 10) p_Manip->reassmParams.sgBpid = reassmManipParams.sgBpid; #endif /* (DPAA_VERSION == 10) */ #if (DPAA_VERSION >= 11) if (reassmManipParams.nonConsistentSpFqid != 0) { p_Manip->reassmParams.ip.nonConsistentSpFqid = reassmManipParams.nonConsistentSpFqid; } #endif /* (DPAA_VERSION >= 11) */ /* Creates and initializes the IP Reassembly common parameter table */ CreateReassCommonTable(p_Manip); /* Creation of IPv4 reassembly manipulation */ if ((p_Manip->reassmParams.hdr == HEADER_TYPE_IPv6) || (p_Manip->reassmParams.hdr == HEADER_TYPE_IPv4)) { res = SetIpv4ReassmManip(p_Manip); if (res != E_OK) return res; } /* Creation of IPv6 reassembly manipulation */ if (p_Manip->reassmParams.hdr == HEADER_TYPE_IPv6) { res = SetIpv6ReassmManip(p_Manip); if (res != E_OK) return res; } return E_OK; } static void setIpReassmSchemeParams(t_FmPcd* p_FmPcd, t_FmPcdKgSchemeParams *p_Scheme, t_Handle h_CcTree, bool ipv4, uint8_t groupId) { uint32_t j; uint8_t res; /* Configures scheme's network environment parameters */ p_Scheme->netEnvParams.numOfDistinctionUnits = 2; if (ipv4) res = FmPcdNetEnvGetUnitId( p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_IPv4, FALSE, 0); else res = FmPcdNetEnvGetUnitId( p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_IPv6, FALSE, 0); ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); p_Scheme->netEnvParams.unitIds[0] = res; res = FmPcdNetEnvGetUnitId( p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_USER_DEFINED_SHIM2, FALSE, 0); ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); p_Scheme->netEnvParams.unitIds[1] = res; /* Configures scheme's next engine parameters*/ p_Scheme->nextEngine = e_FM_PCD_CC; p_Scheme->kgNextEngineParams.cc.h_CcTree = h_CcTree; p_Scheme->kgNextEngineParams.cc.grpId = groupId; p_Scheme->useHash = TRUE; /* Configures scheme's key*/ if (ipv4 == TRUE) { p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 4; p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_BY_HDR; p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = HEADER_TYPE_IPv4; p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_DST_IP; p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_BY_HDR; p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = HEADER_TYPE_IPv4; p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_SRC_IP; p_Scheme->keyExtractAndHashParams.extractArray[2].type = e_FM_PCD_EXTRACT_BY_HDR; p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = HEADER_TYPE_IPv4; p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_PROTO; p_Scheme->keyExtractAndHashParams.extractArray[3].type = e_FM_PCD_EXTRACT_BY_HDR; p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.hdr = HEADER_TYPE_IPv4; p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.ignoreProtocolValidation = FALSE; p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.size = 2; p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.offset = 4; } else /* IPv6 */ { p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 3; p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_BY_HDR; p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = HEADER_TYPE_IPv6; p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv6 = NET_HEADER_FIELD_IPv6_DST_IP; p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_BY_HDR; p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD; p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = HEADER_TYPE_IPv6; p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv6 = NET_HEADER_FIELD_IPv6_SRC_IP; p_Scheme->keyExtractAndHashParams.extractArray[2].type = e_FM_PCD_EXTRACT_BY_HDR; p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = HEADER_TYPE_USER_DEFINED_SHIM2; p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.size = 4; p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.offset = 4; p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.ignoreProtocolValidation = TRUE; } p_Scheme->keyExtractAndHashParams.privateDflt0 = 0x01020304; p_Scheme->keyExtractAndHashParams.privateDflt1 = 0x11121314; p_Scheme->keyExtractAndHashParams.numOfUsedDflts = FM_PCD_KG_NUM_OF_DEFAULT_GROUPS; for (j = 0; j < FM_PCD_KG_NUM_OF_DEFAULT_GROUPS; j++) { p_Scheme->keyExtractAndHashParams.dflts[j].type = (e_FmPcdKgKnownFieldsDfltTypes)j; /* all types */ p_Scheme->keyExtractAndHashParams.dflts[j].dfltSelect = e_FM_PCD_KG_DFLT_GBL_0; } } static t_Error IpReassemblyStats(t_FmPcdManip *p_Manip, t_FmPcdManipReassemIpStats *p_Stats) { ASSERT_COND(p_Manip); ASSERT_COND(p_Stats); ASSERT_COND(p_Manip->reassmParams.p_ReassCommonTbl); p_Stats->timeout = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalTimeOutCounter); p_Stats->rfdPoolBusy = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalRfdPoolBusyCounter); p_Stats->internalBufferBusy = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalInternalBufferBusy); p_Stats->externalBufferBusy = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalExternalBufferBusy); p_Stats->sgFragments = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalSgFragmentCounter); p_Stats->dmaSemaphoreDepletion = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalDmaSemaphoreDepletionCounter); #if (DPAA_VERSION >= 11) p_Stats->nonConsistentSp = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalNCSPCounter); #endif /* (DPAA_VERSION >= 11) */ if (p_Manip->reassmParams.ip.p_Ipv4ReassTbl) { p_Stats->specificHdrStatistics[0].successfullyReassembled = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalSuccessfullyReasmFramesCounter); p_Stats->specificHdrStatistics[0].validFragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalValidFragmentCounter); p_Stats->specificHdrStatistics[0].processedFragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalProcessedFragCounter); p_Stats->specificHdrStatistics[0].malformedFragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalMalformdFragCounter); p_Stats->specificHdrStatistics[0].autoLearnBusy = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalSetBusyCounter); p_Stats->specificHdrStatistics[0].discardedFragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalDiscardedFragsCounter); p_Stats->specificHdrStatistics[0].moreThan16Fragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalMoreThan16FramesCounter); } if (p_Manip->reassmParams.ip.p_Ipv6ReassTbl) { p_Stats->specificHdrStatistics[1].successfullyReassembled = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalSuccessfullyReasmFramesCounter); p_Stats->specificHdrStatistics[1].validFragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalValidFragmentCounter); p_Stats->specificHdrStatistics[1].processedFragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalProcessedFragCounter); p_Stats->specificHdrStatistics[1].malformedFragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalMalformdFragCounter); p_Stats->specificHdrStatistics[1].autoLearnBusy = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalSetBusyCounter); p_Stats->specificHdrStatistics[1].discardedFragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalDiscardedFragsCounter); p_Stats->specificHdrStatistics[1].moreThan16Fragments = GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalMoreThan16FramesCounter); } return E_OK; } static t_Error IpFragmentationStats(t_FmPcdManip *p_Manip, t_FmPcdManipFragIpStats *p_Stats) { t_AdOfTypeContLookup *p_Ad; ASSERT_COND(p_Manip); ASSERT_COND(p_Stats); ASSERT_COND(p_Manip->h_Ad); ASSERT_COND(p_Manip->fragParams.p_Frag); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; p_Stats->totalFrames = GET_UINT32(p_Ad->gmask); p_Stats->fragmentedFrames = GET_UINT32(p_Manip->fragParams.p_Frag->ccAdBase) & 0x00ffffff; p_Stats->generatedFragments = GET_UINT32(p_Manip->fragParams.p_Frag->matchTblPtr); return E_OK; } static t_Error IpFragmentation(t_FmPcdManipFragIpParams *p_ManipParams, t_FmPcdManip *p_Manip) { uint32_t pcAndOffsetsReg = 0, ccAdBaseReg = 0, gmaskReg = 0; t_FmPcd *p_FmPcd; #if (DPAA_VERSION == 10) t_Error err = E_OK; #endif /* (DPAA_VERSION == 10) */ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_ManipParams->sizeForFragmentation != 0xFFFF, E_INVALID_VALUE); p_FmPcd = p_Manip->h_FmPcd; /* Allocation of fragmentation Action Descriptor */ p_Manip->fragParams.p_Frag = (t_AdOfTypeContLookup *)FM_MURAM_AllocMem( p_FmPcd->h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN); if (!p_Manip->fragParams.p_Frag) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Fragmentation table descriptor")); IOMemSet32(p_Manip->fragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); /* Prepare the third Ad register (pcAndOffsets)- OperationCode */ pcAndOffsetsReg = (uint32_t)HMAN_OC_IP_FRAGMENTATION; /* Prepare the first Ad register (ccAdBase) - Don't frag action and Action descriptor type*/ ccAdBaseReg = FM_PCD_AD_CONT_LOOKUP_TYPE; ccAdBaseReg |= (p_ManipParams->dontFragAction << FM_PCD_MANIP_IP_FRAG_DF_SHIFT); /* Set Scatter/Gather BPid */ if (p_ManipParams->sgBpidEn) { ccAdBaseReg |= FM_PCD_MANIP_IP_FRAG_SG_BDID_EN; pcAndOffsetsReg |= ((p_ManipParams->sgBpid << FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT) & FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK); } /* Prepare the first Ad register (gmask) - scratch buffer pool id and Pointer to fragment ID */ gmaskReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr)) - p_FmPcd->physicalMuramBase); #if (DPAA_VERSION == 10) gmaskReg |= p_ManipParams->scratchBpid << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID; #else gmaskReg |= (0xFF) << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID; #endif /* (DPAA_VERSION == 10) */ /* Set all Ad registers */ WRITE_UINT32(p_Manip->fragParams.p_Frag->pcAndOffsets, pcAndOffsetsReg); WRITE_UINT32(p_Manip->fragParams.p_Frag->ccAdBase, ccAdBaseReg); WRITE_UINT32(p_Manip->fragParams.p_Frag->gmask, gmaskReg); /* Saves user's fragmentation manipulation parameters */ p_Manip->frag = TRUE; p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation; #if (DPAA_VERSION == 10) p_Manip->fragParams.scratchBpid = p_ManipParams->scratchBpid; /* scratch buffer pool initialization */ if ((err = FmPcdFragHcScratchPoolFill((t_Handle)p_FmPcd, p_ManipParams->scratchBpid)) != E_OK) { FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_Frag); p_Manip->fragParams.p_Frag = NULL; RETURN_ERROR(MAJOR, err, NO_MSG); } #endif /* (DPAA_VERSION == 10) */ return E_OK; } static t_Error IPManip(t_FmPcdManip *p_Manip) { t_Error err = E_OK; t_FmPcd *p_FmPcd; t_AdOfTypeContLookup *p_Ad; uint32_t tmpReg32 = 0, tmpRegNia = 0; SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); p_FmPcd = p_Manip->h_FmPcd; SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; tmpReg32 = FM_PCD_MANIP_IP_NO_FRAGMENTATION; if (p_Manip->frag == TRUE) { tmpRegNia = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_Frag) - (p_FmPcd->physicalMuramBase)); tmpReg32 = (uint32_t)p_Manip->sizeForFragmentation << FM_PCD_MANIP_IP_MTU_SHIFT; } tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE; tmpReg32 |= HMAN_OC_IP_MANIP; #if (DPAA_VERSION >= 11) tmpRegNia |= FM_PCD_MANIP_IP_CNIA; #endif /* (DPAA_VERSION >= 11) */ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); WRITE_UINT32(p_Ad->ccAdBase, tmpRegNia); WRITE_UINT32(p_Ad->gmask, 0); /* Total frame counter - MUST be initialized to zero.*/ return err; } static t_Error UpdateInitIpFrag(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate) { t_FmPortGetSetCcParams fmPortGetSetCcParams; t_Error err; SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_IP_FRAGMENTATION), E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); UNUSED(h_FmPcd); UNUSED(h_Ad); UNUSED(h_PcdParams); UNUSED(validate); UNUSED(p_Manip); fmPortGetSetCcParams.setCcParams.type = 0; fmPortGetSetCcParams.getCcParams.type = MANIP_EXTRA_SPACE; if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); if (!fmPortGetSetCcParams.getCcParams.internalBufferOffset) DBG(WARNING, ("manipExtraSpace must be larger than '0'")); return E_OK; } static t_Error IPSecManip(t_FmPcdManipParams *p_ManipParams, t_FmPcdManip *p_Manip) { t_AdOfTypeContLookup *p_Ad; t_FmPcdManipSpecialOffloadIPSecParams *p_IPSecParams; t_Error err = E_OK; uint32_t tmpReg32 = 0; uint32_t power; SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_ManipParams, E_INVALID_HANDLE); p_IPSecParams = &p_ManipParams->u.specialOffload.u.ipsec; SANITY_CHECK_RETURN_ERROR( !p_IPSecParams->variableIpHdrLen || p_IPSecParams->decryption, E_INVALID_VALUE); SANITY_CHECK_RETURN_ERROR( !p_IPSecParams->variableIpVersion || !p_IPSecParams->decryption, E_INVALID_VALUE); SANITY_CHECK_RETURN_ERROR( !p_IPSecParams->variableIpVersion || p_IPSecParams->outerIPHdrLen, E_INVALID_VALUE); SANITY_CHECK_RETURN_ERROR( !p_IPSecParams->arwSize || p_IPSecParams->arwAddr, E_INVALID_VALUE); SANITY_CHECK_RETURN_ERROR( !p_IPSecParams->arwSize || p_IPSecParams->decryption, E_INVALID_VALUE); SANITY_CHECK_RETURN_ERROR((p_IPSecParams->arwSize % 16) == 0, E_INVALID_VALUE); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; tmpReg32 |= (p_IPSecParams->decryption) ? FM_PCD_MANIP_IPSEC_DEC : 0; tmpReg32 |= (p_IPSecParams->ecnCopy) ? FM_PCD_MANIP_IPSEC_ECN_EN : 0; tmpReg32 |= (p_IPSecParams->dscpCopy) ? FM_PCD_MANIP_IPSEC_DSCP_EN : 0; tmpReg32 |= (p_IPSecParams->variableIpHdrLen) ? FM_PCD_MANIP_IPSEC_VIPL_EN : 0; tmpReg32 |= (p_IPSecParams->variableIpVersion) ? FM_PCD_MANIP_IPSEC_VIPV_EN : 0; if (p_IPSecParams->arwSize) tmpReg32 |= (uint32_t)((XX_VirtToPhys(UINT_TO_PTR(p_IPSecParams->arwAddr))-FM_MM_MURAM) & (FM_MURAM_SIZE-1)); WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); tmpReg32 = 0; if (p_IPSecParams->arwSize) { NEXT_POWER_OF_2((p_IPSecParams->arwSize + 32), power); LOG2(power, power); tmpReg32 = (p_IPSecParams->arwSize | (power - 5)) << FM_PCD_MANIP_IPSEC_ARW_SIZE_SHIFT; } if (p_ManipParams->h_NextManip) tmpReg32 |= (uint32_t)(XX_VirtToPhys(((t_FmPcdManip *)p_ManipParams->h_NextManip)->h_Ad)- (((t_FmPcd *)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4; WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32); tmpReg32 = HMAN_OC_IPSEC_MANIP; tmpReg32 |= p_IPSecParams->outerIPHdrLen << FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT; if (p_ManipParams->h_NextManip) tmpReg32 |= FM_PCD_MANIP_IPSEC_NADEN; WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); return err; } static t_Error SetCapwapReassmManip(t_FmPcdManip *p_Manip) { t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; /* Allocation if CAPWAP Action descriptor */ p_Manip->reassmParams.capwap.h_Ad = (t_Handle)XX_MallocSmart( FM_PCD_CC_AD_ENTRY_SIZE, p_Manip->reassmParams.dataMemId, FM_PCD_CC_AD_TABLE_ALIGN); if (!p_Manip->reassmParams.capwap.h_Ad) { ReleaseManipHandler(p_Manip, p_FmPcd); RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of CAPWAP table descriptor")); } memset(p_Manip->reassmParams.capwap.h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); /* Fill reassembly manipulation parameter in the Reassembly Action Descriptor */ return FillReassmManipParams(p_Manip, HEADER_TYPE_CAPWAP); } static void setCapwapReassmSchemeParams(t_FmPcd* p_FmPcd, t_FmPcdKgSchemeParams *p_Scheme, t_Handle h_CcTree, uint8_t groupId) { uint8_t res; /* Configures scheme's network environment parameters */ p_Scheme->netEnvParams.numOfDistinctionUnits = 1; res = FmPcdNetEnvGetUnitId( p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_USER_DEFINED_SHIM2, FALSE, 0); ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); p_Scheme->netEnvParams.unitIds[0] = res; /* Configures scheme's next engine parameters*/ p_Scheme->nextEngine = e_FM_PCD_CC; p_Scheme->kgNextEngineParams.cc.h_CcTree = h_CcTree; p_Scheme->kgNextEngineParams.cc.grpId = groupId; p_Scheme->useHash = TRUE; /* Configures scheme's key*/ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 2; p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_NON_HDR; p_Scheme->keyExtractAndHashParams.extractArray[0].extractNonHdr.src = e_FM_PCD_EXTRACT_FROM_PARSE_RESULT; p_Scheme->keyExtractAndHashParams.extractArray[0].extractNonHdr.action = e_FM_PCD_ACTION_NONE; p_Scheme->keyExtractAndHashParams.extractArray[0].extractNonHdr.offset = 20; p_Scheme->keyExtractAndHashParams.extractArray[0].extractNonHdr.size = 4; p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_NON_HDR; p_Scheme->keyExtractAndHashParams.extractArray[1].extractNonHdr.src = e_FM_PCD_EXTRACT_FROM_DFLT_VALUE; p_Scheme->keyExtractAndHashParams.extractArray[1].extractNonHdr.action = e_FM_PCD_ACTION_NONE; p_Scheme->keyExtractAndHashParams.extractArray[1].extractNonHdr.offset = 0; p_Scheme->keyExtractAndHashParams.extractArray[1].extractNonHdr.size = 1; p_Scheme->keyExtractAndHashParams.privateDflt0 = 0x0; p_Scheme->keyExtractAndHashParams.privateDflt1 = 0x0; p_Scheme->keyExtractAndHashParams.numOfUsedDflts = 1; p_Scheme->keyExtractAndHashParams.dflts[0].type = e_FM_PCD_KG_GENERIC_NOT_FROM_DATA; p_Scheme->keyExtractAndHashParams.dflts[0].dfltSelect = e_FM_PCD_KG_DFLT_PRIVATE_0; } #if (DPAA_VERSION >= 11) static t_Error CapwapReassemblyStats(t_FmPcdManip *p_Manip, t_FmPcdManipReassemCapwapStats *p_Stats) { ASSERT_COND(p_Manip); ASSERT_COND(p_Stats); ASSERT_COND(p_Manip->reassmParams.p_ReassCommonTbl); p_Stats->timeout = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalTimeOutCounter); p_Stats->rfdPoolBusy = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalRfdPoolBusyCounter); p_Stats->internalBufferBusy = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalInternalBufferBusy); p_Stats->externalBufferBusy = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalExternalBufferBusy); p_Stats->sgFragments = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalSgFragmentCounter); p_Stats->dmaSemaphoreDepletion = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalDmaSemaphoreDepletionCounter); p_Stats->exceedMaxReassemblyFrameLen = GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalNCSPCounter); p_Stats->successfullyReassembled = GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalSuccessfullyReasmFramesCounter); p_Stats->validFragments = GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalValidFragmentCounter); p_Stats->processedFragments = GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalProcessedFragCounter); p_Stats->malformedFragments = GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalMalformdFragCounter); p_Stats->autoLearnBusy = GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalSetBusyCounter); p_Stats->discardedFragments = GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalDiscardedFragsCounter); p_Stats->moreThan16Fragments = GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalMoreThan16FramesCounter); return E_OK; } static t_Error CapwapFragmentationStats(t_FmPcdManip *p_Manip, t_FmPcdManipFragCapwapStats *p_Stats) { t_AdOfTypeContLookup *p_Ad; ASSERT_COND(p_Manip); ASSERT_COND(p_Stats); ASSERT_COND(p_Manip->h_Ad); ASSERT_COND(p_Manip->fragParams.p_Frag); p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; p_Stats->totalFrames = GET_UINT32(p_Ad->gmask); return E_OK; } static t_Error CapwapReassembly(t_FmPcdManipReassemParams *p_ManipReassmParams, t_FmPcdManip *p_Manip) { uint32_t maxSetNumber = 10000; t_FmPcdManipReassemCapwapParams reassmManipParams = p_ManipReassmParams->u.capwapReassem; t_Error res; SANITY_CHECK_RETURN_ERROR(p_Manip->h_FmPcd, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(((t_FmPcd *)p_Manip->h_FmPcd)->h_Hc, E_INVALID_HANDLE); /* Check validation of user's parameter.*/ if ((reassmManipParams.timeoutThresholdForReassmProcess < 1000) || (reassmManipParams.timeoutThresholdForReassmProcess > 8000000)) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("timeoutThresholdForReassmProcess should be 1msec - 8sec")); /* It is recommended that the total number of entries in this table (number of sets * number of ways) will be twice the number of frames that are expected to be reassembled simultaneously.*/ if (reassmManipParams.maxNumFramesInProcess > (reassmManipParams.maxNumFramesInProcess * maxSetNumber / 2)) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("maxNumFramesInProcess has to be less than (maximun set number * number of ways / 2)")); /* Saves user's reassembly manipulation parameters */ p_Manip->reassmParams.capwap.relativeSchemeId = reassmManipParams.relativeSchemeId; p_Manip->reassmParams.capwap.numOfFramesPerHashEntry = reassmManipParams.numOfFramesPerHashEntry; p_Manip->reassmParams.capwap.maxRessembledsSize = reassmManipParams.maxReassembledFrameLength; p_Manip->reassmParams.maxNumFramesInProcess = reassmManipParams.maxNumFramesInProcess; p_Manip->reassmParams.timeOutMode = reassmManipParams.timeOutMode; p_Manip->reassmParams.fqidForTimeOutFrames = reassmManipParams.fqidForTimeOutFrames; p_Manip->reassmParams.timeoutThresholdForReassmProcess = reassmManipParams.timeoutThresholdForReassmProcess; p_Manip->reassmParams.dataMemId = reassmManipParams.dataMemId; p_Manip->reassmParams.dataLiodnOffset = reassmManipParams.dataLiodnOffset; /* Creates and initializes the Reassembly common parameter table */ CreateReassCommonTable(p_Manip); res = SetCapwapReassmManip(p_Manip); if (res != E_OK) return res; return E_OK; } static t_Error CapwapFragmentation(t_FmPcdManipFragCapwapParams *p_ManipParams, t_FmPcdManip *p_Manip) { t_FmPcd *p_FmPcd; t_AdOfTypeContLookup *p_Ad; uint32_t pcAndOffsetsReg = 0, ccAdBaseReg = 0, gmaskReg = 0; uint32_t tmpReg32 = 0, tmpRegNia = 0; SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_ManipParams->sizeForFragmentation != 0xFFFF, E_INVALID_VALUE); p_FmPcd = p_Manip->h_FmPcd; SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); /* Allocation of fragmentation Action Descriptor */ p_Manip->fragParams.p_Frag = (t_AdOfTypeContLookup *)FM_MURAM_AllocMem( p_FmPcd->h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN); if (!p_Manip->fragParams.p_Frag) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Fragmentation table descriptor")); IOMemSet32(p_Manip->fragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); /* Prepare the third Ad register (pcAndOffsets)- OperationCode */ pcAndOffsetsReg = (uint32_t)HMAN_OC_CAPWAP_FRAGMENTATION; /* Prepare the first Ad register (ccAdBase) - Don't frag action and Action descriptor type*/ ccAdBaseReg = FM_PCD_AD_CONT_LOOKUP_TYPE; ccAdBaseReg |= (p_ManipParams->compressModeEn) ? FM_PCD_MANIP_CAPWAP_FRAG_COMPRESS_EN : 0; /* Set Scatter/Gather BPid */ if (p_ManipParams->sgBpidEn) { ccAdBaseReg |= FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_EN; pcAndOffsetsReg |= ((p_ManipParams->sgBpid << FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_SHIFT) & FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_MASK); } /* Prepare the first Ad register (gmask) - scratch buffer pool id and Pointer to fragment ID */ gmaskReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcd->capwapFrameIdAddr)) - p_FmPcd->physicalMuramBase); gmaskReg |= (0xFF) << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID; /* Set all Ad registers */ WRITE_UINT32(p_Manip->fragParams.p_Frag->pcAndOffsets, pcAndOffsetsReg); WRITE_UINT32(p_Manip->fragParams.p_Frag->ccAdBase, ccAdBaseReg); WRITE_UINT32(p_Manip->fragParams.p_Frag->gmask, gmaskReg); /* Saves user's fragmentation manipulation parameters */ p_Manip->frag = TRUE; p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation; p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; tmpRegNia = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_Frag) - (p_FmPcd->physicalMuramBase)); tmpReg32 = (uint32_t)p_Manip->sizeForFragmentation << FM_PCD_MANIP_CAPWAP_FRAG_CHECK_MTU_SHIFT; tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE; tmpReg32 |= HMAN_OC_CAPWAP_FRAG_CHECK; tmpRegNia |= FM_PCD_MANIP_CAPWAP_FRAG_CHECK_CNIA; WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); WRITE_UINT32(p_Ad->ccAdBase, tmpRegNia); WRITE_UINT32(p_Ad->gmask, 0); /* Total frame counter - MUST be initialized to zero.*/ return E_OK; } static t_Error UpdateInitCapwapFrag(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate) { t_FmPortGetSetCcParams fmPortGetSetCcParams; t_Error err; SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION), E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); UNUSED(h_FmPcd); UNUSED(h_Ad); UNUSED(h_PcdParams); UNUSED(validate); UNUSED(p_Manip); fmPortGetSetCcParams.setCcParams.type = 0; fmPortGetSetCcParams.getCcParams.type = MANIP_EXTRA_SPACE; if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); if (!fmPortGetSetCcParams.getCcParams.internalBufferOffset) DBG(WARNING, ("manipExtraSpace must be larger than '0'")); return E_OK; } static t_Error CapwapManip(t_FmPcdManipParams *p_ManipParams, t_FmPcdManip *p_Manip) { t_AdOfTypeContLookup *p_Ad; t_FmPcdManipSpecialOffloadCapwapParams *p_Params; t_Error err = E_OK; uint32_t tmpReg32 = 0; SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_ManipParams, E_INVALID_HANDLE); p_Params = &p_ManipParams->u.specialOffload.u.capwap; p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; tmpReg32 |= (p_Params->dtls) ? FM_PCD_MANIP_CAPWAP_DTLS : 0; /* TODO - add 'qosSrc' */ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); tmpReg32 = HMAN_OC_CAPWAP_MANIP; if (p_ManipParams->h_NextManip) { WRITE_UINT32( p_Ad->matchTblPtr, (uint32_t)(XX_VirtToPhys(((t_FmPcdManip *)p_ManipParams->h_NextManip)->h_Ad)- (((t_FmPcd *)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4); tmpReg32 |= FM_PCD_MANIP_CAPWAP_NADEN; } WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); return err; } #endif /* (DPAA_VERSION >= 11) */ static t_Handle ManipOrStatsSetNode(t_Handle h_FmPcd, t_Handle *p_Params, bool stats) { t_FmPcdManip *p_Manip; t_Error err; t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip)); if (!p_Manip) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); return NULL; } memset(p_Manip, 0, sizeof(t_FmPcdManip)); p_Manip->type = ((t_FmPcdManipParams *)p_Params)->type; memcpy((uint8_t*)&p_Manip->manipParams, p_Params, sizeof(p_Manip->manipParams)); if (!stats) err = CheckManipParamsAndSetType(p_Manip, (t_FmPcdManipParams *)p_Params); #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) else err = CheckStatsParamsAndSetType(p_Manip, (t_FmPcdStatsParams *)p_Params); #else /* not (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ else { REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Statistics node!")); XX_Free(p_Manip); return NULL; } #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ if (err) { REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Invalid header manipulation type")); XX_Free(p_Manip); return NULL; } if ((p_Manip->opcode != HMAN_OC_IP_REASSEMBLY) && (p_Manip->opcode != HMAN_OC_CAPWAP_REASSEMBLY)) { /* In Case of reassembly manipulation the reassembly action descriptor will be defines later on */ if (p_Manip->muramAllocate) { p_Manip->h_Ad = (t_Handle)FM_MURAM_AllocMem( p_FmPcd->h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN); if (!p_Manip->h_Ad) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation action descriptor")); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; } IOMemSet32(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); } else { p_Manip->h_Ad = (t_Handle)XX_Malloc( FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); if (!p_Manip->h_Ad) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor")); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; } memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); } } p_Manip->h_FmPcd = h_FmPcd; return p_Manip; } static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip( t_FmPcdManip *p_CrntMdfManip, t_List *h_NodesLst) { t_CcNodeInformation *p_CcNodeInformation; t_FmPcdCcNode *p_NodePtrOnCurrentMdfManip = NULL; t_List *p_Pos; int i = 0; t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/; t_CcNodeInformation ccNodeInfo; LIST_FOR_EACH(p_Pos, &p_CrntMdfManip->nodesLst) { p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); p_NodePtrOnCurrentMdfManip = (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode; ASSERT_COND(p_NodePtrOnCurrentMdfManip); /* Search in the previous node which exact index points on this current modified node for getting AD */ for (i = 0; i < p_NodePtrOnCurrentMdfManip->numOfKeys + 1; i++) { if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC) { if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.h_Manip == (t_Handle)p_CrntMdfManip) { if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj) p_AdTablePtOnCrntCurrentMdfNode = p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd; else p_AdTablePtOnCrntCurrentMdfNode = PTR_MOVE(p_NodePtrOnCurrentMdfManip->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE); memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode; EnqueueNodeInfoToRelevantLst(h_NodesLst, &ccNodeInfo, NULL); } } } ASSERT_COND(i != p_NodePtrOnCurrentMdfManip->numOfKeys); } } static void BuildHmtd(uint8_t *p_Dest, uint8_t *p_Src, uint8_t *p_Hmcd, t_FmPcd *p_FmPcd) { t_Error err; /* Copy the HMTD */ IO2IOCpy32(p_Dest, (uint8_t*)p_Src, 16); /* Replace the HMCT table pointer */ WRITE_UINT32( ((t_Hmtd *)p_Dest)->hmcdBasePtr, (uint32_t)(XX_VirtToPhys(p_Hmcd) - ((t_FmPcd*)p_FmPcd)->physicalMuramBase)); /* Call Host Command to replace HMTD by a new HMTD */ err = FmHcPcdCcDoDynamicChange( p_FmPcd->h_Hc, (uint32_t)(XX_VirtToPhys(p_Src) - p_FmPcd->physicalMuramBase), (uint32_t)(XX_VirtToPhys(p_Dest) - p_FmPcd->physicalMuramBase)); if (err) REPORT_ERROR(MINOR, err, ("Failed in dynamic manip change, continued to the rest of the owners.")); } static t_Error FmPcdManipInitUpdate(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; t_Error err = E_OK; SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); UNUSED(level); UNUSED(h_FmTree); switch (p_Manip->opcode) { #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): err = UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(h_FmPort, p_Manip, h_Ad, validate); break; case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): if (!p_Manip->h_Frag) break; case (HMAN_OC_CAPWAP_FRAGMENTATION): err = UpdateInitCapwapFragmentation(h_FmPort, p_Manip, h_Ad, validate, h_FmTree); break; case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): if (p_Manip->h_Frag) err = UpdateInitCapwapReasm(h_FmPcd, h_FmPort, p_Manip, h_Ad, validate); break; case (HMAN_OC_CAPWAP_INDEXED_STATS): err = UpdateIndxStats(h_FmPcd, h_FmPort, p_Manip); break; #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ case (HMAN_OC_IP_REASSEMBLY): err = UpdateInitReasm(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, validate); break; case (HMAN_OC_IP_FRAGMENTATION): err = UpdateInitIpFrag(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, validate); break; #if (DPAA_VERSION >= 11) case (HMAN_OC_CAPWAP_FRAGMENTATION): err = UpdateInitCapwapFrag(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, validate); break; case (HMAN_OC_CAPWAP_REASSEMBLY): err = UpdateInitReasm(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, validate); break; #endif /* (DPAA_VERSION >= 11) */ default: return E_OK; } return err; } static t_Error FmPcdManipModifyUpdate(t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; t_Error err = E_OK; UNUSED(level); switch (p_Manip->opcode) { #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): RETURN_ERROR( MAJOR, E_INVALID_STATE, ("modify node with this type of manipulation is not suppported")); case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): if (p_Manip->h_Frag) { if (!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) && !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) && !(p_Manip->shadowUpdateParams & OFFSET_OF_PR)) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("modify node with this type of manipulation requires manipulation be updated previously in SetPcd function")); } break; case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): if (p_Manip->h_Frag) err = UpdateModifyCapwapFragmenation(p_Manip, h_Ad, validate, h_FmTree); break; #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ default: return E_OK; } return err; } /*****************************************************************************/ /* Inter-module API routines */ /*****************************************************************************/ t_Error FmPcdManipUpdate(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree, bool modify) { t_Error err; if (!modify) err = FmPcdManipInitUpdate(h_FmPcd, h_PcdParams, h_FmPort, h_Manip, h_Ad, validate, level, h_FmTree); else err = FmPcdManipModifyUpdate(h_Manip, h_Ad, validate, level, h_FmTree); return err; } void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add) { uint32_t intFlags; intFlags = XX_LockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock); if (add) ((t_FmPcdManip *)h_Manip)->owner++; else { ASSERT_COND(((t_FmPcdManip *)h_Manip)->owner); ((t_FmPcdManip *)h_Manip)->owner--; } XX_UnlockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock, intFlags); } t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip) { ASSERT_COND(h_Manip); return &((t_FmPcdManip *)h_Manip)->nodesLst; } t_List *FmPcdManipGetSpinlock(t_Handle h_Manip) { ASSERT_COND(h_Manip); return ((t_FmPcdManip *)h_Manip)->h_Spinlock; } t_Error FmPcdManipCheckParamsForCcNextEngine( t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, uint32_t *requiredAction) { t_FmPcdManip *p_Manip; #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) t_Error err = E_OK; #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10))*/ bool pointFromCc = TRUE; SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams->h_Manip, E_NULL_POINTER); p_Manip = (t_FmPcdManip *)(p_FmPcdCcNextEngineParams->h_Manip); *requiredAction = 0; while (p_Manip) { switch (p_Manip->opcode) { #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) case (HMAN_OC_CAPWAP_INDEXED_STATS): if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE")); if (p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid) p_Manip->cnia = TRUE; case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA; case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): p_Manip->ownerTmp++; break; case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) && !p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE with fqidForCtrlFlow FALSE")); p_Manip->ownerTmp++; break; case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_CC) && (FmPcdCcGetParseCode(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode) != CC_PC_GENERIC_IC_HASH_INDEXED)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation next engine has to be CC and action = e_FM_PCD_ACTION_INDEXED_LOOKUP")); err = UpdateManipIc(p_FmPcdCcNextEngineParams->h_Manip, FmPcdCcGetOffset(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA; break; #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ case (HMAN_OC_IP_FRAGMENTATION): case (HMAN_OC_IP_REASSEMBLY): #if (DPAA_VERSION >= 11) case (HMAN_OC_CAPWAP_REASSEMBLY): case (HMAN_OC_CAPWAP_FRAGMENTATION): #endif /* (DPAA_VERSION >= 11) */ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE")); p_Manip->ownerTmp++; break; case (HMAN_OC_IPSEC_MANIP): #if (DPAA_VERSION >= 11) case (HMAN_OC_CAPWAP_MANIP): #endif /* (DPAA_VERSION >= 11) */ p_Manip->ownerTmp++; break; case (HMAN_OC): if ((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC) && MANIP_IS_CASCADED(p_Manip)) RETURN_ERROR( MINOR, E_INVALID_STATE, ("Can't have a cascaded manipulation when and Next Engine is CC")); if (!MANIP_IS_FIRST(p_Manip) && pointFromCc) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("h_Manip is already used and may not be shared (no sharing of non-head manip nodes)")); break; default: RETURN_ERROR( MAJOR, E_INVALID_STATE, ("invalid type of header manipulation for this state")); } p_Manip = p_Manip->h_NextManip; pointFromCc = FALSE; } return E_OK; } t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, t_Handle h_FmPcdCcNode) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; t_Error err = E_OK; SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(h_FmPcdCcNode, E_INVALID_HANDLE); switch (p_Manip->opcode) { #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) case (HMAN_OC_CAPWAP_INDEXED_STATS): if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode)) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("The manipulation of the type statistics flowId if exist has to be pointed by all numOfKeys")); break; case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): if (p_Manip->h_Frag) { if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode)) RETURN_ERROR( MAJOR, E_INVALID_VALUE, ("The manipulation of the type remove DTLS if exist has to be pointed by all numOfKeys")); err = UpdateManipIc(h_Manip, FmPcdCcGetOffset(h_FmPcdCcNode)); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); } break; #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ default: break; } return err; } void FmPcdManipUpdateAdResultForCc( t_Handle h_Manip, t_FmPcdCcNextEngineParams *p_CcNextEngineParams, t_Handle p_Ad, t_Handle *p_AdNewPtr) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; /* This routine creates a Manip AD and can return in "p_AdNewPtr" * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */ ASSERT_COND(p_Manip); ASSERT_COND(p_CcNextEngineParams); ASSERT_COND(p_Ad); ASSERT_COND(p_AdNewPtr); FmPcdManipUpdateOwner(h_Manip, TRUE); /* According to "type", either build & initialize a new AD (p_AdNew) or initialize * p_Ad ( the AD in the match table) and set p_AdNew = NULL. */ switch (p_Manip->opcode) { #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): case (HMAN_OC_CAPWAP_INDEXED_STATS): *p_AdNewPtr = p_Manip->h_Ad; break; case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): case (HMAN_OC_CAPWAP_FRAGMENTATION): WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->fqid, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->fqid); WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->plcrProfile, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->plcrProfile); WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->nia, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->nia); *p_AdNewPtr = NULL; break; #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ case (HMAN_OC_IPSEC_MANIP): #if (DPAA_VERSION >= 11) case (HMAN_OC_CAPWAP_MANIP): #endif /* (DPAA_VERSION >= 11) */ *p_AdNewPtr = p_Manip->h_Ad; break; case (HMAN_OC_IP_FRAGMENTATION): #if (DPAA_VERSION >= 11) case (HMAN_OC_CAPWAP_FRAGMENTATION): #endif /* (DPAA_VERSION >= 11) */ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_DONE) && (!p_CcNextEngineParams->params.enqueueParams.overrideFqid)) { memcpy((uint8_t *)p_Ad, (uint8_t *)p_Manip->h_Ad, sizeof(t_AdOfTypeContLookup)); #if (DPAA_VERSION >= 11) WRITE_UINT32( ((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) & ~FM_PCD_MANIP_IP_CNIA); #endif /* (DPAA_VERSION >= 11) */ *p_AdNewPtr = NULL; } else *p_AdNewPtr = p_Manip->h_Ad; break; case (HMAN_OC_IP_REASSEMBLY): if (FmPcdManipIpReassmIsIpv6Hdr(p_Manip)) { if (!p_Manip->reassmParams.ip.ipv6Assigned) { *p_AdNewPtr = p_Manip->reassmParams.ip.h_Ipv6Ad; p_Manip->reassmParams.ip.ipv6Assigned = TRUE; FmPcdManipUpdateOwner(h_Manip, FALSE); } else { *p_AdNewPtr = p_Manip->reassmParams.ip.h_Ipv4Ad; p_Manip->reassmParams.ip.ipv6Assigned = FALSE; } } else *p_AdNewPtr = p_Manip->reassmParams.ip.h_Ipv4Ad; memcpy((uint8_t *)p_Ad, (uint8_t *)*p_AdNewPtr, sizeof(t_AdOfTypeContLookup)); *p_AdNewPtr = NULL; break; #if (DPAA_VERSION >= 11) case (HMAN_OC_CAPWAP_REASSEMBLY): *p_AdNewPtr = p_Manip->reassmParams.capwap.h_Ad; memcpy((uint8_t *)p_Ad, (uint8_t *)*p_AdNewPtr, sizeof(t_AdOfTypeContLookup)); *p_AdNewPtr = NULL; break; #endif /* (DPAA_VERSION >= 11) */ case (HMAN_OC): /* Allocate and initialize HMTD */ *p_AdNewPtr = p_Manip->h_Ad; break; default: break; } } void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNewPtr, uint32_t adTableOffset) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; /* This routine creates a Manip AD and can return in "p_AdNewPtr" * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */ ASSERT_COND(p_Manip); FmPcdManipUpdateOwner(h_Manip, TRUE); switch (p_Manip->opcode) { #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->ccAdBase); WRITE_UINT32( ((t_AdOfTypeContLookup *)p_Ad)->matchTblPtr, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->matchTblPtr); WRITE_UINT32( ((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->pcAndOffsets); WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->gmask, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->gmask); WRITE_UINT32( ((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, (GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) | adTableOffset)); *p_AdNewPtr = NULL; break; #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ case (HMAN_OC): /* Initialize HMTD within the match table*/ IOMemSet32(p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); /* copy the existing HMTD *//* ask Alla - memcpy??? */ memcpy((uint8_t*)p_Ad, p_Manip->h_Ad, sizeof(t_Hmtd)); /* update NADEN to be "1"*/ WRITE_UINT16( ((t_Hmtd *)p_Ad)->cfg, (uint16_t)(GET_UINT16(((t_Hmtd *)p_Ad)->cfg) | HMTD_CFG_NEXT_AD_EN)); /* update next action descriptor */ WRITE_UINT16(((t_Hmtd *)p_Ad)->nextAdIdx, (uint16_t)(adTableOffset >> 4)); /* mark that Manip's HMTD is not used */ *p_AdNewPtr = NULL; break; default: break; } } t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, bool isIpv4, uint8_t groupId) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; t_FmPcdKgSchemeParams *p_SchemeParams = NULL; t_Handle h_Scheme; ASSERT_COND(p_FmPcd); ASSERT_COND(h_NetEnv); ASSERT_COND(p_Manip); /* scheme was already build, no need to check for IPv6 */ if (p_Manip->reassmParams.ip.h_Ipv4Scheme) return E_OK; if (isIpv4) { h_Scheme = FmPcdKgGetSchemeHandle(p_FmPcd, p_Manip->reassmParams.ip.relativeSchemeId[0]); if (h_Scheme) { /* scheme was found */ p_Manip->reassmParams.ip.h_Ipv4Scheme = h_Scheme; return E_OK; } } else { h_Scheme = FmPcdKgGetSchemeHandle(p_FmPcd, p_Manip->reassmParams.ip.relativeSchemeId[1]); if (h_Scheme) { /* scheme was found */ p_Manip->reassmParams.ip.h_Ipv6Scheme = h_Scheme; return E_OK; } } p_SchemeParams = XX_Malloc(sizeof(t_FmPcdKgSchemeParams)); if (!p_SchemeParams) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation failed for scheme")); /* Configures the IPv4 or IPv6 scheme*/ memset(p_SchemeParams, 0, sizeof(t_FmPcdKgSchemeParams)); p_SchemeParams->netEnvParams.h_NetEnv = h_NetEnv; p_SchemeParams->id.relativeSchemeId = (uint8_t)( (isIpv4 == TRUE) ? p_Manip->reassmParams.ip.relativeSchemeId[0] : p_Manip->reassmParams.ip.relativeSchemeId[1]); p_SchemeParams->schemeCounter.update = TRUE; #if (DPAA_VERSION >= 11) p_SchemeParams->alwaysDirect = TRUE; p_SchemeParams->bypassFqidGeneration = TRUE; #else p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids = 1; p_SchemeParams->baseFqid = 0xFFFFFF; /*TODO- baseFqid*/ #endif /* (DPAA_VERSION >= 11) */ setIpReassmSchemeParams(p_FmPcd, p_SchemeParams, h_CcTree, isIpv4, groupId); /* Sets the new scheme */ if (isIpv4) p_Manip->reassmParams.ip.h_Ipv4Scheme = FM_PCD_KgSchemeSet( p_FmPcd, p_SchemeParams); else p_Manip->reassmParams.ip.h_Ipv6Scheme = FM_PCD_KgSchemeSet( p_FmPcd, p_SchemeParams); XX_Free(p_SchemeParams); return E_OK; } t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ASSERT_COND(p_Manip); if ((p_Manip->reassmParams.ip.h_Ipv4Scheme) && !FmPcdKgIsSchemeHasOwners(p_Manip->reassmParams.ip.h_Ipv4Scheme)) FM_PCD_KgSchemeDelete(p_Manip->reassmParams.ip.h_Ipv4Scheme); if ((p_Manip->reassmParams.ip.h_Ipv6Scheme) && !FmPcdKgIsSchemeHasOwners(p_Manip->reassmParams.ip.h_Ipv6Scheme)) FM_PCD_KgSchemeDelete(p_Manip->reassmParams.ip.h_Ipv6Scheme); return E_OK; } bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ASSERT_COND(p_Manip); return (p_Manip->reassmParams.hdr == HEADER_TYPE_IPv6); } t_Error FmPcdManipBuildCapwapReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, uint8_t groupId) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; t_FmPcdKgSchemeParams *p_SchemeParams = NULL; ASSERT_COND(p_FmPcd); ASSERT_COND(h_NetEnv); ASSERT_COND(p_Manip); /* scheme was already build, no need to check for IPv6 */ if (p_Manip->reassmParams.capwap.h_Scheme) return E_OK; p_SchemeParams = XX_Malloc(sizeof(t_FmPcdKgSchemeParams)); if (!p_SchemeParams) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation failed for scheme")); memset(p_SchemeParams, 0, sizeof(t_FmPcdKgSchemeParams)); p_SchemeParams->netEnvParams.h_NetEnv = h_NetEnv; p_SchemeParams->id.relativeSchemeId = (uint8_t)p_Manip->reassmParams.capwap.relativeSchemeId; p_SchemeParams->schemeCounter.update = TRUE; p_SchemeParams->bypassFqidGeneration = TRUE; setCapwapReassmSchemeParams(p_FmPcd, p_SchemeParams, h_CcTree, groupId); p_Manip->reassmParams.capwap.h_Scheme = FM_PCD_KgSchemeSet(p_FmPcd, p_SchemeParams); XX_Free(p_SchemeParams); return E_OK; } t_Error FmPcdManipDeleteCapwapReassmSchemes(t_Handle h_Manip) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ASSERT_COND(p_Manip); if (p_Manip->reassmParams.capwap.h_Scheme) FM_PCD_KgSchemeDelete(p_Manip->reassmParams.capwap.h_Scheme); return E_OK; } #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) t_Handle FmPcdManipApplSpecificBuild(void) { t_FmPcdManip *p_Manip; p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip)); if (!p_Manip) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); return NULL; } memset(p_Manip, 0, sizeof(t_FmPcdManip)); p_Manip->opcode = HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX; p_Manip->muramAllocate = FALSE; p_Manip->h_Ad = (t_Handle)XX_Malloc(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); if (!p_Manip->h_Ad) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor")); XX_Free(p_Manip); return NULL; } memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); /*treatFdStatusFieldsAsErrors = TRUE hardcoded - assumption its always come after CAAM*/ /*Application specific = type of flowId index, move internal frame header from data to IC, SEC errors check*/ if (MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE)!= E_OK) { XX_Free(p_Manip->h_Ad); XX_Free(p_Manip); return NULL; } return p_Manip; } bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ASSERT_COND(h_Manip); return (bool)((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST) ? TRUE : FALSE); } #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ /*********************** End of inter-module routines ************************/ /****************************************/ /* API Init unit functions */ /****************************************/ t_Handle FM_PCD_ManipNodeSet(t_Handle h_FmPcd, t_FmPcdManipParams *p_ManipParams) { t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; t_FmPcdManip *p_Manip; t_Error err; SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); SANITY_CHECK_RETURN_VALUE(p_ManipParams, E_INVALID_HANDLE, NULL); p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_ManipParams, FALSE); if (!p_Manip) return NULL; if (((p_Manip->opcode == HMAN_OC_IP_REASSEMBLY) || (p_Manip->opcode == HMAN_OC_IP_FRAGMENTATION) || (p_Manip->opcode == HMAN_OC) || (p_Manip->opcode == HMAN_OC_IPSEC_MANIP) #if (DPAA_VERSION >= 11) || (p_Manip->opcode == HMAN_OC_CAPWAP_MANIP) || (p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->opcode == HMAN_OC_CAPWAP_REASSEMBLY) #endif /* (DPAA_VERSION >= 11) */ ) && (!FmPcdIsAdvancedOffloadSupported(p_FmPcd))) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled")); XX_Free(p_Manip); return NULL; } p_Manip->h_Spinlock = XX_InitSpinlock(); if (!p_Manip->h_Spinlock) { REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; }INIT_LIST(&p_Manip->nodesLst); switch (p_Manip->opcode) { case (HMAN_OC_IP_REASSEMBLY): /* IpReassembly */ err = IpReassembly(&p_ManipParams->u.reassem, p_Manip); break; case (HMAN_OC_IP_FRAGMENTATION): /* IpFragmentation */ err = IpFragmentation(&p_ManipParams->u.frag.u.ipFrag, p_Manip); if (err) break; err = IPManip(p_Manip); break; case (HMAN_OC_IPSEC_MANIP): err = IPSecManip(p_ManipParams, p_Manip); break; #if (DPAA_VERSION >= 11) case (HMAN_OC_CAPWAP_REASSEMBLY): /* CapwapReassembly */ err = CapwapReassembly(&p_ManipParams->u.reassem, p_Manip); break; case (HMAN_OC_CAPWAP_FRAGMENTATION): /* CapwapFragmentation */ err = CapwapFragmentation(&p_ManipParams->u.frag.u.capwapFrag, p_Manip); break; case (HMAN_OC_CAPWAP_MANIP): err = CapwapManip(p_ManipParams, p_Manip); break; #endif /* (DPAA_VERSION >= 11) */ #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): /* HmanType1 */ err = RmvHdrTillSpecLocNOrInsrtIntFrmHdr(&p_ManipParams->u.hdr.rmvParams, p_Manip); break; case (HMAN_OC_CAPWAP_FRAGMENTATION): err = CapwapFragmentation(&p_ManipParams->fragOrReasmParams.u.capwapFragParams, p_Manip, p_FmPcd, p_ManipParams->fragOrReasmParams.sgBpid); if (err) { REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; } if (p_Manip->insrt) p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): /* HmanType2 + if user asked only for fragmentation still need to allocate HmanType2 */ err = InsrtHdrByTempl(&p_ManipParams->u.hdr.insrtParams, p_Manip, p_FmPcd); break; case (HMAN_OC_CAPWAP_REASSEMBLY): err = CapwapReassembly(&p_ManipParams->fragOrReasmParams.u.capwapReasmParams, p_Manip, p_FmPcd, p_ManipParams->fragOrReasmParams.sgBpid); if (err) { REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; } if (p_Manip->rmv) p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): /*CAPWAP decapsulation + if user asked only for reassembly still need to allocate CAPWAP decapsulation*/ err = CapwapRmvDtlsHdr(p_FmPcd, p_Manip); break; case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): /*Application Specific type 1*/ err = MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE); break; #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ case (HMAN_OC): /* New Manip */ err = CreateManipActionNew(p_Manip, p_ManipParams); break; default: REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; } if (err) { REPORT_ERROR(MAJOR, err, NO_MSG); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; } if (p_ManipParams->h_NextManip) { /* in the check routine we've verified that h_NextManip has no owners * and that only supported types are allowed. */ p_Manip->h_NextManip = p_ManipParams->h_NextManip; /* save a "prev" pointer in h_NextManip */ MANIP_SET_PREV(p_Manip->h_NextManip, p_Manip); FmPcdManipUpdateOwner(p_Manip->h_NextManip, TRUE); } return p_Manip; } t_Error FM_PCD_ManipNodeReplace(t_Handle h_Manip, t_FmPcdManipParams *p_ManipParams) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip, *p_FirstManip; t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Manip->h_FmPcd); t_Error err; uint8_t *p_WholeHmct = NULL, *p_ShadowHmct = NULL, *p_Hmtd = NULL; t_List lstOfNodeshichPointsOnCrntMdfManip, *p_Pos; t_CcNodeInformation *p_CcNodeInfo; SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_ManipParams, E_INVALID_HANDLE); INIT_LIST(&lstOfNodeshichPointsOnCrntMdfManip); if ((p_ManipParams->type != e_FM_PCD_MANIP_HDR) || (p_Manip->type != e_FM_PCD_MANIP_HDR)) RETURN_ERROR( MINOR, E_NOT_SUPPORTED, ("FM_PCD_ManipNodeReplace Functionality supported only for Header Manipulation.")); ASSERT_COND(p_Manip->opcode == HMAN_OC); ASSERT_COND(p_Manip->manipParams.h_NextManip == p_Manip->h_NextManip); memcpy((uint8_t*)&p_Manip->manipParams, p_ManipParams, sizeof(p_Manip->manipParams)); p_Manip->manipParams.h_NextManip = p_Manip->h_NextManip; /* The replacement of the HdrManip depends on the node type.*/ /* * (1) If this is an independent node, all its owners should be updated. * * (2) If it is the head of a cascaded chain (it does not have a "prev" but * it has a "next" and it has a "cascaded" indication), the next * node remains unchanged, and the behavior is as in (1). * * (3) If it is not the head, but a part of a cascaded chain, in can be * also replaced as a regular node with just one owner. * * (4) If it is a part of a chain implemented as a unified table, the * whole table is replaced and the owners of the head node must be updated. * */ /* lock shadow */ if (!p_FmPcd->p_CcShadow) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated")); if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) return ERROR_CODE(E_BUSY); /* this routine creates a new manip action in the CC Shadow. */ err = CreateManipActionShadow(p_Manip, p_ManipParams); if (err) RETURN_ERROR(MINOR, err, NO_MSG); /* If the owners list is empty (these are NOT the "owners" counter, but pointers from CC) * replace only HMTD and no lcok is required. Otherwise * lock the whole PCD * In case 4 MANIP_IS_UNIFIED_NON_FIRST(p_Manip) - Use the head node instead. */ if (!FmPcdLockTryLockAll(p_FmPcd)) { DBG(TRACE, ("FmPcdLockTryLockAll failed")); return ERROR_CODE(E_BUSY); } p_ShadowHmct = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16); p_FirstManip = (t_FmPcdManip*)GetManipInfo(p_Manip, e_MANIP_HANDLER_TABLE_OWNER); ASSERT_COND(p_FirstManip); if (!LIST_IsEmpty(&p_FirstManip->nodesLst)) UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip( p_FirstManip, &lstOfNodeshichPointsOnCrntMdfManip); p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD); ASSERT_COND(p_Hmtd); BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd))); LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip) { p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd))); } p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ASSERT_COND(p_WholeHmct); /* re-build the HMCT n the original location */ err = CreateManipActionBackToOrig(p_Manip, p_ManipParams); if (err) { RELEASE_LOCK(p_FmPcd->shadowLock); RETURN_ERROR(MINOR, err, NO_MSG); } p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD); ASSERT_COND(p_Hmtd); BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_WholeHmct, ((t_FmPcd*)p_Manip->h_FmPcd)); /* If LIST > 0, create a list of p_Ad's that point to the HMCT. Join also t_HMTD to this list. * For each p_Hmct (from list+fixed): * call Host Command to replace HMTD by a new one */LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip) { p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, p_WholeHmct, ((t_FmPcd*)(p_Manip->h_FmPcd))); } ReleaseLst(&lstOfNodeshichPointsOnCrntMdfManip); FmPcdLockUnlockAll(p_FmPcd); /* unlock shadow */ RELEASE_LOCK(p_FmPcd->shadowLock); return E_OK; } t_Error FM_PCD_ManipNodeDelete(t_Handle h_ManipNode) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode; SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); if (p_Manip->owner) RETURN_ERROR( MAJOR, E_INVALID_STATE, ("This manipulation node not be removed because this node is occupied, first - unbind this node ")); if (p_Manip->h_NextManip) { MANIP_SET_PREV(p_Manip->h_NextManip, NULL); FmPcdManipUpdateOwner(p_Manip->h_NextManip, FALSE); } if (p_Manip->p_Hmct && (MANIP_IS_UNIFIED_FIRST(p_Manip) || !MANIP_IS_UNIFIED(p_Manip))) FM_MURAM_FreeMem(((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, p_Manip->p_Hmct); if (p_Manip->h_Spinlock) { XX_FreeSpinlock(p_Manip->h_Spinlock); p_Manip->h_Spinlock = NULL; } ReleaseManipHandler(p_Manip, p_Manip->h_FmPcd); XX_Free(h_ManipNode); return E_OK; } t_Error FM_PCD_ManipGetStatistics(t_Handle h_ManipNode, t_FmPcdManipStats *p_FmPcdManipStats) { t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode; SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_FmPcdManipStats, E_NULL_POINTER); switch (p_Manip->opcode) { case (HMAN_OC_IP_REASSEMBLY): return IpReassemblyStats(p_Manip, &p_FmPcdManipStats->u.reassem.u.ipReassem); case (HMAN_OC_IP_FRAGMENTATION): return IpFragmentationStats(p_Manip, &p_FmPcdManipStats->u.frag.u.ipFrag); #if (DPAA_VERSION >= 11) case (HMAN_OC_CAPWAP_REASSEMBLY): return CapwapReassemblyStats( p_Manip, &p_FmPcdManipStats->u.reassem.u.capwapReassem); case (HMAN_OC_CAPWAP_FRAGMENTATION): return CapwapFragmentationStats( p_Manip, &p_FmPcdManipStats->u.frag.u.capwapFrag); #endif /* (DPAA_VERSION >= 11) */ default: RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("no statistics to this type of manip")); } return E_OK; } #if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) t_Handle FM_PCD_StatisticsSetNode(t_Handle h_FmPcd, t_FmPcdStatsParams *p_StatsParams) { t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; t_FmPcdManip *p_Manip; t_Error err; SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL); SANITY_CHECK_RETURN_VALUE(p_StatsParams,E_INVALID_HANDLE,NULL); p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_StatsParams, TRUE); if (!p_Manip) return NULL; switch (p_Manip->opcode) { case (HMAN_OC_CAPWAP_INDEXED_STATS): /* Indexed statistics */ err = IndxStats(p_StatsParams, p_Manip, p_FmPcd); break; default: REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED Statistics type")); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; } if (err) { REPORT_ERROR(MAJOR, err, NO_MSG); ReleaseManipHandler(p_Manip, p_FmPcd); XX_Free(p_Manip); return NULL; } return p_Manip; } #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */