#include "iavf.h"
#include "iavf_generic_flow.h"
#include "virtchnl.h"
+#include "iavf_rxtx.h"
#define IAVF_FDIR_MAX_QREGION_SIZE 128
IAVF_INSET_IPV6_TC | IAVF_INSET_IPV6_HOP_LIMIT | \
IAVF_INSET_SCTP_SRC_PORT | IAVF_INSET_SCTP_DST_PORT)
+#define IAVF_FDIR_INSET_IPV4_GTPU (\
+ IAVF_INSET_IPV4_SRC | IAVF_INSET_IPV4_DST | \
+ IAVF_INSET_GTPU_TEID)
+
+#define IAVF_FDIR_INSET_IPV4_GTPU_EH (\
+ IAVF_INSET_IPV4_SRC | IAVF_INSET_IPV4_DST | \
+ IAVF_INSET_GTPU_TEID | IAVF_INSET_GTPU_QFI)
+
+#define IAVF_FDIR_INSET_IPV6_GTPU (\
+ IAVF_INSET_IPV6_SRC | IAVF_INSET_IPV6_DST | \
+ IAVF_INSET_GTPU_TEID)
+
+#define IAVF_FDIR_INSET_IPV6_GTPU_EH (\
+ IAVF_INSET_IPV6_SRC | IAVF_INSET_IPV6_DST | \
+ IAVF_INSET_GTPU_TEID | IAVF_INSET_GTPU_QFI)
+
+#define IAVF_FDIR_INSET_L2TPV3OIP (\
+ IAVF_L2TPV3OIP_SESSION_ID)
+
+#define IAVF_FDIR_INSET_ESP (\
+ IAVF_INSET_ESP_SPI)
+
+#define IAVF_FDIR_INSET_AH (\
+ IAVF_INSET_AH_SPI)
+
+#define IAVF_FDIR_INSET_IPV4_NATT_ESP (\
+ IAVF_INSET_IPV4_SRC | IAVF_INSET_IPV4_DST | \
+ IAVF_INSET_ESP_SPI)
+
+#define IAVF_FDIR_INSET_IPV6_NATT_ESP (\
+ IAVF_INSET_IPV6_SRC | IAVF_INSET_IPV6_DST | \
+ IAVF_INSET_ESP_SPI)
+
+#define IAVF_FDIR_INSET_PFCP (\
+ IAVF_INSET_PFCP_S_FIELD)
+
static struct iavf_pattern_match_item iavf_fdir_pattern[] = {
{iavf_pattern_ethertype, IAVF_FDIR_INSET_ETH, IAVF_INSET_NONE},
{iavf_pattern_eth_ipv4, IAVF_FDIR_INSET_ETH_IPV4, IAVF_INSET_NONE},
{iavf_pattern_eth_ipv6_udp, IAVF_FDIR_INSET_ETH_IPV6_UDP, IAVF_INSET_NONE},
{iavf_pattern_eth_ipv6_tcp, IAVF_FDIR_INSET_ETH_IPV6_TCP, IAVF_INSET_NONE},
{iavf_pattern_eth_ipv6_sctp, IAVF_FDIR_INSET_ETH_IPV6_SCTP, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv4_gtpu, IAVF_FDIR_INSET_IPV4_GTPU, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv4_gtpu_eh, IAVF_FDIR_INSET_IPV4_GTPU_EH, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv6_gtpu, IAVF_FDIR_INSET_IPV6_GTPU, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv6_gtpu_eh, IAVF_FDIR_INSET_IPV6_GTPU_EH, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv4_l2tpv3, IAVF_FDIR_INSET_L2TPV3OIP, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv6_l2tpv3, IAVF_FDIR_INSET_L2TPV3OIP, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv4_esp, IAVF_FDIR_INSET_ESP, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv6_esp, IAVF_FDIR_INSET_ESP, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv4_ah, IAVF_FDIR_INSET_AH, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv6_ah, IAVF_FDIR_INSET_AH, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv4_udp_esp, IAVF_FDIR_INSET_IPV4_NATT_ESP, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv6_udp_esp, IAVF_FDIR_INSET_IPV6_NATT_ESP, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv4_pfcp, IAVF_FDIR_INSET_PFCP, IAVF_INSET_NONE},
+ {iavf_pattern_eth_ipv6_pfcp, IAVF_FDIR_INSET_PFCP, IAVF_INSET_NONE},
};
static struct iavf_flow_parser iavf_fdir_parser;
goto free_entry;
}
+ if (filter->mark_flag == 1)
+ iavf_fdir_rx_proc_enable(ad, 1);
+
rte_memcpy(rule, filter, sizeof(*rule));
flow->rule = rule;
return -rte_errno;
}
+ if (filter->mark_flag == 1)
+ iavf_fdir_rx_proc_enable(ad, 0);
+
flow->rule = NULL;
rte_free(filter);
struct iavf_fdir_conf *filter)
{
const struct rte_flow_action_queue *act_q;
+ const struct rte_flow_action_mark *mark_spec = NULL;
uint32_t dest_num = 0;
+ uint32_t mark_num = 0;
int ret;
int number = 0;
filter->add_fltr.rule_cfg.action_set.count = ++number;
break;
+ case RTE_FLOW_ACTION_TYPE_MARK:
+ mark_num++;
+
+ filter->mark_flag = 1;
+ mark_spec = actions->conf;
+ filter_action = &filter->add_fltr.rule_cfg.action_set.actions[number];
+
+ filter_action->type = VIRTCHNL_ACTION_MARK;
+ filter_action->act_conf.mark_id = mark_spec->id;
+
+ filter->add_fltr.rule_cfg.action_set.count = ++number;
+ break;
+
default:
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, actions,
return -rte_errno;
}
- if (dest_num == 0 || dest_num >= 2) {
+ if (dest_num >= 2) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION, actions,
"Unsupported action combination");
return -rte_errno;
}
+ if (mark_num >= 2) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, actions,
+ "Too many mark actions");
+ return -rte_errno;
+ }
+
+ if (dest_num + mark_num == 0) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, actions,
+ "Empty action");
+ return -rte_errno;
+ }
+
+ /* Mark only is equal to mark + passthru. */
+ if (dest_num == 0) {
+ filter_action = &filter->add_fltr.rule_cfg.action_set.actions[number];
+ filter_action->type = VIRTCHNL_ACTION_PASSTHRU;
+ filter->add_fltr.rule_cfg.action_set.count = ++number;
+ }
+
return 0;
}
const struct rte_flow_item_udp *udp_spec, *udp_mask;
const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
+ const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
+ const struct rte_flow_item_gtp_psc *gtp_psc_spec, *gtp_psc_mask;
+ const struct rte_flow_item_l2tpv3oip *l2tpv3oip_spec, *l2tpv3oip_mask;
+ 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_pfcp *pfcp_spec, *pfcp_mask;
uint64_t input_set = IAVF_INSET_NONE;
enum rte_flow_item_type next_type;
filter->add_fltr.rule_cfg.proto_hdrs.count = ++layer;
break;
+ case RTE_FLOW_ITEM_TYPE_GTPU:
+ gtp_spec = item->spec;
+ gtp_mask = item->mask;
+
+ hdr = &filter->add_fltr.rule_cfg.proto_hdrs.proto_hdr[layer];
+
+ VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_IP);
+
+ if (gtp_spec && gtp_mask) {
+ if (gtp_mask->v_pt_rsv_flags ||
+ gtp_mask->msg_type ||
+ gtp_mask->msg_len) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item, "Invalid GTP mask");
+ return -rte_errno;
+ }
+
+ if (gtp_mask->teid == UINT32_MAX) {
+ input_set |= IAVF_INSET_GTPU_TEID;
+ VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, GTPU_IP, TEID);
+ }
+
+ rte_memcpy(hdr->buffer,
+ gtp_spec, sizeof(*gtp_spec));
+ }
+
+ filter->add_fltr.rule_cfg.proto_hdrs.count = ++layer;
+ break;
+
+ case RTE_FLOW_ITEM_TYPE_GTP_PSC:
+ gtp_psc_spec = item->spec;
+ gtp_psc_mask = item->mask;
+
+ hdr = &filter->add_fltr.rule_cfg.proto_hdrs.proto_hdr[layer];
+
+ VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_EH);
+
+ if (gtp_psc_spec && gtp_psc_mask) {
+ if (gtp_psc_mask->qfi == UINT8_MAX) {
+ input_set |= IAVF_INSET_GTPU_QFI;
+ VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, GTPU_EH, QFI);
+ }
+
+ rte_memcpy(hdr->buffer, gtp_psc_spec,
+ sizeof(*gtp_psc_spec));
+ }
+
+ filter->add_fltr.rule_cfg.proto_hdrs.count = ++layer;
+ break;
+
+ case RTE_FLOW_ITEM_TYPE_L2TPV3OIP:
+ l2tpv3oip_spec = item->spec;
+ l2tpv3oip_mask = item->mask;
+
+ hdr = &filter->add_fltr.rule_cfg.proto_hdrs.proto_hdr[layer];
+
+ VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, L2TPV3);
+
+ if (l2tpv3oip_spec && l2tpv3oip_mask) {
+ if (l2tpv3oip_mask->session_id == UINT32_MAX) {
+ input_set |= IAVF_L2TPV3OIP_SESSION_ID;
+ VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, L2TPV3, SESS_ID);
+ }
+
+ rte_memcpy(hdr->buffer, l2tpv3oip_spec,
+ sizeof(*l2tpv3oip_spec));
+ }
+
+ filter->add_fltr.rule_cfg.proto_hdrs.count = ++layer;
+ break;
+
+ case RTE_FLOW_ITEM_TYPE_ESP:
+ esp_spec = item->spec;
+ esp_mask = item->mask;
+
+ hdr = &filter->add_fltr.rule_cfg.proto_hdrs.proto_hdr[layer];
+
+ VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, ESP);
+
+ if (esp_spec && esp_mask) {
+ if (esp_mask->hdr.spi == UINT32_MAX) {
+ input_set |= IAVF_INSET_ESP_SPI;
+ VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, ESP, SPI);
+ }
+
+ rte_memcpy(hdr->buffer, &esp_spec->hdr,
+ sizeof(esp_spec->hdr));
+ }
+
+ filter->add_fltr.rule_cfg.proto_hdrs.count = ++layer;
+ break;
+
+ case RTE_FLOW_ITEM_TYPE_AH:
+ ah_spec = item->spec;
+ ah_mask = item->mask;
+
+ hdr = &filter->add_fltr.rule_cfg.proto_hdrs.proto_hdr[layer];
+
+ VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, AH);
+
+ if (ah_spec && ah_mask) {
+ if (ah_mask->spi == UINT32_MAX) {
+ input_set |= IAVF_INSET_AH_SPI;
+ VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, AH, SPI);
+ }
+
+ rte_memcpy(hdr->buffer, ah_spec,
+ sizeof(*ah_spec));
+ }
+
+ filter->add_fltr.rule_cfg.proto_hdrs.count = ++layer;
+ break;
+
+ case RTE_FLOW_ITEM_TYPE_PFCP:
+ pfcp_spec = item->spec;
+ pfcp_mask = item->mask;
+
+ hdr = &filter->add_fltr.rule_cfg.proto_hdrs.proto_hdr[layer];
+
+ VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, PFCP);
+
+ if (pfcp_spec && pfcp_mask) {
+ if (pfcp_mask->s_field == UINT8_MAX) {
+ input_set |= IAVF_INSET_PFCP_S_FIELD;
+ VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, PFCP, S_FIELD);
+ }
+
+ rte_memcpy(hdr->buffer, pfcp_spec,
+ sizeof(*pfcp_spec));
+ }
+
+ filter->add_fltr.rule_cfg.proto_hdrs.count = ++layer;
+ break;
+
case RTE_FLOW_ITEM_TYPE_VOID:
break;