Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/intel/ice/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 185 kB image not shown  

Quelle  ice_switch.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, Intel Corporation. */

#include "ice_lib.h"
#include "ice_switch.h"
#include "ice_trace.h"

#define ICE_ETH_DA_OFFSET  0
#define ICE_ETH_ETHTYPE_OFFSET  12
#define ICE_ETH_VLAN_TCI_OFFSET  14
#define ICE_MAX_VLAN_ID   0xFFF
#define ICE_IPV6_ETHER_ID  0x86DD

/* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
 * struct to configure any switch filter rules.
 * {DA (6 bytes), SA(6 bytes),
 * Ether type (2 bytes for header without VLAN tag) OR
 * VLAN tag (4 bytes for header with VLAN tag) }
 *
 * Word on Hardcoded values
 * byte 0 = 0x2: to identify it as locally administered DA MAC
 * byte 6 = 0x2: to identify it as locally administered SA MAC
 * byte 12 = 0x81 & byte 13 = 0x00:
 *      In case of VLAN filter first two bytes defines ether type (0x8100)
 *      and remaining two bytes are placeholder for programming a given VLAN ID
 *      In case of Ether type filter it is treated as header without VLAN tag
 *      and byte 12 and 13 is used to program a given Ether type instead
 */

static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
       0x2, 0, 0, 0, 0, 0,
       0x81, 0, 0, 0};

enum {
 ICE_PKT_OUTER_IPV6 = BIT(0),
 ICE_PKT_TUN_GTPC = BIT(1),
 ICE_PKT_TUN_GTPU = BIT(2),
 ICE_PKT_TUN_NVGRE = BIT(3),
 ICE_PKT_TUN_UDP  = BIT(4),
 ICE_PKT_INNER_IPV6 = BIT(5),
 ICE_PKT_INNER_TCP = BIT(6),
 ICE_PKT_INNER_UDP = BIT(7),
 ICE_PKT_GTP_NOPAY = BIT(8),
 ICE_PKT_KMALLOC  = BIT(9),
 ICE_PKT_PPPOE  = BIT(10),
 ICE_PKT_L2TPV3  = BIT(11),
 ICE_PKT_PFCP  = BIT(12),
};

struct ice_dummy_pkt_offsets {
 enum ice_protocol_type type;
 u16 offset; /* ICE_PROTOCOL_LAST indicates end of list */
};

struct ice_dummy_pkt_profile {
 const struct ice_dummy_pkt_offsets *offsets;
 const u8 *pkt;
 u32 match;
 u16 pkt_len;
 u16 offsets_len;
};

#define ICE_DECLARE_PKT_OFFSETS(type)     \
 static const struct ice_dummy_pkt_offsets   \
 ice_dummy_##type##_packet_offsets[]

#define ICE_DECLARE_PKT_TEMPLATE(type)     \
 static const u8 ice_dummy_##type##_packet[]

