net/i40e: fix parsing packet type for NEON
[dpdk.git] / drivers / net / ice / base / ice_switch.c
index 692a147..3dc7642 100644 (file)
@@ -14,6 +14,7 @@
 #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.
@@ -911,39 +912,7 @@ static const u8 dummy_ipv6_gtpu_ipv6_udp_packet[] = {
        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 },
@@ -1125,8 +1094,38 @@ static const u8 dummy_ipv6_gtpu_ipv6_packet[] = {
        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 },
@@ -1611,6 +1610,7 @@ static const u8 dummy_ipv6_l2tpv3_pkt[] = {
 
 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 },
@@ -1621,7 +1621,8 @@ static const u8 dummy_qinq_ipv4_pkt[] = {
        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 */
@@ -1640,6 +1641,7 @@ static const u8 dummy_qinq_ipv4_pkt[] = {
 
 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 },
@@ -1650,7 +1652,8 @@ static const u8 dummy_qinq_ipv6_pkt[] = {
        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 */
@@ -1677,6 +1680,7 @@ static const u8 dummy_qinq_ipv6_pkt[] = {
 
 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 },
@@ -1686,6 +1690,7 @@ static const struct ice_dummy_pkt_offsets dummy_qinq_pppoe_packet_offsets[] = {
 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 },
@@ -1697,7 +1702,8 @@ static const u8 dummy_qinq_pppoe_ipv4_pkt[] = {
        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 */
@@ -3174,6 +3180,64 @@ ice_aq_get_recipe(struct ice_hw *hw,
        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
@@ -3441,6 +3505,7 @@ ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
                 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;
@@ -3513,6 +3578,8 @@ ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
                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;
@@ -3556,6 +3623,8 @@ ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
        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 */
@@ -6009,7 +6078,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
                                          &remove_list_head);
        ice_release_lock(rule_lock);
        if (status)
-               return;
+               goto free_fltr_list;
 
        switch (lkup) {
        case ICE_SW_LKUP_MAC:
@@ -6037,6 +6106,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
                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);
@@ -7737,26 +7807,6 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
                *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) {
@@ -7905,6 +7955,32 @@ ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
                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);