/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2020 Intel Corporation
+ * Copyright(c) 2001-2021 Intel Corporation
*/
#include "ice_switch.h"
#define ICE_PPP_IPV6_PROTO_ID 0x0057
#define ICE_IPV6_ETHER_ID 0x86DD
#define ICE_TCP_PROTO_ID 0x06
+#define ICE_ETH_P_8021Q 0x8100
/* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
* struct to configure any switch filter rules.
0x00, 0x00, /* 2 bytes for 4 byte alignment */
};
-static const struct ice_dummy_pkt_offsets dummy_udp_gtp_packet_offsets[] = {
- { ICE_MAC_OFOS, 0 },
- { ICE_IPV4_OFOS, 14 },
- { ICE_UDP_OF, 34 },
- { ICE_GTP, 42 },
- { ICE_PROTOCOL_LAST, 0 },
-};
-
-static const u8 dummy_udp_gtp_packet[] = {
- 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00,
-
- 0x45, 0x00, 0x00, 0x30, /* ICE_IPV4_OFOS 14 */
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x11, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-
- 0x00, 0x00, 0x08, 0x68, /* ICE_UDP_OF 34 */
- 0x00, 0x1c, 0x00, 0x00,
-
- 0x34, 0xff, 0x00, 0x0c, /* ICE_GTP 42 */
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x85,
-
- 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
- 0x00, 0x00, 0x00, 0x00,
-};
-
-static const
-struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv4_packet_offsets[] = {
+static const struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv4_packet_offsets[] = {
{ ICE_MAC_OFOS, 0 },
{ ICE_IPV4_OFOS, 14 },
{ ICE_UDP_OF, 34 },
0x00, 0x00,
};
-static const
-struct ice_dummy_pkt_offsets dummy_ipv4_gtp_no_pay_packet_offsets[] = {
+static const struct ice_dummy_pkt_offsets dummy_udp_gtp_packet_offsets[] = {
+ { ICE_MAC_OFOS, 0 },
+ { ICE_IPV4_OFOS, 14 },
+ { ICE_UDP_OF, 34 },
+ { ICE_GTP, 42 },
+ { ICE_PROTOCOL_LAST, 0 },
+};
+
+static const u8 dummy_udp_gtp_packet[] = {
+ 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00,
+
+ 0x45, 0x00, 0x00, 0x30, /* ICE_IPV4_OFOS 14 */
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x00, 0x00, 0x08, 0x68, /* ICE_UDP_OF 34 */
+ 0x00, 0x1c, 0x00, 0x00,
+
+ 0x34, 0xff, 0x00, 0x0c, /* ICE_GTP 42 */
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x85,
+
+ 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+static const struct ice_dummy_pkt_offsets dummy_ipv4_gtp_no_pay_packet_offsets[] = {
{ ICE_MAC_OFOS, 0 },
{ ICE_IPV4_OFOS, 14 },
{ ICE_UDP_OF, 34 },
static const struct ice_dummy_pkt_offsets dummy_qinq_ipv4_packet_offsets[] = {
{ ICE_MAC_OFOS, 0 },
+ { ICE_ETYPE_OL, 12 },
{ ICE_VLAN_EX, 14 },
{ ICE_VLAN_OFOS, 18 },
{ ICE_IPV4_OFOS, 22 },
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
- 0x91, 0x00,
+
+ 0x91, 0x00, /* ICE_ETYPE_OL 12 */
0x00, 0x00, 0x81, 0x00, /* ICE_VLAN_EX 14 */
0x00, 0x00, 0x08, 0x00, /* ICE_VLAN_OFOS 18 */
static const struct ice_dummy_pkt_offsets dummy_qinq_ipv6_packet_offsets[] = {
{ ICE_MAC_OFOS, 0 },
+ { ICE_ETYPE_OL, 12 },
{ ICE_VLAN_EX, 14 },
{ ICE_VLAN_OFOS, 18 },
{ ICE_IPV6_OFOS, 22 },
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
- 0x91, 0x00,
+
+ 0x91, 0x00, /* ICE_ETYPE_OL 12 */
0x00, 0x00, 0x81, 0x00, /* ICE_VLAN_EX 14 */
0x00, 0x00, 0x86, 0xDD, /* ICE_VLAN_OFOS 18 */
static const struct ice_dummy_pkt_offsets dummy_qinq_pppoe_packet_offsets[] = {
{ ICE_MAC_OFOS, 0 },
+ { ICE_ETYPE_OL, 12 },
{ ICE_VLAN_EX, 14 },
{ ICE_VLAN_OFOS, 18 },
{ ICE_PPPOE, 22 },
static const
struct ice_dummy_pkt_offsets dummy_qinq_pppoe_ipv4_packet_offsets[] = {
{ ICE_MAC_OFOS, 0 },
+ { ICE_ETYPE_OL, 12 },
{ ICE_VLAN_EX, 14 },
{ ICE_VLAN_OFOS, 18 },
{ ICE_PPPOE, 22 },
0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
- 0x91, 0x00,
+
+ 0x91, 0x00, /* ICE_ETYPE_OL 12 */
0x00, 0x00, 0x81, 0x00, /* ICE_VLAN_EX 14 */
0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 18 */
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.
+ */
+enum ice_status
+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;
+ enum ice_status status;
+
+ rcp_list = (struct ice_aqc_recipe_data_elem *)ice_malloc(hw, num_recps * sizeof(*rcp_list));
+ if (!rcp_list)
+ return ICE_ERR_NO_MEMORY;
+
+ /* 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:
+ ice_free(hw, rcp_list);
+ return status;
+}
+
/**
* ice_aq_map_recipe_to_profile - Map recipe to packet profile
* @hw: pointer to the HW struct
struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
{
u16 vlan_id = ICE_MAX_VLAN_ID + 1;
+ u16 vlan_tpid = ICE_ETH_P_8021Q;
void *daddr = NULL;
u16 eth_hdr_sz;
u8 *eth_hdr;
break;
case ICE_SW_LKUP_VLAN:
vlan_id = f_info->l_data.vlan.vlan_id;
+ if (f_info->l_data.vlan.tpid_valid)
+ vlan_tpid = f_info->l_data.vlan.tpid;
if (f_info->fltr_act == ICE_FWD_TO_VSI ||
f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
act |= ICE_SINGLE_ACT_PRUNE;
if (!(vlan_id > ICE_MAX_VLAN_ID)) {
off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
*off = CPU_TO_BE16(vlan_id);
+ off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
+ *off = CPU_TO_BE16(vlan_tpid);
}
/* Create the switch rule with the final dummy Ethernet header */
ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
vsi_list_id);
+ if (!m_entry->vsi_list_info)
+ return ICE_ERR_NO_MEMORY;
+
/* If this entry was large action then the large action needs
* to be updated to point to FWD to VSI list
*/
return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
fm_entry->fltr_info.vsi_handle == vsi_handle) ||
(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
+ fm_entry->vsi_list_info &&
(ice_is_bit_set(fm_entry->vsi_list_info->vsi_map,
vsi_handle))));
}
LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head,
ice_fltr_mgmt_list_entry, list_entry) {
- struct ice_fltr_info *fi;
-
- fi = &fm_entry->fltr_info;
- if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle))
+ if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
continue;
status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
- vsi_list_head, fi);
+ vsi_list_head,
+ &fm_entry->fltr_info);
if (status)
return status;
}
&remove_list_head);
ice_release_lock(rule_lock);
if (status)
- return;
+ goto free_fltr_list;
switch (lkup) {
case ICE_SW_LKUP_MAC:
break;
}
+free_fltr_list:
LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
ice_fltr_list_entry, list_entry) {
LIST_DEL(&fm_entry->list_entry);
*pkt_len = sizeof(dummy_ipv6_gtpu_ipv6_packet);
*offsets = dummy_ipv6_gtp_no_pay_packet_offsets;
return;
- } else if (tun_type == ICE_SW_TUN_IPV4_GTPU_IPV4) {
- *pkt = dummy_ipv4_gtpu_ipv4_packet;
- *pkt_len = sizeof(dummy_ipv4_gtpu_ipv4_packet);
- *offsets = dummy_ipv4_gtpu_ipv4_packet_offsets;
- return;
- } else if (tun_type == ICE_SW_TUN_IPV4_GTPU_IPV6) {
- *pkt = dummy_ipv4_gtpu_ipv6_packet;
- *pkt_len = sizeof(dummy_ipv4_gtpu_ipv6_packet);
- *offsets = dummy_ipv4_gtpu_ipv6_packet_offsets;
- return;
- } else if (tun_type == ICE_SW_TUN_IPV6_GTPU_IPV4) {
- *pkt = dummy_ipv6_gtpu_ipv4_packet;
- *pkt_len = sizeof(dummy_ipv6_gtpu_ipv4_packet);
- *offsets = dummy_ipv6_gtpu_ipv4_packet_offsets;
- return;
- } else if (tun_type == ICE_SW_TUN_IPV6_GTPU_IPV6) {
- *pkt = dummy_ipv6_gtpu_ipv6_packet;
- *pkt_len = sizeof(dummy_ipv6_gtpu_ipv6_packet);
- *offsets = dummy_ipv6_gtpu_ipv6_packet_offsets;
- return;
}
if (tun_type == ICE_SW_TUN_IPV4_ESP) {
return;
}
+ /* Support GTP tunnel + L3 */
+ if (tun_type == ICE_SW_TUN_IPV4_GTPU_IPV4) {
+ *pkt = dummy_ipv4_gtpu_ipv4_packet;
+ *pkt_len = sizeof(dummy_ipv4_gtpu_ipv4_packet);
+ *offsets = dummy_ipv4_gtpu_ipv4_packet_offsets;
+ return;
+ }
+ if (tun_type == ICE_SW_TUN_IPV4_GTPU_IPV6) {
+ *pkt = dummy_ipv4_gtpu_ipv6_packet;
+ *pkt_len = sizeof(dummy_ipv4_gtpu_ipv6_packet);
+ *offsets = dummy_ipv4_gtpu_ipv6_packet_offsets;
+ return;
+ }
+ if (tun_type == ICE_SW_TUN_IPV6_GTPU_IPV4) {
+ *pkt = dummy_ipv6_gtpu_ipv4_packet;
+ *pkt_len = sizeof(dummy_ipv6_gtpu_ipv4_packet);
+ *offsets = dummy_ipv6_gtpu_ipv4_packet_offsets;
+ return;
+ }
+ if (tun_type == ICE_SW_TUN_IPV6_GTPU_IPV6) {
+ *pkt = dummy_ipv6_gtpu_ipv6_packet;
+ *pkt_len = sizeof(dummy_ipv6_gtpu_ipv6_packet);
+ *offsets = dummy_ipv6_gtpu_ipv6_packet_offsets;
+ return;
+ }
+
if (tun_type == ICE_ALL_TUNNELS) {
*pkt = dummy_gre_udp_packet;
*pkt_len = sizeof(dummy_gre_udp_packet);