#define ICE_PKT_PROFILE(type, m) {     \
 .match  = (m),      \
 .pkt  = ice_dummy_##type##_packet,   \
 .pkt_len = sizeof(ice_dummy_##type##_packet),  \
 .offsets = ice_dummy_##type##_packet_offsets,  \
 .offsets_len = sizeof(ice_dummy_##type##_packet_offsets), \
}

ICE_DECLARE_PKT_OFFSETS(vlan) = {
 { ICE_VLAN_OFOS,        12 },
};

ICE_DECLARE_PKT_TEMPLATE(vlan) = {
 0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_OFOS 12 */
};

ICE_DECLARE_PKT_OFFSETS(qinq) = {
 { ICE_VLAN_EX,          12 },
 { ICE_VLAN_IN,          16 },
};

ICE_DECLARE_PKT_TEMPLATE(qinq) = {
 0x91, 0x00, 0x00, 0x00, /* ICE_VLAN_EX 12 */
 0x81, 0x00, 0x00, 0x00, /* ICE_VLAN_IN 16 */
};

ICE_DECLARE_PKT_OFFSETS(gre_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_NVGRE,  34 },
 { ICE_MAC_IL,  42 },
 { ICE_ETYPE_IL,  54 },
 { ICE_IPV4_IL,  56 },
 { ICE_TCP_IL,  76 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(gre_tcp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x3E, /* ICE_IPV4_OFOS 14 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x2F, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_IL 54 */

 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 56 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x06, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 76 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x02, 0x20, 0x00,
 0x00, 0x00, 0x00, 0x00
};

ICE_DECLARE_PKT_OFFSETS(gre_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_NVGRE,  34 },
 { ICE_MAC_IL,  42 },
 { ICE_ETYPE_IL,  54 },
 { ICE_IPV4_IL,  56 },
 { ICE_UDP_ILOS,  76 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(gre_udp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x3E, /* ICE_IPV4_OFOS 14 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x2F, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_IL 54 */

 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 56 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 76 */
 0x00, 0x08, 0x00, 0x00,
};

ICE_DECLARE_PKT_OFFSETS(udp_tun_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_VXLAN,  42 },
 { ICE_GENEVE,  42 },
 { ICE_VXLAN_GPE, 42 },
 { ICE_MAC_IL,  50 },
 { ICE_ETYPE_IL,  62 },
 { ICE_IPV4_IL,  64 },
 { ICE_TCP_IL,  84 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(udp_tun_tcp) = {
 0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */
 0x00, 0x01, 0x00, 0x00,
 0x40, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
 0x00, 0x46, 0x00, 0x00,

 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_IL 62 */

 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_IL 64 */
 0x00, 0x01, 0x00, 0x00,
 0x40, 0x06, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 84 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x02, 0x20, 0x00,
 0x00, 0x00, 0x00, 0x00
};

ICE_DECLARE_PKT_OFFSETS(udp_tun_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_VXLAN,  42 },
 { ICE_GENEVE,  42 },
 { ICE_VXLAN_GPE, 42 },
 { ICE_MAC_IL,  50 },
 { ICE_ETYPE_IL,  62 },
 { ICE_IPV4_IL,  64 },
 { ICE_UDP_ILOS,  84 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(udp_tun_udp) = {
 0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */
 0x00, 0x01, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
 0x00, 0x3a, 0x00, 0x00,

 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_IL 62 */

 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 64 */
 0x00, 0x01, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 84 */
 0x00, 0x08, 0x00, 0x00,
};

ICE_DECLARE_PKT_OFFSETS(gre_ipv6_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_NVGRE,  34 },
 { ICE_MAC_IL,  42 },
 { ICE_ETYPE_IL,  54 },
 { ICE_IPV6_IL,  56 },
 { ICE_TCP_IL,  96 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(gre_ipv6_tcp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x66, /* ICE_IPV4_OFOS 14 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x2F, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x86, 0xdd,  /* ICE_ETYPE_IL 54 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 56 */
 0x00, 0x08, 0x06, 0x40,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 96 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x02, 0x20, 0x00,
 0x00, 0x00, 0x00, 0x00
};

ICE_DECLARE_PKT_OFFSETS(gre_ipv6_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_NVGRE,  34 },
 { ICE_MAC_IL,  42 },
 { ICE_ETYPE_IL,  54 },
 { ICE_IPV6_IL,  56 },
 { ICE_UDP_ILOS,  96 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(gre_ipv6_udp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x2F, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x86, 0xdd,  /* ICE_ETYPE_IL 54 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 56 */
 0x00, 0x08, 0x11, 0x40,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 96 */
 0x00, 0x08, 0x00, 0x00,
};

ICE_DECLARE_PKT_OFFSETS(udp_tun_ipv6_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_VXLAN,  42 },
 { ICE_GENEVE,  42 },
 { ICE_VXLAN_GPE, 42 },
 { ICE_MAC_IL,  50 },
 { ICE_ETYPE_IL,  62 },
 { ICE_IPV6_IL,  64 },
 { ICE_TCP_IL,  104 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(udp_tun_ipv6_tcp) = {
 0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x6e, /* ICE_IPV4_OFOS 14 */
 0x00, 0x01, 0x00, 0x00,
 0x40, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
 0x00, 0x5a, 0x00, 0x00,

 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x86, 0xdd,  /* ICE_ETYPE_IL 62 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 64 */
 0x00, 0x08, 0x06, 0x40,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 104 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x02, 0x20, 0x00,
 0x00, 0x00, 0x00, 0x00
};

ICE_DECLARE_PKT_OFFSETS(udp_tun_ipv6_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_VXLAN,  42 },
 { ICE_GENEVE,  42 },
 { ICE_VXLAN_GPE, 42 },
 { ICE_MAC_IL,  50 },
 { ICE_ETYPE_IL,  62 },
 { ICE_IPV6_IL,  64 },
 { ICE_UDP_ILOS,  104 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(udp_tun_ipv6_udp) = {
 0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x62, /* ICE_IPV4_OFOS 14 */
 0x00, 0x01, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
 0x00, 0x4e, 0x00, 0x00,

 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x86, 0xdd,  /* ICE_ETYPE_IL 62 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 64 */
 0x00, 0x08, 0x11, 0x40,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 104 */
 0x00, 0x08, 0x00, 0x00,
};

/* offset info for MAC + IPv4 + UDP dummy packet */
ICE_DECLARE_PKT_OFFSETS(udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_ILOS,  34 },
 { ICE_PROTOCOL_LAST, 0 },
};

/* Dummy packet for MAC + IPv4 + UDP */
ICE_DECLARE_PKT_TEMPLATE(udp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 14 */
 0x00, 0x01, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 34 */
 0x00, 0x08, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

/* offset info for MAC + IPv4 + TCP dummy packet */
ICE_DECLARE_PKT_OFFSETS(tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_TCP_IL,  34 },
 { ICE_PROTOCOL_LAST, 0 },
};

/* Dummy packet for MAC + IPv4 + TCP */
ICE_DECLARE_PKT_TEMPLATE(tcp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 14 */
 0x00, 0x01, 0x00, 0x00,
 0x00, 0x06, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 34 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(tcp_ipv6) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_TCP_IL,  54 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(tcp_ipv6) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x86, 0xDD,  /* ICE_ETYPE_OL 12 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 54 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

/* IPv6 + UDP */
ICE_DECLARE_PKT_OFFSETS(udp_ipv6) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_UDP_ILOS,  54 },
 { ICE_PROTOCOL_LAST, 0 },
};

/* IPv6 + UDP dummy packet */
ICE_DECLARE_PKT_TEMPLATE(udp_ipv6) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x86, 0xDD,  /* ICE_ETYPE_OL 12 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
 0x00, 0x10, 0x11, 0x00, /* Next header UDP */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 54 */
 0x00, 0x10, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* needed for ESP packets */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_GTP,  42 },
 { ICE_IPV4_IL,  62 },
 { ICE_TCP_IL,  82 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4_tcp) = {
 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x08, 0x00,

 0x45, 0x00, 0x00, 0x58, /* IP 14 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x08, 0x68, /* UDP 34 */
 0x00, 0x44, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
 0x00, 0x00, 0x00, 0x00,

 0x45, 0x00, 0x00, 0x28, /* IP 62 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x06, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* TCP 82 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

/* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner UDP */
ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_GTP,  42 },
 { ICE_IPV4_IL,  62 },
 { ICE_UDP_ILOS,  82 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4_udp) = {
 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x08, 0x00,

 0x45, 0x00, 0x00, 0x4c, /* IP 14 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x08, 0x68, /* UDP 34 */
 0x00, 0x38, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
 0x00, 0x00, 0x00, 0x00,

 0x45, 0x00, 0x00, 0x1c, /* IP 62 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* UDP 82 */
 0x00, 0x08, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

/* Outer IPv6 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv6_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_GTP,  42 },
 { ICE_IPV6_IL,  62 },
 { ICE_TCP_IL,  102 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv6_tcp) = {
 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x08, 0x00,

 0x45, 0x00, 0x00, 0x6c, /* IP 14 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x08, 0x68, /* UDP 34 */
 0x00, 0x58, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
 0x00, 0x00, 0x00, 0x00,

 0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
 0x00, 0x14, 0x06, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* TCP 102 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv6_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_GTP,  42 },
 { ICE_IPV6_IL,  62 },
 { ICE_UDP_ILOS,  102 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv6_udp) = {
 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x08, 0x00,

 0x45, 0x00, 0x00, 0x60, /* IP 14 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x08, 0x68, /* UDP 34 */
 0x00, 0x4c, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
 0x00, 0x00, 0x00, 0x00,

 0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
 0x00, 0x08, 0x11, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* UDP 102 */
 0x00, 0x08, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv4_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_UDP_OF,  54 },
 { ICE_GTP,  62 },
 { ICE_IPV4_IL,  82 },
 { ICE_TCP_IL,  102 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv4_tcp) = {
 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x86, 0xdd,

 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
 0x00, 0x44, 0x11, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x08, 0x68, /* UDP 54 */
 0x00, 0x44, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x34, /* ICE_GTP Header 62 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
 0x00, 0x00, 0x00, 0x00,

 0x45, 0x00, 0x00, 0x28, /* IP 82 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x06, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* TCP 102 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv4_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_UDP_OF,  54 },
 { ICE_GTP,  62 },
 { ICE_IPV4_IL,  82 },
 { ICE_UDP_ILOS,  102 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv4_udp) = {
 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x86, 0xdd,

 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
 0x00, 0x38, 0x11, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x08, 0x68, /* UDP 54 */
 0x00, 0x38, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x28, /* ICE_GTP Header 62 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
 0x00, 0x00, 0x00, 0x00,

 0x45, 0x00, 0x00, 0x1c, /* IP 82 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* UDP 102 */
 0x00, 0x08, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv6_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_UDP_OF,  54 },
 { ICE_GTP,  62 },
 { ICE_IPV6_IL,  82 },
 { ICE_TCP_IL,  122 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv6_tcp) = {
 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x86, 0xdd,

 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
 0x00, 0x58, 0x11, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x08, 0x68, /* UDP 54 */
 0x00, 0x58, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x48, /* ICE_GTP Header 62 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
 0x00, 0x00, 0x00, 0x00,

 0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
 0x00, 0x14, 0x06, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* TCP 122 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv6_gtpu_ipv6_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_UDP_OF,  54 },
 { ICE_GTP,  62 },
 { ICE_IPV6_IL,  82 },
 { ICE_UDP_ILOS,  122 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv6_gtpu_ipv6_udp) = {
 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x86, 0xdd,

 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
 0x00, 0x4c, 0x11, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x08, 0x68, /* UDP 54 */
 0x00, 0x4c, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x3c, /* ICE_GTP Header 62 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
 0x00, 0x00, 0x00, 0x00,

 0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
 0x00, 0x08, 0x11, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* UDP 122 */
 0x00, 0x08, 0x00, 0x00,

 0x00, 0x00, /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv4_gtpu_ipv4) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_OF,  34 },
 { ICE_GTP_NO_PAY, 42 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv4_gtpu_ipv4) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x08, 0x00,

 0x45, 0x00, 0x00, 0x44, /* ICE_IPV4_OFOS 14 */
 0x00, 0x00, 0x40, 0x00,
 0x40, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 34 */
 0x00, 0x00, 0x00, 0x00,

 0x34, 0xff, 0x00, 0x28, /* ICE_GTP 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x85,

 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
 0x00, 0x00, 0x00, 0x00,

 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 62 */
 0x00, 0x00, 0x40, 0x00,
 0x40, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00,
};

ICE_DECLARE_PKT_OFFSETS(ipv6_gtp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_UDP_OF,  54 },
 { ICE_GTP_NO_PAY, 62 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv6_gtp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x86, 0xdd,

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
 0x00, 0x6c, 0x11, 0x00, /* Next header UDP*/
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 54 */
 0x00, 0x00, 0x00, 0x00,

 0x30, 0x00, 0x00, 0x28, /* ICE_GTP 62 */
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00,
};

ICE_DECLARE_PKT_OFFSETS(pfcp_session_ipv4) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_UDP_ILOS,  34 },
 { ICE_PFCP,  42 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(pfcp_session_ipv4) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x2c, /* ICE_IPV4_OFOS 14 */
 0x00, 0x01, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x22, 0x65, /* ICE_UDP_ILOS 34 */
 0x00, 0x18, 0x00, 0x00,

 0x21, 0x01, 0x00, 0x0c, /* ICE_PFCP 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00,  /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(pfcp_session_ipv6) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_UDP_ILOS,  54 },
 { ICE_PFCP,  62 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(pfcp_session_ipv6) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x86, 0xdd,  /* ICE_ETYPE_OL 12 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
 0x00, 0x10, 0x11, 0x00, /* Next header UDP */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x22, 0x65, /* ICE_UDP_ILOS 54 */
 0x00, 0x18, 0x00, 0x00,

 0x21, 0x01, 0x00, 0x0c, /* ICE_PFCP 62 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00,  /* 2 bytes for 4 byte alignment */
};

ICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_PPPOE,  14 },
 { ICE_IPV4_OFOS, 22 },
 { ICE_TCP_IL,  42 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv4_tcp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x88, 0x64,  /* ICE_ETYPE_OL 12 */

 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
 0x00, 0x16,

 0x00, 0x21,  /* PPP Link Layer 20 */

 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 22 */
 0x00, 0x01, 0x00, 0x00,
 0x00, 0x06, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 42 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00,  /* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(pppoe_ipv4_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_PPPOE,  14 },
 { ICE_IPV4_OFOS, 22 },
 { ICE_UDP_ILOS,  42 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv4_udp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x88, 0x64,  /* ICE_ETYPE_OL 12 */

 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
 0x00, 0x16,

 0x00, 0x21,  /* PPP Link Layer 20 */

 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 22 */
 0x00, 0x01, 0x00, 0x00,
 0x00, 0x11, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 42 */
 0x00, 0x08, 0x00, 0x00,

 0x00, 0x00,  /* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(pppoe_ipv6_tcp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_PPPOE,  14 },
 { ICE_IPV6_OFOS, 22 },
 { ICE_TCP_IL,  62 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_tcp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x88, 0x64,  /* ICE_ETYPE_OL 12 */

 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
 0x00, 0x2a,

 0x00, 0x57,  /* PPP Link Layer 20 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 62 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x50, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00,  /* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(pppoe_ipv6_udp) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_PPPOE,  14 },
 { ICE_IPV6_OFOS, 22 },
 { ICE_UDP_ILOS,  62 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(pppoe_ipv6_udp) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x88, 0x64,  /* ICE_ETYPE_OL 12 */

 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 14 */
 0x00, 0x2a,

 0x00, 0x57,  /* PPP Link Layer 20 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
 0x00, 0x08, 0x11, 0x00, /* Next header UDP*/
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 62 */
 0x00, 0x08, 0x00, 0x00,

 0x00, 0x00,  /* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv4_l2tpv3) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV4_OFOS, 14 },
 { ICE_L2TPV3,  34 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv4_l2tpv3) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x08, 0x00,  /* ICE_ETYPE_OL 12 */

 0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */
 0x00, 0x00, 0x40, 0x00,
 0x40, 0x73, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 34 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00,  /* 2 bytes for 4 bytes alignment */
};

ICE_DECLARE_PKT_OFFSETS(ipv6_l2tpv3) = {
 { ICE_MAC_OFOS,  0 },
 { ICE_ETYPE_OL,  12 },
 { ICE_IPV6_OFOS, 14 },
 { ICE_L2TPV3,  54 },
 { ICE_PROTOCOL_LAST, 0 },
};

ICE_DECLARE_PKT_TEMPLATE(ipv6_l2tpv3) = {
 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x86, 0xDD,  /* ICE_ETYPE_OL 12 */

 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 14 */
 0x00, 0x0c, 0x73, 0x40,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,

 0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 54 */
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00,  /* 2 bytes for 4 bytes alignment */
};

static const struct ice_dummy_pkt_profile ice_dummy_pkt_profiles[] = {
 ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPU | ICE_PKT_OUTER_IPV6 |
      ICE_PKT_GTP_NOPAY),
 ICE_PKT_PROFILE(ipv6_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
         ICE_PKT_OUTER_IPV6 |
         ICE_PKT_INNER_IPV6 |
         ICE_PKT_INNER_UDP),
 ICE_PKT_PROFILE(ipv6_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU |
         ICE_PKT_OUTER_IPV6 |
         ICE_PKT_INNER_IPV6),
 ICE_PKT_PROFILE(ipv6_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU |
         ICE_PKT_OUTER_IPV6 |
         ICE_PKT_INNER_UDP),
 ICE_PKT_PROFILE(ipv6_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU |
         ICE_PKT_OUTER_IPV6),
 ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPU | ICE_PKT_GTP_NOPAY),
 ICE_PKT_PROFILE(ipv4_gtpu_ipv6_udp, ICE_PKT_TUN_GTPU |
         ICE_PKT_INNER_IPV6 |
         ICE_PKT_INNER_UDP),
 ICE_PKT_PROFILE(ipv4_gtpu_ipv6_tcp, ICE_PKT_TUN_GTPU |
         ICE_PKT_INNER_IPV6),
 ICE_PKT_PROFILE(ipv4_gtpu_ipv4_udp, ICE_PKT_TUN_GTPU |
         ICE_PKT_INNER_UDP),
 ICE_PKT_PROFILE(ipv4_gtpu_ipv4_tcp, ICE_PKT_TUN_GTPU),
 ICE_PKT_PROFILE(ipv6_gtp, ICE_PKT_TUN_GTPC | ICE_PKT_OUTER_IPV6),
 ICE_PKT_PROFILE(ipv4_gtpu_ipv4, ICE_PKT_TUN_GTPC),
 ICE_PKT_PROFILE(pfcp_session_ipv6, ICE_PKT_PFCP | ICE_PKT_OUTER_IPV6),
 ICE_PKT_PROFILE(pfcp_session_ipv4, ICE_PKT_PFCP),
 ICE_PKT_PROFILE(pppoe_ipv6_udp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6 |
     ICE_PKT_INNER_UDP),
 ICE_PKT_PROFILE(pppoe_ipv6_tcp, ICE_PKT_PPPOE | ICE_PKT_OUTER_IPV6),
 ICE_PKT_PROFILE(pppoe_ipv4_udp, ICE_PKT_PPPOE | ICE_PKT_INNER_UDP),
 ICE_PKT_PROFILE(pppoe_ipv4_tcp, ICE_PKT_PPPOE),
 ICE_PKT_PROFILE(gre_ipv6_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6 |
          ICE_PKT_INNER_TCP),
 ICE_PKT_PROFILE(gre_tcp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_TCP),
 ICE_PKT_PROFILE(gre_ipv6_udp, ICE_PKT_TUN_NVGRE | ICE_PKT_INNER_IPV6),
 ICE_PKT_PROFILE(gre_udp, ICE_PKT_TUN_NVGRE),
 ICE_PKT_PROFILE(udp_tun_ipv6_tcp, ICE_PKT_TUN_UDP |
       ICE_PKT_INNER_IPV6 |
       ICE_PKT_INNER_TCP),
 ICE_PKT_PROFILE(ipv6_l2tpv3, ICE_PKT_L2TPV3 | ICE_PKT_OUTER_IPV6),
 ICE_PKT_PROFILE(ipv4_l2tpv3, ICE_PKT_L2TPV3),
 ICE_PKT_PROFILE(udp_tun_tcp, ICE_PKT_TUN_UDP | ICE_PKT_INNER_TCP),
 ICE_PKT_PROFILE(udp_tun_ipv6_udp, ICE_PKT_TUN_UDP |
       ICE_PKT_INNER_IPV6),
 ICE_PKT_PROFILE(udp_tun_udp, ICE_PKT_TUN_UDP),
 ICE_PKT_PROFILE(udp_ipv6, ICE_PKT_OUTER_IPV6 | ICE_PKT_INNER_UDP),
 ICE_PKT_PROFILE(udp, ICE_PKT_INNER_UDP),
 ICE_PKT_PROFILE(tcp_ipv6, ICE_PKT_OUTER_IPV6),
 ICE_PKT_PROFILE(tcp, 0),
};

