X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fice%2Fice_switch_filter.c;h=c4b00b6a2f94cbe35e3f499e2a0aaee2b09ad911;hb=e7cc68c70736d6f6c901ea1a64ff90e163b85286;hp=9c87a16dd175652a1572e9bbc020fa837eeaec93;hpb=66ff8851792f3ed32fb17dbc8e3518fcb0ade61e;p=dpdk.git diff --git a/drivers/net/ice/ice_switch_filter.c b/drivers/net/ice/ice_switch_filter.c index 9c87a16dd1..c4b00b6a2f 100644 --- a/drivers/net/ice/ice_switch_filter.c +++ b/drivers/net/ice/ice_switch_filter.c @@ -23,9 +23,14 @@ #include "ice_logs.h" #include "ice_ethdev.h" #include "ice_generic_flow.h" +#include "ice_dcf_ethdev.h" -#define MAX_QGRP_NUM_TYPE 7 +#define MAX_QGRP_NUM_TYPE 7 +#define MAX_INPUT_SET_BYTE 32 +#define ICE_PPP_IPV4_PROTO 0x0021 +#define ICE_PPP_IPV6_PROTO 0x0057 +#define ICE_IPV4_PROTO_NVGRE 0x002F #define ICE_SW_INSET_ETHER ( \ ICE_INSET_DMAC | ICE_INSET_SMAC | ICE_INSET_ETHERTYPE) @@ -95,6 +100,36 @@ ICE_INSET_VLAN_OUTER | ICE_INSET_VLAN_INNER | \ ICE_INSET_DMAC | ICE_INSET_ETHERTYPE | ICE_INSET_PPPOE_SESSION | \ ICE_INSET_PPPOE_PROTO) +#define ICE_SW_INSET_MAC_PPPOE_IPV4 ( \ + ICE_SW_INSET_MAC_PPPOE | ICE_SW_INSET_MAC_IPV4) +#define ICE_SW_INSET_MAC_PPPOE_IPV4_TCP ( \ + ICE_SW_INSET_MAC_PPPOE | ICE_SW_INSET_MAC_IPV4_TCP) +#define ICE_SW_INSET_MAC_PPPOE_IPV4_UDP ( \ + ICE_SW_INSET_MAC_PPPOE | ICE_SW_INSET_MAC_IPV4_UDP) +#define ICE_SW_INSET_MAC_PPPOE_IPV6 ( \ + ICE_SW_INSET_MAC_PPPOE | ICE_SW_INSET_MAC_IPV6) +#define ICE_SW_INSET_MAC_PPPOE_IPV6_TCP ( \ + ICE_SW_INSET_MAC_PPPOE | ICE_SW_INSET_MAC_IPV6_TCP) +#define ICE_SW_INSET_MAC_PPPOE_IPV6_UDP ( \ + ICE_SW_INSET_MAC_PPPOE | ICE_SW_INSET_MAC_IPV6_UDP) +#define ICE_SW_INSET_MAC_IPV4_ESP ( \ + ICE_SW_INSET_MAC_IPV4 | ICE_INSET_ESP_SPI) +#define ICE_SW_INSET_MAC_IPV6_ESP ( \ + ICE_SW_INSET_MAC_IPV6 | ICE_INSET_ESP_SPI) +#define ICE_SW_INSET_MAC_IPV4_AH ( \ + ICE_SW_INSET_MAC_IPV4 | ICE_INSET_AH_SPI) +#define ICE_SW_INSET_MAC_IPV6_AH ( \ + ICE_SW_INSET_MAC_IPV6 | ICE_INSET_AH_SPI) +#define ICE_SW_INSET_MAC_IPV4_L2TP ( \ + ICE_SW_INSET_MAC_IPV4 | ICE_INSET_L2TPV3OIP_SESSION_ID) +#define ICE_SW_INSET_MAC_IPV6_L2TP ( \ + ICE_SW_INSET_MAC_IPV6 | ICE_INSET_L2TPV3OIP_SESSION_ID) +#define ICE_SW_INSET_MAC_IPV4_PFCP ( \ + ICE_SW_INSET_MAC_IPV4 | \ + ICE_INSET_PFCP_S_FIELD | ICE_INSET_PFCP_SEID) +#define ICE_SW_INSET_MAC_IPV6_PFCP ( \ + ICE_SW_INSET_MAC_IPV6 | \ + ICE_INSET_PFCP_S_FIELD | ICE_INSET_PFCP_SEID) struct sw_meta { struct ice_adv_lkup_elem *list; @@ -136,10 +171,6 @@ ice_pattern_match_item ice_switch_pattern_dist_comms[] = { ICE_SW_INSET_DIST_NVGRE_IPV4_UDP, ICE_INSET_NONE}, {pattern_eth_ipv4_nvgre_eth_ipv4_tcp, ICE_SW_INSET_DIST_NVGRE_IPV4_TCP, ICE_INSET_NONE}, - {pattern_eth_pppoed, - ICE_SW_INSET_MAC_PPPOE, ICE_INSET_NONE}, - {pattern_eth_vlan_pppoed, - ICE_SW_INSET_MAC_PPPOE, ICE_INSET_NONE}, {pattern_eth_pppoes, ICE_SW_INSET_MAC_PPPOE, ICE_INSET_NONE}, {pattern_eth_vlan_pppoes, @@ -148,11 +179,51 @@ ice_pattern_match_item ice_switch_pattern_dist_comms[] = { ICE_SW_INSET_MAC_PPPOE_PROTO, ICE_INSET_NONE}, {pattern_eth_vlan_pppoes_proto, ICE_SW_INSET_MAC_PPPOE_PROTO, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv4, + ICE_SW_INSET_MAC_PPPOE_IPV4, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv4_tcp, + ICE_SW_INSET_MAC_PPPOE_IPV4_TCP, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv4_udp, + ICE_SW_INSET_MAC_PPPOE_IPV4_UDP, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv6, + ICE_SW_INSET_MAC_PPPOE_IPV6, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv6_tcp, + ICE_SW_INSET_MAC_PPPOE_IPV6_TCP, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv6_udp, + ICE_SW_INSET_MAC_PPPOE_IPV6_UDP, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv4, + ICE_SW_INSET_MAC_PPPOE_IPV4, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv4_tcp, + ICE_SW_INSET_MAC_PPPOE_IPV4_TCP, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv4_udp, + ICE_SW_INSET_MAC_PPPOE_IPV4_UDP, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv6, + ICE_SW_INSET_MAC_PPPOE_IPV6, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv6_tcp, + ICE_SW_INSET_MAC_PPPOE_IPV6_TCP, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv6_udp, + ICE_SW_INSET_MAC_PPPOE_IPV6_UDP, ICE_INSET_NONE}, + {pattern_eth_ipv4_esp, + ICE_SW_INSET_MAC_IPV4_ESP, ICE_INSET_NONE}, + {pattern_eth_ipv4_udp_esp, + ICE_SW_INSET_MAC_IPV4_ESP, ICE_INSET_NONE}, {pattern_eth_ipv6_esp, - ICE_INSET_NONE, ICE_INSET_NONE}, + ICE_SW_INSET_MAC_IPV6_ESP, ICE_INSET_NONE}, + {pattern_eth_ipv6_udp_esp, + ICE_SW_INSET_MAC_IPV6_ESP, ICE_INSET_NONE}, + {pattern_eth_ipv4_ah, + ICE_SW_INSET_MAC_IPV4_AH, ICE_INSET_NONE}, {pattern_eth_ipv6_ah, + ICE_SW_INSET_MAC_IPV6_AH, ICE_INSET_NONE}, + {pattern_eth_ipv6_udp_ah, ICE_INSET_NONE, ICE_INSET_NONE}, + {pattern_eth_ipv4_l2tp, + ICE_SW_INSET_MAC_IPV4_L2TP, ICE_INSET_NONE}, {pattern_eth_ipv6_l2tp, + ICE_SW_INSET_MAC_IPV6_L2TP, ICE_INSET_NONE}, + {pattern_eth_ipv4_pfcp, + ICE_INSET_NONE, ICE_INSET_NONE}, + {pattern_eth_ipv6_pfcp, ICE_INSET_NONE, ICE_INSET_NONE}, }; @@ -192,6 +263,8 @@ ice_pattern_match_item ice_switch_pattern_dist_os[] = { static struct ice_pattern_match_item ice_switch_pattern_perm[] = { + {pattern_ethertype, + ICE_SW_INSET_ETHER, ICE_INSET_NONE}, {pattern_ethertype_vlan, ICE_SW_INSET_MAC_VLAN, ICE_INSET_NONE}, {pattern_eth_ipv4, @@ -218,11 +291,59 @@ ice_pattern_match_item ice_switch_pattern_perm[] = { ICE_SW_INSET_PERM_TUNNEL_IPV4_UDP, ICE_INSET_NONE}, {pattern_eth_ipv4_nvgre_eth_ipv4_tcp, ICE_SW_INSET_PERM_TUNNEL_IPV4_TCP, ICE_INSET_NONE}, + {pattern_eth_pppoes, + ICE_SW_INSET_MAC_PPPOE, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes, + ICE_SW_INSET_MAC_PPPOE, ICE_INSET_NONE}, + {pattern_eth_pppoes_proto, + ICE_SW_INSET_MAC_PPPOE_PROTO, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_proto, + ICE_SW_INSET_MAC_PPPOE_PROTO, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv4, + ICE_SW_INSET_MAC_PPPOE_IPV4, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv4_tcp, + ICE_SW_INSET_MAC_PPPOE_IPV4_TCP, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv4_udp, + ICE_SW_INSET_MAC_PPPOE_IPV4_UDP, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv6, + ICE_SW_INSET_MAC_PPPOE_IPV6, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv6_tcp, + ICE_SW_INSET_MAC_PPPOE_IPV6_TCP, ICE_INSET_NONE}, + {pattern_eth_pppoes_ipv6_udp, + ICE_SW_INSET_MAC_PPPOE_IPV6_UDP, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv4, + ICE_SW_INSET_MAC_PPPOE_IPV4, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv4_tcp, + ICE_SW_INSET_MAC_PPPOE_IPV4_TCP, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv4_udp, + ICE_SW_INSET_MAC_PPPOE_IPV4_UDP, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv6, + ICE_SW_INSET_MAC_PPPOE_IPV6, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv6_tcp, + ICE_SW_INSET_MAC_PPPOE_IPV6_TCP, ICE_INSET_NONE}, + {pattern_eth_vlan_pppoes_ipv6_udp, + ICE_SW_INSET_MAC_PPPOE_IPV6_UDP, ICE_INSET_NONE}, + {pattern_eth_ipv4_esp, + ICE_SW_INSET_MAC_IPV4_ESP, ICE_INSET_NONE}, + {pattern_eth_ipv4_udp_esp, + ICE_SW_INSET_MAC_IPV4_ESP, ICE_INSET_NONE}, {pattern_eth_ipv6_esp, - ICE_INSET_NONE, ICE_INSET_NONE}, + ICE_SW_INSET_MAC_IPV6_ESP, ICE_INSET_NONE}, + {pattern_eth_ipv6_udp_esp, + ICE_SW_INSET_MAC_IPV6_ESP, ICE_INSET_NONE}, + {pattern_eth_ipv4_ah, + ICE_SW_INSET_MAC_IPV4_AH, ICE_INSET_NONE}, {pattern_eth_ipv6_ah, + ICE_SW_INSET_MAC_IPV6_AH, ICE_INSET_NONE}, + {pattern_eth_ipv6_udp_ah, ICE_INSET_NONE, ICE_INSET_NONE}, + {pattern_eth_ipv4_l2tp, + ICE_SW_INSET_MAC_IPV4_L2TP, ICE_INSET_NONE}, {pattern_eth_ipv6_l2tp, + ICE_SW_INSET_MAC_IPV6_L2TP, ICE_INSET_NONE}, + {pattern_eth_ipv4_pfcp, + ICE_INSET_NONE, ICE_INSET_NONE}, + {pattern_eth_ipv6_pfcp, ICE_INSET_NONE, ICE_INSET_NONE}, }; @@ -350,12 +471,21 @@ 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 input_set_byte = 0; + bool pppoe_elem_valid = 0; + bool pppoe_patt_valid = 0; + bool pppoe_prot_valid = 0; + bool tunnel_valid = 0; + bool profile_rule = 0; + bool nvgre_valid = 0; + bool vxlan_valid = 0; + bool ipv6_valid = 0; + bool ipv4_valid = 0; + bool udp_valid = 0; + bool tcp_valid = 0; uint16_t j, t = 0; - uint16_t tunnel_valid = 0; - uint16_t pppoe_valid = 0; - uint16_t ipv6_valiad = 0; - for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { @@ -413,6 +543,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], m->src_addr[j] = eth_mask->src.addr_bytes[j]; i = 1; + input_set_byte++; } if (eth_mask->dst.addr_bytes[j]) { h->dst_addr[j] = @@ -420,6 +551,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], m->dst_addr[j] = eth_mask->dst.addr_bytes[j]; i = 1; + input_set_byte++; } } if (i) @@ -430,6 +562,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], eth_spec->type; list[t].m_u.ethertype.ethtype_id = eth_mask->type; + input_set_byte += 2; t++; } } @@ -438,6 +571,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], case RTE_FLOW_ITEM_TYPE_IPV4: ipv4_spec = item->spec; ipv4_mask = item->mask; + ipv4_valid = 1; if (ipv4_spec && ipv4_mask) { /* Check IPv4 mask and update input set */ if (ipv4_mask->hdr.version_ihl || @@ -488,30 +622,39 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], ipv4_spec->hdr.src_addr; list[t].m_u.ipv4_hdr.src_addr = ipv4_mask->hdr.src_addr; + input_set_byte += 2; } if (ipv4_mask->hdr.dst_addr) { list[t].h_u.ipv4_hdr.dst_addr = ipv4_spec->hdr.dst_addr; list[t].m_u.ipv4_hdr.dst_addr = ipv4_mask->hdr.dst_addr; + input_set_byte += 2; } if (ipv4_mask->hdr.time_to_live) { list[t].h_u.ipv4_hdr.time_to_live = ipv4_spec->hdr.time_to_live; list[t].m_u.ipv4_hdr.time_to_live = ipv4_mask->hdr.time_to_live; + input_set_byte++; } if (ipv4_mask->hdr.next_proto_id) { list[t].h_u.ipv4_hdr.protocol = ipv4_spec->hdr.next_proto_id; list[t].m_u.ipv4_hdr.protocol = ipv4_mask->hdr.next_proto_id; + input_set_byte++; } + if ((ipv4_spec->hdr.next_proto_id & + ipv4_mask->hdr.next_proto_id) == + ICE_IPV4_PROTO_NVGRE) + *tun_type = ICE_SW_TUN_AND_NON_TUN; if (ipv4_mask->hdr.type_of_service) { list[t].h_u.ipv4_hdr.tos = ipv4_spec->hdr.type_of_service; list[t].m_u.ipv4_hdr.tos = ipv4_mask->hdr.type_of_service; + input_set_byte++; } t++; } @@ -520,7 +663,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], case RTE_FLOW_ITEM_TYPE_IPV6: ipv6_spec = item->spec; ipv6_mask = item->mask; - ipv6_valiad = 1; + ipv6_valid = 1; if (ipv6_spec && ipv6_mask) { if (ipv6_mask->hdr.payload_len) { rte_flow_error_set(error, EINVAL, @@ -589,12 +732,14 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], ipv6_spec->hdr.src_addr[j]; s->src_addr[j] = ipv6_mask->hdr.src_addr[j]; + input_set_byte++; } if (ipv6_mask->hdr.dst_addr[j]) { f->dst_addr[j] = ipv6_spec->hdr.dst_addr[j]; s->dst_addr[j] = ipv6_mask->hdr.dst_addr[j]; + input_set_byte++; } } if (ipv6_mask->hdr.proto) { @@ -602,12 +747,14 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], ipv6_spec->hdr.proto; s->next_hdr = ipv6_mask->hdr.proto; + input_set_byte++; } if (ipv6_mask->hdr.hop_limits) { f->hop_limit = ipv6_spec->hdr.hop_limits; s->hop_limit = ipv6_mask->hdr.hop_limits; + input_set_byte++; } if (ipv6_mask->hdr.vtc_flow & rte_cpu_to_be_32 @@ -625,6 +772,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT; s->be_ver_tc_flow = CPU_TO_BE32(vtf.u.val); + input_set_byte += 4; } t++; } @@ -633,6 +781,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], case RTE_FLOW_ITEM_TYPE_UDP: udp_spec = item->spec; udp_mask = item->mask; + udp_valid = 1; if (udp_spec && udp_mask) { /* Check UDP mask and update input set*/ if (udp_mask->hdr.dgram_len || @@ -669,20 +818,23 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], udp_spec->hdr.src_port; list[t].m_u.l4_hdr.src_port = udp_mask->hdr.src_port; + input_set_byte += 2; } if (udp_mask->hdr.dst_port) { list[t].h_u.l4_hdr.dst_port = udp_spec->hdr.dst_port; list[t].m_u.l4_hdr.dst_port = udp_mask->hdr.dst_port; + input_set_byte += 2; } - t++; + t++; } break; case RTE_FLOW_ITEM_TYPE_TCP: tcp_spec = item->spec; tcp_mask = item->mask; + tcp_valid = 1; if (tcp_spec && tcp_mask) { /* Check TCP mask and update input set */ if (tcp_mask->hdr.sent_seq || @@ -720,12 +872,14 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], tcp_spec->hdr.src_port; list[t].m_u.l4_hdr.src_port = tcp_mask->hdr.src_port; + input_set_byte += 2; } if (tcp_mask->hdr.dst_port) { list[t].h_u.l4_hdr.dst_port = tcp_spec->hdr.dst_port; list[t].m_u.l4_hdr.dst_port = tcp_mask->hdr.dst_port; + input_set_byte += 2; } t++; } @@ -765,12 +919,14 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], sctp_spec->hdr.src_port; list[t].m_u.sctp_hdr.src_port = sctp_mask->hdr.src_port; + input_set_byte += 2; } if (sctp_mask->hdr.dst_port) { list[t].h_u.sctp_hdr.dst_port = sctp_spec->hdr.dst_port; list[t].m_u.sctp_hdr.dst_port = sctp_mask->hdr.dst_port; + input_set_byte += 2; } t++; } @@ -791,7 +947,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], "Invalid VXLAN item"); return 0; } - + vxlan_valid = 1; tunnel_valid = 1; if (vxlan_spec && vxlan_mask) { list[t].type = ICE_VXLAN; @@ -808,6 +964,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], vxlan_mask->vni[0]; input_set |= ICE_INSET_TUN_VXLAN_VNI; + input_set_byte += 2; } t++; } @@ -828,6 +985,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], "Invalid NVGRE item"); return 0; } + nvgre_valid = 1; tunnel_valid = 1; if (nvgre_spec && nvgre_mask) { list[t].type = ICE_NVGRE; @@ -844,6 +1002,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], nvgre_mask->tni[0]; input_set |= ICE_INSET_TUN_NVGRE_TNI; + input_set_byte += 2; } t++; } @@ -872,13 +1031,15 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], list[t].m_u.vlan_hdr.vlan = vlan_mask->tci; input_set |= ICE_INSET_VLAN_OUTER; + input_set_byte += 2; } if (vlan_mask->inner_type) { list[t].h_u.vlan_hdr.type = vlan_spec->inner_type; list[t].m_u.vlan_hdr.type = vlan_mask->inner_type; - input_set |= ICE_INSET_VLAN_OUTER; + input_set |= ICE_INSET_ETHERTYPE; + input_set_byte += 2; } t++; } @@ -900,6 +1061,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], "Invalid pppoe item"); return 0; } + pppoe_patt_valid = 1; if (pppoe_spec && pppoe_mask) { /* Check pppoe mask and update input set */ if (pppoe_mask->length || @@ -918,9 +1080,10 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], list[t].m_u.pppoe_hdr.session_id = pppoe_mask->session_id; input_set |= ICE_INSET_PPPOE_SESSION; + input_set_byte += 2; } t++; - pppoe_valid = 1; + pppoe_elem_valid = 1; } break; @@ -941,7 +1104,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], return 0; } if (pppoe_proto_spec && pppoe_proto_mask) { - if (pppoe_valid) + if (pppoe_elem_valid) t--; list[t].type = ICE_PPPOE; if (pppoe_proto_mask->proto_id) { @@ -950,51 +1113,221 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], list[t].m_u.pppoe_hdr.ppp_prot_id = pppoe_proto_mask->proto_id; input_set |= ICE_INSET_PPPOE_PROTO; + input_set_byte += 2; + pppoe_prot_valid = 1; } + if ((pppoe_proto_mask->proto_id & + pppoe_proto_spec->proto_id) != + CPU_TO_BE16(ICE_PPP_IPV4_PROTO) && + (pppoe_proto_mask->proto_id & + pppoe_proto_spec->proto_id) != + CPU_TO_BE16(ICE_PPP_IPV6_PROTO)) + *tun_type = ICE_SW_TUN_PPPOE_PAY; + else + *tun_type = ICE_SW_TUN_PPPOE; t++; } + break; case RTE_FLOW_ITEM_TYPE_ESP: esp_spec = item->spec; esp_mask = item->mask; - if (esp_spec || esp_mask) { + if ((esp_spec && !esp_mask) || + (!esp_spec && esp_mask)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Invalid esp item"); - return -ENOTSUP; + return 0; + } + /* Check esp mask and update input set */ + if (esp_mask && esp_mask->hdr.seq) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid esp mask"); + return 0; + } + + if (!esp_spec && !esp_mask && !input_set) { + profile_rule = 1; + if (ipv6_valid && udp_valid) + *tun_type = + ICE_SW_TUN_PROFID_IPV6_NAT_T; + else if (ipv6_valid) + *tun_type = ICE_SW_TUN_PROFID_IPV6_ESP; + else if (ipv4_valid) + return 0; + } else if (esp_spec && esp_mask && + esp_mask->hdr.spi){ + if (udp_valid) + list[t].type = ICE_NAT_T; + else + list[t].type = ICE_ESP; + list[t].h_u.esp_hdr.spi = + esp_spec->hdr.spi; + list[t].m_u.esp_hdr.spi = + esp_mask->hdr.spi; + input_set |= ICE_INSET_ESP_SPI; + input_set_byte += 4; + t++; + } + + if (!profile_rule) { + if (ipv6_valid && udp_valid) + *tun_type = ICE_SW_TUN_IPV6_NAT_T; + else if (ipv4_valid && udp_valid) + *tun_type = ICE_SW_TUN_IPV4_NAT_T; + else if (ipv6_valid) + *tun_type = ICE_SW_TUN_IPV6_ESP; + else if (ipv4_valid) + *tun_type = ICE_SW_TUN_IPV4_ESP; } - if (ipv6_valiad) - *tun_type = ICE_SW_TUN_PROFID_IPV6_ESP; break; case RTE_FLOW_ITEM_TYPE_AH: ah_spec = item->spec; ah_mask = item->mask; - if (ah_spec || ah_mask) { + if ((ah_spec && !ah_mask) || + (!ah_spec && ah_mask)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Invalid ah item"); - return -ENOTSUP; + return 0; + } + /* Check ah mask and update input set */ + if (ah_mask && + (ah_mask->next_hdr || + ah_mask->payload_len || + ah_mask->seq_num || + ah_mask->reserved)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid ah mask"); + return 0; + } + + if (!ah_spec && !ah_mask && !input_set) { + profile_rule = 1; + if (ipv6_valid && udp_valid) + *tun_type = + ICE_SW_TUN_PROFID_IPV6_NAT_T; + else if (ipv6_valid) + *tun_type = ICE_SW_TUN_PROFID_IPV6_AH; + else if (ipv4_valid) + return 0; + } else if (ah_spec && ah_mask && + ah_mask->spi){ + list[t].type = ICE_AH; + list[t].h_u.ah_hdr.spi = + ah_spec->spi; + list[t].m_u.ah_hdr.spi = + ah_mask->spi; + input_set |= ICE_INSET_AH_SPI; + input_set_byte += 4; + t++; + } + + if (!profile_rule) { + if (udp_valid) + return 0; + else if (ipv6_valid) + *tun_type = ICE_SW_TUN_IPV6_AH; + else if (ipv4_valid) + *tun_type = ICE_SW_TUN_IPV4_AH; } - if (ipv6_valiad) - *tun_type = ICE_SW_TUN_PROFID_IPV6_AH; break; case RTE_FLOW_ITEM_TYPE_L2TPV3OIP: l2tp_spec = item->spec; l2tp_mask = item->mask; - if (l2tp_spec || l2tp_mask) { + if ((l2tp_spec && !l2tp_mask) || + (!l2tp_spec && l2tp_mask)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, "Invalid l2tp item"); + return 0; + } + + if (!l2tp_spec && !l2tp_mask && !input_set) { + if (ipv6_valid) + *tun_type = + ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3; + else if (ipv4_valid) + return 0; + } else if (l2tp_spec && l2tp_mask && + l2tp_mask->session_id){ + list[t].type = ICE_L2TPV3; + list[t].h_u.l2tpv3_sess_hdr.session_id = + l2tp_spec->session_id; + list[t].m_u.l2tpv3_sess_hdr.session_id = + l2tp_mask->session_id; + input_set |= ICE_INSET_L2TPV3OIP_SESSION_ID; + input_set_byte += 4; + t++; + } + + if (!profile_rule) { + if (ipv6_valid) + *tun_type = + ICE_SW_TUN_IPV6_L2TPV3; + else if (ipv4_valid) + *tun_type = + ICE_SW_TUN_IPV4_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 (ipv6_valiad) - *tun_type = ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3; + 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_valid) + *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_valid) + *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: @@ -1008,6 +1341,46 @@ ice_switch_inset_get(const struct rte_flow_item pattern[], } } + if (pppoe_patt_valid && !pppoe_prot_valid) { + if (ipv6_valid && udp_valid) + *tun_type = ICE_SW_TUN_PPPOE_IPV6_UDP; + else if (ipv6_valid && tcp_valid) + *tun_type = ICE_SW_TUN_PPPOE_IPV6_TCP; + else if (ipv4_valid && udp_valid) + *tun_type = ICE_SW_TUN_PPPOE_IPV4_UDP; + else if (ipv4_valid && tcp_valid) + *tun_type = ICE_SW_TUN_PPPOE_IPV4_TCP; + else if (ipv6_valid) + *tun_type = ICE_SW_TUN_PPPOE_IPV6; + else if (ipv4_valid) + *tun_type = ICE_SW_TUN_PPPOE_IPV4; + else + *tun_type = ICE_SW_TUN_PPPOE; + } + + if (*tun_type == ICE_NON_TUN) { + if (vxlan_valid) + *tun_type = ICE_SW_TUN_VXLAN; + else if (nvgre_valid) + *tun_type = ICE_SW_TUN_NVGRE; + else if (ipv4_valid && tcp_valid) + *tun_type = ICE_SW_IPV4_TCP; + else if (ipv4_valid && udp_valid) + *tun_type = ICE_SW_IPV4_UDP; + else if (ipv6_valid && tcp_valid) + *tun_type = ICE_SW_IPV6_TCP; + else if (ipv6_valid && udp_valid) + *tun_type = ICE_SW_IPV6_UDP; + } + + if (input_set_byte > MAX_INPUT_SET_BYTE) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "too much input set"); + return -ENOTSUP; + } + *lkups_num = t; return input_set; @@ -1016,7 +1389,8 @@ out: } static int -ice_switch_parse_dcf_action(const struct rte_flow_action *actions, +ice_switch_parse_dcf_action(struct ice_dcf_adapter *ad, + const struct rte_flow_action *actions, struct rte_flow_error *error, struct ice_adv_rule_info *rule_info) { @@ -1031,7 +1405,11 @@ ice_switch_parse_dcf_action(const struct rte_flow_action *actions, case RTE_FLOW_ACTION_TYPE_VF: rule_info->sw_act.fltr_act = ICE_FWD_TO_VSI; act_vf = action->conf; - rule_info->sw_act.vsi_handle = act_vf->id; + if (act_vf->original) + rule_info->sw_act.vsi_handle = + ad->real_hw.avf.bus.func; + else + rule_info->sw_act.vsi_handle = act_vf->id; break; default: rte_flow_error_set(error, @@ -1043,6 +1421,7 @@ ice_switch_parse_dcf_action(const struct rte_flow_action *actions, } rule_info->sw_act.src = rule_info->sw_act.vsi_handle; + rule_info->sw_act.flag = ICE_FLTR_RX; rule_info->rx = 1; rule_info->priority = 5; @@ -1072,6 +1451,8 @@ ice_switch_parse_action(struct ice_pf *pf, switch (action_type) { case RTE_FLOW_ACTION_TYPE_RSS: act_qgrop = action->conf; + if (act_qgrop->queue_num <= 1) + goto error; rule_info->sw_act.fltr_act = ICE_FWD_TO_QGRP; rule_info->sw_act.fwd_id.q_id = @@ -1161,7 +1542,7 @@ ice_switch_check_action(const struct rte_flow_action *actions, } } - if (actions_num > 1) { + if (actions_num != 1) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, actions, @@ -1179,6 +1560,11 @@ 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_IPV6_NAT_T: + 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; @@ -1206,18 +1592,11 @@ ice_switch_parse_pattern_action(struct ice_adapter *ad, const struct rte_flow_item *item = pattern; uint16_t item_num = 0; enum ice_sw_tunnel_type tun_type = - ICE_SW_TUN_AND_NON_TUN; + ICE_NON_TUN; struct ice_pattern_match_item *pattern_match_item = NULL; for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { item_num++; - if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN) - tun_type = ICE_SW_TUN_VXLAN; - if (item->type == RTE_FLOW_ITEM_TYPE_NVGRE) - tun_type = ICE_SW_TUN_NVGRE; - if (item->type == RTE_FLOW_ITEM_TYPE_PPPOED || - item->type == RTE_FLOW_ITEM_TYPE_PPPOES) - tun_type = ICE_SW_TUN_PPPOE; if (item->type == RTE_FLOW_ITEM_TYPE_ETH) { const struct rte_flow_item_eth *eth_mask; if (item->mask) @@ -1271,6 +1650,7 @@ ice_switch_parse_pattern_action(struct ice_adapter *ad, goto error; } + memset(&rule_info, 0, sizeof(rule_info)); rule_info.tun_type = tun_type; ret = ice_switch_check_action(actions, error); @@ -1282,7 +1662,8 @@ ice_switch_parse_pattern_action(struct ice_adapter *ad, } if (ad->hw.dcf_enabled) - ret = ice_switch_parse_dcf_action(actions, error, &rule_info); + ret = ice_switch_parse_dcf_action((void *)ad, actions, error, + &rule_info); else ret = ice_switch_parse_action(pf, actions, error, &rule_info); @@ -1329,6 +1710,88 @@ ice_switch_query(struct ice_adapter *ad __rte_unused, return -rte_errno; } +static int +ice_switch_redirect(struct ice_adapter *ad, + struct rte_flow *flow, + struct ice_flow_redirect *rd) +{ + struct ice_rule_query_data *rdata = flow->rule; + struct ice_adv_fltr_mgmt_list_entry *list_itr; + struct ice_adv_lkup_elem *lkups_dp = NULL; + struct LIST_HEAD_TYPE *list_head; + struct ice_adv_rule_info rinfo; + struct ice_hw *hw = &ad->hw; + struct ice_switch_info *sw; + uint16_t lkups_cnt; + int ret; + + if (rdata->vsi_handle != rd->vsi_handle) + return 0; + + sw = hw->switch_info; + if (!sw->recp_list[rdata->rid].recp_created) + return -EINVAL; + + if (rd->type != ICE_FLOW_REDIRECT_VSI) + return -ENOTSUP; + + list_head = &sw->recp_list[rdata->rid].filt_rules; + LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_adv_fltr_mgmt_list_entry, + list_entry) { + rinfo = list_itr->rule_info; + if ((rinfo.fltr_rule_id == rdata->rule_id && + rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI && + rinfo.sw_act.vsi_handle == rd->vsi_handle) || + (rinfo.fltr_rule_id == rdata->rule_id && + rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST)){ + lkups_cnt = list_itr->lkups_cnt; + lkups_dp = (struct ice_adv_lkup_elem *) + ice_memdup(hw, list_itr->lkups, + sizeof(*list_itr->lkups) * + lkups_cnt, ICE_NONDMA_TO_NONDMA); + + if (!lkups_dp) { + PMD_DRV_LOG(ERR, "Failed to allocate memory."); + return -EINVAL; + } + + if (rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST) { + rinfo.sw_act.vsi_handle = rd->vsi_handle; + rinfo.sw_act.fltr_act = ICE_FWD_TO_VSI; + } + break; + } + } + + if (!lkups_dp) + return -EINVAL; + + /* Remove the old rule */ + ret = ice_rem_adv_rule(hw, list_itr->lkups, + lkups_cnt, &rinfo); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to delete the old rule %d", + rdata->rule_id); + ret = -EINVAL; + goto out; + } + + /* Update VSI context */ + hw->vsi_ctx[rd->vsi_handle]->vsi_num = rd->new_vsi_num; + + /* Replay the rule */ + ret = ice_add_adv_rule(hw, lkups_dp, lkups_cnt, + &rinfo, rdata); + if (ret) { + PMD_DRV_LOG(ERR, "Failed to replay the rule"); + ret = -EINVAL; + } + +out: + ice_free(hw, lkups_dp); + return ret; +} + static int ice_switch_init(struct ice_adapter *ad) { @@ -1374,6 +1837,7 @@ ice_flow_engine ice_switch_engine = { .create = ice_switch_create, .destroy = ice_switch_destroy, .query_count = ice_switch_query, + .redirect = ice_switch_redirect, .free = ice_switch_filter_rule_free, .type = ICE_FLOW_ENGINE_SWITCH, };