net/ice: support PFCP
authorWei Zhao <wei.zhao1@intel.com>
Fri, 3 Apr 2020 04:46:04 +0000 (12:46 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 21 Apr 2020 11:57:06 +0000 (13:57 +0200)
This patch add switch filter support for PFCP packets,
it enable switch filter to direct IPv4/IPv6 packets with
PFCP session or node payload to specific action.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
drivers/net/ice/ice_generic_flow.c
drivers/net/ice/ice_generic_flow.h
drivers/net/ice/ice_switch_filter.c

index 189ef6c..04dcaba 100644 (file)
@@ -1400,6 +1400,21 @@ enum rte_flow_item_type pattern_eth_ipv6_l2tp[] = {
        RTE_FLOW_ITEM_TYPE_L2TPV3OIP,
        RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_pfcp[] = {
+       RTE_FLOW_ITEM_TYPE_ETH,
+       RTE_FLOW_ITEM_TYPE_IPV4,
+       RTE_FLOW_ITEM_TYPE_UDP,
+       RTE_FLOW_ITEM_TYPE_PFCP,
+       RTE_FLOW_ITEM_TYPE_END,
+};
+enum rte_flow_item_type pattern_eth_ipv6_pfcp[] = {
+       RTE_FLOW_ITEM_TYPE_ETH,
+       RTE_FLOW_ITEM_TYPE_IPV6,
+       RTE_FLOW_ITEM_TYPE_UDP,
+       RTE_FLOW_ITEM_TYPE_PFCP,
+       RTE_FLOW_ITEM_TYPE_END,
+};
+
 
 
 typedef struct ice_flow_engine * (*parse_engine_t)(struct ice_adapter *ad,
index 006fd00..8a866d2 100644 (file)
@@ -400,6 +400,10 @@ extern enum rte_flow_item_type pattern_eth_ipv6_ah[];
 /* L2TP */
 extern enum rte_flow_item_type pattern_eth_ipv6_l2tp[];
 
+/* PFCP */
+extern enum rte_flow_item_type pattern_eth_ipv4_pfcp[];
+extern enum rte_flow_item_type pattern_eth_ipv6_pfcp[];
+
 struct ice_adapter;
 
 extern const struct rte_flow_ops ice_flow_ops;
index 9c87a16..9b4b934 100644 (file)
@@ -154,6 +154,10 @@ ice_pattern_match_item ice_switch_pattern_dist_comms[] = {
                        ICE_INSET_NONE, ICE_INSET_NONE},
        {pattern_eth_ipv6_l2tp,
                        ICE_INSET_NONE, ICE_INSET_NONE},
+       {pattern_eth_ipv4_pfcp,
+                       ICE_INSET_NONE, ICE_INSET_NONE},
+       {pattern_eth_ipv6_pfcp,
+                       ICE_INSET_NONE, ICE_INSET_NONE},
 };
 
 static struct
@@ -224,6 +228,10 @@ ice_pattern_match_item ice_switch_pattern_perm[] = {
                        ICE_INSET_NONE, ICE_INSET_NONE},
        {pattern_eth_ipv6_l2tp,
                        ICE_INSET_NONE, ICE_INSET_NONE},
+       {pattern_eth_ipv4_pfcp,
+                       ICE_INSET_NONE, ICE_INSET_NONE},
+       {pattern_eth_ipv6_pfcp,
+                       ICE_INSET_NONE, ICE_INSET_NONE},
 };
 
 static int
@@ -350,6 +358,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
        const struct rte_flow_item_esp *esp_spec, *esp_mask;
        const struct rte_flow_item_ah *ah_spec, *ah_mask;
        const struct rte_flow_item_l2tpv3oip *l2tp_spec, *l2tp_mask;
+       const struct rte_flow_item_pfcp *pfcp_spec, *pfcp_mask;
        uint64_t input_set = ICE_INSET_NONE;
        uint16_t j, t = 0;
        uint16_t tunnel_valid = 0;
@@ -996,6 +1005,55 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
                        if (ipv6_valiad)
                                *tun_type = ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3;
                        break;
+               case RTE_FLOW_ITEM_TYPE_PFCP:
+                       pfcp_spec = item->spec;
+                       pfcp_mask = item->mask;
+                       /* Check if PFCP item is used to describe protocol.
+                        * If yes, both spec and mask should be NULL.
+                        * If no, both spec and mask shouldn't be NULL.
+                        */
+                       if ((!pfcp_spec && pfcp_mask) ||
+                           (pfcp_spec && !pfcp_mask)) {
+                               rte_flow_error_set(error, EINVAL,
+                                          RTE_FLOW_ERROR_TYPE_ITEM,
+                                          item,
+                                          "Invalid PFCP item");
+                               return -ENOTSUP;
+                       }
+                       if (pfcp_spec && pfcp_mask) {
+                               /* Check pfcp mask and update input set */
+                               if (pfcp_mask->msg_type ||
+                                       pfcp_mask->msg_len ||
+                                       pfcp_mask->seid) {
+                                       rte_flow_error_set(error, EINVAL,
+                                               RTE_FLOW_ERROR_TYPE_ITEM,
+                                               item,
+                                               "Invalid pfcp mask");
+                                       return -ENOTSUP;
+                               }
+                               if (pfcp_mask->s_field &&
+                                       pfcp_spec->s_field == 0x01 &&
+                                       ipv6_valiad)
+                                       *tun_type =
+                                       ICE_SW_TUN_PROFID_IPV6_PFCP_SESSION;
+                               else if (pfcp_mask->s_field &&
+                                       pfcp_spec->s_field == 0x01)
+                                       *tun_type =
+                                       ICE_SW_TUN_PROFID_IPV4_PFCP_SESSION;
+                               else if (pfcp_mask->s_field &&
+                                       !pfcp_spec->s_field &&
+                                       ipv6_valiad)
+                                       *tun_type =
+                                       ICE_SW_TUN_PROFID_IPV6_PFCP_NODE;
+                               else if (pfcp_mask->s_field &&
+                                       !pfcp_spec->s_field)
+                                       *tun_type =
+                                       ICE_SW_TUN_PROFID_IPV4_PFCP_NODE;
+                               else
+                                       return -ENOTSUP;
+                       }
+                       break;
+
 
                case RTE_FLOW_ITEM_TYPE_VOID:
                        break;
@@ -1179,6 +1237,10 @@ ice_is_profile_rule(enum ice_sw_tunnel_type tun_type)
        case ICE_SW_TUN_PROFID_IPV6_ESP:
        case ICE_SW_TUN_PROFID_IPV6_AH:
        case ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3:
+       case ICE_SW_TUN_PROFID_IPV4_PFCP_NODE:
+       case ICE_SW_TUN_PROFID_IPV4_PFCP_SESSION:
+       case ICE_SW_TUN_PROFID_IPV6_PFCP_NODE:
+       case ICE_SW_TUN_PROFID_IPV6_PFCP_SESSION:
                return true;
        default:
                break;