/* this is a recipe to profile association bitmap */
static DECLARE_BITMAP(recipe_to_profile[ICE_MAX_NUM_RECIPES],
     ICE_MAX_NUM_PROFILES);

/* this is a profile to recipe association bitmap */
static DECLARE_BITMAP(profile_to_recipe[ICE_MAX_NUM_PROFILES],
     ICE_MAX_NUM_RECIPES);

/**
 * ice_init_def_sw_recp - initialize the recipe book keeping tables
 * @hw: pointer to the HW struct
 *
 * Allocate memory for the entire recipe table and initialize the structures/
 * entries corresponding to basic recipes.
 */

int ice_init_def_sw_recp(struct ice_hw *hw)
{
 struct ice_sw_recipe *recps;
 u8 i;

 recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES,
        sizeof(*recps), GFP_KERNEL);
 if (!recps)
  return -ENOMEM;

 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
  recps[i].root_rid = i;
  INIT_LIST_HEAD(&recps[i].filt_rules);
  INIT_LIST_HEAD(&recps[i].filt_replay_rules);
  mutex_init(&recps[i].filt_rule_lock);
 }

 hw->switch_info->recp_list = recps;

 return 0;
}

/**
 * ice_aq_get_sw_cfg - get switch configuration
 * @hw: pointer to the hardware structure
 * @buf: pointer to the result buffer
 * @buf_size: length of the buffer available for response
 * @req_desc: pointer to requested descriptor
 * @num_elems: pointer to number of elements
 * @cd: pointer to command details structure or NULL
 *
 * Get switch configuration (0x0200) to be placed in buf.
 * This admin command returns information such as initial VSI/port number
 * and switch ID it belongs to.
 *
 * NOTE: *req_desc is both an input/output parameter.
 * The caller of this function first calls this function with *request_desc set
 * to 0. If the response from f/w has *req_desc set to 0, all the switch
 * configuration information has been returned; if non-zero (meaning not all
 * the information was returned), the caller should call this function again
 * with *req_desc set to the previous value returned by f/w to get the
 * next block of switch configuration information.
 *
 * *num_elems is output only parameter. This reflects the number of elements
 * in response buffer. The caller of this function to use *num_elems while
 * parsing the response buffer.
 */

