/****************************************************************************** Copyright (c) 2016, 2017 Intel Corporation ******************************************************************************/ /***************************************************************************** Copyright (c) 2012, 2014, 2015 Lantiq Deutschland GmbH For licensing information, see the file 'LICENSE' in the root folder of this software module. ******************************************************************************/ #include #include #define FDMA_LOSSOAM_TYPEn(x) (0xA70 + (x)) #define FDMA_DELAYOAM_TYPEn(x) (0xA60 + (x)) #define FDMA_DELAYOAM_COMP_LSB(x) (0xA58 + (x)*2) #define FDMA_DELAYOAM_COMP_MSB(x) (0xA59 + (x)*2) #define PCE_MC_M3(val, msk, ns, out, len, type, flags, ipv4_len) \ { \ val, msk, (ns << 8 | out << 0), \ (len | type << 5 | flags << 8 | ipv4_len << 7) \ } const PCE_MICROCODE pce_mc_max_ifx_tag_m_31 = { /* V31_09B */ PCE_MC_M3(0x88C3, 0xFFFF, 5, OUT_ITAG0, 4, INSTR, FLAG_ITAG, 0), PCE_MC_M3(0x88C4, 0xFFFF, 3, OUT_ITAG0, 1, INSTR, FLAG_ITAG, 0), PCE_MC_M3(0x0000, 0x0000, 5, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 4, OUT_ITAG2, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 5, OUT_NONE, 2, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 10, OUT_1VTAG0, 2, INSTR, FLAG_1VLAN, 0), PCE_MC_M3(0x88A8, 0xFFFF, 10, OUT_1VTAG0, 2, INSTR, FLAG_1VLAN, 0), PCE_MC_M3(0x9100, 0xFFFF, 10, OUT_1VTAG0, 2, INSTR, FLAG_1VLAN, 0), PCE_MC_M3(0x9200, 0xFFFF, 10, OUT_1VTAG0, 2, INSTR, FLAG_1VLAN, 0), PCE_MC_M3(0x0000, 0x0000, 20, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 15, OUT_2VTAG0, 2, INSTR, FLAG_2VLAN, 0), PCE_MC_M3(0x88A8, 0xFFFF, 15, OUT_2VTAG0, 2, INSTR, FLAG_2VLAN, 0), PCE_MC_M3(0x9100, 0xFFFF, 15, OUT_2VTAG0, 2, INSTR, FLAG_2VLAN, 0), PCE_MC_M3(0x9200, 0xFFFF, 15, OUT_2VTAG0, 2, INSTR, FLAG_2VLAN, 0), PCE_MC_M3(0x0000, 0x0000, 20, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 18, OUT_3VTAG0, 2, INSTR, FLAG_3VLAN, 0), PCE_MC_M3(0x88A8, 0xFFFF, 18, OUT_3VTAG0, 2, INSTR, FLAG_3VLAN, 0), PCE_MC_M3(0x0000, 0x0000, 20, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 18, OUT_NONE, 2, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x88A8, 0xFFFF, 18, OUT_NONE, 2, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x0000, 0xF800, 22, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 28, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0600, 0x0600, 28, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 24, OUT_ETYPE, 1, INSTR, FLAG_LEN, 0), PCE_MC_M3(0xAAAA, 0xFFFF, 26, OUT_APP0, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 120, OUT_APP0, 2, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0300, 0xFF00, 28, OUT_APP1, 2, INSTR, FLAG_SNAP, 0), PCE_MC_M3(0x0000, 0x0000, 120, OUT_APP1, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8864, 0xFFFF, 33, OUT_ETYPE, 4, INSTR, FLAG_PPPOES, 0), PCE_MC_M3(0x0800, 0xFFFF, 36, OUT_ETYPE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x86DD, 0xFFFF, 48, OUT_ETYPE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x888E, 0xFFFF, 109, OUT_ETYPE, 1, INSTR, FLAG_EAPOL, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_ETYPE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0021, 0xFFFF, 36, OUT_PPP, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0057, 0xFFFF, 48, OUT_PPP, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_PPP, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0500, 0x0F00, 40, OUT_1IP0, 3, INSTR, FLAG_1IPV4, 1), PCE_MC_M3(0x0600, 0x0600, 40, OUT_1IP0, 3, INSTR, FLAG_1IPV4, 1), PCE_MC_M3(0x0800, 0x0800, 40, OUT_1IP0, 3, INSTR, FLAG_1IPV4, 1), PCE_MC_M3(0x0000, 0x0000, 119, OUT_1IP0, 10, INSTR, FLAG_1IPV4, 1), PCE_MC_M3(0x0000, 0x3FFF, 42, OUT_1IP3, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 42, OUT_1IP3, 1, INSTR, FLAG_IPFRAG, 0), PCE_MC_M3(0x0011, 0x00FF, 99, OUT_1IP4, 4, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0006, 0x00FF, 96, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0002, 0x00FF, 108, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0029, 0x00FF, 79, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0004, 0x00FF, 69, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 49, OUT_1IP0, 3, INSTR, FLAG_1IPV6, 0), PCE_MC_M3(0x1100, 0xFF00, 105, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0600, 0xFF00, 96, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0400, 0xFF00, 69, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2900, 0xFF00, 79, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0xFF00, 58, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2B00, 0xFF00, 58, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x3C00, 0xFF00, 58, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x3A00, 0xFF00, 110, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x00F8, 60, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0xFF00, 58, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x2B00, 0xFF00, 58, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x3C00, 0xFF00, 58, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x1100, 0xFF00, 105, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x0600, 0xFF00, 96, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x0400, 0xFF00, 69, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x2900, 0xFF00, 79, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x3A00, 0xFF00, 110, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x0500, 0x0F00, 73, OUT_2IP0, 3, INSTR, FLAG_2IPV4, 1), PCE_MC_M3(0x0600, 0x0600, 73, OUT_2IP0, 3, INSTR, FLAG_2IPV4, 1), PCE_MC_M3(0x0800, 0x0800, 73, OUT_2IP0, 3, INSTR, FLAG_2IPV4, 1), PCE_MC_M3(0x0000, 0x0000, 119, OUT_2IP0, 10, INSTR, FLAG_2IPV4, 1), PCE_MC_M3(0x0000, 0x3FFF, 75, OUT_1IP3, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 75, OUT_1IP3, 1, INSTR, FLAG_IPFRAG, 0), PCE_MC_M3(0x0011, 0x00FF, 101, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0006, 0x00FF, 96, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0002, 0x00FF, 108, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 80, OUT_2IP0, 3, INSTR, FLAG_2IPV6, 0), PCE_MC_M3(0x1100, 0xFF00, 105, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0600, 0xFF00, 96, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0xFF00, 87, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2B00, 0xFF00, 87, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x3C00, 0xFF00, 87, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x3A00, 0xFF00, 110, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x00F8, 89, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0xFF00, 87, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x2B00, 0xFF00, 87, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x3C00, 0xFF00, 87, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x1100, 0xFF00, 105, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x0600, 0xFF00, 96, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x3A00, 0xFF00, 110, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x0000, 0x0000, 97, OUT_APP0, 6, INSTR, FLAG_TCP, 0), PCE_MC_M3(0x0010, 0x0010, 120, OUT_APP6, 4, INSTR, FLAG_TCPACK, 0), PCE_MC_M3(0x0000, 0x0010, 120, OUT_APP6, 4, INSTR, FLAG_NO, 0), PCE_MC_M3(0xE000, 0xF000, 101, OUT_1IP8, 2, INSTR, FLAG_IPV4MC, 0), PCE_MC_M3(0x0000, 0x0000, 101, OUT_1IP8, 2, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 102, OUT_APP0, 1, INSTR, FLAG_1UDP, 0), PCE_MC_M3(0x0043, 0xFFFF, 120, OUT_APP1, 3, INSTR, FLAG_DHCPV4, 0), PCE_MC_M3(0x0044, 0xFFFF, 120, OUT_APP1, 3, INSTR, FLAG_DHCPV4, 0), PCE_MC_M3(0x0000, 0x0000, 120, OUT_APP1, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 106, OUT_APP0, 1, INSTR, FLAG_1UDP, 0), PCE_MC_M3(0x0222, 0xFFFE, 120, OUT_APP1, 3, INSTR, FLAG_DHCPV6, 0), PCE_MC_M3(0x0000, 0x0000, 120, OUT_APP1, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 120, OUT_APP0, 4, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x0000, 0x0000, 119, OUT_NONE, 0, INSTR, FLAG_ETYPE_888E, 0), PCE_MC_M3(0x0000, 0x0000, 111, OUT_NONE, 0, INSTR, FLAG_ICMPV6, 0), PCE_MC_M3(0x8200, 0xFE00, 120, OUT_APP0, 2, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x8400, 0xFF00, 120, OUT_APP0, 2, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x8F00, 0xFF00, 120, OUT_APP0, 2, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x9700, 0xFF00, 120, OUT_APP0, 2, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x9800, 0xFE00, 120, OUT_APP0, 2, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x8700, 0xFF00, 120, OUT_APP0, 2, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x8800, 0xFF00, 120, OUT_APP0, 2, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x0000, 0x0000, 120, OUT_APP0, 2, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 120, OUT_APP0, 2, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 121, OUT_1PL, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_2PL, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 122, OUT_NONE, 0, INSTR, FLAG_END, 0), }; const PCE_MICROCODE pce_mc_max_ifx_tag_m_30 = { /* V30_19 */ PCE_MC_M3(0x88C3, 0xFFFF, 2, OUT_ITAG0, 1, INSTR, FLAG_ITAG, 0), PCE_MC_M3(0x0000, 0x0000, 4, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0800, 0x0800, 4, OUT_ITAG1, 3, INSTR, FLAG_4VLAN, 0), PCE_MC_M3(0x0000, 0x0000, 4, OUT_ITAG1, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 7, OUT_1VTAG0, 2, INSTR, FLAG_1VLAN, 0), PCE_MC_M3(0x88A8, 0xFFFF, 7, OUT_1VTAG0, 2, INSTR, FLAG_1VLAN, 0), PCE_MC_M3(0x0000, 0x0000, 15, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 10, OUT_2VTAG0, 2, INSTR, FLAG_2VLAN, 0), PCE_MC_M3(0x88A8, 0xFFFF, 10, OUT_2VTAG0, 2, INSTR, FLAG_2VLAN, 0), PCE_MC_M3(0x0000, 0x0000, 15, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 13, OUT_3VTAG0, 2, INSTR, FLAG_3VLAN, 0), PCE_MC_M3(0x88A8, 0xFFFF, 13, OUT_3VTAG0, 2, INSTR, FLAG_3VLAN, 0), PCE_MC_M3(0x0000, 0x0000, 15, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 13, OUT_NONE, 2, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x88A8, 0xFFFF, 13, OUT_NONE, 2, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x0000, 0xF800, 17, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 23, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0600, 0x0600, 23, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 19, OUT_ETYPE, 1, INSTR, FLAG_LEN, 0), PCE_MC_M3(0xAAAA, 0xFFFF, 21, OUT_APP0, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_APP0, 2, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0300, 0xFF00, 23, OUT_APP1, 2, INSTR, FLAG_SNAP, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_APP1, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8864, 0xFFFF, 28, OUT_ETYPE, 4, INSTR, FLAG_PPPOES, 0), PCE_MC_M3(0x0800, 0xFFFF, 31, OUT_ETYPE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x86DD, 0xFFFF, 55, OUT_ETYPE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x888E, 0xFFFF, 191, OUT_ETYPE, 1, INSTR, FLAG_EAPOL, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_ETYPE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0021, 0xFFFF, 31, OUT_PPP, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0057, 0xFFFF, 55, OUT_PPP, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_PPP, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x4000, 0xF000, 33, OUT_NONE, 0, INSTR, FLAG_1IPV4, 1), PCE_MC_M3(0x0000, 0x0000, 191, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0500, 0x0F00, 38, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0600, 0x0600, 37, OUT_NONE, 0, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0800, 0x0800, 37, OUT_NONE, 0, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_1IP0, 10, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0000, 0x0000, 38, OUT_NONE, 0, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0003, 0x0003, 40, OUT_1IP0, 3, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0000, 0x0000, 40, OUT_1IP0, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x3FFF, 42, OUT_1IP3, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 42, OUT_1IP3, 1, INSTR, FLAG_IPFRAG, 0), PCE_MC_M3(0x0000, 0xFE00, 43, OUT_NONE, 0, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x0011, 0x00FF, 123, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0006, 0x00FF, 109, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0002, 0x00FF, 130, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0029, 0x00FF, 93, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0004, 0x00FF, 81, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x002F, 0x00FF, 147, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0032, 0x00FF, 51, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_1IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 52, OUT_APP0, 4, INSTR, FLAG_NO, 0), PCE_MC_M3(0x4000, 0xF000, 54, OUT_NONE, 6, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 54, OUT_NONE, 10, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_1PL, 2, INSTR, FLAG_NO, 0), PCE_MC_M3(0x6000, 0xF000, 57, OUT_NONE, 0, INSTR, FLAG_1IPV6, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0030, 0x0030, 59, OUT_1IP0, 3, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0000, 0x0000, 59, OUT_1IP0, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x00FE, 60, OUT_NONE, 0, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x1100, 0xFF00, 123, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0600, 0xFF00, 109, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 63, OUT_NONE, 0, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0400, 0xFF00, 81, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2900, 0xFF00, 93, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2F00, 0xFF00, 147, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x3200, 0xFF00, 51, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0xFF00, 71, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2B00, 0xFF00, 71, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x3C00, 0xFF00, 71, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_1IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x00F8, 73, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0xFF00, 71, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x2B00, 0xFF00, 71, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x3C00, 0xFF00, 71, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x1100, 0xFF00, 123, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x0600, 0xFF00, 109, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x0400, 0xFF00, 81, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x2900, 0xFF00, 93, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_1LNH, 1, IPV6, FLAG_1IPV6EXT, 0), PCE_MC_M3(0x0000, 0x0000, 82, OUT_NONE, 0, INSTR, FLAG_2IPV4, 1), PCE_MC_M3(0x0500, 0x0F00, 86, OUT_2IP0, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0600, 0x0600, 86, OUT_2IP0, 3, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0800, 0x0800, 86, OUT_2IP0, 3, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_2IP0, 10, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0000, 0x3FFF, 88, OUT_2IP3, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 88, OUT_2IP3, 1, INSTR, FLAG_IPFRAG, 0), PCE_MC_M3(0x0000, 0xFE00, 89, OUT_NONE, 0, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x0011, 0x00FF, 129, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0006, 0x00FF, 109, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0002, 0x00FF, 130, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 94, OUT_2IP0, 3, INSTR, FLAG_2IPV6, 0), PCE_MC_M3(0x0000, 0x00FE, 95, OUT_NONE, 0, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x1100, 0xFF00, 129, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0600, 0xFF00, 109, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0xFF00, 101, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2B00, 0xFF00, 101, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x3C00, 0xFF00, 101, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x00F8, 103, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0xFF00, 101, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x2B00, 0xFF00, 101, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x3C00, 0xFF00, 101, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x1100, 0xFF00, 129, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x0600, 0xFF00, 109, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_2LNH, 1, IPV6, FLAG_2IPV6EXT, 0), PCE_MC_M3(0x0000, 0x0000, 111, OUT_APP0, 6, INSTR, FLAG_TCP, 0), PCE_MC_M3(0x0000, 0x0000, 111, OUT_1PL, 4, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0040, 0x0040, 112, OUT_NONE, 0, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0080, 0x0080, 113, OUT_NONE, 0, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0020, 0x0020, 114, OUT_NONE, 0, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0008, 0x0008, 115, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0001, 0x0001, 116, OUT_NONE, 0, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x0001, 0x0001, 117, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0004, 0x0004, 118, OUT_NONE, 0, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x0004, 0x0004, 119, OUT_NONE, 0, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0002, 0x0002, 120, OUT_NONE, 0, INSTR, FLAG_LROEXP, 0), PCE_MC_M3(0x0002, 0x0002, 121, OUT_NONE, 0, INSTR, FLAG_TCPSYN, 0), PCE_MC_M3(0x0010, 0x0010, 194, OUT_APP6, 4, INSTR, FLAG_TCPACK, 0), PCE_MC_M3(0x0000, 0x0010, 194, OUT_APP6, 4, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 124, OUT_APP0, 1, INSTR, FLAG_1UDP, 0), PCE_MC_M3(0x06A5, 0xFFFF, 131, OUT_APP1, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x147F, 0xFFFF, 143, OUT_APP1, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2118, 0xFFFF, 189, OUT_APP1, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x12B6, 0xFFFF, 189, OUT_APP1, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_APP1, 3, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_APP0, 4, INSTR, FLAG_2UDP, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_APP0, 4, INSTR, FLAG_IGMP, 0), PCE_MC_M3(0x0000, 0xCA00, 138, OUT_NONE, 3, INSTR, FLAG_L2TP, 0), PCE_MC_M3(0x4000, 0xCA00, 138, OUT_NONE, 4, INSTR, FLAG_L2TP, 0), PCE_MC_M3(0x0200, 0xCA00, 136, OUT_NONE, 3, INSTR, FLAG_L2TP, 0), PCE_MC_M3(0x4200, 0xCA00, 136, OUT_NONE, 4, INSTR, FLAG_L2TP, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_NONE, 0, INSTR, FLAG_L2TP, 0), PCE_MC_M3(0x0000, 0xFFFF, 138, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0xFF03, 0xFFFF, 140, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0021, 0xFFFF, 81, OUT_NONE, 1, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x0057, 0xFFFF, 93, OUT_NONE, 1, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0010, 0x00F8, 145, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x01F8, 192, OUT_NONE, 0, INSTR, FLAG_CAPWAP, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x2000, 0xFFFF, 150, OUT_NONE, 1, INSTR, FLAG_GREK, 0), PCE_MC_M3(0x0000, 0xFFFF, 168, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x6558, 0xFFFF, 154, OUT_NONE, 1, INSTR, FLAG_GRE, 0), PCE_MC_M3(0x0800, 0xFFFF, 166, OUT_NONE, 1, INSTR, FLAG_GRE, 0), PCE_MC_M3(0x86DD, 0xFFFF, 167, OUT_NONE, 1, INSTR, FLAG_GRE, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 155, OUT_1PL, 2, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x0000, 0x0000, 156, OUT_NONE, 6, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 158, OUT_NONE, 2, INSTR, FLAG_GRE_VLAN1, 0), PCE_MC_M3(0x0000, 0x0000, 159, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x8100, 0xFFFF, 159, OUT_NONE, 2, INSTR, FLAG_GRE_VLAN2, 0), PCE_MC_M3(0x8864, 0xFFFF, 163, OUT_NONE, 4, INSTR, FLAG_GRE_PPPOE, 0), PCE_MC_M3(0x0800, 0xFFFF, 172, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x86DD, 0xFFFF, 183, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0021, 0xFFFF, 172, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0057, 0xFFFF, 183, OUT_NONE, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 172, OUT_1PL, 2, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x0000, 0x0000, 183, OUT_1PL, 2, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x6558, 0xFFFF, 155, OUT_NONE, 1, INSTR, FLAG_GRE, 0), PCE_MC_M3(0x0800, 0xFFFF, 172, OUT_NONE, 1, INSTR, FLAG_GRE, 0), PCE_MC_M3(0x86DD, 0xFFFF, 183, OUT_NONE, 1, INSTR, FLAG_GRE, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_NONE, 0, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 173, OUT_NONE, 0, INSTR, FLAG_2IPV4, 1), PCE_MC_M3(0x0500, 0x0F00, 177, OUT_2IP0, 3, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x0600, 0x0600, 177, OUT_2IP0, 3, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0800, 0x0800, 177, OUT_2IP0, 3, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0000, 0x0000, 191, OUT_2IP0, 10, INSTR, FLAG_IPV4OPT, 0), PCE_MC_M3(0x0000, 0x3FFF, 179, OUT_2IP3, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 179, OUT_2IP3, 1, INSTR, FLAG_IPFRAG, 0), PCE_MC_M3(0x0000, 0xFE00, 180, OUT_NONE, 0, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x0011, 0x00FF, 188, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0006, 0x00FF, 109, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_2IP4, 6, LENACCU, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 184, OUT_2IP0, 3, INSTR, FLAG_2IPV6, 0), PCE_MC_M3(0x0000, 0x00FE, 185, OUT_NONE, 0, INSTR, FLAG_ROUTEXP, 0), PCE_MC_M3(0x1100, 0xFF00, 188, OUT_2IP3, 17, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x0600, 0xFF00, 109, OUT_2IP3, 17, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_2IP3, 17, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_APP0, 4, INSTR, FLAG_2UDP, 0), PCE_MC_M3(0x0000, 0x0000, 190, OUT_NONE, 0, INSTR, FLAG_VXLAN, 0), PCE_MC_M3(0x0000, 0x0000, 155, OUT_1PL, 4, INSTR, FLAG_L2TPNEXP, 0), PCE_MC_M3(0x0000, 0x0000, 192, OUT_APP0, 2, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 193, OUT_1PL, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_2PL, 1, INSTR, FLAG_NO, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), PCE_MC_M3(0x0000, 0x0000, 194, OUT_NONE, 0, INSTR, FLAG_END, 0), }; #define 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 \ } const PCE_MICROCODE pce_mc_max_ifx_tag_m = { /*-----------------------------------------------------------------*/ /** value mask ns out_fields L type flags ipv4_len **/ /*-----------------------------------------------------------------*/ PCE_MC_M(0x88c3, 0xFFFF, 1, GOUT_ITAG0, 4, INSTR, GFLAG_ITAG, 0), PCE_MC_M(0x8100, 0xFFFF, 4, GOUT_STAG0, 2, INSTR, GFLAG_SVLAN, 0), PCE_MC_M(0x88A8, 0xFFFF, 4, GOUT_STAG0, 2, INSTR, GFLAG_SVLAN, 0), PCE_MC_M(0x9100, 0xFFFF, 4, GOUT_STAG0, 2, INSTR, GFLAG_SVLAN, 0), PCE_MC_M(0x8100, 0xFFFF, 5, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x88A8, 0xFFFF, 6, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x9100, 0xFFFF, 4, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x8864, 0xFFFF, 20, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0800, 0xFFFF, 24, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x86DD, 0xFFFF, 25, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x8863, 0xFFFF, 19, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xF800, 13, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 44, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0600, 0x0600, 44, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 15, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0xAAAA, 0xFFFF, 17, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0300, 0xFF00, 48, GOUT_NONE, 0, INSTR, GFLAG_SNAP, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_DIP7, 3, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 21, GOUT_DIP7, 3, INSTR, GFLAG_PPPOE, 0), PCE_MC_M(0x0021, 0xFFFF, 24, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0057, 0xFFFF, 25, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 44, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x4000, 0xF000, 27, GOUT_IP0, 4, INSTR, GFLAG_IPV4, 1), PCE_MC_M(0x6000, 0xF000, 30, GOUT_IP0, 3, INSTR, GFLAG_IPV6, 0), PCE_MC_M(0x0000, 0x0000, 44, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 28, GOUT_IP3, 2, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 29, GOUT_SIP0, 4, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 44, GOUT_NONE, 0, LENACCU, GFLAG_NO, 0), PCE_MC_M(0x1100, 0xFF00, 43, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0600, 0xFF00, 43, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xFF00, 41, GOUT_IP3, 17, INSTR, GFLAG_HOP, 0), PCE_MC_M(0x2B00, 0xFF00, 41, GOUT_IP3, 17, INSTR, GFLAG_NO, 0), PCE_MC_M(0x3C00, 0xFF00, 41, GOUT_IP3, 17, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 43, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xFF00, 41, GOUT_NONE, 0, IPV6, GFLAG_HOP, 0), PCE_MC_M(0x2B00, 0xFF00, 41, GOUT_NONE, 0, IPV6, GFLAG_NO, 0), PCE_MC_M(0x3C00, 0xFF00, 41, GOUT_NONE, 0, IPV6, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x00FC, 44, GOUT_PROT, 0, IPV6, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 44, GOUT_NONE, 0, IPV6, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x00F8, 36, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 44, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 44, GOUT_SIP0, 16, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 45, GOUT_APP0, 2, INSTR, GFLAG_IGMP, 0), PCE_MC_M(0x0400, 0x0400, 46, GOUT_NONE, 0, INSTR, GFLAG_NN2, 0), PCE_MC_M(0x0800, 0x0800, 47, GOUT_NONE, 0, INSTR, GFLAG_NN1, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_IGMP0, 2, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_END, 0), }; const PCE_MICROCODE pce_mc_max_ifx_tag_m_1 = { /*-----------------------------------------------------------------*/ /** value mask ns out_fields L type flags ipv4_len **/ /*-----------------------------------------------------------------*/ PCE_MC_M(0x88C3, 0xFFFF, 2, GOUT_ITAG0, 1, INSTR, GFLAG_ITAG, 0), PCE_MC_M(0x0000, 0x0000, 5, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 3, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 4, GOUT_APP0, 1, INSTR, GFLAG_NN2, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_ITAG1, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x8100, 0xFFFF, 8, GOUT_STAG0, 2, INSTR, GFLAG_SVLAN, 0), PCE_MC_M(0x88A8, 0xFFFF, 8, GOUT_STAG0, 2, INSTR, GFLAG_SVLAN, 0), PCE_MC_M(0x9100, 0xFFFF, 8, GOUT_STAG0, 2, INSTR, GFLAG_SVLAN, 0), PCE_MC_M(0x8100, 0xFFFF, 9, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x88A8, 0xFFFF, 10, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x9100, 0xFFFF, 8, GOUT_VTAG0, 2, INSTR, GFLAG_VLAN, 0), PCE_MC_M(0x8864, 0xFFFF, 24, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0800, 0xFFFF, 28, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x86DD, 0xFFFF, 29, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x8863, 0xFFFF, 23, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xF800, 17, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0600, 0x0600, 48, GOUT_ETHTYP, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 19, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0xAAAA, 0xFFFF, 21, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0300, 0xFF00, 52, GOUT_NONE, 0, INSTR, GFLAG_SNAP, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_DIP7, 3, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 25, GOUT_DIP7, 3, INSTR, GFLAG_PPPOE, 0), PCE_MC_M(0x0021, 0xFFFF, 28, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0057, 0xFFFF, 29, GOUT_NONE, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x4000, 0xF000, 31, GOUT_IP0, 4, INSTR, GFLAG_IPV4, 1), PCE_MC_M(0x6000, 0xF000, 34, GOUT_IP0, 3, INSTR, GFLAG_IPV6, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 32, GOUT_IP3, 2, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 33, GOUT_SIP0, 4, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, LENACCU, GFLAG_NO, 0), PCE_MC_M(0x1100, 0xFF00, 47, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0600, 0xFF00, 47, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xFF00, 45, GOUT_IP3, 17, INSTR, GFLAG_HOP, 0), PCE_MC_M(0x2B00, 0xFF00, 45, GOUT_IP3, 17, INSTR, GFLAG_NO, 0), PCE_MC_M(0x3C00, 0xFF00, 45, GOUT_IP3, 17, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 47, GOUT_PROT, 1, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0xFF00, 45, GOUT_NONE, 0, IPV6, GFLAG_HOP, 0), PCE_MC_M(0x2B00, 0xFF00, 45, GOUT_NONE, 0, IPV6, GFLAG_NO, 0), PCE_MC_M(0x3C00, 0xFF00, 45, GOUT_NONE, 0, IPV6, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x00FC, 48, GOUT_PROT, 0, IPV6, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, IPV6, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x00F8, 40, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_NONE, 0, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 48, GOUT_SIP0, 16, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 49, GOUT_APP0, 2, INSTR, GFLAG_IGMP, 0), PCE_MC_M(0x0400, 0x0400, 50, GOUT_NONE, 0, INSTR, GFLAG_NN2, 0), PCE_MC_M(0x0800, 0x0800, 51, GOUT_NONE, 0, INSTR, GFLAG_NN1, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_IGMP0, 2, INSTR, GFLAG_NO, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), PCE_MC_M(0x0000, 0x0000, 52, GOUT_NONE, 0, INSTR, GFLAG_END, 0), }; /* find a matched entry if already written or empty entry and fill */ static int tbl_write(void *tstart, u16 *rcnt, void *parm, u32 tsize, u32 tnum) { int i; /* search if the entry is already available and can be re-used */ for (i = 0; i < tnum; i++) { if (rcnt[i] > 0) { /* entry is used, check if the entry content fits */ if (memcmp(((char *)tstart) + i * tsize, parm, (u8)tsize) == 0) { rcnt[i]++; //pr_err("Using existing entry at %d\n", i); return i; } } } /* find an empty entry and add information */ for (i = 0; i < tnum; i++) { if (rcnt[i] == 0) { memcpy(((char *)tstart) + i * tsize, parm, (u8)tsize); rcnt[i]++; //pr_err("Created new entry at %d\n", i); return i; } } /* table is full, return an error */ pr_err("ERROR:\n\tFile %s\n\tLine %d\n", __FILE__, __LINE__); return -1; } static int tbl_idx_delete(u16 *rcnt, u32 index, u32 tsize) { PCE_ASSERT(index >= tsize); if (rcnt[index] > 0) rcnt[index]--; return GSW_statusOk; } /* Packet Length Table write same for both 3.0 and 3.1*/ static int pce_tm_pkg_lng_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_pkt_length_t *parm) { int status; pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->pkg_lng_tbl, pthandle->pkg_lng_tbl_cnt, parm, sizeof(pce_pkt_length_t), PCE_PKG_LNG_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PACKET_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->pkg_lng; ptbl.mask[0] = parm->pkg_lng_rng; ptbl.valid = 1; status = gsw_pce_table_write(cdev, &ptbl); if (status == GSW_statusOk) return pcindex; else return status; } /* Packet Length Table delete */ static int pce_tm_pkg_lng_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { int status; pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_PKG_LNG_TBL_SIZE); if (pthandle->pkg_lng_tbl_cnt[index] > 0) pthandle->pkg_lng_tbl_cnt[index]--; if (pthandle->pkg_lng_tbl_cnt[index] == 0) { memset((((char *)pthandle->pkg_lng_tbl) + (index * sizeof(pce_pkt_length_t))), 0, sizeof(pce_pkt_length_t)); /* initialize the data structure before using it */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PACKET_INDEX; ptbl.pcindex = index; status = gsw_pce_table_write(cdev, &ptbl); if (status == GSW_statusErr) return status; } return GSW_statusOk; } /* Packet Length Table read */ static int pce_tm_pkg_lng_tbl_read(pcetbl_prog_t *pthandle, int index, pce_pkt_length_t *parm) { PCE_ASSERT(index >= PCE_PKG_LNG_TBL_SIZE); memcpy(parm, &pthandle->pkg_lng_tbl[index], sizeof(pce_pkt_length_t)); return GSW_statusOk; } /* MAC DA Table index write */ static int pce_da_mac_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_da_prog_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->da_mac_tbl, pthandle->da_mac_tbl_cnt, parm, sizeof(pce_da_prog_t), PCE_DASA_MAC_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACDA_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = (parm->mac[4] << 8 | parm->mac[5]); ptbl.key[1] = (parm->mac[2] << 8 | parm->mac[3]); ptbl.key[2] = (parm->mac[0] << 8 | parm->mac[1]); ptbl.mask[0] = parm->mac_mask; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* MAC SA Table index write */ static int pce_sa_mac_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_sa_prog_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->sa_mac_tbl, pthandle->sa_mac_tbl_cnt, parm, sizeof(pce_sa_prog_t), PCE_DASA_MAC_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACSA_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = (parm->mac[4] << 8 | parm->mac[5]); ptbl.key[1] = (parm->mac[2] << 8 | parm->mac[3]); ptbl.key[2] = (parm->mac[0] << 8 | parm->mac[1]); ptbl.mask[0] = parm->mac_mask; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* MAC SA Table delete */ static int pce_tm_sa_mac_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_DASA_MAC_TBL_SIZE); if (pthandle->sa_mac_tbl_cnt[index] > 0) pthandle->sa_mac_tbl_cnt[index]--; if (pthandle->sa_mac_tbl_cnt[index] == 0) { memset((((char *)pthandle->sa_mac_tbl) + (index * sizeof(pce_sa_prog_t))), 0, sizeof(pce_sa_prog_t)); /* initialize the data structure before using it */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACSA_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* MAC DA Table delete */ static int pce_tm_da_mac_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_DASA_MAC_TBL_SIZE); if (pthandle->da_mac_tbl_cnt[index] > 0) pthandle->da_mac_tbl_cnt[index]--; if (pthandle->da_mac_tbl_cnt[index] == 0) { memset((((char *)pthandle->da_mac_tbl) + (index * sizeof(pce_da_prog_t))), 0, sizeof(pce_sa_prog_t)); /* initialize the data structure before using it */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_MACDA_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* MAC DA Table Read */ static int pce_tm_da_mac_tbl_read(pcetbl_prog_t *pthandle, int index, pce_da_prog_t *parm) { PCE_ASSERT(index >= PCE_DASA_MAC_TBL_SIZE); memcpy(parm, &pthandle->da_mac_tbl[index], sizeof(pce_da_prog_t)); return GSW_statusOk; } /* MAC SA Table Read */ static int pce_tm_sa_mac_tbl_read(pcetbl_prog_t *pthandle, int index, pce_sa_prog_t *parm) { PCE_ASSERT(index >= PCE_DASA_MAC_TBL_SIZE); memcpy(parm, &pthandle->sa_mac_tbl[index], sizeof(pce_sa_prog_t)); return GSW_statusOk; } /* Application Table write */ static int pce_appl_tbl_write(void *cdev, pcetbl_prog_t *pthandle, app_tbl_t *parm) { ethsw_api_dev_t *gswdev = GSW_PDATA_GET(cdev); pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->appl_tbl, pthandle->appl_tbl_cnt, parm, sizeof(app_tbl_t), PCE_APPL_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_APPLICATION_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->appl_data; if (VRSN_CMP(gswdev->gipver, LTQ_GSWIP_3_0) >= 0 && parm->mask_range_type == 0) { u32 i, j; for (i = 1, j = 0x0F; i <= 8; i <<= 1, j <<= 4) if (parm->mask_range & i) ptbl.mask[0] |= j; } else { ptbl.mask[0] = parm->mask_range; } ptbl.type = parm->mask_range_type & 1; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* Flags Table write */ static int pce_flags_tbl_write(void *cdev, pcetbl_prog_t *pthandle, flag_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex, i; u8 mask_section, key_section, bit_pos; u16 column[4] = { 0 }; u16 key_val = parm->parser_flag_data; u16 bit_mask = parm->mask_value; pcindex = tbl_write(pthandle->flags_tbl, pthandle->flags_tbl_cnt, parm, sizeof(flag_tbl_t), PCE_FLAGS_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PARSER_FLAGS_INDEX; ptbl.pcindex = pcindex; for (i = 0; i < 4; i++) { mask_section = ((bit_mask >> (i * 4)) & 0xF); key_section = ((key_val >> (i * 4)) & 0xF); bit_pos = key_section; column[i] = (1 << bit_pos); if ((mask_section & 0x1) == 1) { bit_pos = key_section & 0xe; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x1); column[i] |= (1 << bit_pos); } if (((mask_section >> 1) & 0x1) == 1) { bit_pos = key_section & 0xd; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x2); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0x3) == 0x3) { bit_pos = key_section & 0xc; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x3); column[i] |= (1 << bit_pos); } if (((mask_section >> 2) & 0x1) == 0x1) { bit_pos = key_section & 0xb; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x4); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0x5) == 0x5) { bit_pos = key_section & 0xa; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x5); column[i] |= (1 << bit_pos); } if (((mask_section >> 1) & 0x3) == 0x3) { bit_pos = key_section & 0x9; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x6); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0x7) == 0x7) { bit_pos = key_section & 0x8; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x7); column[i] |= (1 << bit_pos); } if (((mask_section >> 3) & 0x1) == 0x1) { bit_pos = key_section & 0x7; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x8); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0x9) == 0x9) { bit_pos = key_section & 0x6; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0x9); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0xa) == 0xa) { bit_pos = key_section & 0x5; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xa); column[i] |= (1 << bit_pos); } if (((mask_section >> 2) & 0x3) == 0x3) { bit_pos = key_section & 0x3; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xc); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0xb) == 0xb) { bit_pos = key_section & 0x4; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xb); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0xd) == 0xd) { bit_pos = key_section & 0x2; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xd); column[i] |= (1 << bit_pos); } if (((mask_section >> 1) & 0x7) == 0x7) { bit_pos = key_section & 0x1; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xe); column[i] |= (1 << bit_pos); } if (((mask_section >> 0) & 0xf) == 0xf) { bit_pos = key_section & 0x0; column[i] |= (1 << bit_pos); bit_pos = (key_section | 0xf); column[i] |= (1 << bit_pos); } } for (i = 0; i < 4; i++) ptbl.key[i] = column[i]; ptbl.valid = 1; ptbl.kformat = 1; gsw_pce_table_write(cdev, &ptbl); gsw_w32(cdev, PCE_TBL_CTRL_KEYFORM_OFFSET, PCE_TBL_CTRL_KEYFORM_SHIFT, PCE_TBL_CTRL_KEYFORM_SIZE, 0); return pcindex; } /* Payload Table write */ static int pce_payload_tbl_write(void *cdev, pcetbl_prog_t *pthandle, payload_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->payload_tbl, pthandle->payload_tbl_cnt, parm, sizeof(payload_tbl_t), PCE_PAYLOAD_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PAYLOAD_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->payload_data; ptbl.mask[0] = parm->mask_range; ptbl.type = parm->mask_range_type; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* Application Table Delete */ static int pce_tm_appl_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_APPL_TBL_SIZE); if (pthandle->appl_tbl_cnt[index] > 0) pthandle->appl_tbl_cnt[index]--; if (pthandle->appl_tbl_cnt[index] == 0) { memset((((char *)pthandle->appl_tbl) + (index * sizeof(app_tbl_t))), 0, sizeof(app_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_APPLICATION_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* Flags Table Delete */ static int pce_tm_flags_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_FLAGS_TBL_SIZE); if (pthandle->flags_tbl_cnt[index] > 0) pthandle->flags_tbl_cnt[index]--; if (pthandle->flags_tbl_cnt[index] == 0) { memset((((char *)pthandle->flags_tbl) + (index * sizeof(flag_tbl_t))), 0, sizeof(flag_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PARSER_FLAGS_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* Payload Table Delete */ static int pce_tm_payload_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_PAYLOAD_TBL_SIZE); if (pthandle->payload_tbl_cnt[index] > 0) pthandle->payload_tbl_cnt[index]--; if (pthandle->payload_tbl_cnt[index] == 0) { memset((((char *)pthandle->payload_tbl) + (index * sizeof(payload_tbl_t))), 0, sizeof(payload_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PAYLOAD_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* Application Table Read */ static int pce_tm_appl_tbl_read(pcetbl_prog_t *pthandle, int index, app_tbl_t *parm) { PCE_ASSERT(index >= PCE_APPL_TBL_SIZE); memcpy(parm, &pthandle->appl_tbl[index], sizeof(app_tbl_t)); return GSW_statusOk; } /* Flags Table Read */ static int pce_tm_flags_tbl_read(pcetbl_prog_t *pthandle, int index, flag_tbl_t *parm) { PCE_ASSERT(index >= PCE_FLAGS_TBL_SIZE); memcpy(parm, &pthandle->flags_tbl[index], sizeof(flag_tbl_t)); return GSW_statusOk; } /* Payload Table Read */ static int pce_tm_payload_tbl_read(pcetbl_prog_t *pthandle, int index, payload_tbl_t *parm) { PCE_ASSERT(index >= PCE_PAYLOAD_TBL_SIZE); memcpy(parm, &pthandle->payload_tbl[index], sizeof(payload_tbl_t)); return GSW_statusOk; } /* IP DA/SA msb Table write */ int pce_dasa_msb_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_dasa_msb_t *parm) { pctbl_prog_t ptbl; int pcindex, i; pcindex = tbl_write(pthandle->ip_dasa_msb_tbl, pthandle->ipmsbtcnt, parm, sizeof(pce_dasa_msb_t), IP_DASA_PC_MSIZE); if (pcindex < 0) return pcindex; memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_IP_DASA_MSB_INDEX; ptbl.pcindex = pcindex; for (i = 0; i < 4; i++) ptbl.key[i] = ((parm->imsb[((i * 2) + 1)] << 8) | parm->imsb[(i * 2)]); ptbl.mask[0] = parm->mask[0]; ptbl.mask[1] = parm->mask[1]; ptbl.mask[2] = parm->mask[2]; ptbl.mask[3] = parm->mask[3]; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* IP DA/SA msb Table delete */ int ip_dasa_msb_tbl_del(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= IP_DASA_PC_MSIZE); if (pthandle->ipmsbtcnt[index] > 0) pthandle->ipmsbtcnt[index]--; if (pthandle->ipmsbtcnt[index] == 0) { memset((((char *)pthandle->ip_dasa_msb_tbl) + (index * sizeof(pce_dasa_msb_t))), 0, sizeof(pce_dasa_msb_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_IP_DASA_MSB_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* IP DA/SA msb Table read */ static int pce_dasa_msb_tbl_read(pcetbl_prog_t *pthandle, int index, pce_dasa_msb_t *parm) { PCE_ASSERT(index >= IP_DASA_PC_MSIZE); memcpy(parm, &pthandle->ip_dasa_msb_tbl[index], sizeof(pce_dasa_msb_t)); return GSW_statusOk; } static int get_tbl_index(void *tstart, void *parm, u32 tsize, u32 tnum) { int i; /* search if the entry is already available and can be re-used */ for (i = 0; i < tnum; i++) { /* entry is used, check if the entry content fits */ if (memcmp(((char *)tstart) + i * tsize, parm, (u8)tsize) == 0) return i; } return 0xFF; } /* Static Function Declaration */ int find_dasa_tbl_entry(pcetbl_prog_t *pthandle, pce_dasa_lsb_t *parm) { return get_tbl_index(pthandle->ip_dasa_lsb_tbl, parm, sizeof(pce_dasa_lsb_t), IP_DASA_PC_LSIZE); } /* Static Function Declaration */ int find_msb_tbl_entry(pcetbl_prog_t *pthandle, pce_dasa_msb_t *parm) { return get_tbl_index(pthandle->ip_dasa_msb_tbl, parm, sizeof(pce_dasa_msb_t), IP_DASA_PC_MSIZE); } /* IP DA/SA lsb Table Write */ int pce_dasa_lsb_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_dasa_lsb_t *parm) { pctbl_prog_t ptbl; int pcindex, i; pcindex = tbl_write(pthandle->ip_dasa_lsb_tbl, pthandle->iplsbtcnt, parm, sizeof(pce_dasa_lsb_t), IP_DASA_PC_LSIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_IP_DASA_LSB_INDEX; ptbl.pcindex = pcindex; for (i = 0; i < 4; i++) ptbl.key[i] = ((parm->ilsb[((i * 2) + 1)] << 8) | parm->ilsb[(i * 2)]); ptbl.mask[0] = parm->mask[0]; ptbl.mask[1] = parm->mask[1]; ptbl.mask[2] = parm->mask[2]; ptbl.mask[3] = parm->mask[3]; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* IP DA/SA lsb Table delete */ int ip_dasa_lsb_tbl_del(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= IP_DASA_PC_LSIZE); if (pthandle->iplsbtcnt[index] > 0) pthandle->iplsbtcnt[index]--; if (pthandle->iplsbtcnt[index] == 0) { memset((((char *)pthandle->ip_dasa_lsb_tbl) + (index * sizeof(pce_dasa_lsb_t))), 0, sizeof(pce_dasa_lsb_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_IP_DASA_LSB_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* IP DA/SA lsb Table index delete */ int ipdslsb_tblidx_del(pcetbl_prog_t *pthandle, u32 index) { return tbl_idx_delete(pthandle->iplsbtcnt, index, IP_DASA_PC_LSIZE); } /* IP DA/SA msb Table index delete */ int ipdsmsb_tblidx_del(pcetbl_prog_t *pthandle, u32 index) { return tbl_idx_delete(pthandle->ipmsbtcnt, index, IP_DASA_PC_MSIZE); } /* IP DA/SA lsb Table read */ int pce_dasa_lsb_tbl_read(pcetbl_prog_t *pthandle, int index, pce_dasa_lsb_t *parm) { PCE_ASSERT(index >= IP_DASA_PC_LSIZE); memcpy(parm, &pthandle->ip_dasa_lsb_tbl[index], sizeof(pce_dasa_lsb_t)); return GSW_statusOk; } /* Protocal Table write */ static int pce_ptcl_tbl_write(void *cdev, pcetbl_prog_t *pthandle, prtcol_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->ptcl_tbl, pthandle->ptcl_tbl_cnt, parm, sizeof(prtcol_tbl_t), PCE_PTCL_TBL_SIZE); PCE_ASSERT(pcindex < 0); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PROTOCOL_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->ethertype; ptbl.mask[0] = parm->emask; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* Get the vlan flow table index*/ int gavlan_tbl_index(pcetbl_prog_t *pthandle, u8 index) { PCE_ASSERT(index >= PCE_VLAN_ACT_TBL_SIZE); if (pthandle->vlan_act_tbl_cnt[index] == 0) return GSW_statusOk; else return -1; } /* Protocal Table delete */ static int pce_tm_ptcl_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_PTCL_TBL_SIZE); if (pthandle->ptcl_tbl_cnt[index] > 0) pthandle->ptcl_tbl_cnt[index]--; if (pthandle->ptcl_tbl_cnt[index] == 0) { memset((((char *)pthandle->ptcl_tbl) + (index * sizeof(prtcol_tbl_t))), 0, sizeof(prtcol_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PROTOCOL_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* Protocal Table Read */ static int pce_tm_ptcl_tbl_read(pcetbl_prog_t *pthandle, int index, prtcol_tbl_t *parm) { PCE_ASSERT(index >= PCE_PTCL_TBL_SIZE); memcpy(parm, &pthandle->ptcl_tbl[index], sizeof(prtcol_tbl_t)); return GSW_statusOk; } /* PPPoE Table Write */ static int pce_tm_pppoe_tbl_write(void *cdev, pcetbl_prog_t *pthandle, pce_ppoe_tbl_t *parm) { pctbl_prog_t ptbl; int pcindex; pcindex = tbl_write(pthandle->pppoe_tbl, pthandle->pppoe_tbl_cnt, parm, sizeof(pce_ppoe_tbl_t), PCE_PPPOE_TBL_SIZE); if (pcindex < 0) return pcindex; /* initialize the data structure before using it */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PPPOE_INDEX; ptbl.pcindex = pcindex; ptbl.key[0] = parm->sess_id; ptbl.valid = 1; gsw_pce_table_write(cdev, &ptbl); return pcindex; } /* PPPoE Table Delete */ static int pce_tm_pppoe_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { pctbl_prog_t ptbl; PCE_ASSERT(index >= PCE_PPPOE_TBL_SIZE); if (pthandle->pppoe_tbl_cnt[index] > 0) pthandle->pppoe_tbl_cnt[index]--; if (pthandle->pppoe_tbl_cnt[index] == 0) { memset((((char *)pthandle->pppoe_tbl) + (index * sizeof(pce_ppoe_tbl_t))), 0, sizeof(pce_ppoe_tbl_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_PPPOE_INDEX; ptbl.pcindex = index; gsw_pce_table_write(cdev, &ptbl); } return GSW_statusOk; } /* PPPoE Table Read */ static int pce_tm_pppoe_tbl_read(pcetbl_prog_t *pthandle, int index, pce_ppoe_tbl_t *parm) { PCE_ASSERT(index >= PCE_PPPOE_TBL_SIZE); memcpy(parm, &pthandle->pppoe_tbl[index], sizeof(pce_ppoe_tbl_t)); return GSW_statusOk; } /* VLAN Table Delete */ static int pce_tm_vlan_act_tbl_delete(void *cdev, pcetbl_prog_t *pthandle, u32 index) { PCE_ASSERT(index >= PCE_VLAN_ACT_TBL_SIZE); if (pthandle->vlan_act_tbl_cnt[index] > 0) pthandle->vlan_act_tbl_cnt[index]--; return GSW_statusOk; } static u32 act_vlan_id_create(void *cdev, u16 vid, int range_flag, u16 range_val) { pctbl_prog_t ptbl; u32 index, vid_index = 0x7F; for (index = 0; index < PCE_VLAN_ACT_TBL_SIZE; index++) { memset(&ptbl, 0, sizeof(pctbl_prog_t)); ptbl.table = PCE_ACTVLAN_INDEX; ptbl.pcindex = index; gsw_pce_table_read(cdev, &ptbl); if (ptbl.valid == 0) { ptbl.pcindex = index; vid_index = index; ptbl.table = PCE_ACTVLAN_INDEX; ptbl.key[0] = vid; if (range_flag) ptbl.mask[0] = range_val; else ptbl.mask[0] = 0; ptbl.valid = 1; ptbl.type = range_flag; gsw_pce_table_write(cdev, &ptbl); break; } } return vid_index; } static int pce_vid_index(void *cdev, pcetbl_prog_t *pthandle, u16 vid) { pctbl_prog_t pcetable_vlan; int index, vid_index = 0x7F; for (index = 0; index < PCE_VLAN_ACT_TBL_SIZE; index++) { memset(&pcetable_vlan, 0, sizeof(pctbl_prog_t)); pcetable_vlan.table = PCE_ACTVLAN_INDEX; pcetable_vlan.pcindex = index; gsw_pce_table_read(cdev, &pcetable_vlan); if (pcetable_vlan.valid == 1) { if (pcetable_vlan.key[0] == vid) { vid_index = index; pthandle->vlan_act_tbl_cnt[index]++; break; } } } return vid_index; } static int pce_vlan_id_fid_index(void *cdev, pcetbl_prog_t *pthandle, avlan_tbl_t *vatable) { pctbl_prog_t pcetable_vlan; int index, vid_index = 0x7F; for (index = 0; index < PCE_VLAN_ACT_TBL_SIZE; index++) { memset(&pcetable_vlan, 0, sizeof(pctbl_prog_t)); pcetable_vlan.table = PCE_ACTVLAN_INDEX; pcetable_vlan.pcindex = index; gsw_pce_table_read(cdev, &pcetable_vlan); if (pcetable_vlan.valid == 1) { if (pcetable_vlan.key[0] == vatable->vid) { vid_index = index; vatable->fid = (pcetable_vlan.val[0] & 0xFF); pthandle->vlan_act_tbl_cnt[index]++; break; } } } return vid_index; } static int pce_oam_write(void *cdev, ltq_pce_table_t *pthandle, GSW_PCE_rule_t *parm) { u32 idx = parm->pattern.nIndex; pce_table_t *ptable = &(pthandle->pce_tbl[idx]); u32 recid = 0; u32 type = 0; u32 i, j, k; u64 timecomp; if (parm->action.eTimestampAction != GSW_PCE_ACTION_TIMESTAMP_STORED) { if (!parm->action.bOamEnable) return 0; if (parm->action.bPceBypassPath) type |= BIT(15); if (parm->action.bTxFlowCnt) type |= BIT(8); if (!parm->action.bNoPktUpdate) { if (parm->action.bAppendToPkt) type |= 1; else type |= parm->action.nPktUpdateOffset & 0xFF; } j = PCE_OAM_LOSS_SIZE; for (i = 0; i < PCE_OAM_LOSS_SIZE; i++) { u32 val = 0; if (!pthandle->pce_sub_tbl.oam_loss_cnt[i]) { if (j == PCE_OAM_LOSS_SIZE) j = i; continue; } gsw_r32_raw(cdev, FDMA_LOSSOAM_TYPEn(i), &val); if (type == val) { j = i; break; } } if (j >= PCE_OAM_LOSS_SIZE) { /* no entry found */ pr_err("%s: no free FDMA_LOSSOAM_TYPE register\n", __FUNCTION__); return -1; } ptable->oam_loss_idx = j; pthandle->pce_sub_tbl.oam_loss_cnt[j]++; if (j != i) gsw_w32_raw(cdev, FDMA_LOSSOAM_TYPEn(j), type); recid = parm->action.nInsExtPoint & 3; recid |= j << 2; recid |= (parm->action.nOamFlowId & 0x3F) << 6; parm->action.nRecordId = recid; return 0; } if (!parm->action.bOamEnable) { recid = parm->action.nInsExtPoint & 3; recid |= (parm->action.nPtpSeqId & 0x3F) << 4; parm->action.nRecordId = recid; return 0; } if (parm->action.nTimeComp >= 0) { i = 0; k = PCE_OAM_COMP_SIZE / 2; timecomp = (u64)parm->action.nTimeComp; } else { i = PCE_OAM_COMP_SIZE / 2; k = PCE_OAM_COMP_SIZE; timecomp = (u64)(-parm->action.nTimeComp); } if (timecomp > 0xFFFFFFFF) { pr_err("%s: action.nTimeComp is out of range (-4,294,967,295 ~ 4,294,967,295)\n", __FUNCTION__); return -1; } j = PCE_OAM_COMP_SIZE; for (; i < k; i++) { u32 msb = 0, lsb = 0; if (!pthandle->pce_sub_tbl.oam_comp_cnt[k]) { if (j == PCE_OAM_COMP_SIZE) j = i; continue; } gsw_r32_raw(cdev, FDMA_DELAYOAM_COMP_MSB(i), &msb); gsw_r32_raw(cdev, FDMA_DELAYOAM_COMP_LSB(i), &lsb); if (timecomp == ((msb << 16) | lsb)) { j = i; break; } } if (j >= PCE_OAM_COMP_SIZE) { /* no entry found */ pr_err("%s: no free FDMA_DELAYOAM_ADD/SUB registers\n", __FUNCTION__); return -1; } ptable->oam_comp_idx = j; pthandle->pce_sub_tbl.oam_comp_cnt[j]++; if (j != i) { gsw_w32_raw(cdev, FDMA_DELAYOAM_COMP_MSB(j), timecomp >> 16); gsw_w32_raw(cdev, FDMA_DELAYOAM_COMP_LSB(j), timecomp & 0xFFFF); } type = j << 8; if (parm->action.bPceBypassPath) type |= BIT(15); if (!parm->action.bNoPktUpdate) { if (parm->action.bAppendToPkt) type |= 1; else type |= parm->action.nPktUpdateOffset & 0xFF; } j = PCE_OAM_DELAY_SIZE; for (i = 0; i < PCE_OAM_DELAY_SIZE; i++) { u32 val = 0; if (!pthandle->pce_sub_tbl.oam_delay_cnt[i]) { if (j == PCE_OAM_DELAY_SIZE) j = i; continue; } gsw_r32_raw(cdev, FDMA_DELAYOAM_TYPEn(i), &val); if (type == val) { j = i; break; } } if (j >= PCE_OAM_DELAY_SIZE) { /* no entry found */ pr_err("%s: no free FDMA_DELAYOAM_TYPE register\n", __FUNCTION__); return -1; } ptable->oam_delay_idx = j; pthandle->pce_sub_tbl.oam_delay_cnt[j]++; if (j != i) gsw_w32_raw(cdev, FDMA_DELAYOAM_TYPEn(j), type); recid = parm->action.nInsExtPoint & 3; recid |= j << 2; recid |= ((u32)parm->action.eTimeFormat & 3) << 6; recid |= 0x0F00; parm->action.nRecordId = recid; return 0; } static void pce_oam_read(void *cdev, GSW_PCE_rule_t *parm) { u32 recid = parm->action.nRecordId; u32 type = 0; if (parm->action.eTimestampAction != GSW_PCE_ACTION_TIMESTAMP_STORED) { if (!parm->action.bOamEnable) return; parm->action.nInsExtPoint = recid & 3; parm->action.nOamFlowId = (recid >> 6) & 0x3F; gsw_r32_raw(cdev, FDMA_LOSSOAM_TYPEn((recid >> 2) & 0x0F), &type); parm->action.bPceBypassPath = (type & BIT(15)) ? LTQ_TRUE : LTQ_FALSE; parm->action.bTxFlowCnt = (type & BIT(8)) ? LTQ_TRUE : LTQ_FALSE; parm->action.nPktUpdateOffset = type & 0xFF; switch (parm->action.nPktUpdateOffset) { case 0: parm->action.bNoPktUpdate = LTQ_TRUE; break; case 1: parm->action.bAppendToPkt = LTQ_TRUE; parm->action.nPktUpdateOffset = 0; break; } return; } if (parm->action.bOamEnable) { u32 comp; u32 lsb = 0, msb = 0; parm->action.nInsExtPoint = recid & 3; parm->action.eTimeFormat = (recid >> 6) & 3; gsw_r32_raw(cdev, FDMA_DELAYOAM_TYPEn((recid >> 2) & 0x0F), &type); parm->action.bPceBypassPath = (type & BIT(15)) ? LTQ_TRUE : LTQ_FALSE; comp = (type >> 8) & 3; gsw_r32_raw(cdev, FDMA_DELAYOAM_COMP_MSB(comp), &msb); gsw_r32_raw(cdev, FDMA_DELAYOAM_COMP_LSB(comp), &lsb); parm->action.nTimeComp = (msb << 16) | lsb; if (comp >= PCE_OAM_COMP_SIZE / 2) parm->action.nTimeComp = -parm->action.nTimeComp; parm->action.nPktUpdateOffset = type & 0xFF; switch (parm->action.nPktUpdateOffset) { case 0: parm->action.bNoPktUpdate = LTQ_TRUE; break; case 1: parm->action.bAppendToPkt = LTQ_TRUE; parm->action.nPktUpdateOffset = 0; break; } } else { parm->action.nInsExtPoint = recid & 3; parm->action.nPtpSeqId = (recid >> 4) & 0x3F; } } static int pce_oam_loss_del(void *cdev, pcetbl_prog_t *pthandle, u32 index) { PCE_ASSERT(index >= PCE_OAM_LOSS_SIZE); if (pthandle->oam_loss_cnt[index] > 0) pthandle->oam_loss_cnt[index]--; return GSW_statusOk; } static int pce_oam_delay_del(void *cdev, pcetbl_prog_t *pthandle, u32 index) { PCE_ASSERT(index >= PCE_OAM_DELAY_SIZE); if (pthandle->oam_delay_cnt[index] > 0) pthandle->oam_delay_cnt[index]--; return GSW_statusOk; } static int pce_oam_comp_del(void *cdev, pcetbl_prog_t *pthandle, u32 index) { PCE_ASSERT(index >= PCE_OAM_COMP_SIZE); if (pthandle->oam_comp_cnt[index] > 0) pthandle->oam_comp_cnt[index]--; return GSW_statusOk; } /* PCE Table Init routine */ int pce_table_init(ltq_pce_table_t *ptable) { int i; PCE_ASSERT(ptable == NULL); memset(&ptable->pce_sub_tbl, 0, sizeof(pcetbl_prog_t)); memset(&ptable->pce_tbl, 0, sizeof(pce_table_t)); memset(&ptable->pce_act, 0, sizeof(GSW_PCE_action_t)); for (i = 0; i < PCE_TABLE_SIZE; i++) ptable->ptblused[i] = 0; return GSW_statusOk; } int gsw_pmicro_code_init_f24s(void *cdev) { u16 i, j; pctbl_prog_t tbl_entry; ethsw_api_dev_t *gswdev = GSW_PDATA_GET(cdev); if (gswdev == NULL) { pr_err("%s:%s:%d", __FILE__, __func__, __LINE__); return GSW_statusErr; } /* Disable all physical port */ for (j = 0; j < gswdev->pnum; j++) { printk("gswdev->pnum =%d j= %d\n", gswdev->pnum, j); gsw_w32(cdev, (SDMA_PCTRL_PEN_OFFSET + (j * 0x6)), SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, 0); } gsw_w32(cdev, PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, PCE_GCTRL_0_MC_VALID_SIZE, 0x0); /* Download the microcode */ for (i = 0; i < 64 /* PCE_MICRO_TABLE_SIZE */; 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.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; gsw_pce_table_write(cdev, &tbl_entry); } gsw_w32(cdev, PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, PCE_GCTRL_0_MC_VALID_SIZE, 0x1); for (j = 0; j < gswdev->pnum; j++) { gsw_w32(cdev, (SDMA_PCTRL_PEN_OFFSET + (j * 0x6)), SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, 1); } /* Enable RMON Counter for all ports */ for (j = 0; j < gswdev->pnum; j++) { gsw_w32(cdev, (BM_PCFG_CNTEN_OFFSET + (j * 0x2)), BM_PCFG_CNTEN_SHIFT, BM_PCFG_CNTEN_SIZE, 1); } gsw_w32(cdev, BM_QUEUE_GCTRL_GL_MOD_OFFSET, BM_QUEUE_GCTRL_GL_MOD_SHIFT, BM_QUEUE_GCTRL_GL_MOD_SIZE, 0); #if 0 printk("PARSER CODE DUMP\n\n"); for (i = 0; i < 64 /* PCE_MICRO_TABLE_SIZE */; i++) { memset(&tbl_entry, 0, sizeof(tbl_entry)); tbl_entry.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; 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; gsw_pce_table_read(cdev, &tbl_entry); printk("0x%04x , 0x%04x , 0x%04x , 0x%04x\n", tbl_entry.val[0], tbl_entry.val[1], tbl_entry.val[2], tbl_entry.val[3]); } printk("\n\nPARSER CODE DUMP Complete\n\n"); #endif return 0; } int gsw_global_pcerule_bitmap_alloc(void *cdev) { ethsw_api_dev_t *gswdev = GSW_PDATA_GET(cdev); if (!cdev || !gswdev) return GSW_statusErr; gswdev->Global_Rule_BitMap.global_rule_map_size = BITS_TO_LONGS(gswdev->num_of_global_rules) * sizeof(unsigned long) * BITS_PER_BYTE; gswdev->Global_Rule_BitMap.global_rule_idx_map = kzalloc(BITS_TO_LONGS(gswdev->num_of_global_rules) * sizeof(unsigned long), GFP_KERNEL); if (!gswdev->Global_Rule_BitMap.global_rule_idx_map) return -ENOMEM; bitmap_set(gswdev->Global_Rule_BitMap.global_rule_idx_map, MPCE_RULES_INDEX, BPDU_PCE_RULE_INDEX + 1); return GSW_statusOk; } /* PCE Table Micro Code Init routine */ int gsw_pmicro_code_init(void *cdev) { ethsw_api_dev_t *gswdev = GSW_PDATA_GET(cdev); pctbl_prog_t tbl_entry; u16 i, j; u8 Gl_Mod_Size = 0; u32 no_ports = 0; if (gswdev == NULL) { pr_err("%s:%s:%d", __FILE__, __func__, __LINE__); return GSW_statusErr; } if (IS_VRSN_31(gswdev->gipver)) no_ports = gswdev->tpnum; else no_ports = gswdev->pnum; /* Disable all physical port */ for (j = 0; j < no_ports; j++) { if (gswdev->sdev == LTQ_FLOW_DEV_INT_R && j == 1) j = 15; gsw_w32(cdev, (FDMA_PCTRL_EN_OFFSET + (j * 0x6)), FDMA_PCTRL_EN_SHIFT, FDMA_PCTRL_EN_SIZE, 0); gsw_w32(cdev, (SDMA_PCTRL_PEN_OFFSET + (j * 0x6)), SDMA_PCTRL_PEN_SHIFT, SDMA_PCTRL_PEN_SIZE, 0); } /*Micro code set invalid*/ gsw_w32(cdev, PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, PCE_GCTRL_0_MC_VALID_SIZE, 0x0); if (gswdev->gipver == LTQ_GSWIP_3_0) { /*GSWIP 3.0*/ gsw_w32(cdev, (GSWT_GCTRL_SE_OFFSET + GSW30_TOP_OFFSET), GSWT_GCTRL_SE_SHIFT, GSWT_GCTRL_SE_SIZE, 1); /* Download the microcode */ for (i = 0; i < 256 /*PCE_MICRO_TABLE_SIZE*/; i++) { memset(&tbl_entry, 0, sizeof(pctbl_prog_t)); tbl_entry.val[3] = pce_mc_max_ifx_tag_m_30[i].val_3; tbl_entry.val[2] = pce_mc_max_ifx_tag_m_30[i].val_2; tbl_entry.val[1] = pce_mc_max_ifx_tag_m_30[i].val_1; tbl_entry.val[0] = pce_mc_max_ifx_tag_m_30[i].val_0; tbl_entry.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; gsw_pce_table_write(cdev, &tbl_entry); //pr_err("%d\t%x\t%x\t%x\t%x\n",i, tbl_entry.val[0], tbl_entry.val[1], tbl_entry.val[2], tbl_entry.val[3]); } } else if (IS_VRSN_31(gswdev->gipver)) { /* Download the microcode */ for (i = 0; i < 256 /*PCE_MICRO_TABLE_SIZE*/; i++) { memset(&tbl_entry, 0, sizeof(pctbl_prog_t)); tbl_entry.val[3] = pce_mc_max_ifx_tag_m_31[i].val_3; tbl_entry.val[2] = pce_mc_max_ifx_tag_m_31[i].val_2; tbl_entry.val[1] = pce_mc_max_ifx_tag_m_31[i].val_1; tbl_entry.val[0] = pce_mc_max_ifx_tag_m_31[i].val_0; tbl_entry.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; gsw_pce_table_write(cdev, &tbl_entry); //pr_err("%d\t%x\t%x\t%x\t%x\n",i, tbl_entry.val[0], tbl_entry.val[1], tbl_entry.val[2], tbl_entry.val[3]); } } else { /*GSWIP 2.2*/ gsw_w32(cdev, (GLOB_CTRL_SE_OFFSET + GSW_TREG_OFFSET), GLOB_CTRL_SE_SHIFT, GLOB_CTRL_SE_SIZE, 1); /* Download the microcode */ if (gswdev->prod_id == PRX300) { for (i = 0; i < 64 /* PCE_MICRO_TABLE_SIZE */; i++) { memset(&tbl_entry, 0, sizeof(tbl_entry)); tbl_entry.val[3] = pce_mc_max_ifx_tag_m_1[i].val_3; tbl_entry.val[2] = pce_mc_max_ifx_tag_m_1[i].val_2; tbl_entry.val[1] = pce_mc_max_ifx_tag_m_1[i].val_1; tbl_entry.val[0] = pce_mc_max_ifx_tag_m_1[i].val_0; tbl_entry.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; gsw_pce_table_write(cdev, &tbl_entry); } } if (gswdev->prod_id == GRX500) { for (i = 0; i < 64 /* PCE_MICRO_TABLE_SIZE */; 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.pcindex = i; tbl_entry.table = PCE_PARS_INDEX; gsw_pce_table_write(cdev, &tbl_entry); } } gsw_w32(cdev, PCE_PMAP_2_DMCPMAP_OFFSET, PCE_PMAP_2_DMCPMAP_SHIFT, PCE_PMAP_2_DMCPMAP_SIZE, 0x7F); gsw_w32(cdev, PCE_PMAP_3_UUCMAP_OFFSET, PCE_PMAP_3_UUCMAP_SHIFT, PCE_PMAP_3_UUCMAP_SIZE, 0x7F); } /*Micro code set valid*/ gsw_w32(cdev, PCE_GCTRL_0_MC_VALID_OFFSET, PCE_GCTRL_0_MC_VALID_SHIFT, PCE_GCTRL_0_MC_VALID_SIZE, 0x1); /* Enable RMON Counter for all ports */ if (gswdev->gipver == LTQ_GSWIP_3_0) { for (j = 0; j < gswdev->pnum; j++) { if (gswdev->sdev == LTQ_FLOW_DEV_INT_R && j == 1) j = 15; gsw_w32(cdev, (BM_PCFG_CNTEN_OFFSET + (j * 0x2)), BM_PCFG_CNTEN_SHIFT, BM_PCFG_CNTEN_SIZE, 1); } for (j = 0; j < gswdev->pnum; j++) { if (gswdev->sdev == LTQ_FLOW_DEV_INT_R && j == 1) j = 15; gsw_w32(cdev, (BM_RMON_CTRL_BCAST_CNT_OFFSET + (j * 0x2)), BM_RMON_CTRL_BCAST_CNT_SHIFT, BM_RMON_CTRL_BCAST_CNT_SIZE, 1); } } if ((gswdev->gipver == LTQ_GSWIP_2_2) || (gswdev->gipver == LTQ_GSWIP_2_2_ETC) || (gswdev->gipver == LTQ_GSWIP_3_0) || (IS_VRSN_31(gswdev->gipver))) Gl_Mod_Size = BM_QUEUE_GCTRL_GL_MOD_SIZE2; else Gl_Mod_Size = BM_QUEUE_GCTRL_GL_MOD_SIZE; gsw_w32(cdev, BM_QUEUE_GCTRL_GL_MOD_OFFSET, BM_QUEUE_GCTRL_GL_MOD_SHIFT, Gl_Mod_Size, 0); return GSW_statusOk; } int pce_action_delete(void *cdev, ltq_pce_table_t *pthandle, u32 index) { pctbl_prog_t ptbl; ethsw_api_dev_t *gswdev = GSW_PDATA_GET(cdev); if (gswdev == NULL) { pr_err("%s:%s:%d", __FILE__, __func__, __LINE__); return GSW_statusErr; } PCE_ASSERT(index >= (gswdev->tftblsize)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); memset(&pthandle->pce_act[index], 0, sizeof(GSW_PCE_action_t)); /* Remove rule action from HW */ ptbl.pcindex = index; /* Traffic-Flow table type */ ptbl.table = PCE_TFLOW_INDEX; //pr_err("\n Before pce table read in %s 0x%x", __func__, cdev); gsw_pce_table_read(cdev, &ptbl); if (ptbl.valid == 1) { if (((ptbl.val[0] >> 1) & 0x1) && (gswdev->gipver == LTQ_GSWIP_3_0)) { u32 index = (ptbl.val[2] & 0x3F); pr_debug("\n VLAN action delete at % index in %s", index, __func__); if (pthandle->pce_sub_tbl.vlan_act_tbl_cnt[index] > 0) pthandle->pce_sub_tbl.vlan_act_tbl_cnt[index]--; } } memset(&ptbl, 0, sizeof(pctbl_prog_t)); /* Remove rule action from HW */ ptbl.pcindex = index; /* Traffic-Flow table type */ ptbl.table = PCE_TFLOW_INDEX; ptbl.valid = 0; //Mark entry as invalid. //pr_err("\n Before pce table write in %s 0x%x", __func__, cdev); gsw_pce_table_write(cdev, &ptbl); return GSW_statusOk; } #define IFX_PCE_TM_IDX_DELETE(x, y, z) \ { \ if (x != y) \ if (0 != z(cdev, &pthandle->pce_sub_tbl, y)) \ GSW_RETURN_PCE; \ } int pce_pattern_delete(void *cdev, ltq_pce_table_t *pthandle, u32 index) { pce_table_t *ptable; ethsw_api_dev_t *gswdev = GSW_PDATA_GET(cdev); if (gswdev == NULL) { pr_err("%s:%s:%d", __FILE__, __func__, __LINE__); return GSW_statusErr; } PCE_ASSERT(index >= (gswdev->tftblsize)); /* Check if an entry is currently programmed and remove it. */ if (pthandle->ptblused[index] == 0) return GSW_statusOk; ptable = &(pthandle->pce_tbl[index]); /* Packet length */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->pkt_lng_idx, pce_tm_pkg_lng_tbl_delete) /* Destination MAC address */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->dst_mac_addr_idx, pce_tm_da_mac_tbl_delete) /* Source MAC address */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->src_mac_addr_idx, pce_tm_sa_mac_tbl_delete) /* Destination Application field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->dst_appl_fld_idx, pce_tm_appl_tbl_delete) /* Source Application field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->src_appl_fld_idx, pce_tm_appl_tbl_delete) /* Parer flags field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->parse_lsb_idx, pce_tm_flags_tbl_delete) /* Parer flags field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->parse_msb_idx, pce_tm_flags_tbl_delete) /* Parer flags field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->parse1_lsb_idx, pce_tm_flags_tbl_delete) /* Parer flags field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->parse1_msb_idx, pce_tm_flags_tbl_delete) if (IS_VRSN_30_31(gswdev->gipver)) { /* Payload1 field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->payload1_idx, pce_tm_payload_tbl_delete) /* payload2 field */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->payload2_idx, pce_tm_payload_tbl_delete) } /* DIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->dip_msb_idx, ip_dasa_msb_tbl_del) /* Inner DIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_dip_msb_idx, ip_dasa_msb_tbl_del) /* DIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->dip_lsb_idx, ip_dasa_lsb_tbl_del) /* Inner DIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_dip_lsb_idx, ip_dasa_lsb_tbl_del) /* SIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->sip_msb_idx, ip_dasa_msb_tbl_del) /* Inner SIP MSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_sip_msb_idx, ip_dasa_msb_tbl_del) /* SIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->sip_lsb_idx, ip_dasa_lsb_tbl_del) /* Inner SIP LSB */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->inr_sip_lsb_idx, ip_dasa_lsb_tbl_del) /* IP protocol */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->ip_prot_idx, pce_tm_ptcl_tbl_delete) /* Ethertype */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->ethertype_idx, pce_tm_ptcl_tbl_delete) if (IS_VRSN_30_31(gswdev->gipver)) { /* PPP Protocol */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->ppp_prot_idx, pce_tm_ptcl_tbl_delete) } /* PPPoE */ IFX_PCE_TM_IDX_DELETE(0xFF, ptable->pppoe_idx, pce_tm_pppoe_tbl_delete) if (gswdev->gipver == LTQ_GSWIP_3_0) { /* VLAN */ IFX_PCE_TM_IDX_DELETE(0x7F, ptable->vlan_idx, pce_tm_vlan_act_tbl_delete) /* SVLAN */ IFX_PCE_TM_IDX_DELETE(0x7F, ptable->svlan_idx, pce_tm_vlan_act_tbl_delete) } if (VRSN_CMP(gswdev->gipver, LTQ_GSWIP_3_1) >= 0) { IFX_PCE_TM_IDX_DELETE(0xFF, ptable->oam_loss_idx, pce_oam_loss_del); IFX_PCE_TM_IDX_DELETE(0xFF, ptable->oam_delay_idx, pce_oam_delay_del); IFX_PCE_TM_IDX_DELETE(0xFF, ptable->oam_comp_idx, pce_oam_comp_del); } /* Mark this TFLOW entry as unused */ pthandle->ptblused[index] = 0; /* Mark all tables in TFLOW to invalid */ memset(ptable, 0xFF, sizeof(pce_table_t)); /* Delete the action for this rule */ pce_action_delete(cdev, pthandle, index); //Delete the associated counters if any. return GSW_statusOk; } int pce_rule_read(void *cdev, ltq_pce_table_t *pthandle, GSW_PCE_rule_t *parm) { ethsw_api_dev_t *gswdev = GSW_PDATA_GET(cdev); u32 i, j, idx = parm->pattern.nIndex; pce_table_t *ptable; static pctbl_prog_t ptbl; PCE_ASSERT(idx >= (gswdev->tftblsize)); /* Initialize to zero */ memset(parm, 0, sizeof(GSW_PCE_rule_t)); memset(&ptbl, 0, sizeof(pctbl_prog_t)); parm->pattern.nIndex = idx; //Table entry to read if (pthandle->ptblused[idx] == 0) return GSW_statusOk; //Return if entry is not in use else parm->pattern.bEnable = 1; ptbl.table = PCE_TFLOW_INDEX; //TFLOW table type to read ptbl.pcindex = idx; //Table entry to read gsw_pce_table_read(cdev, &ptbl); //Read given entry /* Exclude flags */ if (IS_VRSN_30_31(gswdev->gipver)) { if ((ptbl.key[15] >> 0) & 0x1) parm->pattern.bDstMAC_Exclude = 1; if ((ptbl.key[15] >> 1) & 0x1) parm->pattern.bCTAG_PCP_DEI_Exclude = 1; if ((ptbl.key[15] >> 2) & 0x1) parm->pattern.bSTAG_PCP_DEI_Exclude = 1; if ((ptbl.key[15] >> 3) & 0x1) parm->pattern.bDSCP_Exclude = 1; if ((ptbl.key[15] >> 4) & 0x1) parm->pattern.bPktLng_Exclude = 1; if ((ptbl.key[15] >> 5) & 0x1) parm->pattern.bSessionId_Exclude = 1; if ((ptbl.key[15] >> 6) & 0x1) parm->pattern.bSLANVid_Exclude = 1; if ((ptbl.key[15] >> 7) & 0x1) parm->pattern.bPPP_Protocol_Exclude = 1; if ((ptbl.key[15] >> 8) & 0x1) parm->pattern.bInnerDSCP_Exclude = 1; if ((ptbl.key[15] >> 9) & 0x1) parm->pattern.bInnerSrcIP_Exclude = 1; if ((ptbl.key[15] >> 10) & 0x1) parm->pattern.bInnerDstIP_Exclude = 1; if ((ptbl.key[15] >> 11) & 0x1) parm->pattern.bParserFlagLSB_Exclude = 1; if ((ptbl.key[15] >> 12) & 0x1) parm->pattern.bParserFlagMSB_Exclude = 1; if ((ptbl.key[15] >> 13) & 0x1) parm->pattern.bPayload1_Exclude = 1; if ((ptbl.key[15] >> 14) & 0x1) parm->pattern.bPayload2_Exclude = 1; if ((ptbl.key[15] >> 15) & 0x1) parm->pattern.bSubIfId_Exclude = 1; if (IS_VRSN_31(gswdev->gipver)) { if ((ptbl.key[14] >> 5) & 0x1) parm->pattern.bParserFlag1LSB_Exclude = 1; if ((ptbl.key[14] >> 6) & 0x1) parm->pattern.bParserFlag1MSB_Exclude = 1; } if ((ptbl.key[14] >> 7) & 0x1) parm->pattern.bPortId_Exclude = 1; if ((ptbl.key[14] >> 8) & 0x1) parm->pattern.bVid_Exclude = 1; if ((ptbl.key[14] >> 9) & 0x1) parm->pattern.bEtherType_Exclude = 1; if ((ptbl.key[14] >> 10) & 0x1) parm->pattern.bProtocol_Exclude = 1; if ((ptbl.key[14] >> 11) & 0x1) parm->pattern.bSrcIP_Exclude = 1; if ((ptbl.key[14] >> 12) & 0x1) parm->pattern.bDstIP_Exclude = 1; if ((ptbl.key[14] >> 13) & 0x1) parm->pattern.bAppMSB_Exclude = 1; if ((ptbl.key[14] >> 14) & 0x1) parm->pattern.bAppLSB_Exclude = 1; if ((ptbl.key[14] >> 15) & 0x1) parm->pattern.bSrcMAC_Exclude = 1; /*Sub -Interface id 3.0*/ if (gswdev->gipver == LTQ_GSWIP_3_0) { if ((ptbl.key[14] & 0x1F) != 0x1F) { //Is pattern enabled? parm->pattern.nSubIfId = ptbl.key[14] & 0xF; parm->pattern.bSubIfIdEnable = 1; } } /*Sub -Interface id 3.1*/ if (IS_VRSN_31(gswdev->gipver)) { if ((ptbl.key[17] & 0x1FF) != 0x1FF) { //Is pattern enabled? parm->pattern.nSubIfId = ptbl.key[17] & 0xFF; parm->pattern.bSubIfIdEnable = 1; if ((ptbl.key[17] >> 9) & 0x1) parm->pattern.eSubIfIdType = GSW_PCE_SUBIFID_TYPE_BRIDGEPORT; else parm->pattern.eSubIfIdType = GSW_PCE_SUBIFID_TYPE_GROUP; } /* CPU injected traffic flag */ if (((ptbl.key[17] >> 10) & 0x3) != 3) { parm->pattern.bInsertionFlag_Enable = 1; parm->pattern.nInsertionFlag = ((ptbl.key[17] >> 10) & 0x3); } } } /* Port ID field value */ if (gswdev->gipver >= LTQ_GSWIP_3_0) { if ((ptbl.key[0] & 0x1F) != 0x1F) { //Is pattern enabled? parm->pattern.nPortId = ptbl.key[0] & 0xF; parm->pattern.bPortIdEnable = 1; } } else if (gswdev->gipver <= LTQ_GSWIP_2_2_ETC) { if ((ptbl.key[0] & 0xF) != 0xF) { //Is pattern enabled? parm->pattern.nPortId = ptbl.key[0] & 0x7; parm->pattern.bPortIdEnable = 1; } } /* Outer DSCP field value */ if (((ptbl.key[6] >> 8) & 0x7F) != 0x7F) { //Is pattern enabled? parm->pattern.nDSCP = (ptbl.key[6] >> 8) & 0x3F; parm->pattern.bDSCP_Enable = 1; } /* Applicable for 3.0 or less*/ if (gswdev->gipver <= LTQ_GSWIP_3_0) { if (ptbl.val[0] & 0x1) { //If port-map action set. if (ptbl.val[1] == 0x0) { //If port-map IDs not set. if (((ptbl.val[4] >> 2) & 0x3) == 0x3) { //If port-map type is 'tflow'. parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_DISCARD; } else if (((ptbl.val[4] >> 2) & 0x3) == 0x0) { //If port-map type is 'default'. parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_REGULAR; } } else if (ptbl.val[1] != 0x0) { //If port-map IDs set. parm->action.nForwardPortMap[0] = ptbl.val[1]; if (((ptbl.val[4] >> 2) & 0x3) == 0x3) { //If port-map type is 'tflow'. parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_ALTERNATIVE; } else if ((((ptbl.val[4] >> 2) & 0x3) == 0x1)) { //If port-map type is 'MC router'. parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_CPU; } } } } if (IS_VRSN_30_31(gswdev->gipver)) { /* Inner DSCP field value */ if (((ptbl.key[9] >> 8) & 0x7F) != 0x7F) { //Is pattern enabled? parm->pattern.nInnerDSCP = (ptbl.key[9] >> 8) & 0x3F; parm->pattern.bInner_DSCP_Enable = 1; } /* Port filer type action value */ parm->action.ePortFilterType_Action = (ptbl.val[7] >> 1) & 0x3F; if (parm->action.ePortFilterType_Action == 4) parm->action.ePortFilterType_Action = GSW_PCE_PORT_FILTER_ACTION_3; else if (parm->action.ePortFilterType_Action == 8) parm->action.ePortFilterType_Action = GSW_PCE_PORT_FILTER_ACTION_4; else if (parm->action.ePortFilterType_Action == 16) parm->action.ePortFilterType_Action = GSW_PCE_PORT_FILTER_ACTION_5; else if (parm->action.ePortFilterType_Action == 32) parm->action.ePortFilterType_Action = GSW_PCE_PORT_FILTER_ACTION_6; //GEt the port-member map. if (parm->action.ePortFilterType_Action) { for (i = 0; i <= 7; i++) parm->action.nForwardPortMap[i] = ptbl.val[i + 10]; } /* Processing path type action value */ if (ptbl.val[8] & 0x1) parm->action.eProcessPath_Action = (ptbl.val[8] >> 1) & 0x3; } /* L3 Routing type action value */ if (gswdev->gipver == LTQ_GSWIP_3_0) { if (gswdev->sdev == LTQ_FLOW_DEV_INT_R) { parm->action.bRtCtrlEna_Action = ptbl.val[9] & 0x1; parm->action.bRtAccelEna_Action = (ptbl.val[9] >> 1) & 0x1; parm->action.bRtInnerIPasKey_Action = (ptbl.val[9] >> 2) & 0x1; if ((ptbl.val[9] >> 3) & 0x1) parm->action.bRtSrcIpMaskCmp_Action = 0; else parm->action.bRtSrcIpMaskCmp_Action = 1; if ((ptbl.val[9] >> 4) & 0x1) parm->action.bRtDstIpMaskCmp_Action = 0; else parm->action.bRtDstIpMaskCmp_Action = 1; if ((ptbl.val[9] >> 5) & 0x1) parm->action.bRtSrcPortMaskCmp_Action = 0; else parm->action.bRtSrcPortMaskCmp_Action = 1; if ((ptbl.val[9] >> 6) & 0x1) parm->action.bRtDstPortMaskCmp_Action = 0; else parm->action.bRtDstPortMaskCmp_Action = 1; if (((ptbl.val[9] >> 8) & 0xFF) != 0xFF) { parm->action.bRoutExtId_Action = 1; parm->action.nRoutExtId = (ptbl.val[9] >> 8) & 0xFF; } } /* Flow ID action value */ if ((ptbl.val[4] >> 4) & 0x1) { parm->action.bFlowID_Action = 1; parm->action.nFlowID = ptbl.val[1]; } } /* Trunk port, port link selection action value */ parm->action.bPortLinkSelection = (ptbl.val[5] >> 1) & 0x1; parm->action.bPortTrunkAction = (ptbl.val[5] >> 0) & 0x1; /* Cross VLAN action value */ if ((ptbl.val[0] >> 4) & 0x1) { if ((ptbl.val[3] >> 15) & 0x1) parm->action.eVLAN_CrossAction = GSW_PCE_ACTION_CROSS_VLAN_CROSS; else parm->action.eVLAN_CrossAction = GSW_PCE_ACTION_CROSS_VLAN_REGULAR; } /* Applicable for 3.0*/ if (gswdev->gipver == LTQ_GSWIP_3_0) { parm->action.bPortBitMapMuxControl = (ptbl.val[6] >> 0) & 0x1; if (parm->action.bPortBitMapMuxControl) parm->action.nForwardPortMap[0] = ptbl.val[1]; if (((ptbl.val[5] >> 2) & 0x1) && ((ptbl.val[0] >> 1) & 0x1)) parm->action.bCVLAN_Ignore_Control = 1; if ((ptbl.val[0] >> 1) & 0x1) { parm->action.eSVLAN_Action = 1; parm->action.nSVLAN_Id = (ptbl.val[6] >> 4) & 0xFFF; //parm->action.nFId = ((ptbl.val[2] >> 8) & 0xFF); } if ((ptbl.val[0] >> 1) & 0x1) { //Govind - 3.0 same flag for both eVLAN_Action n eSVLAN_Action? parm->action.eVLAN_Action = 1; parm->action.nVLAN_Id = (ptbl.val[5] >> 4) & 0xFFF; parm->action.nFId = ((ptbl.val[2] >> 8) & 0xFF); } } //Extended VLAN tagging action. if (IS_VRSN_31(gswdev->gipver)) { if ((ptbl.val[6] >> 3) & 0x1) { parm->action.bExtendedVlanEnable = 1; //Enable extended VLAN tagging. parm->action.nExtendedVlanBlockId = (ptbl.val[6] >> 4) & 0x3FF; } } /* Applicable for 3.0*/ if (IS_VRSN_NOT_31(gswdev->gipver)) { if ((ptbl.val[0] >> 12) & 0x1) { parm->action.bRMON_Action = 1; parm->action.nRMON_Id = (((ptbl.val[4] >> 8) & 0x1F) - 1); } if ((ptbl.val[0] >> 11) & 0x1) { switch ((ptbl.val[3] >> 6) & 0x3) { case 0: parm->action.eMeterAction = GSW_PCE_ACTION_METER_REGULAR; break; case 1: parm->action.eMeterAction = GSW_PCE_ACTION_METER_1; break; case 3: parm->action.eMeterAction = GSW_PCE_ACTION_METER_1_2; break; default: /* Action Disable, default it was set */ break; } parm->action.nMeterId = ptbl.val[3] & 0x3F; } if (!((ptbl.val[3] >> 13) & 0x1)) parm->action.bRemarkClass = 1; if (!((ptbl.val[3] >> 12) & 0x1)) parm->action.bRemarkDSCP = 1; if (!((ptbl.val[6] >> 2) & 0x1)) parm->action.bRemarkSTAG_DEI = 1; if (!((ptbl.val[6] >> 1) & 0x1)) parm->action.bRemarkSTAG_PCP = 1; if (!((ptbl.val[3] >> 14) & 0x1)) parm->action.bRemarkPCP = 1; if ((ptbl.val[0] >> 3) & 0x1) parm->action.bRemarkAction = 1; if ((ptbl.val[0] >> 6) & 0x1) { if ((ptbl.val[4] >> 14) & 0x1) parm->action.eCritFrameAction = GSW_PCE_ACTION_CRITICAL_FRAME_CRITICAL; else parm->action.eCritFrameAction = GSW_PCE_ACTION_CRITICAL_FRAME_REGULAR; } } /* RMON counter action value */ if (IS_VRSN_31(gswdev->gipver)) { if ((ptbl.val[4] >> 4) & 0x1) { parm->action.bRMON_Action = parm->action.bFlowID_Action = 1; parm->action.nRMON_Id = parm->action.nFlowID = ptbl.val[1] & 0xFF; } /* Metering and counter action value */ if ((ptbl.val[0] >> 11) & 0x1) { if ((ptbl.val[3] >> 7) & 0x1) { parm->action.eMeterAction = GSW_PCE_ACTION_METER_1; parm->action.nMeterId = ptbl.val[3] & 0x7F; } else { parm->action.eMeterAction = GSW_PCE_ACTION_METER_DISABLE; } } /* FID action control */ if ((ptbl.val[0] & BIT(1)) && (ptbl.val[5] & BIT(3))) { parm->action.bFidEnable = 1; parm->action.nFId = (ptbl.val[2] >> 8) & 0x3F; } } /* Applicable for 3.1*/ if (IS_VRSN_31(gswdev->gipver)) { if (ptbl.val[0] & 0x1) { //If port-map action set. if (!(ptbl.val[10]) && !(ptbl.val[11]) && !(ptbl.val[12]) && !(ptbl.val[13]) && !(ptbl.val[14]) && !(ptbl.val[15]) && !(ptbl.val[16]) && !(ptbl.val[17])) { //If port-map IDs not set. if (((ptbl.val[4] >> 2) & 0x3) == 0x3) { //If port-map type is 'tflow'. parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_DISCARD; } else if (((ptbl.val[4] >> 2) & 0x3) == 0x0) { //If port-map type is 'default'. parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_REGULAR; } } else if (((ptbl.val[10]) || (ptbl.val[11]) || (ptbl.val[12])) || ((ptbl.val[13]) || (ptbl.val[14]) || (ptbl.val[15])) || ((ptbl.val[16]) || (ptbl.val[17]))) { /* It is 'traffic-flow' portmap type */ for (i = 0; i <= 7; i++) parm->action.nForwardPortMap[i] = ptbl.val[i + 10]; if ((ptbl.val[10 + gswdev->cport / 16] >> 0) == 0x1) { parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_CPU; } else if (((ptbl.val[4] >> 2) & 0x3) == 0x3) { //If port-map type is 'tflow'. parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_ALTERNATIVE; } else if (((ptbl.val[4] >> 2) & 0x3) == 0x1) { //If port-map type is 'MC router'. parm->action.ePortMapAction = GSW_PCE_ACTION_PORTMAP_MULTICAST_ROUTER; } } } } /* Color action */ if (IS_VRSN_31(gswdev->gipver)) { if ((ptbl.val[0] >> 6) & 0x1) { if ((ptbl.val[2] & 0x7) < 4) { parm->action.eColorFrameAction = GSW_PCE_ACTION_COLOR_FRAME_NO_CHANGE; } else { parm->action.eColorFrameAction = (ptbl.val[2] & 0x7) - 2; } } } if (IS_VRSN_30_31(gswdev->gipver)) { /* TS action control */ if ((ptbl.val[0] >> 7) & 0x1) { if ((ptbl.val[4] >> 15) & 0x1) { parm->action.eTimestampAction = GSW_PCE_ACTION_TIMESTAMP_STORED; parm->action.nRecordId = ((ptbl.val[8] >> 4) & 0xFFF); } else parm->action.eTimestampAction = GSW_PCE_ACTION_TIMESTAMP_REGULAR; } else parm->action.eTimestampAction = GSW_PCE_ACTION_TIMESTAMP_DISABLE; /* Interrupt Request Queue action control */ if ((ptbl.val[0] >> 8) & 0x1) { if ((ptbl.val[0] >> 15) & 0x1) parm->action.eIrqAction = GSW_PCE_ACTION_IRQ_EVENT; else parm->action.eIrqAction = GSW_PCE_ACTION_IRQ_REGULAR; } else parm->action.eIrqAction = GSW_PCE_ACTION_IRQ_DISABLE; } /* Cross state action control */ if ((ptbl.val[0] >> 5) & 0x1) { if ((ptbl.val[4] >> 13) & 0x1) parm->action.eCrossStateAction = GSW_PCE_ACTION_CROSS_STATE_CROSS; else parm->action.eCrossStateAction = GSW_PCE_ACTION_CROSS_STATE_REGULAR; } else parm->action.eCrossStateAction = GSW_PCE_ACTION_CROSS_STATE_DISABLE; /* MAC learning action control */ if ((ptbl.val[0] >> 9) & 0x1) { if (((ptbl.val[4]) & 0x3) == 0) parm->action.eLearningAction = GSW_PCE_ACTION_LEARNING_REGULAR; else if (((ptbl.val[4]) & 0x3) == 1) parm->action.eLearningAction = GSW_PCE_ACTION_LEARNING_DISABLE; else parm->action.eLearningAction = (ptbl.val[4]) & 0x3; } /* IGMP snooping action control */ if ((ptbl.val[0] >> 10) & 0x1) parm->action.eSnoopingTypeAction = ((ptbl.val[4] >> 5) & 0x7) + 1; /* Traffic class action control */ if ((ptbl.val[0] >> 2) & 1) { if ((ptbl.val[0] >> 14) & 1) { parm->action.eTrafficClassAction = GSW_PCE_ACTION_TRAFFIC_CLASS_ALTERNATIVE; parm->action.nTrafficClassAlternate = (ptbl.val[3] >> 8) & 0xF; } else parm->action.eTrafficClassAction = GSW_PCE_ACTION_TRAFFIC_CLASS_REGULAR; } /* Inner CoS & DEI field value for 3.0 */ if (IS_VRSN_NOT_31(gswdev->gipver)) { if (((ptbl.key[6]) & 0xF) != 0xF) { parm->pattern.nPCP = (ptbl.key[6]) & 0x7; parm->pattern.bPCP_Enable = 1; } } /* Inner CoS & DEI field value for 3.1 */ if (IS_VRSN_31(gswdev->gipver)) { if (((ptbl.key[6]) & 0x1F) != 0x1F) { //Is pattern enabled? parm->pattern.nPCP = (ptbl.key[6]) & 0xF; parm->pattern.bPCP_Enable = 1; } } /* Outer CoS & DEI field value */ if (((ptbl.key[8]) & 0x1F) != 0x1F) { //Is pattern enabled? parm->pattern.nSTAG_PCP_DEI = (ptbl.key[8]) & 0xF; parm->pattern.bSTAG_PCP_DEI_Enable = 1; } /* Packet length field table */ ptable = &(pthandle->pce_tbl[idx]); if (ptable->pkt_lng_idx != 0xFF) { //Is table enabled? pce_pkt_length_t pkg_lng_tbl; memset(&pkg_lng_tbl, 0, sizeof(pce_pkt_length_t)); /* Packet length used */ parm->pattern.bPktLngEnable = 1; if (0 != pce_tm_pkg_lng_tbl_read(&pthandle->pce_sub_tbl, ptable->pkt_lng_idx, &pkg_lng_tbl)) GSW_RETURN_PCE; /* Packet length */ parm->pattern.nPktLng = pkg_lng_tbl.pkg_lng; /* Packet length Range */ parm->pattern.nPktLngRange = pkg_lng_tbl.pkg_lng_rng; } /* DMAC field table */ if (ptable->dst_mac_addr_idx != 0xFF) { //Is table enabled? pce_da_prog_t da_mac_tbl; memset(&da_mac_tbl, 0, sizeof(pce_da_prog_t)); if (0 != pce_tm_da_mac_tbl_read(&pthandle->pce_sub_tbl, ptable->dst_mac_addr_idx, &da_mac_tbl)) GSW_RETURN_PCE; /* Destination MAC address used */ parm->pattern.bMAC_DstEnable = 1; /* Destination MAC address */ for (i = 0; i < 6; i++) parm->pattern.nMAC_Dst[i] = da_mac_tbl.mac[i]; /* Destination MAC address mask */ parm->pattern.nMAC_DstMask = da_mac_tbl.mac_mask; } /* SMAC field table */ if (ptable->src_mac_addr_idx != 0xFF) { //Is table enabled? pce_sa_prog_t sa_mac_tbl; memset(&sa_mac_tbl, 0, sizeof(pce_sa_prog_t)); if (0 != pce_tm_sa_mac_tbl_read(&pthandle->pce_sub_tbl, ptable->src_mac_addr_idx, &sa_mac_tbl)) GSW_RETURN_PCE; /* Destination MAC address used */ parm->pattern.bMAC_SrcEnable = 1; /* Destination MAC address */ for (i = 0; i < 6; i++) parm->pattern.nMAC_Src[i] = sa_mac_tbl.mac[i]; /* Destination MAC address mask */ parm->pattern.nMAC_SrcMask = sa_mac_tbl.mac_mask; } /* Application field table */ if (ptable->dst_appl_fld_idx != 0xFF) { //Is table enabled? app_tbl_t appl_tbl; memset(&appl_tbl, 0, sizeof(app_tbl_t)); if (0 != pce_tm_appl_tbl_read(&pthandle->pce_sub_tbl, ptable->dst_appl_fld_idx, &appl_tbl)) GSW_RETURN_PCE; /* Destination Application used */ parm->pattern.bAppDataMSB_Enable = 1; /* Destination Application field */ parm->pattern.nAppDataMSB = appl_tbl.appl_data; /* Destination Application mask/range used */ parm->pattern.bAppMaskRangeMSB_Select = appl_tbl.mask_range_type; /* Destination Application mask/range */ parm->pattern.nAppMaskRangeMSB = appl_tbl.mask_range; } /* Application field table */ if (ptable->src_appl_fld_idx != 0xFF) { //Is table enabled? app_tbl_t appl_tbl; memset(&appl_tbl, 0, sizeof(app_tbl_t)); if (0 != pce_tm_appl_tbl_read(&pthandle->pce_sub_tbl, ptable->src_appl_fld_idx, &appl_tbl)) GSW_RETURN_PCE; /* Source Application used */ parm->pattern.bAppDataLSB_Enable = 1; /* Source Application field */ parm->pattern.nAppDataLSB = appl_tbl.appl_data; /* Destination Application mask/range used */ parm->pattern.bAppMaskRangeLSB_Select = appl_tbl.mask_range_type; /* Source Application mask/range */ parm->pattern.nAppMaskRangeLSB = appl_tbl.mask_range; } /* Parser flags field table */ if (IS_VRSN_30_31(gswdev->gipver)) { if (ptable->parse_lsb_idx != 0xFF) { //Is table enabled? flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); if (0 != pce_tm_flags_tbl_read(&pthandle->pce_sub_tbl, ptable->parse_lsb_idx, &flags_tbl)) GSW_RETURN_PCE; parm->pattern.bParserFlagLSB_Enable = 1; parm->pattern.nParserFlagLSB = flags_tbl.parser_flag_data; parm->pattern.nParserFlagLSB_Mask = flags_tbl.mask_value; } if (ptable->parse_msb_idx != 0xFF) { //Is table enabled? flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); if (0 != pce_tm_flags_tbl_read(&pthandle->pce_sub_tbl, ptable->parse_msb_idx, &flags_tbl)) GSW_RETURN_PCE; parm->pattern.bParserFlagMSB_Enable = 1; parm->pattern.nParserFlagMSB = flags_tbl.parser_flag_data; parm->pattern.nParserFlagMSB_Mask = flags_tbl.mask_value; } /* Payload1 field table */ if (ptable->payload1_idx != 0xFF) { //Is table enabled? payload_tbl_t payload_tbl; memset(&payload_tbl, 0, sizeof(payload_tbl_t)); if (0 != pce_tm_payload_tbl_read(&pthandle->pce_sub_tbl, ptable->payload1_idx, &payload_tbl)) GSW_RETURN_PCE; /* Destination Application used */ parm->pattern.bPayload1_SrcEnable = 1; /* Destination Application field */ parm->pattern.nPayload1 = payload_tbl.payload_data; /* Payload mask/range used */ parm->pattern.bPayload1MaskRange_Select = payload_tbl.mask_range_type; /* Payload mask/range */ parm->pattern.nPayload1_Mask = payload_tbl.mask_range; } /* Payload2 field table */ if (ptable->payload2_idx != 0xFF) { //Is table enabled? payload_tbl_t payload_tbl; memset(&payload_tbl, 0, sizeof(payload_tbl_t)); if (0 != pce_tm_payload_tbl_read(&pthandle->pce_sub_tbl, ptable->payload2_idx, &payload_tbl)) GSW_RETURN_PCE; /* Destination Application used */ parm->pattern.bPayload2_SrcEnable = 1; /* Destination Application field */ parm->pattern.nPayload2 = payload_tbl.payload_data; /* Payload mask/range used */ parm->pattern.bPayload2MaskRange_Select = payload_tbl.mask_range_type; /* Payload mask/range */ parm->pattern.nPayload2_Mask = payload_tbl.mask_range; } /* Parser flags field table extend */ if (IS_VRSN_31(gswdev->gipver)) { if (ptable->parse1_lsb_idx != 0xFF) { //Is table enabled? flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); if (0 != pce_tm_flags_tbl_read(&pthandle->pce_sub_tbl, ptable->parse1_lsb_idx, &flags_tbl)) GSW_RETURN_PCE; parm->pattern.bParserFlag1LSB_Enable = 1; parm->pattern.nParserFlag1LSB = flags_tbl.parser_flag_data; parm->pattern.nParserFlag1LSB_Mask = flags_tbl.mask_value; } if (ptable->parse1_msb_idx != 0xFF) { //Is table enabled? flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); if (0 != pce_tm_flags_tbl_read(&pthandle->pce_sub_tbl, ptable->parse1_msb_idx, &flags_tbl)) GSW_RETURN_PCE; parm->pattern.bParserFlag1MSB_Enable = 1; parm->pattern.nParserFlag1MSB = flags_tbl.parser_flag_data; parm->pattern.nParserFlag1MSB_Mask = flags_tbl.mask_value; } } /* DIP field table */ if ((ptable->inr_dip_msb_idx != 0xFF) && (ptable->inr_dip_lsb_idx != 0xFF)) { //IPv6 pce_dasa_msb_t dasa_tbl; pce_dasa_lsb_t dasa_tbl_lsb; int i, j; memset(&dasa_tbl, 0, sizeof(pce_dasa_msb_t)); memset(&dasa_tbl_lsb, 0, sizeof(pce_dasa_lsb_t)); /* Inner DIP MS8B used */ parm->pattern.eInnerDstIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_msb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_dip_msb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Populate inner DIP MS8B */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nInnerDstIP.nIPv6[i] = (((dasa_tbl.imsb[j] & 0xFF) << 8) | (dasa_tbl.imsb[j - 1] & 0xFF)); /* Inner DIP MS8B nibble mask */ for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nInnerDstIP_Mask |= (1 << ((i * 4) + j + 16)); } } /* Inner DIP LS8B used */ parm->pattern.eInnerDstIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_dip_lsb_idx, &dasa_tbl_lsb)) GSW_RETURN_PCE; /* Populate inner DIP LS8B */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nInnerDstIP.nIPv6[i + 4] = (((dasa_tbl_lsb.ilsb[j] & 0xFF) << 8) | (dasa_tbl_lsb.ilsb[j - 1] & 0xFF)); /* Inner DIP LS8B nibble mask */ for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl_lsb.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nInnerDstIP_Mask |= (1 << ((i * 4) + j)); } } } else if (ptable->inr_dip_lsb_idx != 0xFF) { //IPv4 pce_dasa_lsb_t dasa_tbl; memset(&dasa_tbl, 0, sizeof(pce_dasa_lsb_t)); /*Inner DIP used */ parm->pattern.eInnerDstIP_Select = GSW_PCE_IP_V4; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_dip_lsb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Inner DIP used */ parm->pattern.nInnerDstIP.nIPv4 = (dasa_tbl.ilsb[0] | (dasa_tbl.ilsb[1] << 8) | (dasa_tbl.ilsb[2] << 16) | (dasa_tbl.ilsb[3] << 24)); /* Inner DIP nibble mask */ for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nInnerDstIP_Mask |= (1 << ((i * 4) + j)); } } parm->pattern.nInnerDstIP_Mask |= 0xFF00; } /* SIP field table */ if ((ptable->inr_sip_msb_idx != 0xFF) && (ptable->inr_sip_lsb_idx != 0xFF)) { //IPv6 pce_dasa_msb_t dasa_tbl; pce_dasa_lsb_t dasa_tbl_lsb; int i, j; memset(&dasa_tbl, 0, sizeof(pce_dasa_msb_t)); memset(&dasa_tbl_lsb, 0, sizeof(pce_dasa_lsb_t)); /* Inner SIP MS8B used */ parm->pattern.eInnerSrcIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_msb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_sip_msb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Populate inner SIP MS8B */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nInnerSrcIP.nIPv6[i] = (((dasa_tbl.imsb[j] & 0xFF) << 8) | (dasa_tbl.imsb[j - 1] & 0xFF)); /* Inner SIP MS8B nibble mask */ for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nInnerSrcIP_Mask |= (1 << ((i * 4) + j + 16)); } } /* Inner SIP LS8B used */ parm->pattern.eInnerSrcIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_sip_lsb_idx, &dasa_tbl_lsb)) GSW_RETURN_PCE; /* Populate inner SIP LS8B */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nInnerSrcIP.nIPv6[i + 4] = (((dasa_tbl_lsb.ilsb[j] & 0xFF) << 8) | (dasa_tbl_lsb.ilsb[j - 1] & 0xFF)); /* Inner DIP LS8B nibble mask */ for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl_lsb.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nInnerSrcIP_Mask |= (1 << ((i * 4) + j)); } } } else if (ptable->inr_sip_lsb_idx != 0xFF) { //IPv4 pce_dasa_lsb_t dasa_tbl; memset(&dasa_tbl, 0, sizeof(pce_dasa_lsb_t)); /* Inner SIP used */ parm->pattern.eInnerSrcIP_Select = GSW_PCE_IP_V4; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->inr_sip_lsb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Populate inner SIP */ parm->pattern.nInnerSrcIP.nIPv4 = (dasa_tbl.ilsb[0] | (dasa_tbl.ilsb[1] << 8) | (dasa_tbl.ilsb[2] << 16) | (dasa_tbl.ilsb[3] << 24)); /* Inner SIP nibble mask */ for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nInnerSrcIP_Mask |= (1 << ((i * 4) + j)); } } parm->pattern.nInnerSrcIP_Mask |= 0xFF00; } } /*LTQ_GSWIP_3_0*/ /* Outer DIP n SIP field table */ /* DIP field table */ if ((ptable->dip_msb_idx != 0xFF) && (ptable->dip_lsb_idx != 0xFF)) { //IPv6 pce_dasa_msb_t dasa_tbl; pce_dasa_lsb_t dasa_tbl_lsb; int i, j; memset(&dasa_tbl, 0, sizeof(pce_dasa_msb_t)); memset(&dasa_tbl_lsb, 0, sizeof(pce_dasa_lsb_t)); /* DIP MS8B used */ parm->pattern.eDstIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_msb_tbl_read(&pthandle->pce_sub_tbl, ptable->dip_msb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Populate DIP MS8B used */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nDstIP.nIPv6[i] = (((dasa_tbl.imsb[j] & 0xFF) << 8) | (dasa_tbl.imsb[j - 1] & 0xFF)); /* DIP MS8B nibble mask */ if ((gswdev->gipver == LTQ_GSWIP_3_0) || (IS_VRSN_31(gswdev->gipver))) { for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nDstIP_Mask |= (1 << ((i * 4) + j + 16)); } } } else if ((gswdev->gipver == LTQ_GSWIP_2_2) || (gswdev->gipver == LTQ_GSWIP_2_2_ETC)) parm->pattern.nDstIP_Mask = (u32)dasa_tbl.mask[0] << 16; /* DIP LS8B used */ parm->pattern.eDstIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->dip_lsb_idx, &dasa_tbl_lsb)) GSW_RETURN_PCE; /* Populate DIP LS8B used */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nDstIP.nIPv6[i + 4] = (((dasa_tbl_lsb.ilsb[j] & 0xFF) << 8) | (dasa_tbl_lsb.ilsb[j - 1] & 0xFF)); /* Inner DIP LS8B nibble mask */ if ((gswdev->gipver == LTQ_GSWIP_3_0) || (IS_VRSN_31(gswdev->gipver))) { for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl_lsb.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nDstIP_Mask |= (1 << ((i * 4) + j)); } } } else if ((gswdev->gipver == LTQ_GSWIP_2_2) || (gswdev->gipver == LTQ_GSWIP_2_2_ETC)) parm->pattern.nDstIP_Mask |= (u32)dasa_tbl_lsb.mask[0]; } else if (ptable->dip_lsb_idx != 0xFF) { //IPv4 pce_dasa_lsb_t dasa_tbl; memset(&dasa_tbl, 0, sizeof(pce_dasa_lsb_t)); /* DIP used */ parm->pattern.eDstIP_Select = GSW_PCE_IP_V4; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->dip_lsb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Populate DIP */ parm->pattern.nDstIP.nIPv4 = (dasa_tbl.ilsb[0] | (dasa_tbl.ilsb[1] << 8) | (dasa_tbl.ilsb[2] << 16) | (dasa_tbl.ilsb[3] << 24)); /* DIP nibble mask */ if ((gswdev->gipver == LTQ_GSWIP_3_0) || (IS_VRSN_31(gswdev->gipver))) { for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nDstIP_Mask |= (1 << ((i * 4) + j)); } } parm->pattern.nDstIP_Mask |= 0xFF00; } else if ((gswdev->gipver == LTQ_GSWIP_2_2) || (gswdev->gipver == LTQ_GSWIP_2_2_ETC)) parm->pattern.nDstIP_Mask = dasa_tbl.mask[0]; } /* SIP field table */ if ((ptable->sip_msb_idx != 0xFF) && (ptable->sip_lsb_idx != 0xFF)) { //IPv6 pce_dasa_msb_t dasa_tbl; pce_dasa_lsb_t dasa_tbl_lsb; int i, j; memset(&dasa_tbl, 0, sizeof(pce_dasa_msb_t)); memset(&dasa_tbl_lsb, 0, sizeof(pce_dasa_lsb_t)); /* SIP MS8B used */ parm->pattern.eSrcIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_msb_tbl_read(&pthandle->pce_sub_tbl, ptable->sip_msb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Populate SIP MS8B */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nSrcIP.nIPv6[i] = (((dasa_tbl.imsb[j] & 0xFF) << 8) | (dasa_tbl.imsb[j - 1] & 0xFF)); /* Inner DIP MS8B nibble mask */ if ((gswdev->gipver == LTQ_GSWIP_3_0) || (IS_VRSN_31(gswdev->gipver))) { for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nSrcIP_Mask |= (1 << ((i * 4) + j + 16)); } } } else if ((gswdev->gipver == LTQ_GSWIP_2_2) || (gswdev->gipver == LTQ_GSWIP_2_2_ETC)) parm->pattern.nSrcIP_Mask = dasa_tbl.mask[0] << 16; /* SIP LS8B used */ parm->pattern.eSrcIP_Select = GSW_PCE_IP_V6; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->sip_lsb_idx, &dasa_tbl_lsb)) GSW_RETURN_PCE; /* Populate SIP LS8B */ for (i = 0, j = 7; i < 4; i++, j -= 2) parm->pattern.nSrcIP.nIPv6[i + 4] = (((dasa_tbl_lsb.ilsb[j] & 0xFF) << 8) | (dasa_tbl_lsb.ilsb[j - 1] & 0xFF)); /* Inner DIP LS8B nibble mask */ if ((gswdev->gipver == LTQ_GSWIP_3_0) || (IS_VRSN_31(gswdev->gipver))) { for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl_lsb.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nSrcIP_Mask |= (1 << ((i * 4) + j)); } } } else if ((gswdev->gipver == LTQ_GSWIP_2_2) || (gswdev->gipver == LTQ_GSWIP_2_2_ETC)) parm->pattern.nSrcIP_Mask |= (u32)dasa_tbl_lsb.mask[0]; } else if (ptable->sip_lsb_idx != 0xFF) { //IPv4 pce_dasa_lsb_t dasa_tbl; memset(&dasa_tbl, 0, sizeof(pce_dasa_lsb_t)); /* SIP used */ parm->pattern.eSrcIP_Select = GSW_PCE_IP_V4; if (0 != pce_dasa_lsb_tbl_read(&pthandle->pce_sub_tbl, ptable->sip_lsb_idx, &dasa_tbl)) GSW_RETURN_PCE; /* Populate SIP used */ parm->pattern.nSrcIP.nIPv4 = (dasa_tbl.ilsb[0] | (dasa_tbl.ilsb[1] << 8) | (dasa_tbl.ilsb[2] << 16) | (dasa_tbl.ilsb[3] << 24)); /* SIP nibble mask */ if ((gswdev->gipver == LTQ_GSWIP_3_0) || (IS_VRSN_31(gswdev->gipver))) { for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { if (((dasa_tbl.mask[i] >> (j * 4)) & 0xF) == 0xF) parm->pattern.nSrcIP_Mask |= (1 << ((i * 4) + j)); } } parm->pattern.nSrcIP_Mask |= 0xFF00; } else if ((gswdev->gipver == LTQ_GSWIP_2_2) || (gswdev->gipver == LTQ_GSWIP_2_2_ETC)) parm->pattern.nSrcIP_Mask = dasa_tbl.mask[0]; } /* Protocol field table */ if (ptable->ethertype_idx != 0xFF) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); /* Ethertype used */ parm->pattern.bEtherTypeEnable = 1; if (0 != pce_tm_ptcl_tbl_read(&pthandle->pce_sub_tbl, ptable->ethertype_idx, &pctl_tbl)) GSW_RETURN_PCE; /* Ethertype */ parm->pattern.nEtherType = pctl_tbl.ethertype; /* Ethertype Mask */ parm->pattern.nEtherTypeMask = pctl_tbl.emask; } /* Protocol field table */ if (IS_VRSN_30_31(gswdev->gipver)) { if (ptable->ppp_prot_idx != 0xFF) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); /* Ethertype used */ parm->pattern.bPPP_ProtocolEnable = 1; if (0 != pce_tm_ptcl_tbl_read(&pthandle->pce_sub_tbl, ptable->ppp_prot_idx, &pctl_tbl)) GSW_RETURN_PCE; /* Ethertype */ parm->pattern.nPPP_Protocol = pctl_tbl.ethertype; /* Ethertype Mask */ parm->pattern.nPPP_ProtocolMask = pctl_tbl.emask; } } /* Protocol field table */ if (ptable->ip_prot_idx != 0xFF) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); /* IP protocol used */ if (0 != pce_tm_ptcl_tbl_read(&pthandle->pce_sub_tbl, ptable->ip_prot_idx, &pctl_tbl)) GSW_RETURN_PCE; if ((pctl_tbl.ethertype & 0xFF) == 0xFF) parm->pattern.bProtocolEnable = 0; else parm->pattern.bProtocolEnable = 1; if (((pctl_tbl.ethertype >> 8) & 0xFF) == 0xFF) parm->pattern.bInnerProtocolEnable = 0; else parm->pattern.bInnerProtocolEnable = 1; /* IP protocol */ parm->pattern.nProtocol = pctl_tbl.ethertype & 0xFF; /* IP protocol Mask */ parm->pattern.nProtocolMask = pctl_tbl.emask & 0x3; /* IP protocol */ parm->pattern.nInnerProtocol = (pctl_tbl.ethertype >> 8) & 0xFF; /* IP protocol Mask */ parm->pattern.nInnerProtocolMask = (pctl_tbl.emask >> 2) & 0x3; } /* PPPoE sessio ID field table */ if (ptable->pppoe_idx != 0xFF) { pce_ppoe_tbl_t pppoe_tbl; memset(&pppoe_tbl, 0, sizeof(pce_ppoe_tbl_t)); /* PPPoE used */ parm->pattern.bSessionIdEnable = 1; if (0 != pce_tm_pppoe_tbl_read(&pthandle->pce_sub_tbl, ptable->pppoe_idx, &pppoe_tbl)) GSW_RETURN_PCE; /* PPPoE */ parm->pattern.nSessionId = pppoe_tbl.sess_id; } /* VLAN-ID field table */ if (IS_VRSN_NOT_31(gswdev->gipver)) { /* Inner VLAN-ID field table */ if (ptable->vlan_idx != 0x7F) { pctbl_prog_t pcetable_vlan; memset(&pcetable_vlan, 0, sizeof(pctbl_prog_t)); /* VLAN used */ parm->pattern.bVid = 1; pcetable_vlan.table = PCE_ACTVLAN_INDEX; /*index of the VLAN ID configuration */ pcetable_vlan.pcindex = ptable->vlan_idx; /* ptbl.key[0] = parm->nVId; */ gsw_pce_table_read(cdev, &pcetable_vlan); if (pcetable_vlan.valid == 1) parm->pattern.nVid = pcetable_vlan.key[0] & 0xFFF; } /* Outer VLAN-ID field table */ if (ptable->svlan_idx != 0x7F) { pctbl_prog_t pcetable_vlan; memset(&pcetable_vlan, 0, sizeof(pctbl_prog_t)); /* VLAN used */ parm->pattern.bSLAN_Vid = 1; pcetable_vlan.table = PCE_ACTVLAN_INDEX; /*index of the VLAN ID configuration */ pcetable_vlan.pcindex = ptable->svlan_idx; /* ptbl.key[0] = parm->nVId; */ gsw_pce_table_read(cdev, &pcetable_vlan); if (pcetable_vlan.valid == 1) parm->pattern.nSLAN_Vid = pcetable_vlan.key[0] & 0xFFF; } } /* VLAN-ID field table */ if (IS_VRSN_31(gswdev->gipver)) { /*Inner vlan -CTAG VLAN index*/ if ((ptbl.key[20] & 0x1FFF) != 0x1FFF) { parm->pattern.bVid = LTQ_TRUE; parm->pattern.nVid = ptbl.key[20] & 0xFFF; parm->pattern.bVid_Original = ~(ptbl.key[20] >> 15) & 1; if ((ptbl.key[21] & 0xFFF) != 0) { parm->pattern.bVidRange_Select = 1; parm->pattern.nVidRange = ptbl.key[21] & 0xFFF; } } /*Outer vlan -STAG VLAN index*/ if ((ptbl.key[18] & 0x1FFF) != 0x1FFF) { parm->pattern.bSLAN_Vid = LTQ_TRUE; parm->pattern.nSLAN_Vid = ptbl.key[18] & 0xFFF; parm->pattern.bOuterVid_Original = ~(ptbl.key[18] >> 15) & 1; if ((ptbl.key[19] & 0xFFF) != 0) { parm->pattern.bSVidRange_Select = 1; parm->pattern.nOuterVidRange = ptbl.key[19] & 0xFFF; } } } if (IS_VRSN_30_31(gswdev->gipver)) { /* OAM and Extraction flags field table */ if (((ptbl.val[8] >> 3) & 0x1) || ((ptbl.val[7] >> 8) & 0x1)) { /*OAM flag*/ if ((ptbl.val[8] >> 3) & 0x1) { parm->action.bOamEnable = 1; /*OAM and extraction packet control*/ parm->action.nRecordId = ((ptbl.val[8] >> 4) & 0xFFF); } /*Extraction flag*/ if ((ptbl.val[7] >> 8) & 0x1) { parm->action.bExtractEnable = 1; } } } if (VRSN_CMP(gswdev->gipver, LTQ_GSWIP_3_1) >= 0) pce_oam_read(cdev, parm); return GSW_statusOk; } int pce_rule_write(void *cdev, ltq_pce_table_t *pthandle, GSW_PCE_rule_t *parm) { ethsw_api_dev_t *gswdev = GSW_PDATA_GET(cdev); static pctbl_prog_t ptbl; u32 idx = parm->pattern.nIndex; pce_table_t *ptable; GSW_PCE_action_t *paction; static GSW_PCE_rule_t key_current; int tindex, i, reg_val = 0; signed int status; PCE_ASSERT(idx >= (gswdev->tftblsize)); if (parm->pattern.bEnable == 0) { /* Entry to delete. */ return pce_pattern_delete(cdev, pthandle, idx); } /* Read the rule at given index to check if it is indeed same as current */ key_current.pattern.nIndex = idx; if (pce_rule_read(cdev, pthandle, &key_current) != 0) GSW_RETURN_PCE; if (VRSN_CMP(gswdev->gipver, LTQ_GSWIP_3_1) >= 0) { if (parm->action.nRecordId) pce_oam_read(cdev, parm); else key_current.action.nRecordId = 0; } /* Check if rule already exists */ if (!memcmp(&key_current, parm, sizeof(GSW_PCE_rule_t))) { pr_err("\n Rule already exists\n"); return GSW_statusOk; } /* Init the TFOW table entry to zero */ memset(&ptbl, 0, sizeof(pctbl_prog_t)); gsw_r32(cdev, PCE_GCTRL_1_VLANMD_OFFSET, PCE_GCTRL_1_VLANMD_SHIFT, PCE_GCTRL_1_VLANMD_SIZE, ®_val); /* Clean the old entry before adding the new one. */ if (pthandle->ptblused[idx] != 0) { if (pce_pattern_delete(cdev, pthandle, idx) != 0) GSW_RETURN_PCE; } /* Mark the entry as used */ pthandle->ptblused[idx] = 1; /* Other tables to refer for this TFLOW entry */ ptable = &(pthandle->pce_tbl[idx]); /* Populate 'match' parameter values */ /* Pattern field - PortID value */ if (parm->pattern.bPortIdEnable == 1) ptbl.key[0] = (parm->pattern.nPortId & 0x0F); else ptbl.key[0] = 0xFF; //Mark as don't care. /* Pattern field - DSCP value */ if (parm->pattern.bDSCP_Enable == 1) ptbl.key[6] |= ((parm->pattern.nDSCP & 0x3F) << 8); else ptbl.key[6] |= (0x7F << 8); //Mark as don't care. /* Pattern field - Inner DSCP value */ if (IS_VRSN_30_31(gswdev->gipver)) { if (parm->pattern.bInner_DSCP_Enable == 1) ptbl.key[9] |= ((parm->pattern.nInnerDSCP & 0x3F) << 8); else ptbl.key[9] |= (0x7F << 8); //Mark as don't care. } /* Pattern field - inner PCP n DEI value */ if (IS_VRSN_31(gswdev->gipver)) { if (parm->pattern.bPCP_Enable == 1) ptbl.key[6] |= (parm->pattern.nPCP & 0xF); else ptbl.key[6] |= 0x1F; //Mark as don't care. } else { if (parm->pattern.bPCP_Enable == 1) ptbl.key[6] |= (parm->pattern.nPCP & 0x7); else ptbl.key[6] |= 0xF; //Mark as don't care. } /* Pattern field - outer PCP n DEI value */ if (parm->pattern.bSTAG_PCP_DEI_Enable == 1) { /* PCP value */ ptbl.key[8] |= (parm->pattern.nSTAG_PCP_DEI & 0xF); } else { ptbl.key[8] |= 0x1F; //Mark as don't care. } /* Pattern field - Packet length field table */ if (parm->pattern.bPktLngEnable == 1) { pce_pkt_length_t pkg_lng; /* Packet length */ pkg_lng.pkg_lng = parm->pattern.nPktLng; /* Packet length range, in number of bytes */ pkg_lng.pkg_lng_rng = parm->pattern.nPktLngRange; tindex = pce_tm_pkg_lng_tbl_write(cdev, &pthandle->pce_sub_tbl, &pkg_lng); if (tindex < 0) return tindex; ptable->pkt_lng_idx = tindex; } else { ptable->pkt_lng_idx = 0xFF; //Mark as don't care. } ptbl.key[7] |= ptable->pkt_lng_idx; /* Pattern field - Destination MAC address field table */ if (parm->pattern.bMAC_DstEnable == 1) { pce_da_prog_t da_mac_tbl; for (i = 0; i < 6; i++) da_mac_tbl.mac[i] = parm->pattern.nMAC_Dst[i]; da_mac_tbl.mac_mask = parm->pattern.nMAC_DstMask; tindex = pce_da_mac_tbl_write(cdev, &pthandle->pce_sub_tbl, &da_mac_tbl); if (tindex < 0) return tindex; ptable->dst_mac_addr_idx = tindex; } else { ptable->dst_mac_addr_idx = 0xFF; //Mark as don't care. } ptbl.key[5] |= (ptable->dst_mac_addr_idx << 8); /* Pattern field - Source MAC address field table */ if (parm->pattern.bMAC_SrcEnable == 1) { pce_sa_prog_t sa_mac_tbl; for (i = 0; i < 6; i++) sa_mac_tbl.mac[i] = parm->pattern.nMAC_Src[i]; /* Source MAC address mask */ sa_mac_tbl.mac_mask = parm->pattern.nMAC_SrcMask; tindex = pce_sa_mac_tbl_write(cdev, &pthandle->pce_sub_tbl, &sa_mac_tbl); if (tindex < 0) return tindex; ptable->src_mac_addr_idx = tindex; } else { ptable->src_mac_addr_idx = 0xFF; //Mark as don't care. } ptbl.key[5] |= ptable->src_mac_addr_idx; /* Pattern field - Destination Application used */ if (parm->pattern.bAppDataMSB_Enable == 1) { app_tbl_t appl_tbl; appl_tbl.mask_range_type = parm->pattern.bAppMaskRangeMSB_Select; /* Destination Application field */ appl_tbl.appl_data = parm->pattern.nAppDataMSB; /* Destination Application mask/range */ appl_tbl.mask_range = parm->pattern.nAppMaskRangeMSB; tindex = pce_appl_tbl_write(cdev, &pthandle->pce_sub_tbl, &appl_tbl); if (tindex < 0) return tindex; ptable->dst_appl_fld_idx = tindex; } else { ptable->dst_appl_fld_idx = 0xFF; //Mark as don't care. } ptbl.key[4] |= ptable->dst_appl_fld_idx; /* Pattern field - Source Application field used */ if (parm->pattern.bAppDataLSB_Enable == 1) { app_tbl_t appl_tbl; appl_tbl.mask_range_type = parm->pattern.bAppMaskRangeLSB_Select; /* Source Application field */ appl_tbl.appl_data = parm->pattern.nAppDataLSB; /* Source Application mask/range */ appl_tbl.mask_range = parm->pattern.nAppMaskRangeLSB; tindex = pce_appl_tbl_write(cdev, &pthandle->pce_sub_tbl, &appl_tbl); if (tindex < 0) return tindex; ptable->src_appl_fld_idx = tindex; } else { ptable->src_appl_fld_idx = 0xFF; //Mark as don't care. } ptbl.key[4] |= (ptable->src_appl_fld_idx << 8); /* Pattern field - Parser Flags field table */ if (IS_VRSN_30_31(gswdev->gipver)) { /* Parser flags 15:0 */ if (parm->pattern.bParserFlagLSB_Enable == 1) { flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); flags_tbl.parser_flag_data = parm->pattern.nParserFlagLSB; flags_tbl.mask_value = parm->pattern.nParserFlagLSB_Mask; flags_tbl.valid = 1; tindex = pce_flags_tbl_write(cdev, &pthandle->pce_sub_tbl, &flags_tbl); if (tindex < 0) return tindex; ptable->parse_lsb_idx = tindex; } else { ptable->parse_lsb_idx = 0xFF; //Mark as don't care. } ptbl.key[12] |= ptable->parse_lsb_idx; /* Parser flags 47:32 */ ptable->parse1_lsb_idx = 0xFF; //Mark as don't care. if (IS_VRSN_31(gswdev->gipver)) { if (parm->pattern.bParserFlag1LSB_Enable == 1) { flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); flags_tbl.parser_flag_data = parm->pattern.nParserFlag1LSB; flags_tbl.mask_value = parm->pattern.nParserFlag1LSB_Mask; flags_tbl.valid = 1; tindex = pce_flags_tbl_write(cdev, &pthandle->pce_sub_tbl, &flags_tbl); if (tindex < 0) return tindex; ptable->parse1_lsb_idx = tindex; } ptbl.key[16] |= ptable->parse1_lsb_idx; } /* Parser flags 31:16 */ if (parm->pattern.bParserFlagMSB_Enable == 1) { flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); flags_tbl.parser_flag_data = parm->pattern.nParserFlagMSB; flags_tbl.mask_value = parm->pattern.nParserFlagMSB_Mask; flags_tbl.valid = 1; tindex = pce_flags_tbl_write(cdev, &pthandle->pce_sub_tbl, &flags_tbl); if (tindex < 0) return tindex; ptable->parse_msb_idx = tindex; } else { ptable->parse_msb_idx = 0xFF; //Mark as don't care. } ptbl.key[12] |= (ptable->parse_msb_idx << 8); /* Parser flags 63:48 */ ptable->parse1_msb_idx = 0xFF; //Mark as don't care. if (IS_VRSN_31(gswdev->gipver)) { if (parm->pattern.bParserFlag1MSB_Enable == 1) { flag_tbl_t flags_tbl; memset(&flags_tbl, 0, sizeof(flag_tbl_t)); flags_tbl.parser_flag_data = parm->pattern.nParserFlag1MSB; flags_tbl.mask_value = parm->pattern.nParserFlag1MSB_Mask; flags_tbl.valid = 1; tindex = pce_flags_tbl_write(cdev, &pthandle->pce_sub_tbl, &flags_tbl); if (tindex < 0) return tindex; ptable->parse1_msb_idx = tindex; } ptbl.key[16] |= (ptable->parse1_msb_idx << 8); } /* Pattern field - Payload1 used */ if (parm->pattern.bPayload1_SrcEnable == 1) { payload_tbl_t payload_tbl; memset(&payload_tbl, 0, sizeof(payload_tbl_t)); payload_tbl.mask_range_type = parm->pattern.bPayload1MaskRange_Select; payload_tbl.payload_data = parm->pattern.nPayload1; payload_tbl.mask_range = parm->pattern.nPayload1_Mask; payload_tbl.valid = 1; tindex = pce_payload_tbl_write(cdev, &pthandle->pce_sub_tbl, &payload_tbl); if (tindex < 0) return tindex; ptable->payload1_idx = tindex; } else { ptable->payload1_idx = 0xFF; //Mark as don't care. } ptbl.key[13] |= ptable->payload1_idx; /* Pattern field - Payload2 used */ if (parm->pattern.bPayload2_SrcEnable == 1) { payload_tbl_t payload_tbl; memset(&payload_tbl, 0, sizeof(payload_tbl_t)); payload_tbl.mask_range_type = parm->pattern.bPayload2MaskRange_Select; payload_tbl.payload_data = parm->pattern.nPayload2; /* Destination Application mask/range */ payload_tbl.mask_range = parm->pattern.nPayload2_Mask; payload_tbl.valid = 1; tindex = pce_payload_tbl_write(cdev, &pthandle->pce_sub_tbl, &payload_tbl); if (tindex < 0) return tindex; ptable->payload2_idx = tindex; } else { ptable->payload2_idx = 0xFF; //Mark as don't care. } ptbl.key[13] |= (ptable->payload2_idx << 8); } /* Pattern field - outer DIP field table */ ptable->dip_msb_idx = 0xFF; //Mark as don't care. ptable->dip_lsb_idx = 0xFF; //Mark as don't care. /* DIP MSB used - IPv6 bits 127:64 */ if (parm->pattern.eDstIP_Select == GSW_PCE_IP_V6) { pce_dasa_msb_t mtbl; pce_dasa_lsb_t ltbl; int j; u16 maskNibble; memset(&mtbl, 0, sizeof(pce_dasa_msb_t)); memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { mtbl.imsb[j - 1] = (parm->pattern.nDstIP.nIPv6[i] & 0xFF); mtbl.imsb[j] = ((parm->pattern.nDstIP.nIPv6[i] >> 8) & 0xFF); } if (IS_VRSN_30_31(gswdev->gipver)) { //mtbl.nmask = (u16)((parm->pattern.nDstIP_Mask >> 16) & 0xFFFF); for (i = 0; i < 4; i++) { maskNibble = ((parm->pattern.nDstIP_Mask >> ((i * 4) + 16)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) mtbl.mask[i] |= (0xF << (j * 4)); } } } else { mtbl.mask[0] = (u16)((parm->pattern.nDstIP_Mask >> 16) & 0xFFFF); } mtbl.valid = 1; tindex = pce_dasa_msb_tbl_write(cdev, &pthandle->pce_sub_tbl, &mtbl); if (tindex < 0) { pr_err("%s:%s:%d(DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->dip_msb_idx = tindex; /* DIP LSB used - IPv6 bits 63:0 */ /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { ltbl.ilsb[j - 1] = (parm->pattern.nDstIP.nIPv6[i + 4] & 0xFF); ltbl.ilsb[j] = ((parm->pattern.nDstIP.nIPv6[i + 4] >> 8) & 0xFF); } if (IS_VRSN_30_31(gswdev->gipver)) { //ltbl.nmask = (u16)(parm->pattern.nDstIP_Mask & 0xFFFF); for (i = 0; i < 4; i++) { maskNibble = ((parm->pattern.nDstIP_Mask >> (i * 4)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) ltbl.mask[i] |= (0xF << (j * 4)); } } } else { ltbl.mask[0] = (u16)(parm->pattern.nDstIP_Mask & 0xFFFF); } ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->dip_lsb_idx = tindex; } else if (parm->pattern.eDstIP_Select == GSW_PCE_IP_V4) { /* DIP LSB used - IPv4 bits 31:0 */ pce_dasa_lsb_t ltbl; memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0; i < 4; i++) ltbl.ilsb[i] = ((parm->pattern.nDstIP.nIPv4 >> (i * 8)) & 0xFF); if (IS_VRSN_30_31(gswdev->gipver)) { int j; u16 maskNibble; //ltbl.nmask = (u16)(parm->pattern.nDstIP_Mask) & 0xFFFF; for (i = 0; i < 2; i++) { maskNibble = ((parm->pattern.nDstIP_Mask >> (i * 4)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) ltbl.mask[i] |= (0xF << (j * 4)); } } //Mask out the bits 63:32 always for IPv4. ltbl.mask[3] = ltbl.mask[2] = 0xFFFF; } else { /* DIP LSB Nibble Mask */ ltbl.mask[0] = (u16)(parm->pattern.nDstIP_Mask | 0xFF00) & 0xFFFF; } ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->dip_lsb_idx = tindex; } ptbl.key[3] |= (ptable->dip_msb_idx << 8); ptbl.key[3] |= ptable->dip_lsb_idx; /* Pattern field - SIP field table */ ptable->sip_msb_idx = 0xFF; //Mark as don't care. ptable->sip_lsb_idx = 0xFF; //Mark as don't care. /* SIP MSB used - IPv6 bits 127:64 */ if (parm->pattern.eSrcIP_Select == GSW_PCE_IP_V6) { pce_dasa_msb_t mtbl; pce_dasa_lsb_t ltbl; int j; u16 maskNibble; memset(&mtbl, 0, sizeof(pce_dasa_msb_t)); memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { mtbl.imsb[j - 1] = (parm->pattern.nSrcIP.nIPv6[i] & 0xFF); mtbl.imsb[j] = ((parm->pattern.nSrcIP.nIPv6[i] >> 8) & 0xFF); } if (IS_VRSN_30_31(gswdev->gipver)) { //mtbl.nmask = (u16)((parm->pattern.nSrcIP_Mask >> 16) & 0xFFFF); for (i = 0; i < 4; i++) { maskNibble = ((parm->pattern.nSrcIP_Mask >> ((i * 4) + 16)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) mtbl.mask[i] |= (0xF << (j * 4)); } } } else { mtbl.mask[0] = (u16)((parm->pattern.nSrcIP_Mask >> 16) & 0xFFFF); } mtbl.valid = 1; tindex = pce_dasa_msb_tbl_write(cdev, &pthandle->pce_sub_tbl, &mtbl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->sip_msb_idx = tindex; /* SIP LSB used - IPv6 bits 63:0 */ /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { ltbl.ilsb[j - 1] = (parm->pattern.nSrcIP.nIPv6[i + 4] & 0xFF); ltbl.ilsb[j] = ((parm->pattern.nSrcIP.nIPv6[i + 4] >> 8) & 0xFF); } if (IS_VRSN_30_31(gswdev->gipver)) { //ltbl.nmask = (u16)(parm->pattern.nSrcIP_Mask & 0xFFFF); for (i = 0; i < 4; i++) { maskNibble = ((parm->pattern.nSrcIP_Mask >> (i * 4)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) ltbl.mask[i] |= (0xF << (j * 4)); } } } else { ltbl.mask[0] = (u16)(parm->pattern.nSrcIP_Mask & 0xFFFF); } ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->sip_lsb_idx = tindex; } else if (parm->pattern.eSrcIP_Select == GSW_PCE_IP_V4) { /* SIP LSB used - IPv4 bits 31:0 */ pce_dasa_lsb_t ltbl; memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* Second, search for SIP in the DA/SA table (SIP LSB) */ for (i = 0; i < 4; i++) ltbl.ilsb[i] = ((parm->pattern.nSrcIP.nIPv4 >> (i * 8)) & 0xFF); if (IS_VRSN_30_31(gswdev->gipver)) { int j; u16 maskNibble; //ltbl.nmask = (u16)(parm->pattern.nSrcIP_Mask) & 0xFFFF; for (i = 0; i < 2; i++) { maskNibble = ((parm->pattern.nSrcIP_Mask >> (i * 4)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) ltbl.mask[i] |= (0xF << (j * 4)); } } //Mask out the bits 63:32 always for IPv4. ltbl.mask[3] = ltbl.mask[2] = 0xFFFF; } else { /* DIP LSB Nibble Mask */ ltbl.mask[0] = (u16)(parm->pattern.nSrcIP_Mask | 0xFF00) & 0xFFFF; } ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->sip_lsb_idx = tindex; } ptbl.key[2] |= (ptable->sip_msb_idx << 8); ptbl.key[2] |= ptable->sip_lsb_idx; /* Pattern field - inner DIP field table */ if (IS_VRSN_30_31(gswdev->gipver)) { ptable->inr_dip_msb_idx = 0xFF; //Mark as don't care. ptable->inr_dip_lsb_idx = 0xFF; //Mark as don't care. /* DIP MSB used - IPv6 bits 127:64 */ if (parm->pattern.eInnerDstIP_Select == GSW_PCE_IP_V6) { pce_dasa_msb_t mtbl; pce_dasa_lsb_t ltbl; int j; u16 maskNibble; memset(&mtbl, 0, sizeof(pce_dasa_msb_t)); memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { mtbl.imsb[j - 1] = (parm->pattern.nInnerDstIP.nIPv6[i] & 0xFF); mtbl.imsb[j] = ((parm->pattern.nInnerDstIP.nIPv6[i] >> 8) & 0xFF); } for (i = 0; i < 4; i++) { maskNibble = ((parm->pattern.nInnerDstIP_Mask >> ((i * 4) + 16)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) mtbl.mask[i] |= (0xF << (j * 4)); } } //mtbl.nmask = (u16)((parm->pattern.nInnerDstIP_Mask >> 16) & 0xFFFF); mtbl.valid = 1; tindex = pce_dasa_msb_tbl_write(cdev, &pthandle->pce_sub_tbl, &mtbl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_dip_msb_idx = tindex; /* DIP LSB used - IPv6 bits 63:0 */ /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { ltbl.ilsb[j - 1] = (parm->pattern.nInnerDstIP.nIPv6[i + 4] & 0xFF); ltbl.ilsb[j] = ((parm->pattern.nInnerDstIP.nIPv6[i + 4] >> 8) & 0xFF); } for (i = 0; i < 4; i++) { maskNibble = ((parm->pattern.nInnerDstIP_Mask >> (i * 4)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) ltbl.mask[i] |= (0xF << (j * 4)); } } //ltbl.nmask = (u16)(parm->pattern.nInnerDstIP_Mask & 0xFFFF); ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_dip_lsb_idx = tindex; } else if (parm->pattern.eInnerDstIP_Select == GSW_PCE_IP_V4) { /* DIP LSB used - IPv4 bits 31:0 */ pce_dasa_lsb_t ltbl; int j; u16 maskNibble; memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0; i < 4; i++) ltbl.ilsb[i] = ((parm->pattern.nInnerDstIP.nIPv4 >> (i * 8)) & 0xFF); for (i = 0; i < 2; i++) { maskNibble = ((parm->pattern.nInnerDstIP_Mask >> (i * 4)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) ltbl.mask[i] |= (0xF << (j * 4)); } } //Mask out the bits 63:32 always for IPv4. ltbl.mask[3] = ltbl.mask[2] = 0xFFFF; //ltbl.nmask = (u16)(parm->pattern.nInnerDstIP_Mask & 0xFFFF); ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_dip_lsb_idx = tindex; } ptbl.key[11] |= (ptable->inr_dip_msb_idx << 8); ptbl.key[11] |= ptable->inr_dip_lsb_idx; /* Pattern field - inner SIP field table */ ptable->inr_sip_msb_idx = 0xFF; //Mark as don't care. ptable->inr_sip_lsb_idx = 0xFF; //Mark as don't care. /* SIP MSB used - IPv6 bits 127:64 */ if (parm->pattern.eInnerSrcIP_Select == GSW_PCE_IP_V6) { pce_dasa_msb_t mtbl; pce_dasa_lsb_t ltbl; int j; u16 maskNibble; memset(&mtbl, 0, sizeof(pce_dasa_msb_t)); memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* First, search for DIP in the DA/SA table (DIP MSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { mtbl.imsb[j - 1] = (parm->pattern.nInnerSrcIP.nIPv6[i] & 0xFF); mtbl.imsb[j] = ((parm->pattern.nInnerSrcIP.nIPv6[i] >> 8) & 0xFF); } for (i = 0; i < 4; i++) { maskNibble = ((parm->pattern.nInnerSrcIP_Mask >> ((i * 4) + 16)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) mtbl.mask[i] |= (0xF << (j * 4)); } } //mtbl.nmask = (u16)((parm->pattern.nInnerSrcIP_Mask >> 16) & 0xFFFF); mtbl.valid = 1; tindex = pce_dasa_msb_tbl_write(cdev, &pthandle->pce_sub_tbl, &mtbl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_sip_msb_idx = tindex; /* SIP LSB used - IPv6 bits 63:0 */ /* First, search for DIP in the DA/SA table (DIP LSB) */ for (i = 0, j = 7; i < 4; i++, j -= 2) { ltbl.ilsb[j - 1] = (parm->pattern.nInnerSrcIP.nIPv6[i + 4] & 0xFF); ltbl.ilsb[j] = ((parm->pattern.nInnerSrcIP.nIPv6[i + 4] >> 8) & 0xFF); } for (i = 0; i < 4; i++) { maskNibble = ((parm->pattern.nInnerSrcIP_Mask >> (i * 4)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) ltbl.mask[i] |= (0xF << (j * 4)); } } //ltbl.nmask = (u16)(parm->pattern.nInnerSrcIP_Mask & 0xFFFF); ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_sip_lsb_idx = tindex; } else if (parm->pattern.eInnerSrcIP_Select == GSW_PCE_IP_V4) { /* SIP LSB used - IPv4 bits 31:0 */ pce_dasa_lsb_t ltbl; int j; u16 maskNibble; memset(<bl, 0, sizeof(pce_dasa_lsb_t)); /* Second, search for SIP in the DA/SA table (SIP LSB) */ for (i = 0; i < 4; i++) ltbl.ilsb[i] = ((parm->pattern.nInnerSrcIP.nIPv4 >> (i * 8)) & 0xFF); for (i = 0; i < 2; i++) { maskNibble = ((parm->pattern.nInnerSrcIP_Mask >> (i * 4)) & 0xF); for (j = 0; j < 4; j++) { if ((maskNibble >> j) & 0x1) ltbl.mask[i] |= (0xF << (j * 4)); } } //Mask out the bits 63:32 always for IPv4. ltbl.mask[3] = ltbl.mask[2] = 0xFFFF; //ltbl.nmask = (u16)(parm->pattern.nInnerSrcIP_Mask & 0xFFFF); ltbl.valid = 1; tindex = pce_dasa_lsb_tbl_write(cdev, &pthandle->pce_sub_tbl, <bl); if (tindex < 0) { pr_err("%s:%s:%d (DASA Table full)\n", __FILE__, __func__, __LINE__); return -1; } ptable->inr_sip_lsb_idx = tindex; } ptbl.key[10] |= (ptable->inr_sip_msb_idx << 8); ptbl.key[10] |= ptable->inr_sip_lsb_idx; } /* Pattern field - Ethertype field table */ if (parm->pattern.bEtherTypeEnable == 1) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = parm->pattern.nEtherType; pctl_tbl.emask = parm->pattern.nEtherTypeMask; tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ethertype_idx = tindex; } else { ptable->ethertype_idx = 0xFF; //Mark as don't care. } ptbl.key[1] |= ptable->ethertype_idx; /* Pattern field - PPP Protocol table */ if (IS_VRSN_30_31(gswdev->gipver)) { if (parm->pattern.bPPP_ProtocolEnable == 1) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = parm->pattern.nPPP_Protocol; pctl_tbl.emask = parm->pattern.nPPP_ProtocolMask; tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ppp_prot_idx = tindex; } else { ptable->ppp_prot_idx = 0xFF; //Mark as don't care. } ptbl.key[9] |= ptable->ppp_prot_idx; } /* Pattern field - Both outer n inner IP protocol table */ if ((parm->pattern.bProtocolEnable == 1) && (parm->pattern.bInnerProtocolEnable == 1)) { prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = (parm->pattern.nProtocol & 0xFF); pctl_tbl.ethertype |= ((parm->pattern.nInnerProtocol & 0xFF) << 8); pctl_tbl.emask = (parm->pattern.nProtocolMask & 0x3); pctl_tbl.emask |= ((parm->pattern.nInnerProtocolMask & 0x3) << 2); tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ip_prot_idx = tindex; } else if (parm->pattern.bInnerProtocolEnable == 1) { /* Only inner IP protocol table */ prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = (0xFF); pctl_tbl.ethertype |= ((parm->pattern.nInnerProtocol & 0xFF) << 8); pctl_tbl.emask = 0x3; //Mask out outer Proto value. pctl_tbl.emask |= ((parm->pattern.nInnerProtocolMask & 0x3) << 2); tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ip_prot_idx = tindex; } else if (parm->pattern.bProtocolEnable == 1) { /* Only outer IP protocol table */ prtcol_tbl_t pctl_tbl; memset(&pctl_tbl, 0, sizeof(prtcol_tbl_t)); pctl_tbl.ethertype = (parm->pattern.nProtocol & 0xFF); pctl_tbl.ethertype |= (0xFF << 8); pctl_tbl.emask = (parm->pattern.nProtocolMask & 0x3); pctl_tbl.emask |= (0x3 << 2); //Mask out inner Proto value. tindex = pce_ptcl_tbl_write(cdev, &pthandle->pce_sub_tbl, &pctl_tbl); if (tindex < 0) return tindex; ptable->ip_prot_idx = tindex; } else { ptable->ip_prot_idx = 0xFF; //Mark as don't care. } ptbl.key[1] |= (ptable->ip_prot_idx << 8); /* Pattern field - PPPoE table */ if (parm->pattern.bSessionIdEnable == 1) { pce_ppoe_tbl_t pppoe_tbl; pppoe_tbl.sess_id = parm->pattern.nSessionId; tindex = pce_tm_pppoe_tbl_write(cdev, &pthandle->pce_sub_tbl, &pppoe_tbl); if (tindex < 0) return tindex; ptable->pppoe_idx = tindex; } else { ptable->pppoe_idx = 0xFF; //Mark as don't care. } ptbl.key[7] |= (ptable->pppoe_idx << 8); /* Pattern field - VID value */ if (IS_VRSN_NOT_31(gswdev->gipver)) { tindex = 0x7F; //Mark as don't care. /* Pattern field - inner VID */ if (parm->pattern.bVid == 1) { tindex = pce_vid_index(cdev, &pthandle->pce_sub_tbl, parm->pattern.nVid); if (reg_val == 1) { /*ETC*/ if (tindex == 0x7F) tindex = act_vlan_id_create(cdev, parm->pattern.nVid, parm->pattern.bVidRange_Select, parm->pattern.nVidRange); } else { if (tindex == 0x7F) { pr_err("%s:%s:%d (Create VID before use it)\n", __FILE__, __func__, __LINE__); return -1; } } } ptable->vlan_idx = tindex; ptbl.key[0] &= ~(0xFF << 8); ptbl.key[0] |= (ptable->vlan_idx << 8); /* Pattern field - outer VID */ tindex = 0x7F; //Mark as don't care. /* ETC */ if (reg_val == 1) { if (parm->pattern.bSLAN_Vid == 1) { tindex = pce_vid_index(cdev, &pthandle->pce_sub_tbl, parm->pattern.nSLAN_Vid); if (tindex == 0x7F) tindex = act_vlan_id_create(cdev, parm->pattern.nSLAN_Vid, 0, 0); } } ptable->svlan_idx = tindex; ptbl.key[8] &= ~(0xFF << 8); ptbl.key[8] |= (ptable->svlan_idx << 8); } /* Pattern field - VID value */ if (IS_VRSN_31(gswdev->gipver)) { /* Pattern field - inner VID */ if (parm->pattern.bVid) { ptbl.key[20] |= (parm->pattern.nVid & 0x0FFF); ptbl.key[20] |= parm->pattern.bVid_Original ? 0 : BIT(15); if (parm->pattern.bVidRange_Select) ptbl.key[21] |= (parm->pattern.nVidRange & 0xFFF); } else { ptbl.key[20] |= 0x1FFF; //Mark as don't care. } /* Pattern field - outer VID */ if (parm->pattern.bSLAN_Vid) { ptbl.key[18] |= (parm->pattern.nSLAN_Vid & 0x0FFF); ptbl.key[18] |= parm->pattern.bOuterVid_Original ? 0 : BIT(15); if (parm->pattern.bSVidRange_Select) ptbl.key[19] |= (parm->pattern.nOuterVidRange & 0xFFF); } else { ptbl.key[18] |= 0x1FFF; //Mark as don't care. } } /* Pattern field - Sub-IF ID value */ if (gswdev->gipver == LTQ_GSWIP_3_0) { if (parm->pattern.bSubIfIdEnable == 1) ptbl.key[14] |= (parm->pattern.nSubIfId & 0xF); else ptbl.key[14] |= 0x1F; //Mark as don't care. } /* Pattern field - Sub-IF ID value */ if (IS_VRSN_31(gswdev->gipver)) { if (parm->pattern.bSubIfIdEnable == 1) { ptbl.key[17] |= (parm->pattern.nSubIfId & 0x0FF); switch (parm->pattern.eSubIfIdType) { case GSW_PCE_SUBIFID_TYPE_BRIDGEPORT: ptbl.key[17] |= (0x1 << 9); break; default: break; } } else { ptbl.key[17] |= 0x1FF; //Mark as don't care. } /* Pattern field - 'INS' falg value */ if (parm->pattern.bInsertionFlag_Enable == 1) { if ((parm->pattern.nInsertionFlag) & 0x3) { ptbl.key[17] |= (((parm->pattern.nInsertionFlag) & 0x3) << 10); } } else { ptbl.key[17] |= (3 << 10); //Don't care condition. } /* Pattern field - Exclude bits */ if (parm->pattern.bParserFlag1LSB_Exclude == 1) ptbl.key[14] |= (1 << 5); if (parm->pattern.bParserFlag1MSB_Exclude == 1) ptbl.key[14] |= (1 << 6); } /* Pattern field - Exclude bits */ if (IS_VRSN_30_31(gswdev->gipver)) { if (parm->pattern.bPortId_Exclude == 1) ptbl.key[14] |= (1 << 7); if (parm->pattern.bVid_Exclude == 1) ptbl.key[14] |= (1 << 8); if (parm->pattern.bEtherType_Exclude == 1) ptbl.key[14] |= (1 << 9); if (parm->pattern.bProtocol_Exclude == 1) ptbl.key[14] |= (1 << 10); if (parm->pattern.bSrcIP_Exclude == 1) ptbl.key[14] |= (1 << 11); if (parm->pattern.bDstIP_Exclude == 1) ptbl.key[14] |= (1 << 12); /* source port */ if (parm->pattern.bAppMSB_Exclude == 1) ptbl.key[14] |= (1 << 13); if (parm->pattern.bAppLSB_Exclude == 1) ptbl.key[14] |= (1 << 14); if (parm->pattern.bSrcMAC_Exclude == 1) ptbl.key[14] |= (1 << 15); if (parm->pattern.bDstMAC_Exclude == 1) ptbl.key[15] |= (1 << 0); if (parm->pattern.bCTAG_PCP_DEI_Exclude == 1) ptbl.key[15] |= (1 << 1); if (parm->pattern.bSTAG_PCP_DEI_Exclude == 1) ptbl.key[15] |= (1 << 2); if (parm->pattern.bDSCP_Exclude == 1) ptbl.key[15] |= (1 << 3); if (parm->pattern.bPktLng_Exclude == 1) ptbl.key[15] |= (1 << 4); if (parm->pattern.bSessionId_Exclude == 1) ptbl.key[15] |= (1 << 5); if (parm->pattern.bSLANVid_Exclude == 1) ptbl.key[15] |= (1 << 6); if (parm->pattern.bPPP_Protocol_Exclude == 1) ptbl.key[15] |= (1 << 7); if (parm->pattern.bInnerDSCP_Exclude == 1) ptbl.key[15] |= (1 << 8); if (parm->pattern.bInnerSrcIP_Exclude == 1) ptbl.key[15] |= (1 << 9); if (parm->pattern.bInnerDstIP_Exclude == 1) ptbl.key[15] |= (1 << 10); if (parm->pattern.bParserFlagLSB_Exclude == 1) ptbl.key[15] |= (1 << 11); if (parm->pattern.bParserFlagMSB_Exclude == 1) ptbl.key[15] |= (1 << 12); if (parm->pattern.bPayload1_Exclude == 1) ptbl.key[15] |= (1 << 13); if (parm->pattern.bPayload2_Exclude == 1) ptbl.key[15] |= (1 << 14); if (parm->pattern.bSubIfId_Exclude == 1) ptbl.key[15] |= (1 << 15); } /* Process Record ID before action population */ if (VRSN_CMP(gswdev->gipver, LTQ_GSWIP_3_1) >= 0 && !parm->action.nRecordId) { pce_oam_write(cdev, pthandle, parm); } /* Populate 'action' parameter values */ paction = &(pthandle->pce_act[idx]); memcpy(paction, &parm->action, sizeof(GSW_PCE_action_t)); /* Port forwarding action */ if (paction->ePortMapAction != GSW_PCE_ACTION_PORTMAP_DISABLE) { if (paction->eSnoopingTypeAction == GSW_PCE_ACTION_IGMP_SNOOP_DISABLE) { ptbl.val[0] |= 1; //Enable port-map action. ptbl.val[4] |= (0x3 << 2); //Set to 'traffic-flow' portmap MUX control. switch (paction->ePortMapAction) { case GSW_PCE_ACTION_PORTMAP_REGULAR: ptbl.val[4] &= ~(0x3 << 2); //Set to 'default' portmap MUX control. break; case GSW_PCE_ACTION_PORTMAP_DISCARD: break; case GSW_PCE_ACTION_PORTMAP_CPU: case GSW_PCE_ACTION_PORTMAP_ALTERNATIVE: if (VRSN_CMP(gswdev->gipver, LTQ_GSWIP_3_1) < 0) { ptbl.val[1] = (paction->nForwardPortMap[0] & 0xFFFF); if (paction->ePortMapAction == GSW_PCE_ACTION_PORTMAP_CPU) { /* Applicable for 2.1/2.2/3.0 or multicast hardware enabled */ /* set to 'MC router' portmap MUX control */ ptbl.val[4] &= ~(0x3 << 2); ptbl.val[4] |= (0x1 << 2); } } else { u16 map = 0; for (i = 0; i < 8; i++) { ptbl.val[i + 10] = paction->nForwardPortMap[i]; map |= paction->nForwardPortMap[i]; } if (paction->ePortMapAction == GSW_PCE_ACTION_PORTMAP_CPU) { if (gswdev->mcsthw_snoop == MCAST_HWSNOOP_EN) { /* Applicable for 2.1/2.2/3.0 or multicast hardware enabled */ /* set to 'MC router' portmap MUX control */ ptbl.val[4] &= ~(0x3 << 2); ptbl.val[4] |= (0x1 << 2); } else if (map == 0) { map = 1 << (gswdev->cport % 16); ptbl.val[10 + gswdev->cport / 16] = map; } } } break; /* To fix compilation warnings*/ default: break; } } else { switch (paction->eSnoopingTypeAction) { case GSW_PCE_ACTION_IGMP_SNOOP_REPORT: case GSW_PCE_ACTION_IGMP_SNOOP_LEAVE: ptbl.val[0] |= 1; ptbl.val[4] &= ~(0x3 << 2); //Set to 'MC router' portmap MUX control. ptbl.val[4] |= (0x1 << 2); break; default: ptbl.val[0] |= 1; //Set to 'default' portmap MUX control. ptbl.val[4] &= ~(0x3 << 2); break; } } } else { /* Disable port map action */ ptbl.val[0] &= ~1; if (gswdev->gipver == LTQ_GSWIP_3_0) { ptbl.val[1] = 0xFFFF; } //But why do we need to do below? if (IS_VRSN_31(gswdev->gipver)) { for (i = 0; i <= 7; i++) ptbl.val[i + 10] = 0xFFFF; } ptbl.val[4] &= ~(0x3 << 2); } /* Flow-ID action */ /* In 3.0, bFlowID_Action and ePortMapAction should be exclusively */ if (gswdev->gipver == LTQ_GSWIP_3_0) { if (paction->bFlowID_Action != 0) { if (paction->ePortMapAction == GSW_PCE_ACTION_PORTMAP_DISABLE) { /* Enable flow ID action */ ptbl.val[4] |= (0x1 << 4); ptbl.val[1] = paction->nFlowID & 0xFFFF; } else { pr_err("%s:%s:%d (Portmap & FlowID can be used exclusively)\n", __FILE__, __func__, __LINE__); return -1; } } } /* Inner and outer VLAN action */ if (IS_VRSN_NOT_31(gswdev->gipver)) { tindex = 0x7F; ptbl.val[2] = 0; ptbl.val[0] &= ~(1 << 13); if (paction->eVLAN_Action != GSW_PCE_ACTION_VLAN_DISABLE) { ptbl.val[0] |= (1 << 1); if (paction->eVLAN_Action == GSW_PCE_ACTION_VLAN_ALTERNATIVE) { if (reg_val == 1) { /*ETC */ ptbl.val[5] |= ((paction->nVLAN_Id & 0xFFF) << 4); ptbl.val[2] |= ((paction->nFId & 0xFF) << 8); /* Alternative CTAG VLAN ID and FID */ ptbl.val[5] |= (1 << 3); ptbl.val[0] |= (1 << 13); } else { avlan_tbl_t vatable; memset(&vatable, 0, sizeof(avlan_tbl_t)); vatable.vid = paction->nVLAN_Id; tindex = pce_vlan_id_fid_index(cdev, &pthandle->pce_sub_tbl, &vatable); if (tindex != 0x7F) { ptbl.val[2] = (tindex & 0xFF); ptbl.val[2] |= ((vatable.fid & 0xFF) << 8); ptbl.val[0] |= (1 << 13); } } } } /* ETC */ if (reg_val == 1) { ptbl.val[6] = 0; if (paction->eSVLAN_Action != GSW_PCE_ACTION_VLAN_DISABLE) { ptbl.val[0] |= (1 << 1); /* Default CTAG VLAN ID and FID */ ptbl.val[6] &= ~(1 << 3); if (paction->eSVLAN_Action == GSW_PCE_ACTION_VLAN_ALTERNATIVE) { ptbl.val[6] |= ((paction->nSVLAN_Id & 0xFFF) << 4); ptbl.val[0] |= (1 << 13); ptbl.val[6] |= (1 << 3); } } } } //Extended VLAN tagging action. if (IS_VRSN_31(gswdev->gipver)) { if (paction->bExtendedVlanEnable) { ptbl.val[0] |= (1 << 1); //Enable VLAN action. ptbl.val[6] |= (1 << 3); //Enable extended VLAN tagging. ptbl.val[6] |= ((paction->nExtendedVlanBlockId & 0x3FF) << 4); } } /* Traffic class action */ if (paction->eTrafficClassAction != GSW_PCE_ACTION_TRAFFIC_CLASS_DISABLE) { ptbl.val[0] |= (1 << 2); switch (paction->eTrafficClassAction) { case GSW_PCE_ACTION_TRAFFIC_CLASS_ALTERNATIVE: ptbl.val[0] |= (1 << 14); ptbl.val[3] |= (paction->nTrafficClassAlternate & 0xF) << 8; break; default: break; } } /* Cross VLAN action */ if (paction->eVLAN_CrossAction != GSW_PCE_ACTION_CROSS_VLAN_DISABLE) { ptbl.val[0] |= (1 << 4); if (paction->eVLAN_CrossAction == GSW_PCE_ACTION_CROSS_VLAN_CROSS) ptbl.val[3] |= (1 << 15); } /* Cross state action */ if (paction->eCrossStateAction != GSW_PCE_ACTION_CROSS_STATE_DISABLE) { ptbl.val[0] |= (1 << 5); if (paction->eCrossStateAction == GSW_PCE_ACTION_CROSS_STATE_CROSS) ptbl.val[4] |= (1 << 13); } /* Critical frame action */ if (IS_VRSN_NOT_31(gswdev->gipver)) { if (paction->eCritFrameAction != GSW_PCE_ACTION_CRITICAL_FRAME_DISABLE) { ptbl.val[0] |= (1 << 6); if (paction->eCritFrameAction == GSW_PCE_ACTION_CRITICAL_FRAME_CRITICAL) ptbl.val[4] |= (1 << 14); } } /* Color action */ if (IS_VRSN_31(gswdev->gipver)) { if (paction->eColorFrameAction != GSW_PCE_ACTION_COLOR_FRAME_DISABLE) { ptbl.val[0] |= (1 << 6); switch (paction->eColorFrameAction) { case GSW_PCE_ACTION_COLOR_FRAME_CRITICAL: ptbl.val[2] |= 0x4; break; case GSW_PCE_ACTION_COLOR_FRAME_GREEN: ptbl.val[2] |= 0x5; break; case GSW_PCE_ACTION_COLOR_FRAME_YELLOW: ptbl.val[2] |= 0x6; break; case GSW_PCE_ACTION_COLOR_FRAME_RED: ptbl.val[2] |= 0x7; break; default: /*GSW_PCE_ACTION_COLOR_FRAME_NO_CHANGE*/ break; } } } /* Time stamp action */ if (paction->eTimestampAction != GSW_PCE_ACTION_TIMESTAMP_DISABLE) { ptbl.val[0] |= (1 << 7); if (paction->eTimestampAction == GSW_PCE_ACTION_TIMESTAMP_STORED) { ptbl.val[4] |= (1 << 15); ptbl.val[8] |= ((paction->nRecordId & 0xFFF) << 4); } } /* Interrupt action */ if (paction->eIrqAction != GSW_PCE_ACTION_IRQ_DISABLE) { ptbl.val[0] |= (1 << 8); if (paction->eIrqAction == GSW_PCE_ACTION_IRQ_EVENT) ptbl.val[0] |= (1 << 15); } /* MAC Learning action */ if (paction->eLearningAction != GSW_PCE_ACTION_LEARNING_DISABLE) { ptbl.val[0] |= (1 << 9); switch (paction->eLearningAction) { case GSW_PCE_ACTION_LEARNING_REGULAR: //ptbl.val[4] &= ~(0x3); break; case GSW_PCE_ACTION_LEARNING_FORCE_NOT: ptbl.val[4] |= 0x2; break; case GSW_PCE_ACTION_LEARNING_FORCE: ptbl.val[4] |= 0x3; break; default: ptbl.val[4] |= 0x1; break; } } /* IGMP Snooping action. */ if (paction->eSnoopingTypeAction != GSW_PCE_ACTION_IGMP_SNOOP_DISABLE) { ptbl.val[0] |= (1 << 10); switch (paction->eSnoopingTypeAction) { case GSW_PCE_ACTION_IGMP_SNOOP_REGULAR: //ptbl.val[4] |= (0 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_REPORT: ptbl.val[4] |= (1 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_LEAVE: ptbl.val[4] |= (2 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_AD: ptbl.val[4] |= (3 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_QUERY: ptbl.val[4] |= (4 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_QUERY_GROUP: ptbl.val[4] |= (5 << 5); break; case GSW_PCE_ACTION_IGMP_SNOOP_QUERY_NO_ROUTER: ptbl.val[4] |= (6 << 5); break; default: break; } } /* Metering action */ if (IS_VRSN_NOT_31(gswdev->gipver)) { if (paction->eMeterAction != GSW_PCE_ACTION_METER_DISABLE) { ptbl.val[0] |= (1 << 11); ptbl.val[3] |= (paction->nMeterId & 0x3F); switch (paction->eMeterAction) { case GSW_PCE_ACTION_METER_REGULAR: ptbl.val[3] |= 0 << 6; break; case GSW_PCE_ACTION_METER_1: ptbl.val[3] |= 1 << 6; break; /*case GSW_PCE_ACTION_METER_2: ptbl.val[3] |= 2 << 6; break;*/ case GSW_PCE_ACTION_METER_1_2: ptbl.val[3] |= 3 << 6; break; case GSW_PCE_ACTION_METER_DISABLE: break; } } else { ptbl.val[3] |= 0x1F; } } /* Metering action */ if (IS_VRSN_31(gswdev->gipver)) { if (paction->eMeterAction != GSW_PCE_ACTION_METER_DISABLE) { ptbl.val[0] |= (1 << 11); switch (paction->eMeterAction) { case GSW_PCE_ACTION_METER_1: ptbl.val[3] |= 1 << 7; ptbl.val[3] |= (paction->nMeterId & 0x7F); break; default: break; } } /* FID action */ if (paction->bFidEnable == 1) { ptbl.val[0] |= BIT(1); ptbl.val[5] |= (1 << 3); ptbl.val[2] |= ((paction->nFId) & 0x3F) << 8; } } /* RMON action */ if (IS_VRSN_NOT_31(gswdev->gipver)) { if (paction->bRMON_Action != 0) { ptbl.val[0] |= (1 << 12); ptbl.val[4] &= ~(0x1F << 8); if (paction->nRMON_Id < 24) { ptbl.val[4] |= ((paction->nRMON_Id + 1) << 8); } else { return -1; } } else { ptbl.val[0] &= ~(1 << 12); ptbl.val[4] &= ~(0x1F << 8); } } /* RMON or Flow-ID action. */ if (IS_VRSN_31(gswdev->gipver)) { if ((paction->bFlowID_Action != 0) && (paction->bRMON_Action != 0)) { if (paction->nFlowID != paction->nRMON_Id) { pr_err("RMON counter ID & FlowID should be equal.\n"); return -1; } } if (paction->bFlowID_Action != 0) { if (!(paction->nFlowID)) { pr_err("Flow-ID zero is reserved.\n"); return -1; } ptbl.val[4] |= (0x1 << 4); ptbl.val[1] = paction->nFlowID & 0xFF; } if (paction->bRMON_Action != 0) { if (!(paction->nRMON_Id)) { pr_err("RMON-ID zero is reserved.\n"); return -1; } ptbl.val[4] |= (1 << 4); ptbl.val[1] = paction->nRMON_Id & 0xFF; } } /* Remarking action. */ if (gswdev->gipver <= LTQ_GSWIP_3_0) { ptbl.val[3] |= (0x7 << 12); if (paction->bRemarkDSCP == 1) ptbl.val[3] &= ~(1 << 12); else ptbl.val[3] |= (1 << 12); if (paction->bRemarkClass == 1) ptbl.val[3] &= ~(1 << 13); else ptbl.val[3] |= (1 << 13); if (paction->bRemarkPCP == 1) ptbl.val[3] &= ~(1 << 14); else ptbl.val[3] |= (1 << 14); /* ETC */ if (paction->bRemarkSTAG_PCP == 1) ptbl.val[6] &= ~(1 << 1); else ptbl.val[6] |= (1 << 1); if (paction->bRemarkSTAG_DEI == 1) ptbl.val[6] &= ~(1 << 2); else ptbl.val[6] |= (1 << 2); if (paction->bPortBitMapMuxControl == 1) { ptbl.val[6] |= (1 << 0); ptbl.val[1] = paction->nForwardPortMap[0]; } else ptbl.val[6] &= ~(1 << 0); /* Remarking action enable */ if (paction->bRemarkAction != 0) ptbl.val[0] |= (1 << 3); else ptbl.val[0] &= ~(1 << 3); /* CVLAN Ignore action */ if (paction->bCVLAN_Ignore_Control == 1) { ptbl.val[5] |= (1 << 2); ptbl.val[0] |= (1 << 1); //Govind - why set this bit? } else { ptbl.val[5] &= ~(1 << 2); } } /* Trunking action enable */ if (paction->bPortTrunkAction == 1) ptbl.val[5] |= (1 << 0); /* Port link selection control */ if (paction->bPortLinkSelection == 1) ptbl.val[5] |= (1 << 1); /* IGMP snoop control */ if (IS_VRSN_30_31(gswdev->gipver)) { if (paction->ePortFilterType_Action != GSW_PCE_PORT_FILTER_ACTION_UNUSED) { if (paction->ePortMapAction == GSW_PCE_ACTION_PORTMAP_DISABLE) { ptbl.val[7] &= ~(0x3F << 1); switch (paction->ePortFilterType_Action) { case GSW_PCE_PORT_FILTER_ACTION_1: ptbl.val[7] |= (1 << 1); break; case GSW_PCE_PORT_FILTER_ACTION_2: ptbl.val[7] |= (1 << 2); break; case GSW_PCE_PORT_FILTER_ACTION_3: ptbl.val[7] |= (1 << 3); break; case GSW_PCE_PORT_FILTER_ACTION_4: ptbl.val[7] |= (1 << 4); break; case GSW_PCE_PORT_FILTER_ACTION_5: ptbl.val[7] |= (1 << 5); break; case GSW_PCE_PORT_FILTER_ACTION_6: ptbl.val[7] |= (1 << 6); break; default: break; } if (gswdev->gipver == LTQ_GSWIP_3_0) { ptbl.val[1] = (paction->nForwardPortMap[0] & 0xFFFF); } //Port-member map. if (IS_VRSN_31(gswdev->gipver)) { for (i = 0; i <= 7; i++) ptbl.val[i + 10] = paction->nForwardPortMap[i]; } } } /* Processing path action */ if (paction->eProcessPath_Action != GSW_PCE_PROCESSING_PATH_UNUSED) { ptbl.val[8] |= (1 << 0); switch (paction->eProcessPath_Action) { case GSW_PCE_PROCESSING_PATH_1: ptbl.val[8] |= (1 << 1); break; case GSW_PCE_PROCESSING_PATH_2: ptbl.val[8] |= (1 << 2); break; case GSW_PCE_PROCESSING_PATH_BOTH: ptbl.val[8] |= (3 << 1); break; default: break; } } /* Routing action */ if (gswdev->gipver == LTQ_GSWIP_3_0) { if (gswdev->sdev == LTQ_FLOW_DEV_INT_R) { if (paction->bRoutExtId_Action == 1) ptbl.val[9] |= ((paction->nRoutExtId & 0xFF) << 8); else ptbl.val[9] |= (0xFF << 8); if (paction->bRtDstPortMaskCmp_Action == 1) ptbl.val[9] &= ~(1 << 6); else ptbl.val[9] |= (1 << 6); if (paction->bRtSrcPortMaskCmp_Action == 1) ptbl.val[9] &= ~(1 << 5); else ptbl.val[9] |= (1 << 5); if (paction->bRtDstIpMaskCmp_Action == 1) ptbl.val[9] &= ~(1 << 4); else ptbl.val[9] |= (1 << 4); if (paction->bRtSrcIpMaskCmp_Action == 1) ptbl.val[9] &= ~(1 << 3); else ptbl.val[9] |= (1 << 3); if (paction->bRtInnerIPasKey_Action == 1) ptbl.val[9] |= (1 << 2); else ptbl.val[9] &= ~(1 << 2); if (paction->bRtAccelEna_Action == 1) ptbl.val[9] |= (1 << 1); else ptbl.val[9] &= ~(1 << 1); if (paction->bRtCtrlEna_Action == 1) ptbl.val[9] |= (1 << 0); else ptbl.val[9] &= ~(1 << 0); } } } /* OAM and packet extraction to CPU action */ if (IS_VRSN_31(gswdev->gipver)) { if ((paction->bExtractEnable == 1) || (paction->bOamEnable == 1)) { ptbl.val[8] |= (1 << 0); if (paction->bExtractEnable == 1) { ptbl.val[7] |= (1 << 8); /* Extraction flag */ } if (paction->bOamEnable == 1) { ptbl.val[8] |= (1 << 3); /* OAM flag*/ /*OAM and extraction packet control*/ ptbl.val[8] |= ((paction->nRecordId & 0xFFF) << 4); } } } ptbl.pcindex = idx; ptbl.table = PCE_TFLOW_INDEX; ptbl.valid = 1; status = gsw_pce_table_write(cdev, &ptbl); if (status == GSW_statusOk) return GSW_statusOk; else return status; return GSW_statusOk; }