/**************************************************************************** Copyright (c) 2010 Lantiq Deutschland GmbH Am Campeon 3; 85579 Neubiberg, Germany For licensing information, see the file 'LICENSE' in the root folder of this software module. ***************************************************************************** \file ifx_ethsw_pce.c \remarks implement SWITCH API PCE Table micro code *****************************************************************************/ /* Implement the PCE Table Read/Write Function */ #include /* printk() */ #include #include #include #include #include /* Switch API Micro Code V0.3 */ // parser's microcode output field type #define OUT_MAC0 0 #define OUT_MAC1 1 #define OUT_MAC2 2 #define OUT_MAC3 3 #define OUT_MAC4 4 #define OUT_MAC5 5 #define OUT_ETHTYP 6 #define OUT_VTAG0 7 #define OUT_VTAG1 8 #define OUT_ITAG0 9 #define OUT_ITAG1 10 #define OUT_ITAG2 11 #define OUT_ITAG3 12 #define OUT_IP0 13 #define OUT_IP1 14 #define OUT_IP2 15 #define OUT_IP3 16 #define OUT_SIP0 17 #define OUT_SIP1 18 #define OUT_SIP2 19 #define OUT_SIP3 20 #define OUT_SIP4 21 #define OUT_SIP5 22 #define OUT_SIP6 23 #define OUT_SIP7 24 #define OUT_DIP0 25 #define OUT_DIP1 26 #define OUT_DIP2 27 #define OUT_DIP3 28 #define OUT_DIP4 29 #define OUT_DIP5 30 #define OUT_DIP6 31 #define OUT_DIP7 32 #define OUT_SESID 33 #define OUT_PROT 34 #define OUT_APP0 35 #define OUT_APP1 36 #define OUT_IGMP0 37 #define OUT_IGMP1 38 #define OUT_IPOFF 39 #define OUT_NONE 63 // parser's microcode length type #define INSTR 0 #define IPV6 1 #define LENACCU 2 // parser's microcode flag type #define FLAG_ITAG 0 #define FLAG_VLAN 1 #define FLAG_SNAP 2 #define FLAG_PPPOE 3 #define FLAG_IPV6 4 #define FLAG_IPV6FL 5 #define FLAG_IPV4 6 #define FLAG_IGMP 7 #define FLAG_TU 8 #define FLAG_HOP 9 #define FLAG_NN1 10 #define FLAG_NN2 11 #define FLAG_END 12 #define FLAG_NO 13 // macro to define a microcode row #define IFX_FLOW_PCE_MC_M(val, msk, ns, out, len, type, flags, ipv4_len) \ { val, msk, ns<<10 | out<<4 | len>>1, (len&1)<<15 | type<<13 | flags<<9 | ipv4_len<<8 } IFX_FLOW_PCE_MICROCODE pce_mc_max_ifx_tag_m = { //------------------------------------------------------------------------------------------ // value mask ns out_fields L type flags ipv4_len //------------------------------------------------------------------------------------------ IFX_FLOW_PCE_MC_M(0x88c3, 0xFFFF, 1 , OUT_ITAG0 , 4, INSTR , FLAG_ITAG , 0), // 0 : IFXTAG IFX_FLOW_PCE_MC_M(0x8100, 0xFFFF, 2 , OUT_VTAG0 , 2, INSTR , FLAG_VLAN , 0), // 1 : C_VTAG IFX_FLOW_PCE_MC_M(0x0800, 0xFFFF, 20, OUT_ETHTYP, 1, INSTR , FLAG_NO , 0), // 2 : ET_IPV4 IFX_FLOW_PCE_MC_M(0x86DD, 0xFFFF, 21, OUT_ETHTYP, 1, INSTR , FLAG_NO , 0), // 3 : ET_IPV6 IFX_FLOW_PCE_MC_M(0x8864, 0xFFFF, 17, OUT_ETHTYP, 1, INSTR , FLAG_NO , 0), // 4 : ET_PPPOE_S IFX_FLOW_PCE_MC_M(0x8863, 0xFFFF, 16, OUT_ETHTYP, 1, INSTR , FLAG_NO , 0), // 5 : ET_PPPOE_D IFX_FLOW_PCE_MC_M(0x88A8, 0xFFFF, 1 , OUT_VTAG0 , 2, INSTR , FLAG_VLAN , 0), // 6 : S_VTAG IFX_FLOW_PCE_MC_M(0x8100, 0xFFFF, 1 , OUT_VTAG0 , 2, INSTR , FLAG_VLAN , 0), // 7 : C_VTAG2 IFX_FLOW_PCE_MC_M(0x0000, 0xF800, 10, OUT_NONE , 0, INSTR , FLAG_NO , 0), // 8 : EL_LES_800 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 47, OUT_ETHTYP, 1, INSTR , FLAG_NO , 0), // 9 : ET_OTHER IFX_FLOW_PCE_MC_M(0x0600, 0x0600, 49, OUT_ETHTYP, 1, INSTR , FLAG_NO , 0), // 10: EL_GRE_600 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 12, OUT_NONE , 1, INSTR , FLAG_NO , 0), // 11: EL_LES_600 IFX_FLOW_PCE_MC_M(0xAAAA, 0xFFFF, 14, OUT_NONE , 1, INSTR , FLAG_NO , 0), // 12: SNAP1 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_NO , 0), // 13: NO_SNAP1 IFX_FLOW_PCE_MC_M(0x0300, 0xFF00, 49, OUT_NONE , 0, INSTR , FLAG_SNAP , 0), // 14: SNAP2 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_NO , 0), // 15: NO_SNAP2 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 18, OUT_NONE , 3, INSTR , FLAG_NO , 0), // 16: SESID_IGN IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 18, OUT_DIP7 , 3, INSTR , FLAG_PPPOE, 0), // 17: SESID IFX_FLOW_PCE_MC_M(0x0021, 0xFFFF, 20, OUT_NONE , 1, INSTR , FLAG_NO , 0), // 18: PPPOE_IP IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_NO , 0), // 19: PPPOE_NOIP IFX_FLOW_PCE_MC_M(0x4000, 0xF000, 23, OUT_IP0 , 4, INSTR , FLAG_IPV4 , 1), // 20: IPV4_VER IFX_FLOW_PCE_MC_M(0x6000, 0xF000, 34, OUT_IP0 , 3, INSTR , FLAG_IPV6 , 0), // 21: IPV6_VER IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_NO , 0), // 22: NO_IP IFX_FLOW_PCE_MC_M(0x0011, 0x00FF, 27, OUT_IP3 , 2, INSTR , FLAG_NO , 0), // 23: IPV4_UDP1 IFX_FLOW_PCE_MC_M(0x0006, 0x00FF, 27, OUT_IP3 , 2, INSTR , FLAG_NO , 0), // 24: IPV4_TCP IFX_FLOW_PCE_MC_M(0x0002, 0x00FF, 31, OUT_IP3 , 2, INSTR , FLAG_NO , 0), // 25: IPV4_IGMP1 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 29, OUT_IP3 , 2, INSTR , FLAG_NO , 0), // 26: IPV4_OTH1 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 28, OUT_SIP0 , 4, INSTR , FLAG_NO , 0), // 27: IPV4_UDP2 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 47, OUT_NONE , 0, LENACCU, FLAG_NO , 0), // 28: IPV4_UDP3 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 30, OUT_SIP0 , 4, INSTR , FLAG_NO , 0), // 29: IPV4_OTH2 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_NO , 0), // 30: IPV4_OTH3 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 32, OUT_SIP0 , 4, INSTR , FLAG_NO , 0), // 31: IPV4_IGMP2 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 33, OUT_NONE , 0, LENACCU, FLAG_NO , 0), // 32: IPV4_IGMP3 IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_APP0 , 4, INSTR , FLAG_IGMP , 0), // 33: IPV4_IGMP4 IFX_FLOW_PCE_MC_M(0x1100, 0xFF00, 46, OUT_PROT , 1, INSTR , FLAG_NO , 0), // 34: IPV6_UDP IFX_FLOW_PCE_MC_M(0x0600, 0xFF00, 46, OUT_PROT , 1, INSTR , FLAG_NO , 0), // 35: IPV6_TCP IFX_FLOW_PCE_MC_M(0x0000, 0xFF00, 40, OUT_IP3 , 17, INSTR , FLAG_HOP , 0), // 36: IPV6_HOP IFX_FLOW_PCE_MC_M(0x2B00, 0xFF00, 40, OUT_IP3 , 17, INSTR , FLAG_NN1 , 0), // 37: IPV6_ROU IFX_FLOW_PCE_MC_M(0x3C00, 0xFF00, 40, OUT_IP3 , 17, INSTR , FLAG_NN2 , 0), // 38: IPV6_DES IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 48, OUT_PROT , 1, INSTR , FLAG_NO , 0), // 39: IPV6_OTH IFX_FLOW_PCE_MC_M(0x1100, 0xFF00, 47, OUT_PROT , 0, IPV6 , FLAG_NO , 0), // 40: NXT_HD_UDP IFX_FLOW_PCE_MC_M(0x0600, 0xFF00, 47, OUT_PROT , 0, IPV6 , FLAG_NO , 0), // 41: NXT_HD_TCP IFX_FLOW_PCE_MC_M(0x0000, 0xFF00, 40, OUT_NONE , 0, IPV6 , FLAG_HOP , 0), // 42: NXT_HD_HOP IFX_FLOW_PCE_MC_M(0x2B00, 0xFF00, 40, OUT_NONE , 0, IPV6 , FLAG_NN1 , 0), // 43: NXT_HD_ROU IFX_FLOW_PCE_MC_M(0x3C00, 0xFF00, 40, OUT_NONE , 0, IPV6 , FLAG_NN2 , 0), // 44: NXT_HD_DES IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_PROT , 1, INSTR , FLAG_NO , 0), // 45: NXT_HD_OTH IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 47, OUT_SIP0 , 16, INSTR , FLAG_NO , 0), // 46: TU_IP IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_APP0 , 2, INSTR , FLAG_TU , 0), // 47: TU_PORTS IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_SIP0 , 16, INSTR , FLAG_NO , 0), // 48: IPV6_IP IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 49: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 50: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 51: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 52: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 53: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 54: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 55: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 56: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 57: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 58: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 59: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 60: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 61: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0), // 62: END IFX_FLOW_PCE_MC_M(0x0000, 0x0000, 49, OUT_NONE , 0, INSTR , FLAG_END , 0) // 63: END }; /* Static Function Declaration */ static IFX_int32_t tbl_idx_find( void *pTblStart, IFX_uint16_t *pRefCnt, void *pPar, IFX_uint32_t TblEntrySize, IFX_uint32_t TblEntryNum); static IFX_int32_t tbl_write( void *pTblStart, IFX_uint16_t *pRefCnt, void *pPar, IFX_uint32_t TblEntrySize, IFX_uint32_t TblEntryNum); static IFX_int32_t tbl_delete( void *pTblStart, IFX_uint16_t *pRefCnt, void *pPar, IFX_uint32_t TblSize, IFX_uint32_t TblEntryNum); static IFX_int32_t tbl_idx_delete( IFX_uint16_t *pRefCnt, IFX_uint32_t index, IFX_uint32_t TblSize); /* Function Inplementation */ static IFX_int32_t tbl_idx_find( void *pTblStart, IFX_uint16_t *pRefCnt, void *pPar, IFX_uint32_t TblEntrySize, IFX_uint32_t TblEntryNum) { IFX_int32_t i; /* search if the entry is already available and can be re-used */ for (i = 0; i < TblEntryNum; i++) { if (pRefCnt[i] > 0) { /* entry is used, check if the entry content fits */ if (0 == memcmp(((char*)pTblStart) + i * TblEntrySize, pPar, (IFX_uint8_t)TblEntrySize)) { /* Return the index */ return i; } } else { printk("Search pRefCnt[i] = %d, EntryNum = %d\n",pRefCnt[i], i); } } /* table is full, return an error */ IFX_RETURN_PCETM; } static IFX_int32_t tbl_write( void *pTblStart, IFX_uint16_t *pRefCnt, void *pPar, IFX_uint32_t TblEntrySize, IFX_uint32_t TblEntryNum) { IFX_int32_t i; /* search if the entry is already available and can be re-used */ for (i = 0; i < TblEntryNum; i++) { if (pRefCnt[i] > 0) { /* entry is used, check if the entry content fits */ if (0 == memcmp(((char*)pTblStart) + i * TblEntrySize, pPar, (IFX_uint8_t)TblEntrySize)) { /* content is the same, increment reference counter and return the index*/ pRefCnt[i]++; return i; } } else { // printk("Search pRefCnt[i] = %d, EntryNum = %d\n",pRefCnt[i], i); } } /* find an empty entry and add information */ for (i = 0; i < TblEntryNum; i++) { if (pRefCnt[i] == 0) { memcpy(((char*)pTblStart) + i * TblEntrySize, pPar, (IFX_uint8_t)TblEntrySize); pRefCnt[i]++; return i; } else { // printk("Empty entry but pRefCnt[i] = %d, EntryNum = %d\n",pRefCnt[i], i); } } /* table is full, return an error */ IFX_RETURN_PCETM; } static IFX_int32_t tbl_delete( void *pTblStart, IFX_uint16_t *pRefCnt, void *pPar, IFX_uint32_t TblSize, IFX_uint32_t TblEntryNum) { IFX_uint32_t i; //printk("pRefCnt[TblEntryNum] = %d\n",pRefCnt[TblEntryNum]); if (pRefCnt[TblEntryNum] == 0) { memset(((char*)pTblStart) + TblEntryNum * TblSize, 0, (IFX_uint8_t)TblSize); return 0; } else IFX_RETURN_PCETM; } static IFX_int32_t tbl_idx_delete( IFX_uint16_t *pRefCnt, IFX_uint32_t index, IFX_uint32_t TblSize) { if (index >= TblSize) IFX_RETURN_PCETM; if (pRefCnt[index] > 0) pRefCnt[index]--; return 0; } /* Packet Length Table write */ IFX_int32_t ifx_pce_tm_pkg_lng_tbl_write( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_PKG_LNG_TBL_t *pPar) { IFX_void_t *pDevCtx =IFX_NULL; IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_int_t table_index; table_index = tbl_write(pTmHandle->pkg_lng_tbl, pTmHandle->pkg_lng_tbl_cnt, pPar, sizeof(IFX_PCE_PKG_LNG_TBL_t), IFX_PCE_PKG_LNG_TBL_SIZE); pcetable.table = IFX_ETHSW_PCE_PACKET_INDEX; pcetable.table_index = table_index; pcetable.key[0] =pPar->pkg_lng; pcetable.mask = pPar->pkg_lng_rng; pcetable.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return table_index; } /* Packet Length Table delete */ IFX_int32_t ifx_pce_tm_pkg_lng_tbl_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_PCE_PKG_LNG_TBL_t *pPar=IFX_NULL; IFX_void_t *pDevCtx =IFX_NULL; tbl_delete(pTmHandle->pkg_lng_tbl, pTmHandle->pkg_lng_tbl_cnt, pPar, sizeof(IFX_PCE_PKG_LNG_TBL_t), IFX_PCE_PKG_LNG_TBL_SIZE); if (pTmHandle->pkg_lng_tbl_cnt[index] == 0) { pcetable.table = IFX_ETHSW_PCE_PACKET_INDEX; pcetable.table_index = index; pcetable.key[0] = 0; pcetable.key[1] = 0; pcetable.key[2] = 0; pcetable.mask = 0; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); pTmHandle->pkg_lng_tbl_cnt[index] = 0; } return IFX_SUCCESS; } /* Packet Length Table index delete */ IFX_int32_t ifx_pce_tm_pkg_lng_tbl_idx_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { return tbl_idx_delete( pTmHandle->pkg_lng_tbl_cnt, index, IFX_PCE_PKG_LNG_TBL_SIZE); } /* Packet Length Table read */ IFX_int32_t ifx_pce_tm_pkg_lng_tbl_read( IFX_PCE_HANDLE_t *pTmHandle, IFX_int32_t index, IFX_PCE_PKG_LNG_TBL_t *pPar) { if (index < IFX_PCE_PKG_LNG_TBL_SIZE) { memcpy(pPar, &pTmHandle->pkg_lng_tbl[index],sizeof(IFX_PCE_PKG_LNG_TBL_t)); return 0; } } /* MAC DA/SA Table index write */ IFX_int32_t ifx_pce_tm_dasa_mac_tbl_write( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_DASA_MAC_TBL_t *pPar) { IFX_void_t *pDevCtx =IFX_NULL; IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_int_t table_index; table_index = tbl_write(pTmHandle->dasa_mac_tbl, pTmHandle->dasa_mac_tbl_cnt, pPar, sizeof(IFX_PCE_DASA_MAC_TBL_t), IFX_PCE_DASA_MAC_TBL_SIZE); pcetable.table = IFX_ETHSW_PCE_MAC_DASA_INDEX; pcetable.table_index = table_index; pcetable.key[0] =(pPar->mac[4] << 8 | pPar->mac[5]); pcetable.key[1] =(pPar->mac[2] << 8 | pPar->mac[3]); pcetable.key[2] =(pPar->mac[0] << 8 | pPar->mac[1]); pcetable.mask = pPar->mac_mask; pcetable.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return table_index; } /* MAC DA/SA Table delete */ IFX_int32_t ifx_pce_tm_dasa_mac_tbl_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_PCE_DASA_MAC_TBL_t *pPar=IFX_NULL; IFX_void_t *pDevCtx =IFX_NULL; tbl_delete(pTmHandle->dasa_mac_tbl, pTmHandle->dasa_mac_tbl_cnt, pPar, sizeof(IFX_PCE_DASA_MAC_TBL_t), IFX_PCE_DASA_MAC_TBL_SIZE); if (pTmHandle->dasa_mac_tbl_cnt[index] == 0) { pcetable.table = IFX_ETHSW_PCE_MAC_DASA_INDEX; pcetable.table_index = index; pcetable.key[0] = 0; pcetable.key[1] = 0; pcetable.key[2] = 0; pcetable.mask = 0; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); pTmHandle->dasa_mac_tbl_cnt[index] = 0; } return IFX_SUCCESS; } /* MAC DA/SA Table index delete */ IFX_int32_t ifx_pce_tm_dasa_mac_tbl_idx_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { return tbl_idx_delete( pTmHandle->dasa_mac_tbl_cnt, index, IFX_PCE_DASA_MAC_TBL_SIZE); } /* MAC DA/SA Table Read */ IFX_int32_t ifx_pce_tm_dasa_mac_tbl_read( IFX_PCE_HANDLE_t *pTmHandle, IFX_int32_t index, IFX_PCE_DASA_MAC_TBL_t *pPar) { /* Copy mac address */ memcpy(pPar, &pTmHandle->dasa_mac_tbl[index], sizeof(IFX_PCE_DASA_MAC_TBL_t)); return 0; } /* Application Table write */ IFX_int32_t ifx_pce_tm_appl_tbl_write( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_APPL_TBL_t *pPar) { IFX_void_t *pDevCtx =IFX_NULL; IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_int_t table_index; table_index = tbl_write(pTmHandle->appl_tbl, pTmHandle->appl_tbl_cnt, pPar, sizeof(IFX_PCE_APPL_TBL_t), IFX_PCE_APPL_TBL_SIZE); pcetable.table = IFX_ETHSW_PCE_APPLICATION_INDEX; pcetable.table_index = table_index; pcetable.key[0] =pPar->appl_data; pcetable.mask = pPar->mask_range; pcetable.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return table_index; } /* Application Table Delete */ IFX_int32_t ifx_pce_tm_appl_tbl_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_PCE_APPL_TBL_t *pPar=IFX_NULL; IFX_void_t *pDevCtx =IFX_NULL; tbl_delete(pTmHandle->appl_tbl, pTmHandle->appl_tbl_cnt, pPar, sizeof(IFX_PCE_APPL_TBL_t), IFX_PCE_APPL_TBL_SIZE); if (pTmHandle->appl_tbl_cnt[index] == 0) { pcetable.table = IFX_ETHSW_PCE_APPLICATION_INDEX; pcetable.table_index = index; pcetable.key[0] = 0; pcetable.key[1] = 0; pcetable.key[2] = 0; pcetable.mask = 0; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); pTmHandle->appl_tbl_cnt[index] = 0; } return IFX_SUCCESS; } /* Application Table index Delete */ IFX_int32_t ifx_pce_tm_appl_tbl_idx_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { return tbl_idx_delete( pTmHandle->appl_tbl_cnt, index, IFX_PCE_APPL_TBL_SIZE); } /* Application Table Read */ IFX_int32_t ifx_pce_tm_appl_tbl_read( IFX_PCE_HANDLE_t *pTmHandle, IFX_int32_t index, IFX_PCE_APPL_TBL_t *pPar) { /* Copy Application Table */ memcpy(pPar, &pTmHandle->appl_tbl[index], sizeof(IFX_PCE_APPL_TBL_t)); return 0; } /* IP DA/SA msb Table write */ IFX_int32_t ifx_pce_tm_ip_dasa_msb_tbl_write( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_IP_DASA_MSB_TBL_t *pPar) { IFX_void_t *pDevCtx =IFX_NULL; IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_int_t table_index; table_index = tbl_write(pTmHandle->ip_dasa_msb_tbl, pTmHandle->ip_dasa_msb_tbl_cnt, pPar, sizeof(IFX_PCE_IP_DASA_MSB_TBL_t), IFX_PCE_IP_DASA_MSB_TBL_SIZE); pcetable.table = IFX_ETHSW_PCE_IP_DASA_MSB_INDEX; pcetable.table_index = table_index; pcetable.key[0] =((pPar->ip_msb[1] << 8) |pPar->ip_msb[0]); pcetable.key[1] =((pPar->ip_msb[3] << 8) |pPar->ip_msb[2]); pcetable.key[2] =((pPar->ip_msb[5] << 8) |pPar->ip_msb[4]); pcetable.key[3] =((pPar->ip_msb[7] << 8) |pPar->ip_msb[6]); pcetable.mask = pPar->mask; pcetable.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return table_index; } /* IP DA/SA msb Table delete */ IFX_int32_t ifx_pce_tm_ip_dasa_msb_tbl_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_PCE_IP_DASA_MSB_TBL_t *pPar=IFX_NULL; IFX_void_t *pDevCtx =IFX_NULL; tbl_delete(pTmHandle->ip_dasa_msb_tbl, pTmHandle->ip_dasa_msb_tbl_cnt, pPar, sizeof(IFX_PCE_IP_DASA_MSB_TBL_t), IFX_PCE_IP_DASA_MSB_TBL_SIZE); if (pTmHandle->ip_dasa_msb_tbl_cnt[index] == 0) { pcetable.table = IFX_ETHSW_PCE_IP_DASA_MSB_INDEX; pcetable.table_index = index; pcetable.key[0] = 0; pcetable.key[1] = 0; pcetable.key[2] = 0; pcetable.mask = 0; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); pTmHandle->ip_dasa_msb_tbl_cnt[index] = 0; } return IFX_SUCCESS; } /* IP DA/SA msb Table index delete */ IFX_int32_t ifx_pce_tm_ip_dasa_msb_tbl_idx_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { return tbl_idx_delete( pTmHandle->ip_dasa_msb_tbl_cnt, index, IFX_PCE_IP_DASA_MSB_TBL_SIZE); } /* IP DA/SA msb Table read */ IFX_int32_t ifx_pce_tm_ip_dasa_msb_tbl_read( IFX_PCE_HANDLE_t *pTmHandle, IFX_int32_t index, IFX_PCE_IP_DASA_MSB_TBL_t *pPar) { /* Copy mac address */ memcpy(pPar, &pTmHandle->ip_dasa_msb_tbl[index], sizeof(IFX_PCE_IP_DASA_MSB_TBL_t)); return 0; } /* IP DA/SA lsb Table Write */ IFX_int32_t ifx_pce_tm_ip_dasa_lsb_tbl_write( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_IP_DASA_LSB_TBL_t *pPar) { IFX_void_t *pDevCtx =IFX_NULL; IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_int_t table_index; table_index = tbl_write(pTmHandle->ip_dasa_lsb_tbl, pTmHandle->ip_dasa_lsb_tbl_cnt, pPar, sizeof(IFX_PCE_IP_DASA_LSB_TBL_t), IFX_PCE_IP_DASA_LSB_TBL_SIZE); pcetable.table = IFX_ETHSW_PCE_IP_DASA_LSB_INDEX; pcetable.table_index = table_index; pcetable.key[0] =((pPar->ip_lsb[1] << 8) |pPar->ip_lsb[0]); pcetable.key[1] =((pPar->ip_lsb[3] << 8) |pPar->ip_lsb[2]); pcetable.key[2] =((pPar->ip_lsb[6] << 8) |pPar->ip_lsb[7]); pcetable.key[3] =((pPar->ip_lsb[4] << 8) |pPar->ip_lsb[5]); pcetable.mask = pPar->mask; pcetable.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return table_index; } /* IP DA/SA lsb Table delete */ IFX_int32_t ifx_pce_tm_ip_dasa_lsb_tbl_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_PCE_IP_DASA_LSB_TBL_t *pPar=IFX_NULL; IFX_void_t *pDevCtx =IFX_NULL; tbl_delete(pTmHandle->ip_dasa_lsb_tbl, pTmHandle->ip_dasa_lsb_tbl_cnt, pPar, sizeof(IFX_PCE_IP_DASA_LSB_TBL_t), index); if (pTmHandle->ip_dasa_lsb_tbl_cnt[index] == 0) { pcetable.table = IFX_ETHSW_PCE_IP_DASA_LSB_INDEX; pcetable.table_index = index; pcetable.key[0] = 0; pcetable.key[1] = 0; pcetable.key[2] = 0; pcetable.key[3] = 0; pcetable.mask = 0; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); pTmHandle->ip_dasa_lsb_tbl_cnt[index] = 0; } return IFX_SUCCESS; } /* IP DA/SA lsb Table index delete */ IFX_int32_t ifx_pce_tm_ip_dasa_lsb_tbl_idx_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { return tbl_idx_delete( pTmHandle->ip_dasa_lsb_tbl_cnt, index, IFX_PCE_IP_DASA_LSB_TBL_SIZE); } /* IP DA/SA lsb Table search */ IFX_int32_t ifx_pce_tm_ip_dasa_lsb_tbl_index_search( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_IP_DASA_LSB_TBL_t *pPar) { IFX_int32_t table_index; /* search if the entry is already available and can be re-used */ for (table_index = 0; table_index < IFX_PCE_IP_DASA_LSB_TBL_SIZE; table_index++) { if (pTmHandle->ip_dasa_lsb_tbl_cnt[table_index] > 0) { /* entry is used, check if the entry content fits */ if (0 == memcmp((((char*)pTmHandle->ip_dasa_lsb_tbl) + table_index * sizeof(IFX_PCE_IP_DASA_LSB_TBL_t)), pPar, (IFX_uint8_t)sizeof(IFX_PCE_IP_DASA_LSB_TBL_t))) { /* Return the index */ return table_index; } } } #if 0 table_index = tbl_idx_find(pTmHandle->ip_dasa_lsb_tbl, pTmHandle->ip_dasa_lsb_tbl_cnt, pPar, sizeof(IFX_PCE_IP_DASA_LSB_TBL_t), IFX_PCE_IP_DASA_LSB_TBL_SIZE); #endif // return table_index; } /* IP DA/SA lsb Table read */ IFX_int32_t ifx_pce_tm_ip_dasa_lsb_tbl_read( IFX_PCE_HANDLE_t *pTmHandle, IFX_int32_t index, IFX_PCE_IP_DASA_LSB_TBL_t *pPar) { /* Copy IP address */ memcpy(pPar, &pTmHandle->ip_dasa_lsb_tbl[index], sizeof(IFX_PCE_IP_DASA_LSB_TBL_t)); return 0; } /* Protocal Table write */ IFX_int32_t ifx_pce_tm_ptcl_tbl_write( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_PTCL_TBL_t *pPar) { IFX_void_t *pDevCtx =IFX_NULL; IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_int_t table_index; table_index = tbl_write(pTmHandle->ptcl_tbl, pTmHandle->ptcl_tbl_cnt, pPar, sizeof(IFX_PCE_PTCL_TBL_t), IFX_PCE_PTCL_TBL_SIZE); if (table_index < 0) return table_index; pcetable.table = IFX_ETHSW_PCE_PROTOCOL_INDEX; pcetable.table_index = table_index; /* Should We need to check the entertype ? */ pcetable.key[0] =pPar->key.ethertype; pcetable.mask = pPar->mask.ethertype_mask; pcetable.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return table_index; } /* Protocal Table delete */ IFX_int32_t ifx_pce_tm_ptcl_tbl_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_PCE_PTCL_TBL_t *pPar=IFX_NULL; IFX_void_t *pDevCtx =IFX_NULL; tbl_delete(pTmHandle->ptcl_tbl, pTmHandle->ptcl_tbl_cnt, pPar, sizeof(IFX_PCE_PTCL_TBL_t), IFX_PCE_PTCL_TBL_SIZE); if (pTmHandle->ptcl_tbl_cnt[index] == 0) { pcetable.table = IFX_ETHSW_PCE_PROTOCOL_INDEX; pcetable.table_index = index; pcetable.key[0] = 0; pcetable.key[1] = 0; pcetable.key[2] = 0; pcetable.key[3] = 0; pcetable.mask = 0; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); pTmHandle->ptcl_tbl_cnt[index] = 0; } return IFX_SUCCESS; } /* Protocal Table index delete */ IFX_int32_t ifx_pce_tm_ptcl_tbl_idx_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { return tbl_idx_delete( pTmHandle->ptcl_tbl_cnt, index, IFX_PCE_PTCL_TBL_SIZE); } /* Protocal Table Read */ IFX_int32_t ifx_pce_tm_ptcl_tbl_read( IFX_PCE_HANDLE_t *pTmHandle, IFX_int32_t index, IFX_PCE_PTCL_TBL_t *pPar) { /* Copy mac address */ memcpy(pPar, &pTmHandle->ptcl_tbl[index], sizeof(IFX_PCE_PTCL_TBL_t)); return 0; } /* PPPoE Table Write */ IFX_int32_t ifx_pce_tm_pppoe_tbl_write( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_PPPOE_TBL_t *pPar) { IFX_void_t *pDevCtx =IFX_NULL; IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_int_t table_index; table_index = tbl_write(pTmHandle->pppoe_tbl, pTmHandle->pppoe_tbl_cnt, pPar, sizeof(IFX_PCE_PPPOE_TBL_t), IFX_PCE_PPPOE_TBL_SIZE); if (table_index < 0) return table_index; pcetable.table = IFX_ETHSW_PCE_PPPOE_INDEX; pcetable.table_index = table_index; pcetable.key[0] =pPar->sess_id; pcetable.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return table_index; } /* PPPoE Table Delete */ IFX_int32_t ifx_pce_tm_pppoe_tbl_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_PCE_PPPOE_TBL_t *pPar=IFX_NULL; IFX_void_t *pDevCtx =IFX_NULL; tbl_delete(pTmHandle->pppoe_tbl, pTmHandle->pppoe_tbl_cnt, pPar, sizeof(IFX_PCE_PPPOE_TBL_t), IFX_PCE_PPPOE_TBL_SIZE); if (pTmHandle->pppoe_tbl_cnt[index] == 0) { pcetable.table = IFX_ETHSW_PCE_PPPOE_INDEX; pcetable.table_index = index; pcetable.key[0] = 0; pcetable.key[1] = 0; pcetable.key[2] = 0; pcetable.key[3] = 0; pcetable.mask = 0; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); pTmHandle->pppoe_tbl_cnt[index] = 0; } return IFX_SUCCESS; } /* PPPoE Table index delete */ IFX_int32_t ifx_pce_tm_pppoe_tbl_idx_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { return tbl_idx_delete( pTmHandle->pppoe_tbl_cnt, index, IFX_PCE_PPPOE_TBL_SIZE); } /* PPPoE Table Read */ IFX_int32_t ifx_pce_tm_pppoe_tbl_read( IFX_PCE_HANDLE_t *pTmHandle, IFX_int32_t index, IFX_PCE_PPPOE_TBL_t *pPar) { /* Copy VLAN Action Table*/ memcpy(pPar, &pTmHandle->pppoe_tbl[index], sizeof(IFX_PCE_PPPOE_TBL_t)); return 0; } /* VLAN Table Write */ IFX_int32_t ifx_pce_tm_vlan_act_tbl_write( IFX_PCE_HANDLE_t *pTmHandle, IFX_PCE_VLAN_ACT_TBL_t *pPar) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_int_t table_index; table_index = tbl_write(pTmHandle->vlan_act_tbl, pTmHandle->vlan_act_tbl_cnt, pPar, sizeof(IFX_PCE_VLAN_ACT_TBL_t), IFX_PCE_VLAN_ACT_TBL_SIZE); return table_index; } /* VLAN Table Delete */ IFX_int32_t ifx_pce_tm_vlan_act_tbl_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_PCE_VLAN_ACT_TBL_t *pPar=IFX_NULL; IFX_void_t *pDevCtx=IFX_NULL; tbl_delete(pTmHandle->vlan_act_tbl, pTmHandle->vlan_act_tbl_cnt, pPar, sizeof(IFX_PCE_VLAN_ACT_TBL_t), IFX_PCE_VLAN_ACT_TBL_SIZE); if (pTmHandle->vlan_act_tbl_cnt[index] == 0) { pcetable.table = IFX_ETHSW_PCE_ACTVLAN_INDEX; pcetable.table_index = index; pcetable.key[0] = 0; pcetable.key[1] = 0; pcetable.key[2] = 0; pcetable.key[3] = 0; pcetable.mask = 0; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); pTmHandle->vlan_act_tbl_cnt[index] = 0; } return IFX_SUCCESS; } /* VLAN Table Index Delete */ IFX_int32_t ifx_pce_tm_vlan_act_tbl_idx_delete( IFX_PCE_HANDLE_t *pTmHandle, IFX_uint32_t index) { return tbl_idx_delete( pTmHandle->vlan_act_tbl_cnt, index, IFX_PCE_VLAN_ACT_TBL_SIZE); } /* VLAN Table Read */ IFX_int32_t ifx_pce_tm_vlan_act_tbl_read( IFX_PCE_HANDLE_t *pTmHandle, IFX_int32_t index, IFX_PCE_VLAN_ACT_TBL_t *pPar) { /* Copy VLAN Action Table*/ memcpy(pPar, &pTmHandle->vlan_act_tbl[index], sizeof(IFX_PCE_VLAN_ACT_TBL_t)); return 0; } IFX_int32_t ifx_pce_tm_print_tables(IFX_PCE_HANDLE_t *pTmHandle) { IFX_int32_t i; IFX_int32_t table_printed = 0; table_printed = 0; for (i = 0; i < IFX_PCE_PKG_LNG_TBL_SIZE; i++) { if (pTmHandle->pkg_lng_tbl_cnt[i]) { if (table_printed == 0) { table_printed = 1; printk("\nContent Packet Length Table\n===========================\n"); } printk("\t%d: Pkt lng %d, Pkt lng range %d\n", i, pTmHandle->pkg_lng_tbl[i].pkg_lng, pTmHandle->pkg_lng_tbl[i].pkg_lng_rng); } } table_printed = 0; for (i = 0; i < IFX_PCE_DASA_MAC_TBL_SIZE; i++) { if (pTmHandle->dasa_mac_tbl_cnt[i]) { if (table_printed == 0) { table_printed = 1; printk("\nContent DASA MAC Table\n======================\n"); } printk("\t%d: MAC 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X, Mask 0x%04X\n", i, pTmHandle->dasa_mac_tbl[i].mac[0], pTmHandle->dasa_mac_tbl[i].mac[1], pTmHandle->dasa_mac_tbl[i].mac[2], pTmHandle->dasa_mac_tbl[i].mac[3], pTmHandle->dasa_mac_tbl[i].mac[4], pTmHandle->dasa_mac_tbl[i].mac[5], pTmHandle->dasa_mac_tbl[i].mac_mask); } } table_printed = 0; for (i = 0; i < IFX_PCE_APPL_TBL_SIZE; i++) { if (pTmHandle->appl_tbl_cnt[i]) { if (table_printed == 0) { table_printed = 1; printk("\nContent Application Table\n=========================\n"); } printk("\t%d: Appl data 0x%04X, Mask/Range 0x%04X\n", i, pTmHandle->appl_tbl[i].appl_data, pTmHandle->appl_tbl[i].mask_range); } } table_printed = 0; for (i = 0; i < IFX_PCE_IP_DASA_MSB_TBL_SIZE; i++) { if (pTmHandle->ip_dasa_msb_tbl_cnt[i]) { if (table_printed == 0) { table_printed = 1; printk("\nContent IP DASA MSB Table\n=========================\n"); } printk("\t%d: IP 15:8 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, mask 0x%04X\n", i, pTmHandle->ip_dasa_msb_tbl[i].ip_msb[0], pTmHandle->ip_dasa_msb_tbl[i].ip_msb[1], pTmHandle->ip_dasa_msb_tbl[i].ip_msb[2], pTmHandle->ip_dasa_msb_tbl[i].ip_msb[3], pTmHandle->ip_dasa_msb_tbl[i].ip_msb[4], pTmHandle->ip_dasa_msb_tbl[i].ip_msb[5], pTmHandle->ip_dasa_msb_tbl[i].mask); } } table_printed = 0; for (i = 0; i < IFX_PCE_IP_DASA_LSB_TBL_SIZE; i++) { if (pTmHandle->ip_dasa_lsb_tbl_cnt[i]) { if (table_printed == 0) { table_printed = 1; printk("\nContent IP DASA LSB Table\n=========================\n"); } printk("\t%d: IP 7:0 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, mask 0x%04X\n", i, pTmHandle->ip_dasa_lsb_tbl[i].ip_lsb[0], pTmHandle->ip_dasa_lsb_tbl[i].ip_lsb[1], pTmHandle->ip_dasa_lsb_tbl[i].ip_lsb[2], pTmHandle->ip_dasa_lsb_tbl[i].ip_lsb[3], pTmHandle->ip_dasa_lsb_tbl[i].ip_lsb[4], pTmHandle->ip_dasa_lsb_tbl[i].ip_lsb[5], pTmHandle->ip_dasa_lsb_tbl[i].mask); } } table_printed = 0; for (i = 0; i < IFX_PCE_IP_DASA_LSB_TBL_SIZE; i++) { if (pTmHandle->ptcl_tbl_cnt[i]) { if (table_printed == 0) { table_printed = 1; printk("\nContent Protocl Table\n=====================\n"); } printk("\t%d: Eth 0x%04X, Eth Mask 0x%04X, Prot 0x%02X, Prot Flags 0x%02X, Prot Mask %d, Prot Flag Mask %d\n", i, pTmHandle->ptcl_tbl[i].key.ethertype, pTmHandle->ptcl_tbl[i].mask.ethertype_mask, pTmHandle->ptcl_tbl[i].key.prot.protocol, pTmHandle->ptcl_tbl[i].key.prot.protocol_flags, pTmHandle->ptcl_tbl[i].mask.prot.protocol_mask, pTmHandle->ptcl_tbl[i].mask.prot.protocol_flag_mask); } } table_printed = 0; for (i = 0; i < IFX_PCE_PPPOE_TBL_SIZE; i++) { if (pTmHandle->pppoe_tbl_cnt[i]) { if (table_printed == 0) { table_printed = 1; printk("\nContent Protocl Table\n=====================\n"); } printk("\t%d: PPPoE sess ID 0x%04X\n", i, pTmHandle->pppoe_tbl[i].sess_id); } } table_printed = 0; for (i = 0; i < IFX_PCE_VLAN_ACT_TBL_SIZE; i++) { if (pTmHandle->vlan_act_tbl_cnt[i]) { if (table_printed == 0) { table_printed = 1; printk("\nContent Protocl Table\n=====================\n"); } printk("\t%d: VLAN ID 0x%04X, Repl. Flag %d, FID %d\n", i, pTmHandle->vlan_act_tbl[i].vid, pTmHandle->vlan_act_tbl[i].repl_flg, pTmHandle->vlan_act_tbl[i].fid); } } return 0; } /* PCE Table Init routine */ IFX_int32_t ifx_pce_table_init(IFX_PCE_t *pPCEHandle) { IFX_int32_t i; if (pPCEHandle == IFX_NULL) return IFX_ERROR; memset(&pPCEHandle->pce_sub_tbl, 0, sizeof(IFX_PCE_HANDLE_t)); memset(&pPCEHandle->pce_tbl, 0, sizeof(IFX_PCE_TBL_t)); memset(&pPCEHandle->pce_act, 0, sizeof(IFX_FLOW_PCE_action_t)); for (i = 0;i < 64 ;i++) { pPCEHandle->pce_tbl_used[i] = 0; } return 0; } /* PCE Table Micro Code Init routine */ IFX_return_t IFX_VR9_Switch_PCE_Micro_Code_Int() { IFX_void_t *pDevCtx =IFX_NULL; IFX_uint8_t i,j; IFX_uint32_t value; IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t tbl_entry; #if 0 /* Work wround for Gswitch + PPA Reset */ /* Proceed the switch RESET - Ethernet Switch Reset R0/R1 */ ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_ETHSW_SWRES_R1_OFFSET, VR9_ETHSW_SWRES_R1_SHIFT, VR9_ETHSW_SWRES_R1_SIZE, 1); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_ETHSW_SWRES_R0_OFFSET, VR9_ETHSW_SWRES_R0_SHIFT, VR9_ETHSW_SWRES_R0_SIZE, 1); #endif /* Set GLOB_CTRL.SE */ ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_GLOB_CTRL_SE_OFFSET + 0xC40), VR9_GLOB_CTRL_SE_SHIFT, VR9_GLOB_CTRL_SE_SIZE, 1); /* Disable all physical port - FDMA_PCTRL.EN & SDMA_PCTRL.PEN */ for (j =0; j < 7;j++) { ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_FDMA_PCTRL_EN_OFFSET + (j * 0x6)), VR9_FDMA_PCTRL_EN_SHIFT, VR9_FDMA_PCTRL_EN_SIZE, 0); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_SDMA_PCTRL_PEN_OFFSET + (j * 0x6)), VR9_SDMA_PCTRL_PEN_SHIFT, VR9_SDMA_PCTRL_PEN_SIZE, 0); } /* Download the microcode to the hardware */ for (i = 0; i < IFX_FLOW_PCE_MICROCODE_VALUES; i++) { memset(&tbl_entry, 0, sizeof(tbl_entry)); tbl_entry.val[3] = pce_mc_max_ifx_tag_m[i].val_3; tbl_entry.val[2] = pce_mc_max_ifx_tag_m[i].val_2; tbl_entry.val[1] = pce_mc_max_ifx_tag_m[i].val_1; tbl_entry.val[0] = pce_mc_max_ifx_tag_m[i].val_0; tbl_entry.table_index = i; tbl_entry.table = 0; // PARSER ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &tbl_entry); } /* PCE parser microcode is valid */ ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_GCTRL_0_MC_VALID_OFFSET, VR9_PCE_GCTRL_0_MC_VALID_SHIFT, VR9_PCE_GCTRL_0_MC_VALID_SIZE, 0x1); #if 0 /* PCE Traffic Flow Table Init */ /* UTP: SMS01378497 */ memset(&tbl_entry, 0, sizeof(tbl_entry)); tbl_entry.val[0] = 0x40; tbl_entry.val[1] = 0; tbl_entry.val[2] = 0; tbl_entry.val[3] = 0; tbl_entry.val[4] = 0; tbl_entry.key[0] = 0xFF0F; tbl_entry.key[1] = 0xFFFF; tbl_entry.key[2] = 0xFFFF; tbl_entry.key[3] = 0xFFFF; tbl_entry.key[4] = 0xFFFF; tbl_entry.key[5] = 0xFFFF; tbl_entry.key[6] = 0xFFFF; tbl_entry.key[7] = 0xFFFF; tbl_entry.table_index = 0x3; tbl_entry.table = IFX_ETHSW_PCE_TFLOW_INDEX; // Traffic Flow Table tbl_entry.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &tbl_entry); #endif /* UTP: SMS01358977 */ ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_PMAP_2_DMCPMAP_OFFSET, VR9_PCE_PMAP_2_DMCPMAP_SHIFT, VR9_PCE_PMAP_2_DMCPMAP_SIZE, 0x7F); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_PMAP_3_UUCMAP_OFFSET, VR9_PCE_PMAP_3_UUCMAP_SHIFT, VR9_PCE_PMAP_3_UUCMAP_SIZE, 0x7F); /* Overwrite the default configuration needed by Switch */ /* RMON Counter Enable for all physical ports */ for (j = 0; j < 7; j++) { ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_BM_PCFG_CNTEN_OFFSET + (j * 0x2)), VR9_BM_PCFG_CNTEN_SHIFT, VR9_BM_PCFG_CNTEN_SIZE, 1); } /* FCS generation is disabled on all ports */ for ( j = 0; j < 7; j++) { ifx_ethsw_ll_DirectAccessWrite(pDevCtx, ( VR9_MAC_CTRL_0_FCS_OFFSET + (j * 0xC)), VR9_MAC_CTRL_0_FCS_SHIFT, VR9_MAC_CTRL_0_FCS_SIZE, 0); } /* Overwrite MDIO PHY addresses - TODO in future update */ /* Port 6 Special Tag insertion enable */ ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_FDMA_PCTRL_STEN_OFFSET + ( 6 * 0x6)), VR9_FDMA_PCTRL_STEN_SHIFT, VR9_FDMA_PCTRL_STEN_SIZE, 1); /* set port 6 bypass mode */ ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_MAC_CTRL_6_RBUF_BYPASS_OFFSET + ( 6 * 0x6)), VR9_MAC_CTRL_6_RBUF_BYPASS_SHIFT, VR9_MAC_CTRL_6_RBUF_BYPASS_SIZE, 1); /* increase port 6 inter packet gap - IPG */ ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_PMAC_RX_IPG_IPG_CNT_OFFSET + 0xC40), VR9_PMAC_RX_IPG_IPG_CNT_SHIFT, VR9_PMAC_RX_IPG_IPG_CNT_SIZE, 0xb); /* Enable all physical port - FDMA_PCTRL.EN & SDMA_PCTRL.PEN */ for (j =0; j < 7;j++) { ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_FDMA_PCTRL_EN_OFFSET + (j * 0x6)), VR9_FDMA_PCTRL_EN_SHIFT, VR9_FDMA_PCTRL_EN_SIZE, 1); if ( j < 6) continue; ifx_ethsw_ll_DirectAccessWrite(pDevCtx, (VR9_SDMA_PCTRL_PEN_OFFSET + (j * 0x6)), VR9_SDMA_PCTRL_PEN_SHIFT, VR9_SDMA_PCTRL_PEN_SIZE, 1); } return IFX_SUCCESS; } IFX_return_t ifx_ethsw_xwayflow_pce_table_write(IFX_void_t *pDevCtx, IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t *pData) { IFX_uint32_t value; IFX_uint16_t udata; // printk("DEBUG: pData->Table=[%x]\n",pData->table); #if 1 // check if ready: // PCE_TBL_CTRL.BAS do { ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, VR9_PCE_TBL_CTRL_BAS_SHIFT, VR9_PCE_TBL_CTRL_BAS_SIZE, &value); }while (value != 0); // check if hardware is ready // prepare the table access: // PCE_TBL_ADDR.ADDR = pData->table_index ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_ADDR_ADDR_OFFSET, VR9_PCE_TBL_ADDR_ADDR_SHIFT, VR9_PCE_TBL_ADDR_ADDR_SIZE, pData->table_index); // ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, // 0, 15, &value); // printk("DEBUG: The 0x44F data 0 =[0x%x]\n",pData->table); udata = pData->table; // PCE_TBL_CTRL.ADDR = pData->table ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_ADDR_OFFSET, VR9_PCE_TBL_CTRL_ADDR_SHIFT, VR9_PCE_TBL_CTRL_ADDR_SIZE, udata); // ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, // 0, 15, &value); // printk("DEBUG: The 0x44F data 1 == [0x%x], pData->Table=[%x]\n",value,pData->table); // PCE_TBL_CTRL.OPMOD = ADWR //(address-based write) ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_OPMOD_OFFSET, VR9_PCE_TBL_CTRL_OPMOD_SHIFT, VR9_PCE_TBL_CTRL_OPMOD_SIZE, IFX_ETHSW_LOOKUP_TABLE_ACCESS_OP_MODE_ADWR); /* Need to change the code style -3M */ // PCE_TBL_KEY_'X'.KEY'X' = pData->key['X'] //done for all key values ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_7_KEY7_OFFSET, VR9_PCE_TBL_KEY_7_KEY7_SHIFT, VR9_PCE_TBL_KEY_7_KEY7_SIZE, pData->key[7]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_6_KEY6_OFFSET, VR9_PCE_TBL_KEY_6_KEY6_SHIFT, VR9_PCE_TBL_KEY_6_KEY6_SIZE, pData->key[6]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_5_KEY5_OFFSET, VR9_PCE_TBL_KEY_5_KEY5_SHIFT, VR9_PCE_TBL_KEY_5_KEY5_SIZE, pData->key[5]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_4_KEY4_OFFSET, VR9_PCE_TBL_KEY_4_KEY4_SHIFT, VR9_PCE_TBL_KEY_4_KEY4_SIZE, pData->key[4]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_3_KEY3_OFFSET, VR9_PCE_TBL_KEY_3_KEY3_SHIFT, VR9_PCE_TBL_KEY_3_KEY3_SIZE, pData->key[3]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_2_KEY2_OFFSET, VR9_PCE_TBL_KEY_2_KEY2_SHIFT, VR9_PCE_TBL_KEY_2_KEY2_SIZE, pData->key[2]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_1_KEY1_OFFSET, VR9_PCE_TBL_KEY_1_KEY1_SHIFT, VR9_PCE_TBL_KEY_1_KEY1_SIZE, pData->key[1]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_0_KEY0_OFFSET, VR9_PCE_TBL_KEY_0_KEY0_SHIFT, VR9_PCE_TBL_KEY_0_KEY0_SIZE, pData->key[0]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_MASK_0_MASK0_OFFSET, VR9_PCE_TBL_MASK_0_MASK0_SHIFT, VR9_PCE_TBL_MASK_0_MASK0_SIZE, pData->mask); // PCE_TBL_VAL_'X' = pData->val['X'] //done for all values ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_4_VAL4_OFFSET, VR9_PCE_TBL_VAL_4_VAL4_SHIFT, VR9_PCE_TBL_VAL_4_VAL4_SIZE, pData->val[4]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_3_VAL3_OFFSET, VR9_PCE_TBL_VAL_3_VAL3_SHIFT, VR9_PCE_TBL_VAL_3_VAL3_SIZE, pData->val[3]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_2_VAL2_OFFSET, VR9_PCE_TBL_VAL_2_VAL2_SHIFT, VR9_PCE_TBL_VAL_2_VAL2_SIZE, pData->val[2]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_1_VAL1_OFFSET, VR9_PCE_TBL_VAL_1_VAL1_SHIFT, VR9_PCE_TBL_VAL_1_VAL1_SIZE, pData->val[1]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_0_VAL0_OFFSET, VR9_PCE_TBL_VAL_0_VAL0_SHIFT, VR9_PCE_TBL_VAL_0_VAL0_SIZE, pData->val[0]); #if 0 printk("pData->key[0] = %x\n", pData->key[0]); printk("pData->key[1] = %x\n", pData->key[1]); printk("pData->key[2] = %x\n", pData->key[2]); printk("pData->key[3] = %x\n", pData->key[3]); printk("pData->key[4] = %x\n", pData->key[4]); printk("pData->key[5] = %x\n", pData->key[5]); printk("pData->key[6] = %x\n", pData->key[6]); printk("pData->key[7] = %x\n", pData->key[7]); printk("pData->val[0] = %x\n", pData->val[0]); printk("pData->val[1] = %x\n", pData->val[1]); printk("pData->val[2] = %x\n", pData->val[2]); printk("pData->val[3] = %x\n", pData->val[3]); printk("pData->val[4] = %x\n", pData->val[4]); #endif // PCE_TBL_CTRL.TYPE = pData->type ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_TYPE_OFFSET, VR9_PCE_TBL_CTRL_TYPE_SHIFT, VR9_PCE_TBL_CTRL_TYPE_SIZE, pData->type); // PCE_TBL_CTRL.VLD = pData->valid ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_VLD_OFFSET, VR9_PCE_TBL_CTRL_VLD_SHIFT, VR9_PCE_TBL_CTRL_VLD_SIZE, pData->valid); // PCE_TBL_CTRL.GMAP'X' = pData->group'X' //done for all groups ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_GMAP_OFFSET, VR9_PCE_TBL_CTRL_GMAP_SHIFT, VR9_PCE_TBL_CTRL_GMAP_SIZE, pData->group); // start the table access: // PCE_TBL_CTRL.BAS = BUSY //(start the write access) ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, VR9_PCE_TBL_CTRL_BAS_SHIFT, VR9_PCE_TBL_CTRL_BAS_SIZE, IFX_TRUE); do { ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, VR9_PCE_TBL_CTRL_BAS_SHIFT, VR9_PCE_TBL_CTRL_BAS_SIZE, &value); }while (value != 0); // check if hardware is ready ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, 0, 15, &value); // printk("DEBUG: The 0x44F data = [0x%x]\n",value); #endif return IFX_SUCCESS; } IFX_return_t ifx_ethsw_xwayflow_pce_table_read(IFX_void_t *pDevCtx, IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t *pData) { IFX_uint32_t value; // check if ready: // PCE_TBL_CTRL.BAS do { ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, VR9_PCE_TBL_CTRL_BAS_SHIFT, VR9_PCE_TBL_CTRL_BAS_SIZE, &value); }while (value != 0); // check if hardware is ready // prepare the table access: // PCE_TBL_ADDR.ADDR = pData->table_index ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_ADDR_ADDR_OFFSET, VR9_PCE_TBL_ADDR_ADDR_SHIFT, VR9_PCE_TBL_ADDR_ADDR_SIZE, pData->table_index); // PCE_TBL_CTRL.ADDR = pData->table ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_ADDR_OFFSET, VR9_PCE_TBL_CTRL_ADDR_SHIFT, VR9_PCE_TBL_CTRL_ADDR_SIZE, pData->table); // PCE_TBL_CTRL.OPMOD = ADRD //(address-based read) ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_OPMOD_OFFSET, VR9_PCE_TBL_CTRL_OPMOD_SHIFT, VR9_PCE_TBL_CTRL_OPMOD_SIZE, IFX_ETHSW_LOOKUP_TABLE_ACCESS_OP_MODE_ADRD); // start the table access: // PCE_TBL_CTRL.BAS = BUSY //(start the read access) ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, VR9_PCE_TBL_CTRL_BAS_SHIFT, VR9_PCE_TBL_CTRL_BAS_SIZE, IFX_TRUE); //check if ready: //do { // ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_STAT_TBUSY_OFFSET, // VR9_PCE_TBL_STAT_TBUSY_SHIFT, VR9_PCE_TBL_STAT_TBUSY_SIZE, &value); //}while (value != 0); // check if hardware is ready do { ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, VR9_PCE_TBL_CTRL_BAS_SHIFT, VR9_PCE_TBL_CTRL_BAS_SIZE, &value); }while (value != 0); // check if hardware is ready // evaluate the results: // pData->key['X'] = PCE_TBL_KEY_'X'.KEY'X' //done for all key values ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_KEY_7_KEY7_OFFSET, VR9_PCE_TBL_KEY_7_KEY7_SHIFT, VR9_PCE_TBL_KEY_7_KEY7_SIZE, &value); pData->key[7] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_KEY_6_KEY6_OFFSET, VR9_PCE_TBL_KEY_6_KEY6_SHIFT, VR9_PCE_TBL_KEY_6_KEY6_SIZE, &value); pData->key[6] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_KEY_5_KEY5_OFFSET, VR9_PCE_TBL_KEY_5_KEY5_SHIFT, VR9_PCE_TBL_KEY_5_KEY5_SIZE, &value); pData->key[5] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_KEY_4_KEY4_OFFSET, VR9_PCE_TBL_KEY_4_KEY4_SHIFT, VR9_PCE_TBL_KEY_4_KEY4_SIZE, &value); pData->key[4] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_KEY_3_KEY3_OFFSET, VR9_PCE_TBL_KEY_3_KEY3_SHIFT, VR9_PCE_TBL_KEY_3_KEY3_SIZE, &value); pData->key[3] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_KEY_2_KEY2_OFFSET, VR9_PCE_TBL_KEY_2_KEY2_SHIFT, VR9_PCE_TBL_KEY_2_KEY2_SIZE, &value); pData->key[2] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_KEY_1_KEY1_OFFSET, VR9_PCE_TBL_KEY_1_KEY1_SHIFT, VR9_PCE_TBL_KEY_1_KEY1_SIZE, &value); pData->key[1] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_KEY_0_KEY0_OFFSET, VR9_PCE_TBL_KEY_0_KEY0_SHIFT, VR9_PCE_TBL_KEY_0_KEY0_SIZE, &value); pData->key[0] = value; // pData->val['X'] = PCE_TBL_VAL_'X' //done for all values ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_VAL_4_VAL4_OFFSET, VR9_PCE_TBL_VAL_4_VAL4_SHIFT, VR9_PCE_TBL_VAL_4_VAL4_SIZE, &value); pData->val[4] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_VAL_3_VAL3_OFFSET, VR9_PCE_TBL_VAL_3_VAL3_SHIFT, VR9_PCE_TBL_VAL_3_VAL3_SIZE, &value); pData->val[3] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_VAL_2_VAL2_OFFSET, VR9_PCE_TBL_VAL_2_VAL2_SHIFT, VR9_PCE_TBL_VAL_2_VAL2_SIZE, &value); pData->val[2] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_VAL_1_VAL1_OFFSET, VR9_PCE_TBL_VAL_1_VAL1_SHIFT, VR9_PCE_TBL_VAL_1_VAL1_SIZE, &value); pData->val[1] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_VAL_0_VAL0_OFFSET, VR9_PCE_TBL_VAL_0_VAL0_SHIFT, VR9_PCE_TBL_VAL_0_VAL0_SIZE, &value); pData->val[0] = value; ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_MASK_0_MASK0_OFFSET, VR9_PCE_TBL_MASK_0_MASK0_SHIFT, VR9_PCE_TBL_MASK_0_MASK0_SIZE, &value); pData->mask = value; #if 0 printk("pData->key[0] = %x\n", pData->key[0]); printk("pData->key[1] = %x\n", pData->key[1]); printk("pData->key[2] = %x\n", pData->key[2]); printk("pData->key[3] = %x\n", pData->key[3]); printk("pData->key[4] = %x\n", pData->key[4]); printk("pData->key[5] = %x\n", pData->key[5]); printk("pData->key[6] = %x\n", pData->key[6]); printk("pData->key[7] = %x\n", pData->key[7]); printk("pData->val[0] = %x\n", pData->val[0]); printk("pData->val[1] = %x\n", pData->val[1]); printk("pData->val[2] = %x\n", pData->val[2]); printk("pData->val[3] = %x\n", pData->val[3]); printk("pData->val[4] = %x\n", pData->val[4]); #endif // pData->type = PCE_TBL_CTRL.TYPE ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_TYPE_OFFSET, VR9_PCE_TBL_CTRL_TYPE_SHIFT, VR9_PCE_TBL_CTRL_TYPE_SIZE, &value); pData->type = value; // pData->valid = PCE_TBL_CTRL.VLD ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_VLD_OFFSET, VR9_PCE_TBL_CTRL_VLD_SHIFT, VR9_PCE_TBL_CTRL_VLD_SIZE, &value); pData->valid = value; // pData->group'X' = PCE_TBL_CTRL.GMAP'X' //done for all groups ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_GMAP_OFFSET, VR9_PCE_TBL_CTRL_GMAP_SHIFT, VR9_PCE_TBL_CTRL_GMAP_SIZE, &value); pData->group = value; return IFX_SUCCESS; } IFX_return_t ifx_ethsw_xwayflow_pce_table_cam_write(IFX_void_t *pDevCtx, IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t *pData) { IFX_uint32_t value; //check if ready: do { ifx_ethsw_ll_DirectAccessRead(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, VR9_PCE_TBL_CTRL_BAS_SHIFT, VR9_PCE_TBL_CTRL_BAS_SIZE, &value); }while (value != 0); // check if hardware is ready // prepare the table access: // PCE_TBL_ADDR.ADDR = pData->table_index // ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_ADDR_ADDR_OFFSET, // VR9_PCE_TBL_ADDR_ADDR_SHIFT, VR9_PCE_TBL_ADDR_ADDR_SIZE, pData->table_index); // PCE_TBL_CTRL.ADDR = pData->table ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_ADDR_OFFSET, VR9_PCE_TBL_CTRL_ADDR_SHIFT, VR9_PCE_TBL_CTRL_ADDR_SIZE, pData->table); // PCE_TBL_CTRL.OPMOD = KSWR //(Key-based search write access) ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_OPMOD_OFFSET, VR9_PCE_TBL_CTRL_OPMOD_SHIFT, VR9_PCE_TBL_CTRL_OPMOD_SIZE, IFX_ETHSW_LOOKUP_TABLE_ACCESS_OP_MODE_KSWR); // PCE_TBL_KEY_'X'.KEY'X' = pData->key['X'] //done for all key values ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_7_KEY7_OFFSET, VR9_PCE_TBL_KEY_7_KEY7_SHIFT, VR9_PCE_TBL_KEY_7_KEY7_SIZE, pData->key[7]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_6_KEY6_OFFSET, VR9_PCE_TBL_KEY_6_KEY6_SHIFT, VR9_PCE_TBL_KEY_6_KEY6_SIZE, pData->key[6]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_5_KEY5_OFFSET, VR9_PCE_TBL_KEY_5_KEY5_SHIFT, VR9_PCE_TBL_KEY_5_KEY5_SIZE, pData->key[5]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_4_KEY4_OFFSET, VR9_PCE_TBL_KEY_4_KEY4_SHIFT, VR9_PCE_TBL_KEY_4_KEY4_SIZE, pData->key[4]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_3_KEY3_OFFSET, VR9_PCE_TBL_KEY_3_KEY3_SHIFT, VR9_PCE_TBL_KEY_3_KEY3_SIZE, pData->key[3]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_2_KEY2_OFFSET, VR9_PCE_TBL_KEY_2_KEY2_SHIFT, VR9_PCE_TBL_KEY_2_KEY2_SIZE, pData->key[2]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_1_KEY1_OFFSET, VR9_PCE_TBL_KEY_1_KEY1_SHIFT, VR9_PCE_TBL_KEY_1_KEY1_SIZE, pData->key[1]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_KEY_0_KEY0_OFFSET, VR9_PCE_TBL_KEY_0_KEY0_SHIFT, VR9_PCE_TBL_KEY_0_KEY0_SIZE, pData->key[0]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_MASK_0_MASK0_OFFSET, VR9_PCE_TBL_MASK_0_MASK0_SHIFT, VR9_PCE_TBL_MASK_0_MASK0_SIZE, pData->mask); // PCE_TBL_VAL_'X' = pData->val['X'] //done for all values ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_4_VAL4_OFFSET, VR9_PCE_TBL_VAL_4_VAL4_SHIFT, VR9_PCE_TBL_VAL_4_VAL4_SIZE, pData->val[4]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_3_VAL3_OFFSET, VR9_PCE_TBL_VAL_3_VAL3_SHIFT, VR9_PCE_TBL_VAL_3_VAL3_SIZE, pData->val[3]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_2_VAL2_OFFSET, VR9_PCE_TBL_VAL_2_VAL2_SHIFT, VR9_PCE_TBL_VAL_2_VAL2_SIZE, pData->val[2]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_1_VAL1_OFFSET, VR9_PCE_TBL_VAL_1_VAL1_SHIFT, VR9_PCE_TBL_VAL_1_VAL1_SIZE, pData->val[1]); ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_VAL_0_VAL0_OFFSET, VR9_PCE_TBL_VAL_0_VAL0_SHIFT, VR9_PCE_TBL_VAL_0_VAL0_SIZE, pData->val[0]); // PCE_TBL_CTRL.TYPE = pData->type ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_TYPE_OFFSET, VR9_PCE_TBL_CTRL_TYPE_SHIFT, VR9_PCE_TBL_CTRL_TYPE_SIZE, pData->type); // PCE_TBL_CTRL.VLD = pData->valid ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_VLD_OFFSET, VR9_PCE_TBL_CTRL_VLD_SHIFT, VR9_PCE_TBL_CTRL_VLD_SIZE, pData->valid); // PCE_TBL_CTRL.GMAP'X' = pData->group'X' //done for all groups ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_GMAP_OFFSET, VR9_PCE_TBL_CTRL_GMAP_SHIFT, VR9_PCE_TBL_CTRL_GMAP_SIZE, pData->group); // start the table access: // PCE_TBL_CTRL.BAS = BUSY //(start the write access) ifx_ethsw_ll_DirectAccessWrite(pDevCtx, VR9_PCE_TBL_CTRL_BAS_OFFSET, VR9_PCE_TBL_CTRL_BAS_SHIFT, VR9_PCE_TBL_CTRL_BAS_SIZE, IFX_TRUE); return IFX_SUCCESS; } IFX_int32_t ifx_pce_print_tables(IFX_PCE_t *pHandle) { IFX_uint32_t i; // ifx_pce_table_init(pHandle); if (pHandle == IFX_NULL) return IFX_ERROR; for (i = 0; i < IFX_PCE_TBL_SIZE; i++) { IFX_PCE_TBL_t *pFet = &pHandle->pce_tbl[i]; IFX_FLOW_PCE_action_t *pAct = &pHandle->pce_act; if (pHandle->pce_tbl_used[i] == 1) { printk("Rule %d:\n",i); printk("\tdscp\t%d\n", pFet->dscp); printk("\tpcp\t%d\n", pFet->pcp); printk("\tpkt_lng_idx\t%d\n", pFet->pkt_lng_idx); printk("\tdst_mac_addr_idx\t%d\n", pFet->dst_mac_addr_idx); printk("\tsrc_mac_addr_idx\t%d\n", pFet->src_mac_addr_idx); printk("\tdst_appl_fld_idx\t%d\n", pFet->dst_appl_fld_idx); printk("\tsrc_appl_fld_idx\t%d\n", pFet->src_appl_fld_idx); printk("\tdip_msb_idx\t%d\n", pFet->dip_msb_idx); printk("\tdip_lsb_idx\t%d\n", pFet->dip_lsb_idx); printk("\tsip_msb_idx\t%d\n", pFet->sip_msb_idx); printk("\tsip_lsb_idx\t%d\n", pFet->sip_lsb_idx); printk("\tip_prot_idx\t%d\n", pFet->ip_prot_idx); printk("\tethertype_idx\t%d\n", pFet->ethertype_idx); printk("\tpppoe_idx\t%d\n", pFet->pppoe_idx); printk("\tvlan_idx\t%d\n", pFet->vlan_idx); printk("\tport_id\t%d\n", pFet->port_id); printk("Action %d:\n",i); printk("\teTrafficClassAction\t%d\n", pAct->eTrafficClassAction); printk("\tnTrafficClassAlternate\t%d\n", pAct->nTrafficClassAlternate); printk("\teSnoopingTypeAction\t%d\n", pAct->eSnoopingTypeAction); printk("\teLearningAction\t%d\n", pAct->eLearningAction); printk("\teIrqAction\t%d\n", pAct->eIrqAction); printk("\teCrossStateAction\t%d\n", pAct->eCrossStateAction); printk("\teCritFrameAction\t%d\n", pAct->eCritFrameAction); printk("\teTimestampAction\t%d\n", pAct->eTimestampAction); printk("\tePortMapAction\t%d\n", pAct->ePortMapAction); printk("\tnForwardPortMap\t%d\n", pAct->nForwardPortMap); printk("\tbRemarkAction\t%d\n", pAct->bRemarkAction); printk("\tbRemarkPCP\t%d\n", pAct->bRemarkPCP); printk("\tbRemarkDSCP\t%d\n", pAct->bRemarkDSCP); printk("\tbRemarkClass\t%d\n", pAct->bRemarkClass); printk("\teMeterAction\t%d\n", pAct->eMeterAction); printk("\tnMeterId\t%d\n", pAct->nMeterId); printk("\tbRMON_Action\t%d\n", pAct->bRMON_Action); printk("\tnRMON_Id\t%d\n", pAct->nRMON_Id); printk("\teVLAN_Action\t%d\n", pAct->eVLAN_Action); printk("\tnVLAN_Id\t%d\n", pAct->nVLAN_Id); printk("\teVLAN_CrossAction\t%d\n", pAct->eVLAN_CrossAction); printk("\n"); } } // return ifx_pce_tm_print_tables(&pHandle->pce_sub_tbl); } IFX_int32_t ifx_pce_pattern_delete(IFX_PCE_t *pHandle, IFX_uint32_t index) { IFX_PCE_TBL_t *pFet; /* During the hareware initialization the rule "3" was taken, So we increase the rule number to add one for all the rule upon 3 */ if(index >= 3) index = index+1; if (index >= IFX_PCE_TBL_SIZE) IFX_RETURN_PCE; /* Check if an entry is currently programmed and remove that one. */ if (pHandle->pce_tbl_used[index] == 0) return 0; pFet = &(pHandle->pce_tbl[index]); #define IFX_PCE_TM_IDX_DELETE(x, y, z) \ if (x != y) \ if (0 != z( \ &pHandle->pce_sub_tbl, y)) \ IFX_RETURN_PCE; /* Packet length */ IFX_PCE_TM_IDX_DELETE(0x1F, pFet->pkt_lng_idx, ifx_pce_tm_pkg_lng_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0x1F, pFet->pkt_lng_idx, ifx_pce_tm_pkg_lng_tbl_delete) /* Destination MAC address */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->dst_mac_addr_idx,ifx_pce_tm_dasa_mac_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->dst_mac_addr_idx,ifx_pce_tm_dasa_mac_tbl_delete) /* Source MAC address */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->src_mac_addr_idx,ifx_pce_tm_dasa_mac_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->src_mac_addr_idx,ifx_pce_tm_dasa_mac_tbl_delete) /* Destination Application field */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->dst_appl_fld_idx, ifx_pce_tm_appl_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->dst_appl_fld_idx, ifx_pce_tm_appl_tbl_delete) /* Source Application field */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->src_appl_fld_idx, ifx_pce_tm_appl_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->src_appl_fld_idx, ifx_pce_tm_appl_tbl_delete) /* DIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->dip_msb_idx, ifx_pce_tm_ip_dasa_msb_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->dip_msb_idx, ifx_pce_tm_ip_dasa_msb_tbl_delete) /* DIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->dip_lsb_idx, ifx_pce_tm_ip_dasa_lsb_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->dip_lsb_idx, ifx_pce_tm_ip_dasa_lsb_tbl_delete) /* SIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->sip_msb_idx, ifx_pce_tm_ip_dasa_msb_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->sip_msb_idx, ifx_pce_tm_ip_dasa_msb_tbl_delete) /* SIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->sip_lsb_idx, ifx_pce_tm_ip_dasa_lsb_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->sip_lsb_idx, ifx_pce_tm_ip_dasa_lsb_tbl_delete) /* IP protocol */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->ip_prot_idx, ifx_pce_tm_ptcl_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->ip_prot_idx, ifx_pce_tm_ptcl_tbl_delete) /* Ethertype */ IFX_PCE_TM_IDX_DELETE(0xFF, pFet->ethertype_idx, ifx_pce_tm_ptcl_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0xFF, pFet->ethertype_idx, ifx_pce_tm_ptcl_tbl_delete) /* PPPoE */ IFX_PCE_TM_IDX_DELETE(0x1F, pFet->pppoe_idx, ifx_pce_tm_pppoe_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0x1F, pFet->pppoe_idx, ifx_pce_tm_pppoe_tbl_delete) /* VLAN */ IFX_PCE_TM_IDX_DELETE(0x7F, pFet->vlan_idx, ifx_pce_tm_vlan_act_tbl_idx_delete) IFX_PCE_TM_IDX_DELETE(0x7F, pFet->vlan_idx, ifx_pce_tm_vlan_act_tbl_delete) /* reset the flag that this rule line is used */ pHandle->pce_tbl_used[index] = 0; /* reset the rule line */ memset(pFet, 0xFF, sizeof(IFX_PCE_TBL_t)); /* WRITE DOWN THE NEW LINE TO THE HARDWARE */ /* also remove the action for this rule */ return ifx_pce_action_delete(pHandle, index); } IFX_int32_t ifx_pce_action_delete(IFX_PCE_t *pHandle, IFX_uint32_t index) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_void_t *pDevCtx =IFX_NULL; if (index >= IFX_PCE_TBL_SIZE) IFX_RETURN_PCE; memset(&pHandle->pce_act[index], 0, sizeof(IFX_FLOW_PCE_action_t)); /* REMOVE RULE ACTION FROM HARDWARE DEVICE */ pcetable.table_index = index; //index of the Traffic Flow Table index configuration pcetable.table = IFX_ETHSW_PCE_TFLOW_INDEX; pcetable.valid = 0; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return 0; } IFX_int32_t ifx_pce_rule_read(IFX_PCE_t *pHandle, IFX_FLOW_PCE_rule_t *pPar) { IFX_uint32_t i, idx = pPar->pattern.nIndex; IFX_PCE_TBL_t *pFet; /** During the hareware initialization the rule "3" was taken, So we increase the rule number to add one for all the rule upon 3 */ if(idx >= 3) idx = idx+1; if (idx >= IFX_PCE_TBL_SIZE) IFX_RETURN_PCE; /* initialize to zero the structure before writing the parameters */ memset(pPar, 0, sizeof(IFX_FLOW_PCE_rule_t)); pPar->pattern.nIndex = idx; if (pHandle->pce_tbl_used[idx] == 0) { /* rule is not used */ pPar->pattern.bEnable = IFX_FALSE; return 0; } else pPar->pattern.bEnable = IFX_TRUE; pFet = &(pHandle->pce_tbl[idx]); /* Port ID */ if (pFet->port_id == 0xFF) pPar->pattern.nPortId = 0; else pPar->pattern.nPortId = (IFX_uint8_t)pFet->port_id; /* Port ID is assigned then the Port ID is Enable */ if (pFet->port_id != 0xFF) pPar->pattern.bPortIdEnable = IFX_TRUE; else pPar->pattern.bPortIdEnable = IFX_FALSE; /* todo: check how pPar->bDscp should be used or is needed */ /* DSCP value */ if (pFet->dscp == 0x7F) pPar->pattern.nDSCP = 0; else pPar->pattern.nDSCP = (IFX_uint8_t)pFet->dscp; /* DSCP is assigned and Enable */ if (pFet->dscp != 0x7F) pPar->pattern.bDSCP_Enable = IFX_TRUE; else pPar->pattern.bDSCP_Enable = IFX_FALSE; /* todo: check how pPar->bPcp should be used or is needed */ /* PCP value */ if (pFet->pcp == 0xF) pPar->pattern.nPCP = 0; else pPar->pattern.nPCP = (IFX_uint8_t)pFet->pcp; /* PCP is assigned and Enable */ if (pFet->pcp != 0xF) pPar->pattern.bPCP_Enable = IFX_TRUE; else pPar->pattern.bPCP_Enable = IFX_FALSE; if (pFet->pkt_lng_idx != 0x1F) { IFX_PCE_PKG_LNG_TBL_t pkg_lng_tbl; /* Packet length used */ pPar->pattern.bPktLngEnable = IFX_TRUE; if (0 != ifx_pce_tm_pkg_lng_tbl_read( &pHandle->pce_sub_tbl, pFet->pkt_lng_idx, &pkg_lng_tbl)) IFX_RETURN_PCE; /* Packet length */ pPar->pattern.nPktLng = pkg_lng_tbl.pkg_lng; /* Packet length Range */ pPar->pattern.nPktLngRange = pkg_lng_tbl.pkg_lng_rng; } if (pFet->dst_mac_addr_idx != 0xFF) { IFX_PCE_DASA_MAC_TBL_t dasa_mac_tbl; if (0 != ifx_pce_tm_dasa_mac_tbl_read( &pHandle->pce_sub_tbl, pFet->dst_mac_addr_idx, &dasa_mac_tbl)) IFX_RETURN_PCE; /* Destination MAC address used */ pPar->pattern.bMAC_DstEnable = IFX_TRUE; #if 0 printk(" DestMAC = %02x:%02x:%02x:%02x:%02x:%02x | idx = %d\n", dasa_mac_tbl.mac[0], dasa_mac_tbl.mac[1], dasa_mac_tbl.mac[2], dasa_mac_tbl.mac[3], dasa_mac_tbl.mac[4], dasa_mac_tbl.mac[5], pFet->dst_mac_addr_idx ); #endif /* Destination MAC address */ for (i = 0; i < 6; i++) pPar->pattern.nMAC_Dst[i] = dasa_mac_tbl.mac[i]; #if 0 printk(" DestMAC = %02x:%02x:%02x:%02x:%02x:%02x \n", pPar->pattern.nMAC_Dst[0], pPar->pattern.nMAC_Dst[1], pPar->pattern.nMAC_Dst[2], pPar->pattern.nMAC_Dst[3], pPar->pattern.nMAC_Dst[4], pPar->pattern.nMAC_Dst[5]); #endif /* Destination MAC address mask */ pPar->pattern.nMAC_DstMask = dasa_mac_tbl.mac_mask; } if (pFet->src_mac_addr_idx != 0xFF) { IFX_PCE_DASA_MAC_TBL_t dasa_mac_tbl; if (0 != ifx_pce_tm_dasa_mac_tbl_read( &pHandle->pce_sub_tbl, pFet->src_mac_addr_idx, &dasa_mac_tbl)) IFX_RETURN_PCE; /* Destination MAC address used */ pPar->pattern.bMAC_SrcEnable = IFX_TRUE; /* Destination MAC address */ for (i = 0; i < 6; i++) pPar->pattern.nMAC_Src[i] = dasa_mac_tbl.mac[i]; #if 0 printk(" DestMAC = %02x:%02x:%02x:%02x:%02x:%02x \n", pPar->pattern.nMAC_Src[0], pPar->pattern.nMAC_Src[1], pPar->pattern.nMAC_Src[2], pPar->pattern.nMAC_Src[3], pPar->pattern.nMAC_Src[4], pPar->pattern.nMAC_Src[5]); #endif /* Destination MAC address mask */ pPar->pattern.nMAC_SrcMask = dasa_mac_tbl.mac_mask; } if (pFet->dst_appl_fld_idx != 0xFF) { IFX_PCE_APPL_TBL_t appl_tbl; if (0 != ifx_pce_tm_appl_tbl_read( &pHandle->pce_sub_tbl, pFet->dst_appl_fld_idx, &appl_tbl)) IFX_RETURN_PCE; /* Destination Application used */ pPar->pattern.bAppDataMSB_Enable = IFX_TRUE; /* Destination Application field */ pPar->pattern.nAppDataMSB = appl_tbl.appl_data; /* Destination Application mask/range */ pPar->pattern.nAppMaskRangeMSB = appl_tbl.mask_range; } if (pFet->src_appl_fld_idx != 0xFF) { IFX_PCE_APPL_TBL_t appl_tbl; if (0 != ifx_pce_tm_appl_tbl_read( &pHandle->pce_sub_tbl, pFet->src_appl_fld_idx, &appl_tbl)) IFX_RETURN_PCE; /* Source Application used */ pPar->pattern.bAppDataLSB_Enable = IFX_TRUE; /* Source Application field */ pPar->pattern.nAppDataLSB = appl_tbl.appl_data; /* Source Application mask/range */ pPar->pattern.nAppMaskRangeLSB = appl_tbl.mask_range; } if (pFet->dip_msb_idx != 0xFF) { IFX_PCE_IP_DASA_MSB_TBL_t dasa_tbl; /* DIP MSB used */ pPar->pattern.eDstIP_Select = 2; if (0 != ifx_pce_tm_ip_dasa_msb_tbl_read( &pHandle->pce_sub_tbl, pFet->dip_msb_idx, &dasa_tbl)) IFX_RETURN_PCE; for (i = 0; i < 8; i++) pPar->pattern.nDstIP.nIPv6[i] = dasa_tbl.ip_msb[i]; /* DIP MSB Nibble Mask */ pPar->pattern.nDstIP_MsbMask = dasa_tbl.mask; } if (pFet->dip_lsb_idx != 0xFF) { IFX_PCE_IP_DASA_LSB_TBL_t dasa_tbl; /* DIP LSB used */ pPar->pattern.eDstIP_Select = 1; if (0 != ifx_pce_tm_ip_dasa_lsb_tbl_read( &pHandle->pce_sub_tbl, pFet->dip_lsb_idx, &dasa_tbl)) IFX_RETURN_PCE; for (i = 0; i < 8; i++) pPar->pattern.nDstIP.nIPv6[i] = dasa_tbl.ip_lsb[i]; /* DIP LSB */ pPar->pattern.nDstIP.nIPv4 = dasa_tbl.ip_lsb[0] | (dasa_tbl.ip_lsb[1] << 8) | (dasa_tbl.ip_lsb[2] << 16) | (dasa_tbl.ip_lsb[3] << 24); #if 0 printk(" DstIP = %03d.%03d.%03d.%03d \n", pPar->pattern.nDstIP.nIPv4 & 0xFF, (pPar->pattern.nDstIP.nIPv4 >> 8 ) & 0xFF, (pPar->pattern.nDstIP.nIPv4 >> 16 ) & 0xFF, (pPar->pattern.nDstIP.nIPv4 >> 24 ) & 0xFF); #endif /* DIP LSB Nibble Mask */ pPar->pattern.nDstIP_MsbMask = dasa_tbl.mask; } if (pFet->sip_msb_idx != 0xFF) { IFX_PCE_IP_DASA_MSB_TBL_t dasa_tbl; /* SIP MSB used */ pPar->pattern.eSrcIP_Select = IFX_TRUE; if (0 != ifx_pce_tm_ip_dasa_msb_tbl_read( &pHandle->pce_sub_tbl, pFet->sip_msb_idx, &dasa_tbl)) IFX_RETURN_PCE; /* SIP MSB */ for (i = 0; i < 8; i++) pPar->pattern.nSrcIP.nIPv6[i] = dasa_tbl.ip_msb[i]; /* SIP MSB Nibble Mask */ pPar->pattern.nSrcIP_MsbMask = dasa_tbl.mask; } if (pFet->sip_lsb_idx != 0xFF) { IFX_PCE_IP_DASA_LSB_TBL_t dasa_tbl; /* SIP LSB used */ pPar->pattern.eSrcIP_Select = 1; if (0 != ifx_pce_tm_ip_dasa_lsb_tbl_read( &pHandle->pce_sub_tbl, pFet->sip_lsb_idx, &dasa_tbl)) IFX_RETURN_PCE; for (i = 0; i < 8; i++) pPar->pattern.nSrcIP.nIPv6[i] = dasa_tbl.ip_lsb[i]; /* SIP LSB */ pPar->pattern.nSrcIP.nIPv4 = dasa_tbl.ip_lsb[0] | (dasa_tbl.ip_lsb[1] << 8) | (dasa_tbl.ip_lsb[2] << 16)| (dasa_tbl.ip_lsb[3] << 24); #if 0 printk(" SrcIP = %03d.%03d.%03d.%03d \n", pPar->pattern.nSrcIP.nIPv4 & 0xFF, (pPar->pattern.nSrcIP.nIPv4 >> 8 ) & 0xFF, (pPar->pattern.nSrcIP.nIPv4 >> 16 ) & 0xFF, (pPar->pattern.nSrcIP.nIPv4 >> 24 ) & 0xFF); #endif /* SIP LSB Nibble Mask */ pPar->pattern.nSrcIP_MsbMask = dasa_tbl.mask; } if (pFet->ethertype_idx != 0xFF) { IFX_PCE_PTCL_TBL_t pctl_tbl; /* Ethertype used */ pPar->pattern.bEtherTypeEnable = IFX_TRUE; if (0 != ifx_pce_tm_ptcl_tbl_read( &pHandle->pce_sub_tbl, pFet->ethertype_idx, &pctl_tbl)) IFX_RETURN_PCE; /* Ethertype */ pPar->pattern.nEtherType = pctl_tbl.key.ethertype; /* Ethertype Mask */ pPar->pattern.nEtherTypeMask = pctl_tbl.mask.ethertype_mask; } if (pFet->ip_prot_idx != 0xFF) { IFX_PCE_PTCL_TBL_t pctl_tbl; /* IP protocol used */ pPar->pattern.bProtocolEnable = IFX_TRUE; if (0 != ifx_pce_tm_ptcl_tbl_read( &pHandle->pce_sub_tbl, pFet->ip_prot_idx, &pctl_tbl)) IFX_RETURN_PCE; /* IP protocol */ pPar->pattern.nProtocol = (IFX_uint8_t)pctl_tbl.key.prot.protocol; /* IP protocol Mask */ pPar->pattern.nProtocolMask = (IFX_uint8_t)pctl_tbl.mask.prot.protocol_mask; } if (pFet->pppoe_idx != 0x1F) { IFX_PCE_PPPOE_TBL_t pppoe_tbl; /* PPPoE used */ pPar->pattern.bSessionIdEnable = IFX_TRUE; if (0 != ifx_pce_tm_pppoe_tbl_read( &pHandle->pce_sub_tbl, pFet->pppoe_idx, &pppoe_tbl)) IFX_RETURN_PCE; /* PPPoE */ pPar->pattern.nSessionId = pppoe_tbl.sess_id; } if (pFet->vlan_idx != 0x7F) { IFX_PCE_VLAN_ACT_TBL_t vlan_act_tbl; /* VLAN used */ pPar->pattern.bVid = IFX_TRUE; if (0 != ifx_pce_tm_vlan_act_tbl_read( &pHandle->pce_sub_tbl, pFet->vlan_idx, &vlan_act_tbl)) IFX_RETURN_PCE; pPar->pattern.nVid = vlan_act_tbl.vid; } /* Copy whole action table into action structure */ memcpy(&pPar->action, &pHandle->pce_act[idx], sizeof(IFX_FLOW_PCE_action_t)); return IFX_SUCCESS; } IFX_int32_t ifx_pce_rule_write(IFX_PCE_t *pHandle, IFX_FLOW_PCE_rule_t *pPar) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable; IFX_uint32_t idx = pPar->pattern.nIndex; IFX_void_t *pDevCtx =IFX_NULL; IFX_PCE_TBL_t *pFet; IFX_FLOW_PCE_action_t *pAct; /* During the hareware initialization the rule "3" was taken, So we increase the rule number to add one for all the rule upon 3 */ if(idx >= 3) idx = idx+1; if (idx >= IFX_PCE_TBL_SIZE) IFX_RETURN_PCE; if (pPar->pattern.bEnable == IFX_FALSE) { /* Entry to delete. */ return ifx_pce_pattern_delete(pHandle, idx); } { /* first read the current value context from the table to compare if the new configuration is the same. */ IFX_FLOW_PCE_rule_t key_current; key_current.pattern.nIndex = idx; if (ifx_pce_rule_read(pHandle, &key_current) != 0) IFX_RETURN_PCE; if (memcmp(&key_current, pPar, sizeof(IFX_FLOW_PCE_rule_t)) == 0) { /* This key is already programmed on the hardware, no need to update the current hardware programming. */ return 0; } } memset(&pcetable, 0, sizeof(IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t)); if (pHandle->pce_tbl_used[idx] != 0) { /* Delete the old entry before adding the new one. */ if (ifx_pce_pattern_delete(pHandle, idx) != 0) IFX_RETURN_PCE; } /* Mark the entry as taken already and then program it. */ pHandle->pce_tbl_used[idx] = 1; /* Now convert the parameter and add to the table. */ pFet = &(pHandle->pce_tbl[idx]); /* Port ID */ if (pPar->pattern.bPortIdEnable == 1) pFet->port_id = pPar->pattern.nPortId; else pFet->port_id = 0xFF; pcetable.key[0] = pFet->port_id; /* DSCP value used */ if (pPar->pattern.bDSCP_Enable == IFX_TRUE) { /* DSCP value */ pFet->dscp = pPar->pattern.nDSCP; } else pFet->dscp = 0x7F; pcetable.key[6] |= (pFet->dscp << 8); /* PCP value used */ if (pPar->pattern.bPCP_Enable == IFX_TRUE) { /* PCP value */ pFet->pcp = pPar->pattern.nPCP; } else pFet->pcp = 0xF; pcetable.key[6] |= pFet->pcp; /* Packet length used */ if (pPar->pattern.bPktLngEnable == IFX_TRUE) { IFX_int32_t tab_index; IFX_PCE_PKG_LNG_TBL_t pkg_lng; /* Packet length */ pkg_lng.pkg_lng = pPar->pattern.nPktLng; /* Packet length range, in number of bytes */ pkg_lng.pkg_lng_rng = pPar->pattern.nPktLngRange; tab_index = ifx_pce_tm_pkg_lng_tbl_write( &pHandle->pce_sub_tbl, &pkg_lng); if (tab_index < 0) IFX_RETURN_PCE; pFet->pkt_lng_idx = tab_index; } else pFet->pkt_lng_idx = 0xFF; pcetable.key[7] = pFet->pkt_lng_idx; /* Destination MAC address used */ if (pPar->pattern.bMAC_DstEnable == IFX_TRUE) { IFX_int32_t tab_index,i; IFX_PCE_DASA_MAC_TBL_t dasa_mac_tbl; /* Destination MAC address */ for (i = 0; i < 6; i++) dasa_mac_tbl.mac[i] = pPar->pattern.nMAC_Dst[i]; /* Destination MAC address mask */ dasa_mac_tbl.mac_mask = pPar->pattern.nMAC_DstMask; tab_index = ifx_pce_tm_dasa_mac_tbl_write( &pHandle->pce_sub_tbl, &dasa_mac_tbl); #if 0 printk(" DestMAC = %02x:%02x:%02x:%02x:%02x:%02x | tab_index=%d\n", dasa_mac_tbl.mac[0], dasa_mac_tbl.mac[1], dasa_mac_tbl.mac[2], dasa_mac_tbl.mac[3], dasa_mac_tbl.mac[4], dasa_mac_tbl.mac[5],tab_index); #endif if (tab_index < 0) IFX_RETURN_PCE; pFet->dst_mac_addr_idx = tab_index; } else pFet->dst_mac_addr_idx = 0xFF; pcetable.key[5] |= (pFet->dst_mac_addr_idx << 8); /* Source MAC address used */ if (pPar->pattern.bMAC_SrcEnable == IFX_TRUE) { IFX_int32_t tab_index,i; IFX_PCE_DASA_MAC_TBL_t dasa_mac_tbl; /* Source MAC address */ for (i = 0; i < 6; i++) dasa_mac_tbl.mac[i] = pPar->pattern.nMAC_Src[i]; /* Source MAC address mask */ dasa_mac_tbl.mac_mask = pPar->pattern.nMAC_SrcMask; tab_index = ifx_pce_tm_dasa_mac_tbl_write( &pHandle->pce_sub_tbl, &dasa_mac_tbl); #if 0 printk(" SrcMAC = %02x:%02x:%02x:%02x:%02x:%02x \n", dasa_mac_tbl.mac[0], dasa_mac_tbl.mac[1], dasa_mac_tbl.mac[2], dasa_mac_tbl.mac[3], dasa_mac_tbl.mac[4], dasa_mac_tbl.mac[5]); #endif if (tab_index < 0) IFX_RETURN_PCE; //printk("MAC Table INDEX = %d\n",tab_index); pFet->src_mac_addr_idx = tab_index; } else pFet->src_mac_addr_idx = 0xFF; pcetable.key[5] |= pFet->src_mac_addr_idx; /* Destination Application used */ if (pPar->pattern.bAppDataMSB_Enable == IFX_TRUE) { IFX_int32_t tab_index; IFX_PCE_APPL_TBL_t appl_tbl; /* Destination Application field */ appl_tbl.appl_data = pPar->pattern.nAppDataMSB; /* Destination Application mask/range */ appl_tbl.mask_range = pPar->pattern.nAppMaskRangeMSB; tab_index = ifx_pce_tm_appl_tbl_write(&pHandle->pce_sub_tbl, &appl_tbl); if (tab_index < 0) IFX_RETURN_PCE; pFet->dst_appl_fld_idx = tab_index; } else pFet->dst_appl_fld_idx = 0xFF; pcetable.key[4] |= pFet->dst_appl_fld_idx; /* Source Application field used */ if (pPar->pattern.bAppDataLSB_Enable == IFX_TRUE) { IFX_int32_t tab_index; IFX_PCE_APPL_TBL_t appl_tbl; /* Source Application field */ appl_tbl.appl_data = pPar->pattern.nAppDataLSB; /* Source Application mask/range */ appl_tbl.mask_range = pPar->pattern.nAppMaskRangeLSB; tab_index = ifx_pce_tm_appl_tbl_write(&pHandle->pce_sub_tbl, &appl_tbl); if (tab_index < 0) IFX_RETURN_PCE; pFet->src_appl_fld_idx = tab_index; } else pFet->src_appl_fld_idx = 0xFF; pcetable.key[4] |= (pFet->src_appl_fld_idx << 8); /* DIP MSB used */ if (pPar->pattern.eDstIP_Select == 2) { IFX_int32_t tab_index,i; IFX_PCE_IP_DASA_MSB_TBL_t dasa_msb_tbl; /* DIP MSB */ for (i = 0; i < 8; i++) dasa_msb_tbl.ip_msb[i] = pPar->pattern.nDstIP.nIPv6[i]; /* DIP MSB Nibble Mask */ dasa_msb_tbl.mask = pPar->pattern.nDstIP_MsbMask; tab_index = ifx_pce_tm_ip_dasa_msb_tbl_write( &pHandle->pce_sub_tbl, &dasa_msb_tbl); if (tab_index < 0) IFX_RETURN_PCE; pFet->dip_msb_idx = tab_index; } else pFet->dip_msb_idx = 0xFF; pcetable.key[3] |= (pFet->dip_msb_idx << 8); /* DIP LSB used */ if (pPar->pattern.eDstIP_Select == IFX_FLOW_PCE_IP_V4) { IFX_int32_t tab_index; IFX_PCE_IP_DASA_LSB_TBL_t dasa_lsb_tbl; /* DIP LSB */ dasa_lsb_tbl.ip_lsb[3] = pPar->pattern.nDstIP.nIPv4 & 0xFF; dasa_lsb_tbl.ip_lsb[2] = (pPar->pattern.nDstIP.nIPv4 >> 8 ) & 0xFF; dasa_lsb_tbl.ip_lsb[1] = (pPar->pattern.nDstIP.nIPv4 >> 16 ) & 0xFF; dasa_lsb_tbl.ip_lsb[0] = (pPar->pattern.nDstIP.nIPv4 >> 24 ) & 0xFF; /* DIP LSB Nibble Mask */ dasa_lsb_tbl.mask = pPar->pattern.nDstIP_MsbMask; tab_index = ifx_pce_tm_ip_dasa_lsb_tbl_write( &pHandle->pce_sub_tbl, &dasa_lsb_tbl); if (tab_index < 0) IFX_RETURN_PCE; pFet->dip_lsb_idx = (IFX_uint16_t)tab_index; #if 0 printk(" DstIP = %03d.%03d.%03d.%03d \n", dasa_lsb_tbl.ip_lsb[3], dasa_lsb_tbl.ip_lsb[2], dasa_lsb_tbl.ip_lsb[1], dasa_lsb_tbl.ip_lsb[0]); #endif } else pFet->dip_lsb_idx = 0xFF; pcetable.key[3] |= pFet->dip_lsb_idx; /* SIP MSB used */ if (pPar->pattern.eSrcIP_Select == IFX_FLOW_PCE_IP_V6) { IFX_int32_t tab_index,i; IFX_PCE_IP_DASA_MSB_TBL_t dasa_msb_tbl; /* SIP MSB */ for (i = 0; i < 8; i++) dasa_msb_tbl.ip_msb[i] = pPar->pattern.nSrcIP.nIPv6[i]; /* SIP MSB Nibble Mask */ dasa_msb_tbl.mask = pPar->pattern.nSrcIP_MsbMask; tab_index = ifx_pce_tm_ip_dasa_msb_tbl_write( &pHandle->pce_sub_tbl, &dasa_msb_tbl); if (tab_index < 0) IFX_RETURN_PCE; pFet->sip_msb_idx = (IFX_uint16_t)tab_index; } else pFet->sip_msb_idx = 0xFF; pcetable.key[2] |= (pFet->sip_msb_idx << 8); /* SIP LSB used */ if (pPar->pattern.eSrcIP_Select == IFX_FLOW_PCE_IP_V4) { IFX_int32_t tab_index; IFX_PCE_IP_DASA_LSB_TBL_t dasa_lsb_tbl; /* SIP LSB */ dasa_lsb_tbl.ip_lsb[3] = pPar->pattern.nSrcIP.nIPv4 & 0xFF; dasa_lsb_tbl.ip_lsb[2] = (pPar->pattern.nSrcIP.nIPv4 >> 8 ) & 0xFF; dasa_lsb_tbl.ip_lsb[1] = (pPar->pattern.nSrcIP.nIPv4 >> 16 ) & 0xFF; dasa_lsb_tbl.ip_lsb[0] = (pPar->pattern.nSrcIP.nIPv4 >> 24 ) & 0xFF; /* SIP LSB Nibble Mask */ dasa_lsb_tbl.mask = pPar->pattern.nSrcIP_MsbMask; tab_index = ifx_pce_tm_ip_dasa_lsb_tbl_write( &pHandle->pce_sub_tbl, &dasa_lsb_tbl); if (tab_index < 0) IFX_RETURN_PCE; pFet->sip_lsb_idx = (IFX_uint16_t)tab_index; #if 0 printk(" DstIP = %03d.%03d.%03d.%03d \n", dasa_lsb_tbl.ip_lsb[3], dasa_lsb_tbl.ip_lsb[2], dasa_lsb_tbl.ip_lsb[1], dasa_lsb_tbl.ip_lsb[0]); #endif } else pFet->sip_lsb_idx = 0xFF; pcetable.key[2] |= pFet->sip_lsb_idx; /* Ethertype used */ if (pPar->pattern.bEtherTypeEnable == IFX_TRUE) { IFX_int32_t tab_index; IFX_PCE_PTCL_TBL_t pctl_tbl; /* Ethertype */ pctl_tbl.key.ethertype = pPar->pattern.nEtherType; /* Ethertype Mask */ pctl_tbl.mask.ethertype_mask = pPar->pattern.nEtherTypeMask; tab_index = ifx_pce_tm_ptcl_tbl_write(&pHandle->pce_sub_tbl, &pctl_tbl); if (tab_index < 0) IFX_RETURN_PCE; pFet->ethertype_idx = (IFX_uint16_t)tab_index; } else pFet->ethertype_idx = 0xFF; pcetable.key[1] |= pFet->ethertype_idx; /* IP protocol used */ if (pPar->pattern.bProtocolEnable == IFX_TRUE) { IFX_int32_t tab_index; IFX_PCE_PTCL_TBL_t pctl_tbl; /* IP protocol */ pctl_tbl.key.prot.protocol = pPar->pattern.nProtocol; /* IP protocol Mask */ pctl_tbl.mask.prot.protocol_mask = pPar->pattern.nProtocolMask; /* todo: define API parameter for the flags. */ pctl_tbl.key.prot.protocol_flags = 0xFF; /* todo: define API parameter for the flags. */ pctl_tbl.mask.prot.protocol_flag_mask = 0xFF; tab_index = ifx_pce_tm_ptcl_tbl_write(&pHandle->pce_sub_tbl, &pctl_tbl); if (tab_index < 0) IFX_RETURN_PCE; pFet->ip_prot_idx = (IFX_uint16_t)tab_index; } else pFet->ip_prot_idx = 0xFF; pcetable.key[1] |= (pFet->ip_prot_idx << 8); /* PPPoE used */ if (pPar->pattern.bSessionIdEnable == IFX_TRUE) { IFX_int32_t tab_index; IFX_PCE_PPPOE_TBL_t pppoe_tbl; /* PPPoE */ pppoe_tbl.sess_id = pPar->pattern.nSessionId; tab_index = ifx_pce_tm_pppoe_tbl_write( &pHandle->pce_sub_tbl, (IFX_PCE_PPPOE_TBL_t *)pPar); if (tab_index < 0) IFX_RETURN_PCE; pFet->pppoe_idx = (IFX_uint16_t)tab_index; } else pFet->pppoe_idx = 0xFF; pcetable.key[7] |= (pFet->pppoe_idx << 8); /* VLAN used */ if (pPar->pattern.bVid == IFX_TRUE) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable_vlan; IFX_int32_t tab_index; IFX_int32_t table_index; /* VLAN software Table update from hardware table */ /* Read out the real VLAN action table and write back into software table */ for (table_index = 0; table_index < IFX_PCE_VLAN_ACT_TBL_SIZE ; table_index++) { pcetable_vlan.table = IFX_ETHSW_PCE_ACTVLAN_INDEX; pcetable_vlan.table_index = table_index; //index of the VLAN ID configuration // pcetable.key[0] = pPar->nVId; ifx_ethsw_xwayflow_pce_table_read(pDevCtx, &pcetable_vlan); if ( pcetable_vlan.valid == IFX_TRUE ) { if ( pcetable_vlan.key[0] == pPar->pattern.nVid ) { tab_index = table_index; pcetable.key[0] |= (tab_index << 8); // pcetable.val[2] = tab_index | (pcetable_vlan.val[0] & 0xF); } printk("VLAN ID Found match\n"); } } } else pcetable.key[0] |= (0xFF << 8); pAct = &(pHandle->pce_act[idx]); /* take over the rule action */ // memcpy(&pHandle->pce_act[idx], pPar->action, sizeof(IFX_FLOW_PCE_action_t)); memcpy(pAct, &pPar->action, sizeof(IFX_FLOW_PCE_action_t)); /* now programm the cached memory configuration to the hardware!! */ /* prepare the action table data */ #if 0 printk("pAct->ePortMapAction = %d\n",pAct->ePortMapAction); printk("pAct->eVLAN_Action = %d\n",pAct->eVLAN_Action); printk("pAct->eTrafficClassAction = %d\n",pAct->eTrafficClassAction); printk("pAct->bRemarkClass = %d\n",pAct->bRemarkClass); printk("pAct->eVLAN_CrossAction = %d\n",pAct->eVLAN_CrossAction); printk("pAct->eCrossStateAction = %d\n",pAct->eCrossStateAction); printk("pAct->eCritFrameAction = %d\n",pAct->eCritFrameAction ); printk("pAct->eTimestampAction = %d\n",pAct->eTimestampAction); printk("pAct->eIrqAction = %d\n",pAct->eIrqAction); printk("pAct->eLearningAction = %d\n",pAct->eLearningAction); printk("pAct->eTimestampAction = %d\n",pAct->eTimestampAction); printk("pAct->bRMON_Action = %d\n",pAct->bRMON_Action); printk("pAct->nTrafficClassAlternate = %d\n",pAct->nTrafficClassAlternate); printk("pAct->nForwardPortMap = %d\n",pAct->nForwardPortMap); printk("pAct->nMeterId = %d\n",pAct->nMeterId); printk("pAct->eMeterAction = %d\n",pAct->eMeterAction); printk("pAct->bRemarkDSCP = %d\n",pAct->bRemarkDSCP); printk("pAct->bRemarkDSCP = %d\n",pAct->bRemarkDSCP); #endif /* Fill the Action parameter into the pcetable.val[x] */ /* Action "Forwarding" Group. */ if (pAct->ePortMapAction != IFX_FLOW_PCE_ACTION_PORTMAP_DISABLE) { if (pAct->eSnoopingTypeAction == 0) { pcetable.val[0] = 1; pcetable.val[4] |= (0x3 << 2); if(pAct->ePortMapAction == IFX_FLOW_PCE_ACTION_PORTMAP_REGULAR) pcetable.val[4] &= ~(0x3 << 2); else if(pAct->ePortMapAction == IFX_FLOW_PCE_ACTION_PORTMAP_DISCARD) pcetable.val[1] = 0; else if(pAct->ePortMapAction == IFX_FLOW_PCE_ACTION_PORTMAP_CPU) { pcetable.val[1] = 0x40; /* Port 6 */ pcetable.val[4] &= ~(0x3 << 2); pcetable.val[4] |= (0x1 << 2); } else if(pAct->ePortMapAction == IFX_FLOW_PCE_ACTION_PORTMAP_ALTERNATIVE) pcetable.val[1] = pAct->nForwardPortMap & 0xFFFF; } else { if (pAct->ePortMapAction == 5) { pcetable.val[0] = 1; pcetable.val[4] &= ~(0x3 << 2); /* Forwarding Action enabled. Select Multicast Router Port-Map (output of Multicast - HW Table). */ pcetable.val[4] |= (0x1 << 2); } else { pcetable.val[0] = 0; pcetable.val[1] = 0xFFFF; } } } else { pcetable.val[0] = 0; pcetable.val[1] = 0xFFFF; pcetable.val[4] &= ~(0x3 << 2); } /** Action "VLAN" Group. VLAN action enable */ if (pAct->eVLAN_Action != IFX_FLOW_PCE_ACTION_VLAN_DISABLE) { pcetable.val[0] |= ( 1 << 1 ); /* Todo: */ if (pAct->eVLAN_Action == IFX_FLOW_PCE_ACTION_VLAN_REGULAR) pcetable.val[0] &= ~( 1 << 13 ); else if (pAct->eVLAN_Action == IFX_FLOW_PCE_ACTION_VLAN_ALTERNATIVE) { IFX_ETHSW_XWAYFLOW_PCE_TABLE_ENTRY_t pcetable_vlan; IFX_int32_t tab_index; IFX_int32_t table_index; /* VLAN software Table update from hardware table */ /* Read out the real VLAN mapping table and write back into software table */ for (table_index = 0; table_index < IFX_PCE_VLAN_ACT_TBL_SIZE ; table_index++) { pcetable_vlan.table = IFX_ETHSW_PCE_VLANMAP_INDEX; pcetable_vlan.table_index = table_index; //index of the VLAN ID configuration // pcetable.key[0] = pPar->nVId; ifx_ethsw_xwayflow_pce_table_read(pDevCtx, &pcetable_vlan); if ( pcetable_vlan.val[0] == pAct->nVLAN_Id ) { pcetable.val[2] = (table_index & 0xFF); break; } } /* VLAN software Table update from hardware table */ /* Read out the real VLAN action table and write back into software table */ for (table_index = 0; table_index < IFX_PCE_VLAN_ACT_TBL_SIZE ; table_index++) { pcetable_vlan.table = IFX_ETHSW_PCE_ACTVLAN_INDEX; pcetable_vlan.table_index = table_index; //index of the VLAN ID configuration // pcetable.key[0] = pPar->nVId; ifx_ethsw_xwayflow_pce_table_read(pDevCtx, &pcetable_vlan); if ( pcetable_vlan.valid == IFX_TRUE ) { if ( pcetable_vlan.key[0] == pAct->nVLAN_Id ) { pcetable.val[2] |= ((pcetable_vlan.val[0] & 0xFF) << 8); break; } } } pcetable.val[0] |= ( 1 << 13 ); } } else { pcetable.val[2] = 0; pcetable.val[0] &= ~(1 << 13 ); } /** Action "Traffic Class" Group. Traffic class action enable */ if (pAct->eTrafficClassAction != IFX_FLOW_PCE_ACTION_TRAFFIC_CLASS_DISABLE) { pcetable.val[0] |= ( 1 << 2 ); if (pAct->eTrafficClassAction == IFX_FLOW_PCE_ACTION_TRAFFIC_CLASS_REGULAR) pcetable.val[0] &= ~(1 << 14); else if (pAct->eTrafficClassAction == IFX_FLOW_PCE_ACTION_TRAFFIC_CLASS_ALTERNATIVE) { pcetable.val[0] |= (1 << 14); pcetable.val[3] &= ~(0xF << 8); pcetable.val[3] |= (pAct->nTrafficClassAlternate & 0xF) << 8; } } else { pcetable.val[0] &= ~((1 << 2) | (1 << 14)); pcetable.val[3] |= (0xF << 8); } /** Action "Remarking" Group. Remarking action enable */ if (pAct->bRemarkAction != IFX_FALSE) pcetable.val[0] |= (1 << 3); else pcetable.val[0] &= ~(1 << 3); /** Action "Cross VLAN" Group. Cross VLAN action enable */ if (pAct->eVLAN_CrossAction != IFX_FLOW_PCE_ACTION_CROSS_VLAN_DISABLE) { pcetable.val[0] |= ( 1 << 4 ); if (pAct->eVLAN_CrossAction == IFX_FLOW_PCE_ACTION_CROSS_VLAN_REGULAR) pcetable.val[3] &= ~(0 << 15); else pcetable.val[3] |= (1 << 15); } else { pcetable.val[0] &= ~ (1 << 4); pcetable.val[3] &= ~(0 << 15); } /** Action "Cross State" Group. Cross state action control and enable */ if (pAct->eCrossStateAction != IFX_FLOW_PCE_ACTION_CROSS_STATE_DISABLE) { pcetable.val[0] |= ( 1 << 5 ); if (pAct->eCrossStateAction == IFX_FLOW_PCE_ACTION_CROSS_STATE_CROSS) pcetable.val[4] |= ( 1 << 13 ); else pcetable.val[4] &= ~(1 << 13 ); } else { pcetable.val[4] &= ~(1 << 13 ); pcetable.val[0] &= ~(1 << 5 ); } /** Action "Critical Frames" Group. Critical Frame action control and enable */ if (pAct->eCritFrameAction != IFX_FLOW_PCE_ACTION_CRITICAL_FRAME_DISABLE) { pcetable.val[0] |= ( 1 << 6 ); if (pAct->eCritFrameAction == IFX_FLOW_PCE_ACTION_CRITICAL_FRAME_CRITICAL) pcetable.val[4] |= ( 1 << 14 ); else pcetable.val[4] &= ~(1 << 14 ); } else { pcetable.val[0] &= ~(1 << 6 ); pcetable.val[4] &= ~(1 << 14 ); } /** Action "Timestamp" Group. Time stamp action control and enable */ if (pAct->eTimestampAction != IFX_FLOW_PCE_ACTION_TIMESTAMP_DISABLE) { pcetable.val[0] |= ( 1 << 7 ); if (pAct->eTimestampAction == IFX_FLOW_PCE_ACTION_TIMESTAMP_STORED) pcetable.val[4] |= ( 1 << 15 ); else pcetable.val[4] &= ~(1 << 15 ); } else { pcetable.val[0] &= ~(1 << 7 ); pcetable.val[4] &= ~(1 << 15 ); } /** Action "Interrupt" Group. Interrupt action generate and enable */ if (pAct->eIrqAction != IFX_FLOW_PCE_ACTION_IRQ_DISABLE) { pcetable.val[0] |= ( 1 << 8 ); if ( pAct->eIrqAction == IFX_FLOW_PCE_ACTION_IRQ_EVENT) pcetable.val[0] |= ( 1 << 15 ); else pcetable.val[0] &= ~(1 << 15 ); } else pcetable.val[0] &= ~((1 << 8) | (1 << 15)); /** Action "Learning" Group. Learning action control and enable */ if (pAct->eLearningAction != IFX_FLOW_PCE_ACTION_LEARNING_DISABLE) { pcetable.val[0] |= ( 1 << 9 ); /* Todo: Learning Rule need to be check */ if (pAct->eLearningAction == IFX_FLOW_PCE_ACTION_LEARNING_REGULAR) pcetable.val[4] &= ~0x3; else if (pAct->eLearningAction == IFX_FLOW_PCE_ACTION_LEARNING_FORCE_NOT) pcetable.val[4] = (pcetable.val[4] & ~0x3) | 0x2; else if (pAct->eLearningAction == IFX_FLOW_PCE_ACTION_LEARNING_FORCE) pcetable.val[4] |= 0x3; } else { pcetable.val[0] &= ~(1 << 9 ); pcetable.val[4] &= ~0x3; } /** Action "IGMP Snooping" Group. */ if (pAct->eSnoopingTypeAction != IFX_FLOW_PCE_ACTION_IGMP_SNOOP_DISABLE) { pcetable.val[0] |= ( 1 << 10 ); if (pAct->eSnoopingTypeAction == IFX_FLOW_PCE_ACTION_IGMP_SNOOP_REGULAR) pcetable.val[4] |=( 1 << 5 ); else if (pAct->eSnoopingTypeAction == IFX_FLOW_PCE_ACTION_IGMP_SNOOP_REPORT) pcetable.val[4] |=( 2 << 5 ); else if (pAct->eSnoopingTypeAction == IFX_FLOW_PCE_ACTION_IGMP_SNOOP_LEAVE) pcetable.val[4] |=( 3 << 5 ); else if (pAct->eSnoopingTypeAction == IFX_FLOW_PCE_ACTION_IGMP_SNOOP_QUERY) pcetable.val[4] |=( 4 << 5 ); else if (pAct->eSnoopingTypeAction == IFX_FLOW_PCE_ACTION_IGMP_SNOOP_AD) pcetable.val[4] |=( 5 << 5 ); } else { pcetable.val[0] &= ~(1 << 10 ); pcetable.val[4] &= ~(0x7 << 5); } /** Action "Meter" Group. Meter action control and enable. */ if (pAct->eMeterAction != IFX_FLOW_PCE_ACTION_METER_DISABLE) { pcetable.val[0] |= ( 1 << 11 ); if (pAct->eMeterAction == IFX_FLOW_PCE_ACTION_METER_1) pcetable.val[3] = (pAct->nMeterId & 0x1F); if (pAct->eMeterAction == IFX_FLOW_PCE_ACTION_METER_2) pcetable.val[3] = (pAct->nMeterId & 0x1F); if (pAct->eMeterAction == IFX_FLOW_PCE_ACTION_METER_1_2) pcetable.val[3] = (pAct->nMeterId & 0x1F); } else { pcetable.val[0] &= ~(1 << 11 ); pcetable.val[3] |= 0x1F; } /** Action "RMON" Group. RMON action enable */ if (pAct->bRMON_Action != IFX_FALSE) { pcetable.val[0] |= ( 1 << 12 ); pcetable.val[4] = (pcetable.val[4] & (~(0x1F << 8))) | (pAct->nRMON_Id << 8); } else { pcetable.val[0] &= ~(1 << 12 ); pcetable.val[4] &= ~(0x1F << 8); } pcetable.val[3] |= (0x7 << 12); if(pAct->bRemarkDSCP == IFX_TRUE) pcetable.val[3] &= ~(1 << 12); if(pAct->bRemarkClass == IFX_TRUE) pcetable.val[3] &= ~(1 << 13); if(pAct->bRemarkPCP == IFX_TRUE) pcetable.val[3] &= ~(1 << 14); pcetable.table_index = idx; //index of the Traffic Flow Table index configuration pcetable.table = IFX_ETHSW_PCE_TFLOW_INDEX; pcetable.valid = 1; ifx_ethsw_xwayflow_pce_table_write(pDevCtx, &pcetable); return IFX_SUCCESS; }