static int
ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
    u16 buf_size, u16 *req_desc, u16 *num_elems,
    struct ice_sq_cd *cd)
{
 struct ice_aqc_get_sw_cfg *cmd;
 struct libie_aq_desc desc;
 int status;

 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
 cmd = libie_aq_raw(&desc);
 cmd->element = cpu_to_le16(*req_desc);

 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
 if (!status) {
  *req_desc = le16_to_cpu(cmd->element);
  *num_elems = le16_to_cpu(cmd->num_elems);
 }

 return status;
}

/**
 * ice_aq_add_vsi
 * @hw: pointer to the HW struct
 * @vsi_ctx: pointer to a VSI context struct
 * @cd: pointer to command details structure or NULL
 *
 * Add a VSI context to the hardware (0x0210)
 */

static int
ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
        struct ice_sq_cd *cd)
{
 struct ice_aqc_add_update_free_vsi_resp *res;
 struct ice_aqc_add_get_update_free_vsi *cmd;
 struct libie_aq_desc desc;
 int status;

 cmd = libie_aq_raw(&desc);
 res = libie_aq_raw(&desc);

 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);

 if (!vsi_ctx->alloc_from_pool)
  cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num |
        ICE_AQ_VSI_IS_VALID);
 cmd->vf_id = vsi_ctx->vf_num;

 cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);

 desc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);

 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
     sizeof(vsi_ctx->info), cd);

 if (!status) {
  vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M;
  vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used);
  vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free);
 }

 return status;
}

