f-stack/freebsd/contrib/ncsw/Peripherals/FM/Pcd/fm_manip.c

2638 lines
115 KiB
C
Raw Normal View History

2017-04-21 10:43:26 +00:00
/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
* All rights reserved.
*
* 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 ...
*//***************************************************************************/
#ifdef CONFIG_FMAN_P1023
#ifdef FM_CAPWAP_SUPPORT
#include "std_ext.h"
#include "error_ext.h"
#include "string_ext.h"
#include "debug_ext.h"
#include "fm_pcd_ext.h"
#include "fm_muram_ext.h"
#include "memcpy_ext.h"
#include "fm_common.h"
#include "fm_hc.h"
#include "fm_manip.h"
#ifdef CORE_8BIT_ACCESS_ERRATA
#undef WRITE_UINT16
#undef GET_UINT16
#undef WRITE_UINT8
#undef GET_UINT8
#define WRITE_UINT16(addr, val) \
do{ \
if((int)&(addr) % 4) \
WRITE_UINT32(*(uint32_t*)(uint32_t)((uint32_t)&addr & ~0x3L), \
((GET_UINT32(*(uint32_t*)(uint32_t)((uint32_t)&addr & ~0x3L)) & 0xffff0000) | (uint32_t)val)); \
else \
WRITE_UINT32(*(uint32_t*)&addr, \
((GET_UINT32(*(uint32_t*)&addr) & 0x0000ffff) | (uint32_t)val<<16)); \
}while(0);
#define GET_UINT16(addr) (((uint32_t)&addr%4) ? \
((uint16_t)GET_UINT32(*(uint32_t*)(uint32_t)((uint32_t)&addr & ~0x3L))): \
((uint16_t)(GET_UINT32(*(uint32_t*)(uint32_t)&addr) >> 16)))
#define WRITE_UINT8(addr,val) WRITE_UINT8_ERRATA(&addr,val)
#define GET_UINT8(addr) GET_UINT8_ERRATA(&addr)
#endif /* CORE_8BIT_ACCESS_ERRATA */
static void WRITE_UINT8_ERRATA(uint8_t *addr, uint8_t val)
{
uint32_t newAddr, newVal;
newAddr = (uint32_t)addr & ~0x3L;
switch ((uint32_t)addr%4)
{
case (0):
newVal = GET_UINT32(*(uint32_t*)newAddr);
newVal = (newVal & 0x00ffffff) | (((uint32_t)val)<<24);
WRITE_UINT32(*(uint32_t*)newAddr, newVal);
break;
case (1):
newVal = GET_UINT32(*(uint32_t*)newAddr);
newVal = (newVal & 0xff00ffff) | (((uint32_t)val)<<16);
WRITE_UINT32(*(uint32_t*)newAddr, newVal);
break;
case (2):
newVal = GET_UINT32(*(uint32_t*)newAddr);
newVal = (newVal & 0xffff00ff) | (((uint32_t)val)<<8);
WRITE_UINT32(*(uint32_t*)newAddr, newVal);
break;
case (3):
newVal = GET_UINT32(*(uint32_t*)newAddr);
newVal = (newVal & 0xffffff00) | val;
WRITE_UINT32(*(uint32_t*)newAddr, newVal);
break;
}
}
static uint8_t GET_UINT8_ERRATA(uint8_t *addr)
{
uint32_t newAddr, newVal=0;
newAddr = (uint32_t)addr & ~0x3L;
switch ((uint32_t)addr%4)
{
case (0):
newVal = GET_UINT32(*(uint32_t*)newAddr);
newVal = (newVal & 0xff000000)>>24;
break;
case (1):
newVal = GET_UINT32(*(uint32_t*)newAddr);
newVal = (newVal & 0x00ff0000)>>16;
break;
case (2):
newVal = GET_UINT32(*(uint32_t*)newAddr);
newVal = (newVal & 0x0000ff00)>>8;
break;
case (3):
newVal = GET_UINT32(*(uint32_t*)newAddr);
newVal = (newVal & 0x000000ff);
break;
}
return (uint8_t)newVal;
}
static t_Error GetPrOffsetByNonHeader(uint8_t *parseArrayOffset)
{
/*For now - the only field in the Parse Array from the NON_BY_TYPE can be e_FM_PCD_KG_EXTRACT_FROM_CURR_END_OF_PARSE*/
/*Maybe extended in the future*/
*parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET;
return E_OK;
}
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->type)
{
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 previousely by different value"););
}
break;
#ifdef FM_CAPWAP_SUPPORT
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;
#endif /* FM_CAPWAP_SUPPORT */
}
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->type & 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"));
}
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;
}
#ifdef FM_CAPWAP_SUPPORT
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->type == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->type == 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->updateParams & BUFFER_POOL_ID_FOR_MANIP)) ||
((p_Manip->shadowUpdateParams & OFFSET_OF_DATA) || (p_Manip->shadowUpdateParams & BUFFER_POOL_ID_FOR_MANIP)))
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree, e_FM_MANIP_CAPWAP_INDX);
if(!p_SavedManipParams)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type"));
p_Manip->fragParams.poolId = p_SavedManipParams->capwapParams.poolId;
p_Manip->fragParams.dataOffset = p_SavedManipParams->capwapParams.dataOffset;
tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets);
tmpReg32 |= ((uint32_t)p_Manip->fragParams.poolId << 8);
tmpReg32 |= ((uint32_t)p_Manip->fragParams.dataOffset<< 16);
WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32);
p_Manip->updateParams &= ~OFFSET_OF_DATA;
p_Manip->updateParams &= ~BUFFER_POOL_ID_FOR_MANIP;
p_Manip->shadowUpdateParams |= (OFFSET_OF_DATA | BUFFER_POOL_ID_FOR_MANIP);
}
else if (validate)
{
p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree, e_FM_MANIP_CAPWAP_INDX);
if(!p_SavedManipParams)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type"));
if((p_Manip->fragParams.poolId != p_SavedManipParams->capwapParams.poolId) ||
(p_Manip->fragParams.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->type == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->type == 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->updateParams & BUFFER_POOL_ID_FOR_MANIP)) ||
((p_Manip->shadowUpdateParams & OFFSET_OF_DATA) || (p_Manip->shadowUpdateParams & BUFFER_POOL_ID_FOR_MANIP)))
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_FRAG | NIA_ENG_FM_CTL;
fmPortGetSetCcParams.getCcParams.poolIndex = p_Manip->fragParams.poolIndx;
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(fmPortGetSetCcParams.getCcParams.type & BUFFER_POOL_ID_FOR_MANIP)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Buffer pool doe header manipulation wasn't configured previousely"));
p_SavedManipParams = (t_FmPcdCcSavedManipParams *)XX_Malloc(sizeof(t_FmPcdCcSavedManipParams));
p_SavedManipParams->capwapParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
p_SavedManipParams->capwapParams.poolId = fmPortGetSetCcParams.getCcParams.poolIdForManip;
#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
ASSERT_COND(!(p_SavedManipParams->capwapParams.dataOffset % 16));
#endif
FmPcdCcTreeSetSavedManipParams(h_FmTree, (t_Handle)p_SavedManipParams, e_FM_MANIP_CAPWAP_INDX);
}
else if (validate)
{
if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) &&
!(p_Manip->shadowUpdateParams & BUFFER_POOL_ID_FOR_MANIP)) ||
((p_Manip->updateParams & OFFSET_OF_DATA) ||
(p_Manip->updateParams & BUFFER_POOL_ID_FOR_MANIP)))
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
fmPortGetSetCcParams.getCcParams.poolIndex = p_Manip->fragParams.poolIndx;
fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | 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(fmPortGetSetCcParams.getCcParams.type & BUFFER_POOL_ID_FOR_MANIP)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Buffer pool doe header manipulation wasn't configured previousely"));
}
if(p_Manip->updateParams)
{
tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets);
tmpReg32 |= ((uint32_t)fmPortGetSetCcParams.getCcParams.poolIdForManip << 8);
tmpReg32 |= ((uint32_t)fmPortGetSetCcParams.getCcParams.dataOffset<< 16);
WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32);
p_Manip->updateParams &= ~OFFSET_OF_DATA;
p_Manip->updateParams &= ~BUFFER_POOL_ID_FOR_MANIP;
p_Manip->shadowUpdateParams |= (OFFSET_OF_DATA | BUFFER_POOL_ID_FOR_MANIP);
p_Manip->fragParams.poolId = fmPortGetSetCcParams.getCcParams.poolIdForManip;
p_Manip->fragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
}
else if (validate)
{
if((p_Manip->fragParams.poolId != fmPortGetSetCcParams.getCcParams.poolIdForManip) ||
(p_Manip->fragParams.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->type == 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 & BUFFER_POOL_ID_FOR_MANIP) &&
!(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 & BUFFER_POOL_ID_FOR_MANIP) ||
(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.getCcParams.poolIndex = p_Manip->fragParams.poolIndx;
fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | 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 & BUFFER_POOL_ID_FOR_MANIP)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("buffser pool id 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
}
else if (validate)
{
if((!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) && (!(p_Manip->shadowUpdateParams & BUFFER_POOL_ID_FOR_MANIP)) &&
(!(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 & BUFFER_POOL_ID_FOR_MANIP) ||
(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.getCcParams.poolIndex = p_Manip->fragParams.poolIndx;
fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | 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 previousely"));
if(fmPortGetSetCcParams.getCcParams.type & BUFFER_POOL_ID_FOR_MANIP)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Buffer pool for header manipulation 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"));
}
if(p_Manip->updateParams)
{
if(p_Manip->updateParams & NUM_OF_TASKS)
{
size = (uint16_t)(p_Manip->fragParams.maxNumFramesInProcess + fmPortGetSetCcParams.getCcParams.numOfTasks);
if(size > 255)
RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("numOfOpenReassmEntries + numOfTasks per port can not be greater than 256"));
p_Manip->fragParams.numOfTasks = fmPortGetSetCcParams.getCcParams.numOfTasks;
/*p_ReassmFrmDescrIndxPoolTbl*/
p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
(uint32_t)(size + 1),
4);
if(!p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
IOMemSet32(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size + 1));
for( i = 0; i < size; i++)
WRITE_UINT8(*(uint8_t *)PTR_MOVE(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl, i), (uint8_t)(i+1));
tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl) - p_FmPcd->physicalMuramBase);
WRITE_UINT32(p_ReassmTbl->reasmFrmDescIndexPoolTblPtr, tmpReg32);
/*p_ReassmFrmDescrPoolTbl*/
p_Manip->fragParams.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->fragParams.p_ReassmFrmDescrPoolTbl)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
IOMemSet32(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl, 0, (uint32_t)((size +1)* FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE));
tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl) - p_FmPcd->physicalMuramBase);
WRITE_UINT32(p_ReassmTbl->reasmFrmDescPoolTblPtr, tmpReg32);
/*p_TimeOutTbl*/
p_Manip->fragParams.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->fragParams.p_TimeOutTbl)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
IOMemSet32(p_Manip->fragParams.p_TimeOutTbl, 0, (uint16_t)((size + 1)*FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE));
tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.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 & BUFFER_POOL_ID_FOR_MANIP)
{
p_Manip->fragParams.poolId = fmPortGetSetCcParams.getCcParams.poolIdForManip;
tmpReg32 = GET_UINT32(p_ReassmTbl->bufferPoolIdAndRisc1SetIndexes);
tmpReg32 |= (uint32_t)p_Manip->fragParams.poolId << 16;
WRITE_UINT32(p_ReassmTbl->bufferPoolIdAndRisc1SetIndexes, tmpReg32);
p_Manip->updateParams &= ~BUFFER_POOL_ID_FOR_MANIP;
p_Manip->shadowUpdateParams |= BUFFER_POOL_ID_FOR_MANIP;
}
if(p_Manip->updateParams & OFFSET_OF_DATA)
{
p_Manip->fragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
tmpReg32 = GET_UINT32(p_ReassmTbl->mode);
tmpReg32|= p_Manip->fragParams.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->fragParams.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->fragParams.prOffset << 24;
WRITE_UINT32(p_ReassmTbl->intStatsTblPtr, tmpReg32);
p_Manip->updateParams &= ~OFFSET_OF_PR;
p_Manip->shadowUpdateParams |= OFFSET_OF_PR;
}
else
{
p_Manip->fragParams.prOffset = 0xff;
p_Manip->updateParams &= ~OFFSET_OF_PR;
p_Manip->shadowUpdateParams |= OFFSET_OF_PR;
}
p_Manip->fragParams.hwPortId = fmPortGetSetCcParams.getCcParams.hardwarePortId;
p_Manip->updateParams &= ~HW_PORT_ID;
p_Manip->shadowUpdateParams |= HW_PORT_ID;
/*timeout hc */
ccCapwapReassmTimeoutParams.fqidForTimeOutFrames = p_Manip->fragParams.fqidForTimeOutFrames;
ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl = (uint32_t)p_Manip->fragParams.hwPortId << 24;
ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl |= (uint32_t)((XX_VirtToPhys(p_ReassmTbl) - p_FmPcd->physicalMuramBase));
ccCapwapReassmTimeoutParams.timeoutRequestTime = (((uint32_t)1<<p_Manip->fragParams.bitFor1Micro) * p_Manip->fragParams.timeoutRoutineRequestTime)/2;
return FmHcPcdCcCapwapTimeoutReassm(p_FmPcd->h_Hc,&ccCapwapReassmTimeoutParams);
}
else if(validate)
{
if(fmPortGetSetCcParams.getCcParams.hardwarePortId != p_Manip->fragParams.hwPortId)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Reassembly manipulation previously was assigned to another port"));
if(fmPortGetSetCcParams.getCcParams.numOfTasks != p_Manip->fragParams.numOfTasks)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfTasks for this manipulation previously was defined by another value "));
if(fmPortGetSetCcParams.getCcParams.poolIdForManip != p_Manip->fragParams.poolId)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("poolId for this manipulation previously was defined by another value "));
if(!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR))
{
if(p_Manip->fragParams.prOffset != fmPortGetSetCcParams.getCcParams.prOffset)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value "));
}
else
{
if(p_Manip->fragParams.prOffset != 0xff)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value "));
}
if(fmPortGetSetCcParams.getCcParams.dataOffset != p_Manip->fragParams.dataOffset)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Data offset previously was defined by another value "));
}
return E_OK;
}
#endif /* FM_CAPWAP_SUPPORT */
#if (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC))
static t_Error UpdateInitIPSec(t_Handle h_FmPort, t_FmPcdManip *p_Manip)
{
SANITY_CHECK_RETURN_ERROR(h_FmPort,E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_Manip->type == HMAN_OC_IPSEC, E_INVALID_STATE);
/*
if(p_Manip->cnia)
{
p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
WRITE_UINT32(p_Ad->ccAdBase, GET_UINT32(p_Ad->ccAdBase) | FM_PCD_MANIP_IPSEC_CNIA);
}
*/
return E_OK;
}
#endif /* (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC))*/
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
static t_Error UpdateInitIpFragmentation(t_Handle h_FmPort, t_FmPcdManip *p_Manip)
{
t_FmPortGetSetCcParams fmPortGetSetCcParams;
t_Error err;
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->type == HMAN_OC_IP_FRAGMENTATION, E_INVALID_STATE);
fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
if(err)
RETURN_ERROR(MAJOR, err, NO_MSG);
return E_OK;
}
static t_Error CreateIpReassCommonParamTable(t_FmPcdManip *p_Manip,
t_FmPcd *p_FmPcd ,
t_IpReasmCommonTbl *p_IpReasmCommonPramTbl)
{
uint32_t tmpReg32 = 0, i;
uint64_t tmpReg64, size;
p_Manip->ipReassmParams.h_IpReassCommonParamsTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE,
FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_ALIGN);
if(!p_Manip->ipReassmParams.h_IpReassCommonParamsTbl)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
p_IpReasmCommonPramTbl = (t_IpReasmCommonTbl *)(p_Manip->ipReassmParams.h_IpReassCommonParamsTbl);
IOMemSet32(p_IpReasmCommonPramTbl, 0, FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE);
tmpReg32 = 0;
if(p_Manip->ipReassmParams.timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES)
tmpReg32 |= FM_PCD_MANIP_IP_REASM_TIME_OUT_BETWEEN_FRAMES;
tmpReg32 |= p_Manip->ipReassmParams.fqidForTimeOutFrames;
WRITE_UINT32(p_IpReasmCommonPramTbl->timeoutModeAndFqid, tmpReg32);
size = p_Manip->ipReassmParams.maxNumFramesInProcess + 129;
/*p_ReassmFrmDescrIndxPoolTbl */
p_Manip->ipReassmParams.h_ReassmFrmDescrIndxPoolTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
(uint32_t)(size * 2),
256);
if(!p_Manip->ipReassmParams.h_ReassmFrmDescrIndxPoolTbl)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
IOMemSet32(p_Manip->ipReassmParams.h_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size * 2));
for( i = 0; i < size - 1; i++)
WRITE_UINT8(*(uint8_t *)PTR_MOVE(p_Manip->ipReassmParams.h_ReassmFrmDescrIndxPoolTbl, i), (uint8_t)(i+1));
tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.h_ReassmFrmDescrIndxPoolTbl) - p_FmPcd->physicalMuramBase);
WRITE_UINT32(p_IpReasmCommonPramTbl->reassFrmDescIndexPoolTblPtr, tmpReg32);
/*p_ReassmFrmDescrPoolTbl*/
p_Manip->ipReassmParams.h_ReassmFrmDescrPoolTbl = (t_Handle)XX_MallocSmart((uint32_t)(size * 32), p_Manip->ipReassmParams.dataMemId, 32);
if(!p_Manip->ipReassmParams.h_ReassmFrmDescrPoolTbl)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
IOMemSet32(p_Manip->ipReassmParams.h_ReassmFrmDescrPoolTbl, 0, (uint32_t)(size * 32));
tmpReg64 = (uint64_t)(XX_VirtToPhys(p_Manip->ipReassmParams.h_ReassmFrmDescrPoolTbl));
tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.liodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.liodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
WRITE_UINT32(p_IpReasmCommonPramTbl->liodnAndReassFrmDescPoolPtrHi, (uint32_t)(tmpReg64 >> 32));
WRITE_UINT32(p_IpReasmCommonPramTbl->reassFrmDescPoolPtrLow, (uint32_t)tmpReg64);
/*p_TimeOutTbl*/
p_Manip->ipReassmParams.h_TimeOutTbl = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
(uint32_t)(size * 8),8);
if(!p_Manip->ipReassmParams.h_TimeOutTbl)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
IOMemSet32(p_Manip->ipReassmParams.h_TimeOutTbl, 0, (uint16_t)(size * 8));
tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.h_TimeOutTbl) - p_FmPcd->physicalMuramBase);
WRITE_UINT32(p_IpReasmCommonPramTbl->timeOutTblPtr, tmpReg32);
/* Expiration Delay */
tmpReg32 = 0;
tmpReg32 |= p_Manip->ipReassmParams.timeoutThresholdForReassmProcess;
WRITE_UINT32(p_IpReasmCommonPramTbl->expirationDelay, tmpReg32);
/* Counts the number of TimeOut occurrences - Must be initialized to zero.*/
WRITE_UINT32(p_IpReasmCommonPramTbl->totalTimeOutCounter, 0);
/* Counts the number of failed attempts to allocate a Reassembly Frame Descriptor - Must be initialized to zero.*/
WRITE_UINT32(p_IpReasmCommonPramTbl->totalRfdPoolBusyCounter, 0);
/* Counts the number of times an internal buffer busy occured.*/
WRITE_UINT32(p_IpReasmCommonPramTbl->totalInternalBufferBusy, 0);
/* Counts the number of times external buffer busy occured. */
WRITE_UINT32(p_IpReasmCommonPramTbl->totalExternalBufferBusy, 0);
return E_OK;
}
static t_Error CreateIpReassParamTable(t_FmPcdManip *p_Manip, t_Handle h_IpReassParamsTblPtr, bool ipv4)
{
t_IpReasmPram *p_Table;
t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
t_FmPcd *p_FmPcd = p_Manip->h_FmPcd;
uint32_t tmpReg32, autoLearnHashTblSize;
uint32_t numOfWays, setSize, setSizeCode, tmpSetSize;
uint32_t waySize, numOfSets, tmpNumOfSets, numOfEntries;
uint64_t tmpReg64;
t_Handle h_AutoLearnHashTbl, h_AutoLearnSetLockTblPtr;
/*Pointer to fragment ID*/
h_IpReassParamsTblPtr = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
FM_PCD_MANIP_IP_REASM_TABLE_SIZE,
FM_PCD_MANIP_IP_REASM_TABLE_ALIGN);
if(!h_IpReassParamsTblPtr)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
IOMemSet32(h_IpReassParamsTblPtr, 0, FM_PCD_MANIP_IP_REASM_TABLE_SIZE);
p_Table = (t_IpReasmPram *)h_IpReassParamsTblPtr;
tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.h_IpReassCommonParamsTbl) - p_FmPcd->physicalMuramBase);
WRITE_UINT32(((t_IpReasmPram *)h_IpReassParamsTblPtr)->ipReassCommonPrmTblPtr, tmpReg32);
/* waysNumAndSetSize calculation */
numOfWays = p_Manip->ipReassmParams.numOfFramesPerHashEntry;
/*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->ipReassmParams.maxNumFramesInProcess * 2);
/* sets number calculation - number of entries = number of sets * number of ways */
numOfSets = numOfEntries / numOfWays;
/*TODO - Handle way size*/
switch(p_Manip->ipReassmParams.hdr)
{
case(HEADER_TYPE_IPv6):
/* WaySize is rounded-up to next multiple of 8 */
waySize = ROUND_UP(((16 + 16 + 4 + 2) /* * numOfWays*/),8);
break;
case(HEADER_TYPE_IPv4):
break;
default:
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for reassembly"));
}
/* Set size is rounded-up to next power of 2 */
LOG2(numOfWays * waySize, tmpSetSize);
setSize = (uint32_t)(1 << (tmpSetSize + (POWER_OF_2(numOfWays * waySize) ? 0 : 1)));
LOG2(setSize, setSizeCode);
WRITE_UINT16(((t_IpReasmPram *)p_Table)->waysNumAndSetSize, (uint16_t)((numOfWays << 8) | setSizeCode));
LOG2(numOfSets, tmpNumOfSets);
numOfSets = (uint32_t)(1 << (tmpNumOfSets + (POWER_OF_2(numOfSets) ? 0 : 1)));
WRITE_UINT16(((t_IpReasmPram *)p_Table)->autoLearnHashKeyMask, (uint16_t)(numOfSets - 1));
/*autoLearnHashTbl allocation
Table size = set size * number of sets
This table<EFBFBD>s base address should be aligned to SetSize.*/
autoLearnHashTblSize = numOfSets * setSize;
if (ipv4)
h_AutoLearnHashTbl = p_Manip->ipReassmParams.h_Ipv4AutoLearnHashTbl;
else
h_AutoLearnHashTbl = p_Manip->ipReassmParams.h_Ipv6AutoLearnHashTbl;
h_AutoLearnHashTbl = (t_Handle)XX_MallocSmart(autoLearnHashTblSize, p_Manip->ipReassmParams.dataMemId, setSizeCode);
if(!h_AutoLearnHashTbl)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
IOMemSet32(h_AutoLearnHashTbl, 0, autoLearnHashTblSize);
tmpReg64 = ((uint64_t)(p_Manip->ipReassmParams.liodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.liodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
tmpReg64 |= XX_VirtToPhys(h_AutoLearnHashTbl);
WRITE_UINT32(((t_IpReasmPram *)p_Table)->liodnAlAndAutoLearnHashTblPtrHi, (uint32_t)(tmpReg64 >> 32));
WRITE_UINT32(((t_IpReasmPram *)p_Table)->autoLearnHashTblPtrLow, (uint32_t)tmpReg64);
/* AutoLearnSetLockTbl allocation - The size of this table is (number of sets in the IP
Reassembly Automatic Learning Hash table)*4 bytes. This table resides in external memory
and its base address should be 4-byte aligned */
if (ipv4)
h_AutoLearnSetLockTblPtr = p_Manip->ipReassmParams.h_Ipv4AutoLearnSetLockTblPtr;
else
h_AutoLearnSetLockTblPtr = p_Manip->ipReassmParams.h_Ipv6AutoLearnSetLockTblPtr;
h_AutoLearnSetLockTblPtr = (t_Handle)XX_MallocSmart((uint32_t)(numOfSets * 4), p_Manip->ipReassmParams.dataMemId, 4);
if(!h_AutoLearnSetLockTblPtr)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
IOMemSet32(h_AutoLearnSetLockTblPtr, 0, (numOfSets * 4));
tmpReg64 = ((uint64_t)(p_Manip->ipReassmParams.liodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.liodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
tmpReg64 |= XX_VirtToPhys(h_AutoLearnSetLockTblPtr);
WRITE_UINT32(((t_IpReasmPram *)p_Table)->liodnSlAndAutoLearnSetLockTblPtrHi, (uint32_t)(tmpReg64 >> 32));
WRITE_UINT32(((t_IpReasmPram *)p_Table)->autoLearnSetLockTblPtrLow, (uint32_t)tmpReg64);
/* Setting the First/Middle fragment minimum size in Bytes */
WRITE_UINT32(((t_IpReasmPram *)p_Table)->minFragSize, p_Manip->ipReassmParams.minFragSize);
/* Zeroes all counters */
WRITE_UINT32(((t_IpReasmPram *)p_Table)->totalSuccessfullyReasmFramesCounter, 0);
WRITE_UINT32(((t_IpReasmPram *)p_Table)->totalValidFragmentCounter, 0);
WRITE_UINT32(((t_IpReasmPram *)p_Table)->totalProcessedFragCounter, 0);
WRITE_UINT32(((t_IpReasmPram *)p_Table)->totalMalformdFragCounter, 0);
WRITE_UINT32(((t_IpReasmPram *)p_Table)->totalSetBusyCounter, 0);
WRITE_UINT32(((t_IpReasmPram *)p_Table)->totalDiscardedFragsCounter, 0);
WRITE_UINT32(((t_IpReasmPram *)p_Table)->totalMoreThan16FramesCounter, 0);
return E_OK;
}
static t_Error UpdateInitIpReasm(t_Handle h_FmPcd,
t_Handle h_FmPort,
t_FmPcdManip *p_Manip,
t_Handle h_Ad,
bool validate)
{
t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
t_IpReasmCommonTbl *p_ReassmCommonTbl = NULL;
t_FmPortGetSetCcParams fmPortGetSetCcParams;
uint8_t i = 0;
uint32_t tmpReg32;
t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
t_Error err;
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->type == HMAN_OC_IP_REASSEMBLY), E_INVALID_STATE);
SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc,E_INVALID_HANDLE);
UNUSED(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->updateParams)
{
if((!(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 & BUFFER_POOL_ID_FOR_MANIP) ||
(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.getCcParams.poolIndex = p_Manip->fragParams.poolIndx;
fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_RFENE;
fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CLOSING_FRAG_CHECK;
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"));
}
else if (validate)
{
if((!(p_Manip->shadowUpdateParams & BUFFER_POOL_ID_FOR_MANIP) &&
(!(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.getCcParams.poolIndex = p_Manip->fragParams.poolIndx;
fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_FRAG | NIA_ENG_FM_CTL;
fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_RFENE;
fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CLOSING_FRAG_CHECK;
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 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"));
}
if(p_Manip->updateParams)
{
if(p_Manip->updateParams & OFFSET_OF_DATA)
{
p_Manip->ipReassmParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
tmpReg32 = GET_UINT32(p_Ad->matchTblPtr);
tmpReg32 |= p_Manip->ipReassmParams.dataOffset;
WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32);
p_Manip->updateParams &= ~OFFSET_OF_DATA;
p_Manip->shadowUpdateParams |= OFFSET_OF_DATA;
}
p_Manip->updateParams &= ~HW_PORT_ID;
p_Manip->shadowUpdateParams |= HW_PORT_ID;
}
else
{
if(validate)
{
/* TODO - Handle validate..*/
/*if(fmPortGetSetCcParams.getCcParams.hardwarePortId != p_Manip->fragParams.hwPortId)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Reassembly manipulation previously was assigned to another port"));
if(fmPortGetSetCcParams.getCcParams.numOfTasks != p_Manip->fragParams.numOfTasks)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfTasks for this manipulation previously was defined by another value "));
if(fmPortGetSetCcParams.getCcParams.poolIdForManip != p_Manip->fragParams.poolId)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("poolId for this manipulation previously was defined by another value "));
if(!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR))
{
if(p_Manip->fragParams.prOffset != fmPortGetSetCcParams.getCcParams.prOffset)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value "));
}
else
{
if(p_Manip->fragParams.prOffset != 0xff)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value "));
}
if(fmPortGetSetCcParams.getCcParams.dataOffset != p_Manip->fragParams.dataOffset)
RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Data offset previously was defined by another value "));*/
}
}
return E_OK;
}
#endif /*UNDER_CONSTRUCTION_FRAG_REASSEMBLY*/
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(p_Manip->h_Frag)
{
if(p_Manip->fragParams.p_AutoLearnHashTbl)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_AutoLearnHashTbl);
if(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_ReassmFrmDescrPoolTbl);
if(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl);
if(p_Manip->fragParams.p_TimeOutTbl)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_TimeOutTbl);
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Frag);
}
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
if (p_Manip->ipFragParams.h_Frag)
{
if(p_Manip->ipFragParams.h_FragId)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipFragParams.h_FragId);
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipFragParams.h_Frag);
}
if (p_Manip->reassm)
{
if(p_Manip->ipReassmParams.h_Ipv4AutoLearnHashTbl)
XX_Free(p_Manip->ipReassmParams.h_Ipv4AutoLearnHashTbl);
if(p_Manip->ipReassmParams.h_Ipv6AutoLearnHashTbl)
XX_Free(p_Manip->ipReassmParams.h_Ipv6AutoLearnHashTbl);
if(p_Manip->ipReassmParams.h_Ipv4AutoLearnSetLockTblPtr)
XX_Free(p_Manip->ipReassmParams.h_Ipv4AutoLearnSetLockTblPtr);
if(p_Manip->ipReassmParams.h_Ipv6AutoLearnSetLockTblPtr)
XX_Free(p_Manip->ipReassmParams.h_Ipv6AutoLearnSetLockTblPtr);
if(p_Manip->ipReassmParams.h_Ipv4ReassParamsTblPtr)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.h_Ipv4ReassParamsTblPtr);
if(p_Manip->ipReassmParams.h_Ipv6ReassParamsTblPtr)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.h_Ipv6ReassParamsTblPtr);
if(p_Manip->ipReassmParams.h_IpReassCommonParamsTbl)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.h_IpReassCommonParamsTbl);
if(p_Manip->ipReassmParams.h_ReassmFrmDescrIndxPoolTbl)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.h_ReassmFrmDescrIndxPoolTbl);
if(p_Manip->ipReassmParams.h_ReassmFrmDescrPoolTbl)
XX_Free(p_Manip->ipReassmParams.h_ReassmFrmDescrPoolTbl);
}
#endif /* UNDER_CONSTRUCTION_FRAG_REASSEMBLY */
if(p_Manip->p_StatsTbl)
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_StatsTbl);
}
static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams)
{
if(p_ManipParams->rmv)
{
switch(p_ManipParams->rmvParams.type)
{
case(e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_INCLUDE_SPECIFIC_LOCATION):
switch(p_ManipParams->rmvParams.rmvSpecificLocationParams.type)
{
case(e_FM_PCD_MANIP_LOC_BY_HDR) :
switch(p_ManipParams->rmvParams.rmvSpecificLocationParams.manipByHdr.hdr)
{
case(HEADER_TYPE_CAPWAP_DTLS) :
p_Manip->type = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST;
p_Manip->muramAllocate = TRUE;
if(p_ManipParams->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->type = 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"));
}
break;
default:
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("non valid type of remove location"));
}
break;
case(e_FM_PCD_MANIP_RMV_INT_FRAME_HDR) :
if(p_ManipParams->insrt || p_ManipParams->fragOrReasm)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For the type of remove e_FM_PCD_MANIP_RMV_INT_FRAME_HDR the only valid option rmv = TRUE, insrt = FALSE, fragOrReasm = FALSE"));
p_Manip->type = HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX;
p_Manip->muramAllocate = FALSE;
break;
case(e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_TILL_SPECIFIC_LOCATION) :
if (p_ManipParams->fragOrReasm ||
((p_ManipParams->insrt) && p_ManipParams->insrtParams.type != e_FM_PCD_MANIP_INSRT_TO_START_OF_FRAME_INT_FRAME_HDR))
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for the type of remove e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_TILL_SPECIFIC_LOCATION the only allowed insertion type is e_FM_PCD_MANIP_INSRT_TO_START_OF_FRAME_INT_FRAME_HDR"));
p_Manip->type = HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR;
p_Manip->muramAllocate = TRUE;
break;
default:
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
}
}
else if(p_ManipParams->insrt)
{
switch(p_ManipParams->insrtParams.type)
{
case(e_FM_PCD_MANIP_INSRT_TO_START_OF_FRAME_TEMPLATE) :
p_Manip->type = 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->type = HMAN_OC_CAPWAP_FRAGMENTATION;
break;
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;
case(e_FM_PCD_MANIP_INSRT_TO_START_OF_FRAME_INT_FRAME_HDR) :
if(p_ManipParams->fragOrReasm)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of insert can not be fragOrReasm = TRUE"));
p_Manip->type = HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR;
p_Manip->muramAllocate = TRUE;
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->type = HMAN_OC_CAPWAP_FRAGMENTATION;
p_Manip->muramAllocate = FALSE;
break;
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
case(HEADER_TYPE_IPv4):
p_Manip->type = HMAN_OC_IP_FRAGMENTATION;
p_Manip->muramAllocate = TRUE;
break;
#endif /* UNDER_CONSTRUCTION_FRAG_REASSEMBLY */
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"));
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
case(HEADER_TYPE_IPv4):
p_Manip->type = HMAN_OC_IP_REASSEMBLY;
p_Manip->muramAllocate = TRUE;
p_Manip->ipReassmParams.hdr = HEADER_TYPE_IPv4;
break;
case(HEADER_TYPE_IPv6):
p_Manip->type = HMAN_OC_IP_REASSEMBLY;
p_Manip->muramAllocate = TRUE;
p_Manip->ipReassmParams.hdr = HEADER_TYPE_IPv6;
break;
#endif /* UNDER_CONSTRUCTION_FRAG_REASSEMBLY */
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->insrt;
p_Manip->rmv = p_ManipParams->rmv;
return E_OK;
}
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, ("Memory allocation in MURAM FAILED"));
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 FmPcdManipInitUpdate(t_Handle h_FmPcd, 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(h_FmPcd);
UNUSED(h_FmTree);
switch(p_Manip->type)
{
case(HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
if(level != 1)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For CAPWAP reassembly the manipulation has to be in the first level of the tree"));
err = UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(h_FmPort, p_Manip, h_Ad, validate);
break;
#ifdef FM_CAPWAP_SUPPORT
case(HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
if(!p_Manip->h_Frag)
break;
case(HMAN_OC_CAPWAP_FRAGMENTATION):
if(level != 2)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For CAPWAP fragmentation the manipulation has to be in the first level of the tree"));
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)
{
if(level != 2)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For CAPWAP reassembly the manipulation has to be in the first level of the tree"));
err = UpdateInitCapwapReasm(h_FmPcd, h_FmPort, p_Manip, h_Ad, validate);
}
break;
#endif /* FM_CAPWAP_SUPPORT */
#if (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC))
case(HMAN_OC_IPSEC):
err = UpdateInitIPSec(h_FmPort, p_Manip);
if (err != E_OK)
RETURN_ERROR(MAJOR, err, ("UpdateInitIPSec failed"));
if(!p_Manip->h_Frag)
break;
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
case(HMAN_OC_IP_FRAGMENTATION):
err = UpdateInitIpFragmentation(h_FmPort, p_Manip);
break;
case(HMAN_OC_IP_REASSEMBLY):
err = UpdateInitIpReasm(h_FmPcd, h_FmPort, p_Manip, h_Ad, validate);
break;
#endif /* UNDER_CONSTRUCTION_FRAG_REASSEMBLY */
#endif /* (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC))*/
case(HMAN_OC_CAPWAP_INDEXED_STATS):
if(level != 2)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For index statistics the manipulation has to be in the first level of the tree"));
err = UpdateIndxStats(h_FmPcd, h_FmPort, p_Manip);
break;
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;
switch(p_Manip->type)
{
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 & BUFFER_POOL_ID_FOR_MANIP) &&
!(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 previousely in SetPcd function"));
if(level != 2)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For CAPWAP reassembly the manipulation has to be in the first level of the tree"));
}
break;
#ifdef FM_CAPWAP_SUPPORT
case(HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
if(p_Manip->h_Frag)
{
if(level != 2)
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For CAPWAP fragmentation the manipulation has to be in the first level of the tree"));
err = UpdateModifyCapwapFragmenation(p_Manip, h_Ad, validate, h_FmTree);
}
break;
#endif /* FM_CAPWAP_SUPPORT */
default:
return E_OK;
}
return err;
}
static t_Error GetPrOffsetByHeaderOrField(t_FmPcdManipLocationParams *p_ManipParams, uint8_t *parseArrayOffset)
{
e_NetHeaderType hdr = p_ManipParams->manipByHdr.hdr;
e_FmPcdHdrIndex hdrIndex = p_ManipParams->manipByHdr.hdrIndex;
bool byField = p_ManipParams->manipByHdr.byField;
t_FmPcdFields field;
if(byField)
field = p_ManipParams->manipByHdr.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;
/* TODO - to take care about SHIM3
case(HEADER_TYPE_USER_DEFINED_SHIM3):
*parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM3_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;
default:
RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header is not supported"));
}
}
return E_OK;
}
static t_Error RmvHdrTillSpecLocNOrInsrtIntFrmHdr(t_FmPcdManipRmvParams *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)
{
switch(p_ManipParams->rmvSpecificLocationParams.type)
{
case(e_FM_PCD_MANIP_LOC_BY_HDR) :
err = GetPrOffsetByHeaderOrField(&p_ManipParams->rmvSpecificLocationParams, &prsArrayOffset);
break;
case(e_FM_PCD_MANIP_LOC_NON_HDR) :
err = GetPrOffsetByNonHeader(&prsArrayOffset);
break;
default :
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid type of location header manipulation of type Remove"));
}
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;
/*TODO - update offsetInBufferPrefixForIntFrameHdr when port connected to tree
tmpReg32 = 0;
tmpReg32 |= offsetInBufferPrefixForIntFrameHdr;
*(uint32_t *)&p_Ad->matchTblPtr = 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;
}
#ifdef FM_CAPWAP_SUPPORT
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 poolIndex)
{
t_Handle p_Table;
uint32_t tmpReg32 = 0;
int i = 0;
uint8_t log2Num;
uint8_t numOfSets;
uint32_t j = 0;
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"));
}
p_Manip->updateParams |= (NUM_OF_TASKS | BUFFER_POOL_ID_FOR_MANIP | 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, ("Memory allocation in MURAM FAILED"));
IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE);
p_Table = (t_CapwapReasmPram *)p_Manip->h_Frag;
p_Manip->fragParams.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);
IOMemSet32(p_Manip->fragParams.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->fragParams.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; j < p_ManipParams->maxNumFramesInProcess * 2; j++)
{
if(((j / i) % 2)== 0)
{
WRITE_UINT32(*(uint32_t *)PTR_MOVE(p_Manip->fragParams.p_AutoLearnHashTbl, j * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), 0x80000000);
}
}
WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->bufferPoolIdAndRisc1SetIndexes, 0x00008000);
WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc23SetIndexes, 0x80008000);
WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc4SetIndexesAndExtendedStatsTblPtr, 0x80000000);
p_Manip->fragParams.maxNumFramesInProcess = p_ManipParams->maxNumFramesInProcess;
p_Manip->fragParams.poolIndx = poolIndex;
p_Manip->fragParams.fqidForTimeOutFrames = p_ManipParams->fqidForTimeOutFrames;
p_Manip->fragParams.timeoutRoutineRequestTime = p_ManipParams->timeoutRoutineRequestTime;
/*TODO - to take care about this function FmGetTimeStampScale - it return t_Error
now we have problems with all calls to this fucntion*/
p_Manip->fragParams.bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm);
tmpReg32 = 0;
tmpReg32 |= (((uint32_t)1<<p_Manip->fragParams.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 poolIndex)
{
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 | BUFFER_POOL_ID_FOR_MANIP;
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, ("Memory allocation in MURAM FAILED"));
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;
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->fragParams.poolIndx = poolIndex;
return E_OK;
}
#endif /* FM_CAPWAP_SUPPORT */
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
static t_Error IpFragmentation(t_IpFragmentationParams *p_ManipParams,t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd, uint8_t poolIndex)
{
t_AdOfTypeContLookup *p_Ad;
uint32_t tmpReg32 = 0;
SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
p_Manip->ipFragParams.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->ipFragParams.h_Frag)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
IOMemSet32( p_Manip->ipFragParams.h_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE);
p_Ad = (t_AdOfTypeContLookup *)p_Manip->ipFragParams.h_Frag;
tmpReg32 = 0;
tmpReg32 |= (uint32_t)HMAN_OC_IP_FRAGMENTATION;
WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
tmpReg32 = 0;
tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
tmpReg32 |= (p_ManipParams->dontFragAction << 30);
WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
p_Manip->frag = TRUE;
p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation;
p_Manip->ipFragParams.poolIndx = poolIndex;
/*Pointer to fragment ID*/
p_Manip->ipFragParams.h_FragId= (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,4, 4);
if(!p_Manip->ipFragParams.h_FragId)
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
IOMemSet32(p_Manip->ipFragParams.h_FragId, 0, 4);
tmpReg32 = 0;
tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->ipFragParams.h_FragId) - (p_FmPcd->physicalMuramBase));
tmpReg32 |= p_ManipParams->scratchBpid << 24;
WRITE_UINT32(p_Ad->gmask, tmpReg32);
return E_OK;
}
static t_Error FillReassmManipParams(t_FmPcdManip *p_Manip, t_Handle h_Ad, bool ipv4)
{
t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad;
t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
uint32_t tmpReg32;
t_Error err;
t_Handle h_IpReassParamsTblPtr;
/* First Ad register */
tmpReg32 = 0;
tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
if (ipv4)
h_IpReassParamsTblPtr = p_Manip->ipReassmParams.h_Ipv4ReassParamsTblPtr;
else
h_IpReassParamsTblPtr = p_Manip->ipReassmParams.h_Ipv6ReassParamsTblPtr;
err = CreateIpReassParamTable(p_Manip, h_IpReassParamsTblPtr, ipv4);
if (err == E_OK)
tmpReg32 |= (uint32_t)(XX_VirtToPhys(h_IpReassParamsTblPtr) - (p_FmPcd->physicalMuramBase));
else
return err;
WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
/* Second Ad register */
tmpReg32 = (uint32_t)(p_Manip->ipReassmParams.bpid << 8);
WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32);
p_Manip->updateParams = OFFSET_OF_DATA;
/* Third Ad register */
tmpReg32 = 0;
tmpReg32 |= (uint32_t)HMAN_OC_IP_REASSEMBLY;
tmpReg32 |= (uint64_t)(p_Manip->ipReassmParams.liodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT;
tmpReg32 |= (uint64_t)(p_Manip->ipReassmParams.liodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT;
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;
if(p_Manip->muramAllocate)
{
p_Manip->ipReassmParams.h_Ipv4Ad = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
FM_PCD_CC_AD_ENTRY_SIZE,
FM_PCD_CC_AD_TABLE_ALIGN);
if(!p_Manip->ipReassmParams.h_Ipv4Ad)
{
ReleaseManipHandler(p_Manip, p_FmPcd);
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
}
IOMemSet32(p_Manip->ipReassmParams.h_Ipv4Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
}
else
{
p_Manip->ipReassmParams.h_Ipv4Ad = (t_Handle)XX_MallocSmart(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t), p_Manip->ipReassmParams.dataMemId, 0);
if(!p_Manip->ipReassmParams.h_Ipv4Ad)
{
ReleaseManipHandler(p_Manip, p_FmPcd);
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
}
memset(p_Manip->ipReassmParams.h_Ipv4Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
}
FillReassmManipParams(p_Manip, p_Manip->ipReassmParams.h_Ipv6Ad, TRUE);
return E_OK;
}
static t_Error SetIpv6ReassmManip(t_FmPcdManip *p_Manip)
{
t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
if(p_Manip->muramAllocate)
{
p_Manip->ipReassmParams.h_Ipv6Ad = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
FM_PCD_CC_AD_ENTRY_SIZE,
FM_PCD_CC_AD_TABLE_ALIGN);
if(!p_Manip->ipReassmParams.h_Ipv6Ad)
{
ReleaseManipHandler(p_Manip, p_FmPcd);
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
}
IOMemSet32(p_Manip->ipReassmParams.h_Ipv6Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
}
else
{
p_Manip->ipReassmParams.h_Ipv6Ad = (t_Handle)XX_MallocSmart(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t), p_Manip->ipReassmParams.dataMemId, 0);
if(!p_Manip->ipReassmParams.h_Ipv6Ad)
{
ReleaseManipHandler(p_Manip, p_FmPcd);
RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
}
memset(p_Manip->ipReassmParams.h_Ipv6Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
}
FillReassmManipParams(p_Manip, p_Manip->ipReassmParams.h_Ipv6Ad, FALSE);
return E_OK;
}
static t_Error IpReassembly(t_FmPcdManipFragOrReasmParams *p_ManipParams,t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd)
{
uint32_t tmpReg32 = 0, maxSetNumber = 10000;
t_IpReasmCommonTbl *p_IpReasmCommonPramTbl = NULL;
t_IpReassemblyParams reassmManipParams = p_ManipParams->ipReasmParams;
t_Error err;
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(reassmManipParams.maxNumFramesInProcess))
RETURN_ERROR(MAJOR, E_INVALID_VALUE,("maxNumFramesInProcess has to be power of 2"));
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)"));
p_Manip->ipReassmParams.maxNumFramesInProcess = reassmManipParams.maxNumFramesInProcess;
p_Manip->ipReassmParams.timeOutMode = reassmManipParams.timeOutMode;
p_Manip->ipReassmParams.fqidForTimeOutFrames = reassmManipParams.fqidForTimeOutFrames;
p_Manip->ipReassmParams.numOfFramesPerHashEntry = reassmManipParams.numOfFramesPerHashEntry;
p_Manip->ipReassmParams.timeoutThresholdForReassmProcess = reassmManipParams.timeoutThresholdForReassmProcess;
p_Manip->ipReassmParams.liodnOffset = reassmManipParams.liodnOffset;
p_Manip->ipReassmParams.minFragSize = reassmManipParams.minFragSize;
p_Manip->ipReassmParams.dataMemId = reassmManipParams.dataMemId;
p_Manip->ipReassmParams.bpid = p_ManipParams->extBufPoolIndx;
CreateIpReassCommonParamTable(p_Manip, p_FmPcd, p_IpReasmCommonPramTbl);
if ((p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv4_AND_IPv6) || (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv4))
return SetIpv4ReassmManip(p_Manip);
if ((p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv4_AND_IPv6) || (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6))
return SetIpv6ReassmManip(p_Manip);
err = FM_PCD_RegisterReassmPort(p_FmPcd, p_IpReasmCommonPramTbl);
if (err != E_OK)
{
FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_IpReasmCommonPramTbl);
RETURN_ERROR(MAJOR, err, ("port registration"));
}
return E_OK;
}
#endif /*UNDER_CONSTRUCTION_FRAG_REASSEMBLY*/
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_FmPcdManipInsrtParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd)
{
t_FmPcdManipInsrtByTemplateParams *p_InsrtByTemplate = &p_ManipParams->insrtByTemplateParams;
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;
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 == 4)
{
if((IP_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"));
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"));
p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IP_DSCECN_FIELD_OFFSET_FROM_IP] = (uint8_t)p_InsrtByTemplate->modifyOuterIpParams.dscpEcn;
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"));
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 + IP_TOTALLENGTH_FIELD_OFFSET_FROM_IP + 1] = blockSize;
p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IP_TOTALLENGTH_FIELD_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes);
p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IP_ID_FIELD_OFFSET_FROM_IP] = 0x00;
p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IP_ID_FIELD_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize;
/*IP header template - relevant only for ipv4 CheckSum = 0*/
p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IP_HDRCHECKSUM_FIELD_OFFSET_FROM_IP] = 0x00;
p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IP_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + 1] = 0x00;
/*UDP checksum has to be 0*/
if(p_InsrtByTemplate->modifyOuterIpParams.udpPresent)
{
if((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_UDPHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_UDPCHECKSUM_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_UDPHECKSUM_FIELD_OFFSET_FROM_UDP ] = 0x00;
p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_UDPHECKSUM_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
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;
}
#if defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC)
static t_Error IPSecManip(t_FmPcdManipParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd)
{
t_Error err = E_OK;
t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
uint32_t tmpReg32 = 0, tmpRegNia = 0;
SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_INVALID_HANDLE);
if(p_Manip->frag == TRUE)
{
tmpRegNia |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase));
tmpReg32 |= (uint32_t)p_Manip->sizeForFragmentation << 16;
}
else
tmpReg32 = 0xffff0000;
tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE;
tmpReg32 |= HMAN_OC_IPSEC;
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.*/
/*
TODO - Fill the following:
- Over write OuterTos
- SaveInnerTos
- support in CNIA
*/
return err;
}
#endif /* (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || ... */
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->type = HMAN_OC_CAPWAP_INDEXED_STATS;
p_Manip->muramAllocate = TRUE;
break;
default:
RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported statistics type"));
}
return E_OK;
}
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));
if(!stats)
{
err = CheckManipParamsAndSetType(p_Manip, (t_FmPcdManipParams *)p_Params);
}
else
{
err = CheckStatsParamsAndSetType(p_Manip, (t_FmPcdStatsParams *)p_Params);
}
if(err)
{
REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("INVALID HEADER MANIPULATION TYPE"));
ReleaseManipHandler(p_Manip, p_FmPcd);
XX_Free(p_Manip);
return NULL;
}
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
if(p_Manip->type != HMAN_OC_IP_REASSEMBLY)
{
#endif /* UNDER_CONSTRUCTION_FRAG_REASSEMBLY */
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, ("Memory allocation in MURAM FAILED"));
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, ("Memory allocation in MURAM FAILED"));
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));
}
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
}
#endif /* UNDER_CONSTRUCTION_FRAG_REASSEMBLY */
p_Manip->h_FmPcd = h_FmPcd;
return p_Manip;
}
t_Error FmPcdManipUpdate(t_Handle h_FmPcd, 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_FmPort, h_Manip, h_Ad, validate, level, h_FmTree);
}
else
{
err = FmPcdManipModifyUpdate(h_Manip, h_Ad, validate, level, h_FmTree);
}
return err;
}
uint32_t FmPcdManipGetRequiredAction (t_Handle h_Manip)
{
t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
ASSERT_COND(h_Manip);
switch(p_Manip->type)
{
case(HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
case(HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
return UPDATE_NIA_ENQ_WITHOUT_DMA;
default:
return 0;
}
}
void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add)
{
if(add)
((t_FmPcdManip *)h_Manip)->owner++;
else
{
ASSERT_COND(((t_FmPcdManip *)h_Manip)->owner);
((t_FmPcdManip *)h_Manip)->owner--;
}
}
t_Error FmPcdManipCheckParamsForCcNextEgine(t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, uint32_t *requiredAction)
{
t_FmPcdManip *p_Manip;
t_Error err;
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;
switch(p_Manip->type)
{
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;
#if (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC))
case(HMAN_OC_IPSEC):
if((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_DONE) &&
!p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid)
p_Manip->cnia = FALSE;
else
p_Manip->cnia = TRUE;
if(!p_Manip->h_Frag)
{
p_Manip->ownerTmp++;
break;
}
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
case(HMAN_OC_IP_FRAGMENTATION):
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;
#endif /*UNDER_CONSTRUCTION_FRAG_REASSEMBLY*/
break;
#endif /* (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || ... */
default:
RETURN_ERROR(MAJOR, E_INVALID_STATE,("invalid type of header manipulation for this state"));
}
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->type)
{
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;
default:
break;
}
return err;
}
void FmPcdManipUpdateAdResultForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNew)
{
t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
ASSERT_COND(p_Manip);
FmPcdManipUpdateOwner(h_Manip, TRUE);
switch(p_Manip->type)
{
case(HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR):
case(HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
case(HMAN_OC_CAPWAP_INDEXED_STATS):
#if (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC))
case(HMAN_OC_IP_FRAGMENTATION):
case(HMAN_OC_IP_REASSEMBLY):
#endif /* (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || ... */
*p_AdNew = 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_AdNew = NULL;
break;
#if (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC))
case(HMAN_OC_IPSEC):
if (p_Manip->cnia)
*p_AdNew = p_Manip->h_Ad;
else
{
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_AdNew = NULL;
}
break;
#endif /* (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || ... */
default:
break;
}
}
void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNew, uint32_t adTableOffset)
{
t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
ASSERT_COND(p_Manip);
FmPcdManipUpdateOwner(h_Manip, TRUE);
switch(p_Manip->type)
{
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_AdNew = NULL;
break;
default:
break;
}
}
t_Handle FM_PCD_ManipSetNode(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;
switch(p_Manip->type)
{
case(HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR):
/* HmanType1 */
err = RmvHdrTillSpecLocNOrInsrtIntFrmHdr(&p_ManipParams->rmvParams, p_Manip);
break;
#ifdef UNDER_CONSTRUCTION_FRAG_REASSEMBLY
case(HMAN_OC_IP_REASSEMBLY):
/* IpReassembly */
err = IpReassembly(&p_ManipParams->fragOrReasmParams, p_Manip, p_FmPcd);
if(err)
{
REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
ReleaseManipHandler(p_Manip, p_FmPcd);
XX_Free(p_Manip);
return NULL;
}
break;
case(HMAN_OC_IP_FRAGMENTATION):
/* IpFragmentation */
err = IpFragmentation(&p_ManipParams->fragOrReasmParams.ipFragParams ,p_Manip, p_FmPcd, p_ManipParams->fragOrReasmParams.extBufPoolIndx);
if(err)
{
REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
ReleaseManipHandler(p_Manip, p_FmPcd);
XX_Free(p_Manip);
return NULL;
}
#endif /* UNDER_CONSTRUCTION_FRAG_REASSEMBLY */
#if (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || defined(UNDER_CONSTRUCTION_IPSEC))
case(HMAN_OC_IPSEC) :
err = IPSecManip(p_ManipParams, p_Manip, p_FmPcd);
break;
#endif /* (defined(UNDER_CONSTRUCTION_FRAG_REASSEMBLY) || ... */
#ifdef FM_CAPWAP_SUPPORT
case(HMAN_OC_CAPWAP_FRAGMENTATION):
/* CapwapFragmentation */
err = CapwapFragmentation(&p_ManipParams->fragOrReasmParams.capwapFragParams ,p_Manip, p_FmPcd, p_ManipParams->fragOrReasmParams.extBufPoolIndx);
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->type = 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->insrtParams, p_Manip, p_FmPcd);
break;
case(HMAN_OC_CAPWAP_REASSEMBLY) :
/*CAPWAP Reassembly*/
err = CapwapReassembly(&p_ManipParams->fragOrReasmParams.capwapReasmParams,p_Manip, p_FmPcd, p_ManipParams->fragOrReasmParams.extBufPoolIndx);
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->type = 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;
#endif /* FM_CAPWAP_SUPPORT */
case(HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
/*Application Specific type 1*/
err = MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, (bool)(p_ManipParams->treatFdStatusFieldsAsErrors ? TRUE : FALSE));
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;
}
return p_Manip;
}
t_Error FM_PCD_ManipDeleteNode(t_Handle h_FmPcd, t_Handle h_ManipNode)
{
t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode;
SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
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 "));
ReleaseManipHandler(p_Manip,p_FmPcd);
XX_Free(h_ManipNode);
return E_OK;
}
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->type)
{
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 /* FM_CAPWAP_SUPPORT */
#endif /* CONFIG_FMAN_P1023 */