/**
 * ice_aq_free_vsi
 * @hw: pointer to the HW struct
 * @vsi_ctx: pointer to a VSI context struct
 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
 * @cd: pointer to command details structure or NULL
 *
 * Free VSI context info from hardware (0x0213)
 */

static int
ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
  bool keep_vsi_alloc, struct ice_sq_cd *cd)
{
 struct ice_aqc_add_update_free_vsi_resp *resp;
 struct ice_aqc_add_get_update_free_vsi *cmd;
 struct libie_aq_desc desc;
 int status;

 cmd = libie_aq_raw(&desc);
 resp = libie_aq_raw(&desc);

 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);

 cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
 if (keep_vsi_alloc)
  cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC);

 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
 if (!status) {
  vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
  vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
 }

 return status;
}

/**
 * ice_aq_update_vsi
 * @hw: pointer to the HW struct
 * @vsi_ctx: pointer to a VSI context struct
 * @cd: pointer to command details structure or NULL
 *
 * Update VSI context in the hardware (0x0211)
 */

static int
ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
    struct ice_sq_cd *cd)
{
 struct ice_aqc_add_update_free_vsi_resp *resp;
 struct ice_aqc_add_get_update_free_vsi *cmd;
 struct libie_aq_desc desc;
 int status;

 cmd = libie_aq_raw(&desc);
 resp = libie_aq_raw(&desc);

 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);

 cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);

 desc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);

 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
     sizeof(vsi_ctx->info), cd);

 if (!status) {
  vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
  vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
 }

 return status;
}

/**
 * ice_is_vsi_valid - check whether the VSI is valid or not
 * @hw: pointer to the HW struct
 * @vsi_handle: VSI handle
 *
 * check whether the VSI is valid or not
 */

bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
{
 return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
}

/**
 * ice_get_hw_vsi_num - return the HW VSI number
 * @hw: pointer to the HW struct
 * @vsi_handle: VSI handle
 *
 * return the HW VSI number
 * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
 */

u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
{
 return hw->vsi_ctx[vsi_handle]->vsi_num;
}

/**
 * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
 * @hw: pointer to the HW struct
 * @vsi_handle: VSI handle
 *
 * return the VSI context entry for a given VSI handle
 */

struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
{
 return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
}

/**
 * ice_save_vsi_ctx - save the VSI context for a given VSI handle
 * @hw: pointer to the HW struct
 * @vsi_handle: VSI handle
 * @vsi: VSI context pointer
 *
 * save the VSI context entry for a given VSI handle
 */

static void
ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
{
 hw->vsi_ctx[vsi_handle] = vsi;
}

/**
 * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
 * @hw: pointer to the HW struct
 * @vsi_handle: VSI handle
 */

static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
{
 struct ice_vsi_ctx *vsi = ice_get_vsi_ctx(hw, vsi_handle);
 u8 i;

 if (!vsi)
  return;
 ice_for_each_traffic_class(i) {
  devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
  vsi->lan_q_ctx[i] = NULL;
  devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
  vsi->rdma_q_ctx[i] = NULL;
 }
}

/**
 * ice_clear_vsi_ctx - clear the VSI context entry
 * @hw: pointer to the HW struct
 * @vsi_handle: VSI handle
 *
 * clear the VSI context entry
 */

static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
{
 struct ice_vsi_ctx *vsi;

 vsi = ice_get_vsi_ctx(hw, vsi_handle);
 if (vsi) {
  ice_clear_vsi_q_ctx(hw, vsi_handle);
  devm_kfree(ice_hw_to_dev(hw), vsi);
  hw->vsi_ctx[vsi_handle] = NULL;
 }
}

/**
 * ice_clear_all_vsi_ctx - clear all the VSI context entries
 * @hw: pointer to the HW struct
 */

void ice_clear_all_vsi_ctx(struct ice_hw *hw)
{
 u16 i;

 for (i = 0; i < ICE_MAX_VSI; i++)
  ice_clear_vsi_ctx(hw, i);
}

/**
 * ice_add_vsi - add VSI context to the hardware and VSI handle list
 * @hw: pointer to the HW struct
 * @vsi_handle: unique VSI handle provided by drivers
 * @vsi_ctx: pointer to a VSI context struct
 * @cd: pointer to command details structure or NULL
 *
 * Add a VSI context to the hardware also add it into the VSI handle list.
 * If this function gets called after reset for existing VSIs then update
 * with the new HW VSI number in the corresponding VSI handle list entry.
 */

int
ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
     struct ice_sq_cd *cd)
{
 struct ice_vsi_ctx *tmp_vsi_ctx;
 int status;

 if (vsi_handle >= ICE_MAX_VSI)
  return -EINVAL;
 status = ice_aq_add_vsi(hw, vsi_ctx, cd);
 if (status)
  return status;
 tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
 if (!tmp_vsi_ctx) {
  /* Create a new VSI context */
  tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw),
        sizeof(*tmp_vsi_ctx), GFP_KERNEL);
  if (!tmp_vsi_ctx) {
   ice_aq_free_vsi(hw, vsi_ctx, false, cd);
   return -ENOMEM;
  }
  *tmp_vsi_ctx = *vsi_ctx;
  ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
 } else {
  /* update with new HW VSI num */
  tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
 }

 return 0;
}

/**
 * ice_free_vsi- free VSI context from hardware and VSI handle list
 * @hw: pointer to the HW struct
 * @vsi_handle: unique VSI handle
 * @vsi_ctx: pointer to a VSI context struct
 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
 * @cd: pointer to command details structure or NULL
 *
 * Free VSI context info from hardware as well as from VSI handle list
 */

int
ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
      bool keep_vsi_alloc, struct ice_sq_cd *cd)
{
 int status;

 if (!ice_is_vsi_valid(hw, vsi_handle))
  return -EINVAL;
 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
 status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
 if (!status)
  ice_clear_vsi_ctx(hw, vsi_handle);
 return status;
}

/**
 * ice_update_vsi
 * @hw: pointer to the HW struct
 * @vsi_handle: unique VSI handle
 * @vsi_ctx: pointer to a VSI context struct
 * @cd: pointer to command details structure or NULL
 *
 * Update VSI context in the hardware
 */

int
ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
        struct ice_sq_cd *cd)
{
 if (!ice_is_vsi_valid(hw, vsi_handle))
  return -EINVAL;
 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
 return ice_aq_update_vsi(hw, vsi_ctx, cd);
}

/**
 * ice_cfg_rdma_fltr - enable/disable RDMA filtering on VSI
 * @hw: pointer to HW struct
 * @vsi_handle: VSI SW index
 * @enable: boolean for enable/disable
 */

int
ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable)
{
 struct ice_vsi_ctx *ctx, *cached_ctx;
 int status;

 cached_ctx = ice_get_vsi_ctx(hw, vsi_handle);
 if (!cached_ctx)
  return -ENOENT;

 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 if (!ctx)
  return -ENOMEM;

 ctx->info.q_opt_rss = cached_ctx->info.q_opt_rss;
 ctx->info.q_opt_tc = cached_ctx->info.q_opt_tc;
 ctx->info.q_opt_flags = cached_ctx->info.q_opt_flags;

 ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);

 if (enable)
  ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
 else
  ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;

 status = ice_update_vsi(hw, vsi_handle, ctx, NULL);
 if (!status) {
  cached_ctx->info.q_opt_flags = ctx->info.q_opt_flags;
  cached_ctx->info.valid_sections |= ctx->info.valid_sections;
 }

 kfree(ctx);
 return status;
}

/**
 * ice_aq_alloc_free_vsi_list
 * @hw: pointer to the HW struct
 * @vsi_list_id: VSI list ID returned or used for lookup
 * @lkup_type: switch rule filter lookup type
 * @opc: switch rules population command type - pass in the command opcode
 *
 * allocates or free a VSI list resource
 */

static int
ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
      enum ice_sw_lkup_type lkup_type,
      enum ice_adminq_opc opc)
{
 DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
 u16 buf_len = __struct_size(sw_buf);
 struct ice_aqc_res_elem *vsi_ele;
 int status;

 sw_buf->num_elems = cpu_to_le16(1);

 if (lkup_type == ICE_SW_LKUP_MAC ||
     lkup_type == ICE_SW_LKUP_MAC_VLAN ||
     lkup_type == ICE_SW_LKUP_ETHERTYPE ||
     lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
     lkup_type == ICE_SW_LKUP_PROMISC ||
     lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
     lkup_type == ICE_SW_LKUP_DFLT ||
     lkup_type == ICE_SW_LKUP_LAST) {
  sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
 } else if (lkup_type == ICE_SW_LKUP_VLAN) {
  if (opc == ice_aqc_opc_alloc_res)
   sw_buf->res_type =
    cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE |
         ICE_AQC_RES_TYPE_FLAG_SHARED);
  else
   sw_buf->res_type =
    cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
 } else {
  return -EINVAL;
 }

 if (opc == ice_aqc_opc_free_res)
  sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id);

 status = ice_aq_alloc_free_res(hw, sw_buf, buf_len, opc);
 if (status)
  return status;

 if (opc == ice_aqc_opc_alloc_res) {
  vsi_ele = &sw_buf->elem[0];
  *vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp);
 }

 return 0;
}

/**
 * ice_aq_sw_rules - add/update/remove switch rules
 * @hw: pointer to the HW struct
 * @rule_list: pointer to switch rule population list
 * @rule_list_sz: total size of the rule list in bytes
 * @num_rules: number of switch rules in the rule_list
 * @opc: switch rules population command type - pass in the command opcode
 * @cd: pointer to command details structure or NULL
 *
 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
 */

int
ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
  u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
{
 struct ice_aqc_sw_rules *cmd;
 struct libie_aq_desc desc;
 int status;

 if (opc != ice_aqc_opc_add_sw_rules &&
     opc != ice_aqc_opc_update_sw_rules &&
     opc != ice_aqc_opc_remove_sw_rules)
  return -EINVAL;

 ice_fill_dflt_direct_cmd_desc(&desc, opc);
 cmd = libie_aq_raw(&desc);

 desc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);
 cmd->num_rules_fltr_entry_index = cpu_to_le16(num_rules);
 status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
 if (opc != ice_aqc_opc_add_sw_rules &&
     hw->adminq.sq_last_status == LIBIE_AQ_RC_ENOENT)
  status = -ENOENT;

 if (!status) {
  if (opc == ice_aqc_opc_add_sw_rules)
   hw->switch_info->rule_cnt += num_rules;
  else if (opc == ice_aqc_opc_remove_sw_rules)
   hw->switch_info->rule_cnt -= num_rules;
 }

 trace_ice_aq_sw_rules(hw->switch_info);

 return status;
}

/**
 * ice_aq_add_recipe - add switch recipe
 * @hw: pointer to the HW struct
 * @s_recipe_list: pointer to switch rule population list
 * @num_recipes: number of switch recipes in the list
 * @cd: pointer to command details structure or NULL
 *
 * Add(0x0290)
 */

int
ice_aq_add_recipe(struct ice_hw *hw,
    struct ice_aqc_recipe_data_elem *s_recipe_list,
    u16 num_recipes, struct ice_sq_cd *cd)
{
 struct ice_aqc_add_get_recipe *cmd;
 struct libie_aq_desc desc;
 u16 buf_size;

 cmd = libie_aq_raw(&desc);
 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);

 cmd->num_sub_recipes = cpu_to_le16(num_recipes);
 desc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD);

 buf_size = num_recipes * sizeof(*s_recipe_list);

 return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
}

/**
 * ice_aq_get_recipe - get switch recipe
 * @hw: pointer to the HW struct
 * @s_recipe_list: pointer to switch rule population list
 * @num_recipes: pointer to the number of recipes (input and output)
 * @recipe_root: root recipe number of recipe(s) to retrieve
 * @cd: pointer to command details structure or NULL
 *
 * Get(0x0292)
 *
 * On input, *num_recipes should equal the number of entries in s_recipe_list.
 * On output, *num_recipes will equal the number of entries returned in
 * s_recipe_list.
 *
 * The caller must supply enough space in s_recipe_list to hold all possible
 * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES.
 */

int
ice_aq_get_recipe(struct ice_hw *hw,
    struct ice_aqc_recipe_data_elem *s_recipe_list,
    u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd)
{
 struct ice_aqc_add_get_recipe *cmd;
 struct libie_aq_desc desc;
 u16 buf_size;
 int status;

 if (*num_recipes != ICE_MAX_NUM_RECIPES)
  return -EINVAL;

 cmd = libie_aq_raw(&desc);
 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);

 cmd->return_index = cpu_to_le16(recipe_root);
 cmd->num_sub_recipes = 0;

 buf_size = *num_recipes * sizeof(*s_recipe_list);

 status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
 *num_recipes = le16_to_cpu(cmd->num_sub_recipes);

 return status;
}

/**
 * ice_update_recipe_lkup_idx - update a default recipe based on the lkup_idx
 * @hw: pointer to the HW struct
 * @params: parameters used to update the default recipe
 *
 * This function only supports updating default recipes and it only supports
 * updating a single recipe based on the lkup_idx at a time.
 *
 * This is done as a read-modify-write operation. First, get the current recipe
 * contents based on the recipe's ID. Then modify the field vector index and
 * mask if it's valid at the lkup_idx. Finally, use the add recipe AQ to update
 * the pre-existing recipe with the modifications.
 */

int
ice_update_recipe_lkup_idx(struct ice_hw *hw,
      struct ice_update_recipe_lkup_idx_params *params)
{
 struct ice_aqc_recipe_data_elem *rcp_list;
 u16 num_recps = ICE_MAX_NUM_RECIPES;
 int status;

 rcp_list = kcalloc(num_recps, sizeof(*rcp_list), GFP_KERNEL);
 if (!rcp_list)
  return -ENOMEM;

 /* read current recipe list from firmware */
 rcp_list->recipe_indx = params->rid;
 status = ice_aq_get_recipe(hw, rcp_list, &num_recps, params->rid, NULL);
 if (status) {
  ice_debug(hw, ICE_DBG_SW, "Failed to get recipe %d, status %d\n",
     params->rid, status);
  goto error_out;
 }

 /* only modify existing recipe's lkup_idx and mask if valid, while
 * leaving all other fields the same, then update the recipe firmware
 */

 rcp_list->content.lkup_indx[params->lkup_idx] = params->fv_idx;
 if (params->mask_valid)
  rcp_list->content.mask[params->lkup_idx] =
   cpu_to_le16(params->mask);

 if (params->ignore_valid)
  rcp_list->content.lkup_indx[params->lkup_idx] |=
   ICE_AQ_RECIPE_LKUP_IGNORE;

 status = ice_aq_add_recipe(hw, &rcp_list[0], 1, NULL);
 if (status)
  ice_debug(hw, ICE_DBG_SW, "Failed to update recipe %d lkup_idx %d fv_idx %d mask %d mask_valid %s, status %d\n",
     params->rid, params->lkup_idx, params->fv_idx,
     params->mask, params->mask_valid ? "true" : "false",
     status);

error_out:
 kfree(rcp_list);
 return status;
}

/**
 * ice_aq_map_recipe_to_profile - Map recipe to packet profile
 * @hw: pointer to the HW struct
 * @profile_id: package profile ID to associate the recipe with
 * @r_assoc: Recipe bitmap filled in and need to be returned as response
 * @cd: pointer to command details structure or NULL
 * Recipe to profile association (0x0291)
 */

int
ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 r_assoc,
        struct ice_sq_cd *cd)
{
 struct ice_aqc_recipe_to_profile *cmd;
 struct libie_aq_desc desc;

 cmd = libie_aq_raw(&desc);
 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);
 cmd->profile_id = cpu_to_le16(profile_id);
 /* Set the recipe ID bit in the bitmask to let the device know which
 * profile we are associating the recipe to
 */

 cmd->recipe_assoc = cpu_to_le64(r_assoc);

 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
}

/**
 * ice_aq_get_recipe_to_profile - Map recipe to packet profile
 * @hw: pointer to the HW struct
 * @profile_id: package profile ID to associate the recipe with
 * @r_assoc: Recipe bitmap filled in and need to be returned as response
 * @cd: pointer to command details structure or NULL
 * Associate profile ID with given recipe (0x0293)
 */

int
ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 *r_assoc,
        struct ice_sq_cd *cd)
{
 struct ice_aqc_recipe_to_profile *cmd;
 struct libie_aq_desc desc;
 int status;

 cmd = libie_aq_raw(&desc);
 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);
 cmd->profile_id = cpu_to_le16(profile_id);

 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
 if (!status)
  *r_assoc = le64_to_cpu(cmd->recipe_assoc);

 return status;
}

/**
 * ice_init_chk_recipe_reuse_support - check if recipe reuse is supported
 * @hw: pointer to the hardware structure
 */

void ice_init_chk_recipe_reuse_support(struct ice_hw *hw)
{
 struct ice_nvm_info *nvm = &hw->flash.nvm;

 hw->recp_reuse = (nvm->major == 0x4 && nvm->minor >= 0x30) ||
    nvm->major > 0x4;
}

/**
 * ice_alloc_recipe - add recipe resource
 * @hw: pointer to the hardware structure
 * @rid: recipe ID returned as response to AQ call
 */

int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
{
 DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
 u16 buf_len = __struct_size(sw_buf);
 u16 res_type;
 int status;

 sw_buf->num_elems = cpu_to_le16(1);
 res_type = FIELD_PREP(ICE_AQC_RES_TYPE_M, ICE_AQC_RES_TYPE_RECIPE);
 if (hw->recp_reuse)
  res_type |= ICE_AQC_RES_TYPE_FLAG_SUBSCRIBE_SHARED;
 else
  res_type |= ICE_AQC_RES_TYPE_FLAG_SHARED;
 sw_buf->res_type = cpu_to_le16(res_type);
 status = ice_aq_alloc_free_res(hw, sw_buf, buf_len,
           ice_aqc_opc_alloc_res);
 if (!status) {
  *rid = le16_to_cpu(sw_buf->elem[0].e.sw_resp);
  hw->switch_info->recp_cnt++;
 }

 return status;
}

/**
 * ice_free_recipe_res - free recipe resource
 * @hw: pointer to the hardware structure
 * @rid: recipe ID to free
 *
 * Return: 0 on success, and others on error
 */

static int ice_free_recipe_res(struct ice_hw *hw, u16 rid)
{
 int status;

 status = ice_free_hw_res(hw, ICE_AQC_RES_TYPE_RECIPE, 1, &rid);
 if (!status)
  hw->switch_info->recp_cnt--;

 return status;
}

/**
 * ice_release_recipe_res - disassociate and free recipe resource
 * @hw: pointer to the hardware structure
 * @recp: the recipe struct resource to unassociate and free
 *
 * Return: 0 on success, and others on error
 */

static int ice_release_recipe_res(struct ice_hw *hw,
      struct ice_sw_recipe *recp)
{
 DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
 struct ice_switch_info *sw = hw->switch_info;
 u64 recp_assoc;
 u32 rid, prof;
 int status;

 for_each_set_bit(rid, recp->r_bitmap, ICE_MAX_NUM_RECIPES) {
  for_each_set_bit(prof, recipe_to_profile[rid],
     ICE_MAX_NUM_PROFILES) {
   status = ice_aq_get_recipe_to_profile(hw, prof,
             &recp_assoc,
             NULL);
   if (status)
    return status;

   bitmap_from_arr64(r_bitmap, &recp_assoc,
       ICE_MAX_NUM_RECIPES);
   bitmap_andnot(r_bitmap, r_bitmap, recp->r_bitmap,
          ICE_MAX_NUM_RECIPES);
   bitmap_to_arr64(&recp_assoc, r_bitmap,
     ICE_MAX_NUM_RECIPES);
   ice_aq_map_recipe_to_profile(hw, prof,
           recp_assoc, NULL);

   clear_bit(rid, profile_to_recipe[prof]);
   clear_bit(prof, recipe_to_profile[rid]);
  }

  status = ice_free_recipe_res(hw, rid);
  if (status)
   return status;

  sw->recp_list[rid].recp_created = false;
  sw->recp_list[rid].adv_rule = false;
  memset(&sw->recp_list[rid].lkup_exts, 0,
         sizeof(sw->recp_list[rid].lkup_exts));
  clear_bit(rid, recp->r_bitmap);
 }

 return 0;
}

/**
 * ice_get_recp_to_prof_map - updates recipe to profile mapping
 * @hw: pointer to hardware structure
 *
 * This function is used to populate recipe_to_profile matrix where index to
 * this array is the recipe ID and the element is the mapping of which profiles
 * is this recipe mapped to.
 */

static void ice_get_recp_to_prof_map(struct ice_hw *hw)
{
 DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
 u64 recp_assoc;
 u16 i;

 for (i = 0; i < hw->switch_info->max_used_prof_index + 1; i++) {
  u16 j;

  bitmap_zero(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);
  bitmap_zero(r_bitmap, ICE_MAX_NUM_RECIPES);
  if (ice_aq_get_recipe_to_profile(hw, i, &recp_assoc, NULL))
   continue;
  bitmap_from_arr64(r_bitmap, &recp_assoc, ICE_MAX_NUM_RECIPES);
  bitmap_copy(profile_to_recipe[i], r_bitmap,
       ICE_MAX_NUM_RECIPES);
  for_each_set_bit(j, r_bitmap, ICE_MAX_NUM_RECIPES)
   set_bit(i, recipe_to_profile[j]);
 }
}

/**
 * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries
 * @hw: pointer to hardware structure
 * @recps: struct that we need to populate
 * @rid: recipe ID that we are populating
 * @refresh_required: true if we should get recipe to profile mapping from FW
 * @is_add: flag of adding recipe
 *
 * This function is used to populate all the necessary entries into our
 * bookkeeping so that we have a current list of all the recipes that are
 * programmed in the firmware.
 */

static int
ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
      bool *refresh_required, bool is_add)
{
 DECLARE_BITMAP(result_bm, ICE_MAX_FV_WORDS);
 struct ice_aqc_recipe_data_elem *tmp;
 u16 num_recps = ICE_MAX_NUM_RECIPES;
 struct ice_prot_lkup_ext *lkup_exts;
 u8 fv_word_idx = 0;
 u16 sub_recps;
 int status;

 bitmap_zero(result_bm, ICE_MAX_FV_WORDS);

 /* we need a buffer big enough to accommodate all the recipes */
 tmp = kcalloc(ICE_MAX_NUM_RECIPES, sizeof(*tmp), GFP_KERNEL);
 if (!tmp)
  return -ENOMEM;

 tmp[0].recipe_indx = rid;
 status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL);
 /* non-zero status meaning recipe doesn't exist */
 if (status)
  goto err_unroll;

 /* Get recipe to profile map so that we can get the fv from lkups that
 * we read for a recipe from FW. Since we want to minimize the number of
 * times we make this FW call, just make one call and cache the copy
 * until a new recipe is added. This operation is only required the
 * first time to get the changes from FW. Then to search existing
 * entries we don't need to update the cache again until another recipe
 * gets added.
 */

 if (*refresh_required) {
  ice_get_recp_to_prof_map(hw);
  *refresh_required = false;
 }

 /* Start populating all the entries for recps[rid] based on lkups from
 * firmware. Note that we are only creating the root recipe in our
 * database.
 */

 lkup_exts = &recps[rid].lkup_exts;

 for (sub_recps = 0; sub_recps < num_recps; sub_recps++) {
  struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps];
  u8 i, prof, idx, prot = 0;
  bool is_root;
  u16 off = 0;

  idx = root_bufs.recipe_indx;
  is_root = root_bufs.content.rid & ICE_AQ_RECIPE_ID_IS_ROOT;

  /* Mark all result indices in this chain */
  if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
   set_bit(root_bufs.content.result_indx & ~ICE_AQ_RECIPE_RESULT_EN,
    result_bm);

  /* get the first profile that is associated with rid */
  prof = find_first_bit(recipe_to_profile[idx],
          ICE_MAX_NUM_PROFILES);
  for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) {
   u8 lkup_indx = root_bufs.content.lkup_indx[i];
   u16 lkup_mask = le16_to_cpu(root_bufs.content.mask[i]);

   /* If the recipe is a chained recipe then all its
 * child recipe's result will have a result index.
 * To fill fv_words we should not use those result
 * index, we only need the protocol ids and offsets.
 * We will skip all the fv_idx which stores result
 * index in them. We also need to skip any fv_idx which
 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a
 * valid offset value.
 */

   if (!lkup_indx ||
       (lkup_indx & ICE_AQ_RECIPE_LKUP_IGNORE) ||
       test_bit(lkup_indx,
         hw->switch_info->prof_res_bm[prof]))
    continue;

   ice_find_prot_off(hw, ICE_BLK_SW, prof, lkup_indx,
       &prot, &off);
   lkup_exts->fv_words[fv_word_idx].prot_id = prot;
   lkup_exts->fv_words[fv_word_idx].off = off;
   lkup_exts->field_mask[fv_word_idx] = lkup_mask;
   fv_word_idx++;
  }

  /* Propagate some data to the recipe database */
  recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
  recps[idx].need_pass_l2 = !!(root_bufs.content.act_ctrl &
          ICE_AQ_RECIPE_ACT_NEED_PASS_L2);
  recps[idx].allow_pass_l2 = !!(root_bufs.content.act_ctrl &
           ICE_AQ_RECIPE_ACT_ALLOW_PASS_L2);
  bitmap_zero(recps[idx].res_idxs, ICE_MAX_FV_WORDS);
  if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) {
   set_bit(root_bufs.content.result_indx &
    ~ICE_AQ_RECIPE_RESULT_EN, recps[idx].res_idxs);
  }

  if (!is_root) {
   if (hw->recp_reuse && is_add)
    recps[idx].recp_created = true;

   continue;
  }

  /* Only do the following for root recipes entries */
  memcpy(recps[idx].r_bitmap, root_bufs.recipe_bitmap,
         sizeof(recps[idx].r_bitmap));
  recps[idx].root_rid = root_bufs.content.rid &
   ~ICE_AQ_RECIPE_ID_IS_ROOT;
  recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
 }

 /* Complete initialization of the root recipe entry */
 lkup_exts->n_val_words = fv_word_idx;

 /* Copy result indexes */
 bitmap_copy(recps[rid].res_idxs, result_bm, ICE_MAX_FV_WORDS);
 if (is_add)
  recps[rid].recp_created = true;

err_unroll:
 kfree(tmp);
 return status;
}

/* ice_init_port_info - Initialize port_info with switch configuration data
 * @pi: pointer to port_info
 * @vsi_port_num: VSI number or port number
 * @type: Type of switch element (port or VSI)
 * @swid: switch ID of the switch the element is attached to
 * @pf_vf_num: PF or VF number
 * @is_vf: true if the element is a VF, false otherwise
 */

static void
ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
     u16 swid, u16 pf_vf_num, bool is_vf)
{
 switch (type) {
 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
  pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
  pi->sw_id = swid;
  pi->pf_vf_num = pf_vf_num;
  pi->is_vf = is_vf;
  break;
 default:
  ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
  break;
 }
}

--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=89 H=97 G=93

¤ Dauer der Verarbeitung: 0.27 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.