When OVS-DPDK is working as a pure L2 switch, Destination MAC match offload with Mark+RSS action would help the performance speed up. And FVL FDIR should support to change input set to be destination MAC. When create a FDIR rule which pattern only has ether dst_mac like below: flow create 0 ingress pattern eth dst is <mac_addr> / end actions mark id <id> / rss / end The following 11 pctypes of matched packets can Mark+RSS. PCTYPE_NONF_IPV4_UDP PCTYPE_NONF_IPV4_TCP PCTYPE_NONF_IPV4_SCTP PCTYPE_NONF_IPV4_OTHER PCTYPE_FRAG_IPV4 PCTYPE_NONF_IPV6_UDP PCTYPE_NONF_IPV6_TCP PCTYPE_NONF_IPV6_SCTP PCTYPE_NONF_IPV6_OTHER PCTYPE_FRAG_IPV6 PCTYPE_L2_PAYLOAD Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- drivers/net/i40e/i40e_ethdev.c | 92 +++++++------- drivers/net/i40e/i40e_ethdev.h | 10 +- drivers/net/i40e/i40e_fdir.c | 8 +- drivers/net/i40e/i40e_flow.c | 213 +++++++++++++++++++++++++-------- 4 files changed, 226 insertions(+), 97 deletions(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9fbda1c34..bc5522d53 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9337,15 +9337,16 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, */ static const uint64_t valid_fdir_inset_table[] = { [I40E_FILTER_PCTYPE_FRAG_IPV4] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | - I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | - I40E_INSET_IPV4_TTL, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | - I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | - I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | + I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP] = I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | @@ -9357,36 +9358,38 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | - I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | - I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | + I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK] = I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | - I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | - I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | - I40E_INSET_SCTP_VT, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | + I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | - I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | - I40E_INSET_IPV4_TTL, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, [I40E_FILTER_PCTYPE_FRAG_IPV6] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | - I40E_INSET_IPV6_TC | I40E_INSET_IPV6_NEXT_HDR | - I40E_INSET_IPV6_HOP_LIMIT, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV6_SRC | + I40E_INSET_IPV6_DST | I40E_INSET_IPV6_TC | + I40E_INSET_IPV6_NEXT_HDR | I40E_INSET_IPV6_HOP_LIMIT, [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | - I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT | - I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV6_SRC | + I40E_INSET_IPV6_DST | I40E_INSET_IPV6_TC | + I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_SRC_PORT | + I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP] = I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | @@ -9398,29 +9401,30 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | - I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT | - I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV6_SRC | + I40E_INSET_IPV6_DST | I40E_INSET_IPV6_TC | + I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_SRC_PORT | + I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK] = I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | - I40E_INSET_IPV6_TC | I40E_INSET_IPV6_HOP_LIMIT | - I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | - I40E_INSET_SCTP_VT, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV6_SRC | + I40E_INSET_IPV6_DST | I40E_INSET_IPV6_TC | + I40E_INSET_IPV6_HOP_LIMIT | I40E_INSET_SRC_PORT | + I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | - I40E_INSET_IPV6_TC | I40E_INSET_IPV6_NEXT_HDR | - I40E_INSET_IPV6_HOP_LIMIT, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV6_SRC | + I40E_INSET_IPV6_DST | I40E_INSET_IPV6_TC | + I40E_INSET_IPV6_NEXT_HDR | I40E_INSET_IPV6_HOP_LIMIT, [I40E_FILTER_PCTYPE_L2_PAYLOAD] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_LAST_ETHER_TYPE, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_LAST_ETHER_TYPE, }; if (pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..e4f445081 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ +struct i40e_eth_l2_flow { + struct rte_ether_addr src; + struct rte_ether_addr dst; + struct rte_eth_l2_flow i40e_l2_flow; +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_eth_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; @@ -637,6 +644,7 @@ struct i40e_fdir_filter_conf { /* ID, an unique value is required when deal with FDIR entry */ struct i40e_fdir_input input; /* Input set */ struct i40e_fdir_action action; /* Action taken when match */ + bool fdir_dst_mac_rule; /* rule which only includes dst mac pattern */ }; /* diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..d926b1eda 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1062,7 +1062,9 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; - raw_pkt += 2 * sizeof(struct rte_ether_addr); + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + raw_pkt += sizeof(struct rte_ether_addr); if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), @@ -1085,7 +1087,7 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, } if (pctype == I40E_FILTER_PCTYPE_L2_PAYLOAD) - *ether_type = fdir_input->flow.l2_flow.ether_type; + *ether_type = fdir_input->flow.l2_flow.i40e_l2_flow.ether_type; else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_TCP || pctype == I40E_FILTER_PCTYPE_NONF_IPV4_UDP || pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP || @@ -1271,7 +1273,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, * ARP packet is a special case on which the payload * starts after the whole ARP header */ - if (fdir_input->flow.l2_flow.ether_type == + if (fdir_input->flow.l2_flow.i40e_l2_flow.ether_type == rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP)) payload += sizeof(struct rte_arp_hdr); set_idx = I40E_FLXPLD_L2_IDX; diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..cfd530a87 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2595,6 +2595,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, uint32_t vtc_flow_cpu; bool outer_ip = true; int ret; + uint16_t flow_type; memset(off_arr, 0, sizeof(off_arr)); memset(len_arr, 0, sizeof(len_arr)); @@ -2626,8 +2627,16 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || - !rte_is_zero_ether_addr(ð_mask->dst)) { + if (next_type == RTE_FLOW_ITEM_TYPE_END && + rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_zero_ether_addr(ð_mask->src) && + rte_is_zero_ether_addr(ð_spec->src)) { + cons_filter.fdir_filter.fdir_dst_mac_rule = true; + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (!rte_is_zero_ether_addr(ð_mask->src) || + !rte_is_zero_ether_addr(ð_mask->dst)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -2658,7 +2667,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } input_set |= I40E_INSET_LAST_ETHER_TYPE; - filter->input.flow.l2_flow.ether_type = + filter->input.flow.l2_flow.i40e_l2_flow.ether_type = eth_spec->type; } @@ -2703,7 +2712,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } input_set |= I40E_INSET_LAST_ETHER_TYPE; - filter->input.flow.l2_flow.ether_type = + filter->input.flow.l2_flow.i40e_l2_flow.ether_type = vlan_spec->inner_type; } @@ -3217,41 +3226,96 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, /* If customized pctype is not used, set fdir configuration.*/ if (!filter->input.flow_ext.customized_pctype) { - ret = i40e_flow_set_fdir_inset(pf, pctype, input_set); - if (ret == -1) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, item, - "Conflict with the first rule's input set."); - return -rte_errno; - } else if (ret == -EINVAL) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, item, - "Invalid pattern mask."); - return -rte_errno; - } + if (filter->fdir_dst_mac_rule) { + for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; + pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) { + flow_type = i40e_pctype_to_flowtype(pf->adapter, pctype); + + if (flow_type == RTE_ETH_FLOW_UNKNOWN) + continue; + + ret = i40e_flow_set_fdir_inset(pf, + pctype, + input_set); + if (ret == -1) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Conflict with the first rule's input set."); + return -rte_errno; + } else if (ret == -EINVAL) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Invalid pattern mask."); + return -rte_errno; + } - /* Store flex mask to SW */ - ret = i40e_flow_store_flex_mask(pf, pctype, flex_mask); - if (ret == -1) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, - "Exceed maximal number of bitmasks"); - return -rte_errno; - } else if (ret == -2) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ITEM, - item, - "Conflict with the first flexible rule"); - return -rte_errno; - } else if (ret > 0) - cfg_flex_msk = false; + /* Store flex mask to SW */ + ret = i40e_flow_store_flex_mask(pf, + pctype, + flex_mask); + if (ret == -1) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Exceed maximal number of bitmasks"); + return -rte_errno; + } else if (ret == -2) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Conflict with the first flexible rule"); + return -rte_errno; + } else if (ret > 0) { + cfg_flex_msk = false; + } - if (cfg_flex_pit) - i40e_flow_set_fdir_flex_pit(pf, layer_idx, raw_id); + if (cfg_flex_pit) + i40e_flow_set_fdir_flex_pit(pf, + layer_idx, raw_id); - if (cfg_flex_msk) - i40e_flow_set_fdir_flex_msk(pf, pctype); + if (cfg_flex_msk) + i40e_flow_set_fdir_flex_msk(pf, + pctype); + } + } else { + ret = i40e_flow_set_fdir_inset(pf, pctype, input_set); + if (ret == -1) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Conflict with the first rule's input set."); + return -rte_errno; + } else if (ret == -EINVAL) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "Invalid pattern mask."); + return -rte_errno; + } + + /* Store flex mask to SW */ + ret = i40e_flow_store_flex_mask(pf, pctype, flex_mask); + if (ret == -1) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Exceed maximal number of bitmasks"); + return -rte_errno; + } else if (ret == -2) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Conflict with the first flexible rule"); + return -rte_errno; + } else if (ret > 0) { + cfg_flex_msk = false; + } + + if (cfg_flex_pit) + i40e_flow_set_fdir_flex_pit(pf, + layer_idx, raw_id); + + if (cfg_flex_msk) + i40e_flow_set_fdir_flex_msk(pf, pctype); + } } filter->input.pctype = pctype; @@ -4897,6 +4961,8 @@ i40e_flow_create(struct rte_eth_dev *dev, struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); struct rte_flow *flow; int ret; + uint16_t flow_type; + enum i40e_filter_pctype pctype; flow = rte_zmalloc("i40e_flow", sizeof(struct rte_flow), 0); if (!flow) { @@ -4920,10 +4986,32 @@ i40e_flow_create(struct rte_eth_dev *dev, i40e_ethertype_filter_list); break; case RTE_ETH_FILTER_FDIR: - ret = i40e_flow_add_del_fdir_filter(dev, - &cons_filter.fdir_filter, 1); - if (ret) - goto free_flow; + if (!cons_filter.fdir_filter.fdir_dst_mac_rule) { + ret = i40e_flow_add_del_fdir_filter(dev, + &cons_filter.fdir_filter, 1); + if (ret) + goto free_flow; + + flow->rule = TAILQ_LAST(&pf->fdir.fdir_list, + i40e_fdir_filter_list); + break; + } + + for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; + pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) { + flow_type = i40e_pctype_to_flowtype(pf->adapter, pctype); + + if (flow_type == RTE_ETH_FLOW_UNKNOWN) + continue; + + cons_filter.fdir_filter.input.pctype = + pctype; + ret = i40e_flow_add_del_fdir_filter(dev, + &cons_filter.fdir_filter, 1); + if (ret) + goto free_flow; + } + flow->rule = TAILQ_LAST(&pf->fdir.fdir_list, i40e_fdir_filter_list); break; @@ -4965,7 +5053,10 @@ i40e_flow_destroy(struct rte_eth_dev *dev, { struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); enum rte_filter_type filter_type = flow->filter_type; + struct i40e_fdir_filter *fdir_rule = NULL; int ret = 0; + uint16_t flow_type; + enum i40e_filter_pctype pctype; switch (filter_type) { case RTE_ETH_FILTER_ETHERTYPE: @@ -4977,15 +5068,39 @@ i40e_flow_destroy(struct rte_eth_dev *dev, (struct i40e_tunnel_filter *)flow->rule); break; case RTE_ETH_FILTER_FDIR: - ret = i40e_flow_add_del_fdir_filter(dev, - &((struct i40e_fdir_filter *)flow->rule)->fdir, 0); - - /* If the last flow is destroyed, disable fdir. */ - if (!ret && TAILQ_EMPTY(&pf->fdir.fdir_list)) { - i40e_fdir_teardown(pf); - dev->data->dev_conf.fdir_conf.mode = - RTE_FDIR_MODE_NONE; - i40e_fdir_rx_proc_enable(dev, 0); + fdir_rule = (struct i40e_fdir_filter *)flow->rule; + if (!fdir_rule->fdir.fdir_dst_mac_rule) { + ret = i40e_flow_add_del_fdir_filter(dev, + &fdir_rule->fdir, 0); + + /* If the last flow is destroyed, disable fdir. */ + if (!ret && TAILQ_EMPTY(&pf->fdir.fdir_list)) { + i40e_fdir_teardown(pf); + dev->data->dev_conf.fdir_conf.mode = + RTE_FDIR_MODE_NONE; + i40e_fdir_rx_proc_enable(dev, 0); + } + break; + } + + for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; + pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) { + flow_type = i40e_pctype_to_flowtype(pf->adapter, pctype); + + if (flow_type == RTE_ETH_FLOW_UNKNOWN) + continue; + + fdir_rule->fdir.input.pctype = pctype; + ret = i40e_flow_add_del_fdir_filter(dev, + &fdir_rule->fdir, 0); + + /* Last flow is destroyed, disable fdir. */ + if (!ret && TAILQ_EMPTY(&pf->fdir.fdir_list)) { + i40e_fdir_teardown(pf); + dev->data->dev_conf.fdir_conf.mode = + RTE_FDIR_MODE_NONE; + i40e_fdir_rx_proc_enable(dev, 0); + } } break; case RTE_ETH_FILTER_HASH: -- 2.17.1
FVL enable Destination MAC address as FDIR's input set for ipv4-other. When OVS-DPDK is working as a pure L2 switch, destination MAC match offload with Mark+RSS action would help the performance speed up. And FVL FDir supports to change input set to be destination MAC. Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- doc/guides/rel_notes/release_20_05.rst | 6 +++ drivers/net/i40e/i40e_ethdev.c | 8 ++-- drivers/net/i40e/i40e_ethdev.h | 10 ++++- drivers/net/i40e/i40e_fdir.c | 19 +++++++--- drivers/net/i40e/i40e_flow.c | 52 +++++++++++++++++--------- 5 files changed, 68 insertions(+), 27 deletions(-) diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 2190eaf85..a5aac0d2a 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -56,6 +56,12 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Updated Intel i40e driver.** + + Updated i40e PMD with new features and improvements, including: + + * enable dst MAC address as FDIR input set for ipv4-other + Removed Items ------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9fbda1c34..0003b5ae6 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9373,10 +9373,10 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = - I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | - I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | - I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | - I40E_INSET_IPV4_TTL, + I40E_INSET_DMAC | I40E_INSET_VLAN_OUTER | + I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, [I40E_FILTER_PCTYPE_FRAG_IPV6] = I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST | diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..d8361118a 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ +struct i40e_eth_l2_flow { + struct rte_ether_addr src; + struct rte_ether_addr dst; + uint16_t ether_type; /**< Ether type in big endian */ +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_eth_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; @@ -637,6 +644,7 @@ struct i40e_fdir_filter_conf { /* ID, an unique value is required when deal with FDIR entry */ struct i40e_fdir_input input; /* Input set */ struct i40e_fdir_action action; /* Action taken when match */ + bool fdir_dst_mac_rule; /* rule which only includes dst mac pattern */ }; /* diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..b1d7b61b8 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1041,7 +1041,8 @@ static inline int i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, const struct i40e_fdir_input *fdir_input, unsigned char *raw_pkt, - bool vlan) + bool vlan, + bool fdir_dst_mac_input) { struct i40e_customized_pctype *cus_pctype = NULL; static uint8_t vlan_frame[] = {0x81, 0, 0, 0}; @@ -1062,7 +1063,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; - raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (fdir_dst_mac_input) { + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + raw_pkt += sizeof(struct rte_ether_addr); + } else { + raw_pkt += 2 * sizeof(struct rte_ether_addr); + } if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), @@ -1156,7 +1163,8 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, static int i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, const struct i40e_fdir_input *fdir_input, - unsigned char *raw_pkt) + unsigned char *raw_pkt, + bool fdir_dst_mac_input) { unsigned char *payload = NULL; unsigned char *ptr; @@ -1186,7 +1194,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, /* fill the ethernet and IP head */ len = i40e_flow_fdir_fill_eth_ip_head(pf, fdir_input, raw_pkt, - !!fdir_input->flow_ext.vlan_tci); + !!fdir_input->flow_ext.vlan_tci, fdir_dst_mac_input); if (len < 0) return -EINVAL; @@ -1733,7 +1741,8 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev, memset(pkt, 0, I40E_FDIR_PKT_LEN); - ret = i40e_flow_fdir_construct_pkt(pf, &filter->input, pkt); + ret = i40e_flow_fdir_construct_pkt(pf, &filter->input, pkt, + filter->fdir_dst_mac_rule); if (ret < 0) { PMD_DRV_LOG(ERR, "construct packet for fdir fails."); return ret; diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..c26b3e648 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2626,7 +2626,12 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || + if (rte_is_broadcast_ether_addr(ð_mask->dst)) { + cons_filter.fdir_filter.fdir_dst_mac_rule = true; + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (!rte_is_zero_ether_addr(ð_mask->src) || !rte_is_zero_ether_addr(ð_mask->dst)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2635,7 +2640,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } } - if (eth_spec && eth_mask && eth_mask->type) { + if (eth_spec && eth_mask && + next_type == RTE_FLOW_ITEM_TYPE_END) { if (eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2750,21 +2756,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, frag_off & RTE_IPV4_HDR_MF_FLAG) pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; - /* Get the filter info */ - filter->input.flow.ip4_flow.proto = - ipv4_spec->hdr.next_proto_id; - filter->input.flow.ip4_flow.tos = - ipv4_spec->hdr.type_of_service; - filter->input.flow.ip4_flow.ttl = - ipv4_spec->hdr.time_to_live; - filter->input.flow.ip4_flow.src_ip = - ipv4_spec->hdr.src_addr; - filter->input.flow.ip4_flow.dst_ip = - ipv4_spec->hdr.dst_addr; - - filter->input.flow_ext.inner_ip = false; - filter->input.flow_ext.oip_type = - I40E_FDIR_IPTYPE_IPV4; + if (cons_filter.fdir_filter.fdir_dst_mac_rule) { + if (input_set & (I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid MAC_addr mask."); + return -rte_errno; + } + } else { + /* Get the filter info */ + filter->input.flow.ip4_flow.proto = + ipv4_spec->hdr.next_proto_id; + filter->input.flow.ip4_flow.tos = + ipv4_spec->hdr.type_of_service; + filter->input.flow.ip4_flow.ttl = + ipv4_spec->hdr.time_to_live; + filter->input.flow.ip4_flow.src_ip = + ipv4_spec->hdr.src_addr; + filter->input.flow.ip4_flow.dst_ip = + ipv4_spec->hdr.dst_addr; + + filter->input.flow_ext.inner_ip = false; + filter->input.flow_ext.oip_type = + I40E_FDIR_IPTYPE_IPV4; + } } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { filter->input.flow_ext.inner_ip = true; filter->input.flow_ext.iip_type = -- 2.17.1
FVL enable both src MAC address and dst MAC address as FDIR's input set for ipv4-other. And FVL enable only dst MAC address as FDIR's input set for ipv4-other. When OVS-DPDK is working as a pure L2 switch, Both two ways match offload with Mark+RSS action would help the performance speed up. And FVL FDIR supports to change input set as both two ways. Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- v2: - Enable src MAC address as FDIR's input set --- doc/guides/rel_notes/release_20_05.rst | 7 +++ drivers/net/i40e/i40e_ethdev.c | 1 + drivers/net/i40e/i40e_ethdev.h | 18 +++++++- drivers/net/i40e/i40e_fdir.c | 22 +++++++-- drivers/net/i40e/i40e_flow.c | 63 +++++++++++++++++++------- 5 files changed, 89 insertions(+), 22 deletions(-) diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 2190eaf85..f0efc5295 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -56,6 +56,13 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Updated Intel i40e driver.** + + Updated i40e PMD with new features and improvements, including: + + * enable only dst MAC address as FDIR input set for ipv4-other + * enable both src MAC address and dst MAC address as FDIR input set for ipv4-other + Removed Items ------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9fbda1c34..d11df8d83 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9373,6 +9373,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..e8b98b67e 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ +struct i40e_eth_l2_flow { + struct rte_ether_addr dst; + struct rte_ether_addr src; + uint16_t ether_type; /**< Ether type in big endian */ +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_eth_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; @@ -628,6 +635,13 @@ struct i40e_fdir_action { uint8_t flex_off; }; +/* Ether input set kinds */ +enum i40e_fdir_eth_inset { + I40E_ETH_INSET_NULL = 0, + I40E_ETH_INSET_DMAC, + I40E_ETH_INSET_SMAC_DMAC, +}; + /* A structure used to define the flow director filter entry by filter_ctrl API * It supports RTE_ETH_FILTER_FDIR with RTE_ETH_FILTER_ADD and * RTE_ETH_FILTER_DELETE operations. @@ -637,6 +651,8 @@ struct i40e_fdir_filter_conf { /* ID, an unique value is required when deal with FDIR entry */ struct i40e_fdir_input input; /* Input set */ struct i40e_fdir_action action; /* Action taken when match */ + /* rule which only includes dst mac pattern */ + enum i40e_fdir_eth_inset fdir_dst_mac_rule; }; /* diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..a14f14e75 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1041,7 +1041,8 @@ static inline int i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, const struct i40e_fdir_input *fdir_input, unsigned char *raw_pkt, - bool vlan) + bool vlan, + enum i40e_fdir_eth_inset fdir_dst_mac_input) { struct i40e_customized_pctype *cus_pctype = NULL; static uint8_t vlan_frame[] = {0x81, 0, 0, 0}; @@ -1062,7 +1063,18 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; + if (fdir_dst_mac_input == I40E_ETH_INSET_DMAC) { + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + } else if (fdir_dst_mac_input == I40E_ETH_INSET_SMAC_DMAC) { + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), + &fdir_input->flow.l2_flow.src, + sizeof(struct rte_ether_addr)); + } raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), @@ -1156,7 +1168,8 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, static int i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, const struct i40e_fdir_input *fdir_input, - unsigned char *raw_pkt) + unsigned char *raw_pkt, + enum i40e_fdir_eth_inset fdir_dst_mac_input) { unsigned char *payload = NULL; unsigned char *ptr; @@ -1186,7 +1199,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, /* fill the ethernet and IP head */ len = i40e_flow_fdir_fill_eth_ip_head(pf, fdir_input, raw_pkt, - !!fdir_input->flow_ext.vlan_tci); + !!fdir_input->flow_ext.vlan_tci, fdir_dst_mac_input); if (len < 0) return -EINVAL; @@ -1733,7 +1746,8 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev, memset(pkt, 0, I40E_FDIR_PKT_LEN); - ret = i40e_flow_fdir_construct_pkt(pf, &filter->input, pkt); + ret = i40e_flow_fdir_construct_pkt(pf, &filter->input, pkt, + filter->fdir_dst_mac_rule); if (ret < 0) { PMD_DRV_LOG(ERR, "construct packet for fdir fails."); return ret; diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..3d33fc276 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2626,7 +2626,23 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || + if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_zero_ether_addr(ð_mask->src)) { + cons_filter.fdir_filter.fdir_dst_mac_rule = + I40E_ETH_INSET_DMAC; + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + cons_filter.fdir_filter.fdir_dst_mac_rule = + I40E_ETH_INSET_SMAC_DMAC; + filter->input.flow.l2_flow.dst = + eth_spec->dst; + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= (I40E_INSET_DMAC | I40E_INSET_SMAC); + } else if (!rte_is_zero_ether_addr(ð_mask->src) || !rte_is_zero_ether_addr(ð_mask->dst)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } } - if (eth_spec && eth_mask && eth_mask->type) { + if (eth_spec && eth_mask && + next_type == RTE_FLOW_ITEM_TYPE_END) { if (eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2750,21 +2767,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, frag_off & RTE_IPV4_HDR_MF_FLAG) pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; - /* Get the filter info */ - filter->input.flow.ip4_flow.proto = - ipv4_spec->hdr.next_proto_id; - filter->input.flow.ip4_flow.tos = - ipv4_spec->hdr.type_of_service; - filter->input.flow.ip4_flow.ttl = - ipv4_spec->hdr.time_to_live; - filter->input.flow.ip4_flow.src_ip = - ipv4_spec->hdr.src_addr; - filter->input.flow.ip4_flow.dst_ip = - ipv4_spec->hdr.dst_addr; - - filter->input.flow_ext.inner_ip = false; - filter->input.flow_ext.oip_type = - I40E_FDIR_IPTYPE_IPV4; + if (cons_filter.fdir_filter.fdir_dst_mac_rule) { + if (input_set & (I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid MAC_addr mask."); + return -rte_errno; + } + } else { + /* Get the filter info */ + filter->input.flow.ip4_flow.proto = + ipv4_spec->hdr.next_proto_id; + filter->input.flow.ip4_flow.tos = + ipv4_spec->hdr.type_of_service; + filter->input.flow.ip4_flow.ttl = + ipv4_spec->hdr.time_to_live; + filter->input.flow.ip4_flow.src_ip = + ipv4_spec->hdr.src_addr; + filter->input.flow.ip4_flow.dst_ip = + ipv4_spec->hdr.dst_addr; + + filter->input.flow_ext.inner_ip = false; + filter->input.flow_ext.oip_type = + I40E_FDIR_IPTYPE_IPV4; + } } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { filter->input.flow_ext.inner_ip = true; filter->input.flow_ext.iip_type = -- 2.17.1
> -----Original Message----- > From: Cui, LunyuanX <lunyuanx.cui@intel.com> > Sent: Wednesday, March 18, 2020 11:15 AM > To: dev@dpdk.org > Cc: Xing, Beilei <beilei.xing@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>; > Wu, Jingjing <jingjing.wu@intel.com>; Cui, LunyuanX > <lunyuanx.cui@intel.com> > Subject: [PATCH v2] net/i40e: enable MAC address as FDIR input set > > FVL enable both src MAC address and dst MAC address as FDIR's input set > for ipv4-other. And FVL enable only dst MAC address as FDIR's input set for > ipv4-other. Why emphasize input set 'src MAC address and dst MAC address' and ' dst MAC address ' as input set? Can't we support src MAC only? When OVS-DPDK is working as a pure L2 switch, Both two ways > match offload with Mark+RSS action would help the performance speed up. > And FVL FDIR supports to change input set as both two ways. > > Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> > > --- > v2: > - Enable src MAC address as FDIR's input set > --- > doc/guides/rel_notes/release_20_05.rst | 7 +++ > drivers/net/i40e/i40e_ethdev.c | 1 + > drivers/net/i40e/i40e_ethdev.h | 18 +++++++- > drivers/net/i40e/i40e_fdir.c | 22 +++++++-- > drivers/net/i40e/i40e_flow.c | 63 +++++++++++++++++++------- > 5 files changed, 89 insertions(+), 22 deletions(-) > > diff --git a/doc/guides/rel_notes/release_20_05.rst > b/doc/guides/rel_notes/release_20_05.rst > index 2190eaf85..f0efc5295 100644 > --- a/doc/guides/rel_notes/release_20_05.rst > +++ b/doc/guides/rel_notes/release_20_05.rst > @@ -56,6 +56,13 @@ New Features > Also, make sure to start the actual text at the margin. > ========================================================= > > +* **Updated Intel i40e driver.** > + > + Updated i40e PMD with new features and improvements, including: > + > + * enable only dst MAC address as FDIR input set for ipv4-other > + * enable both src MAC address and dst MAC address as FDIR input set > + for ipv4-other > + > Same here. > Removed Items > ------------- > diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c > index 9fbda1c34..d11df8d83 100644 > --- a/drivers/net/i40e/i40e_ethdev.c > +++ b/drivers/net/i40e/i40e_ethdev.c > @@ -9373,6 +9373,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype > pctype, > I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | > I40E_INSET_SCTP_VT, > [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = > + I40E_INSET_DMAC | I40E_INSET_SMAC | > I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | > I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | > I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git > a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index > aac89de91..e8b98b67e 100644 > --- a/drivers/net/i40e/i40e_ethdev.h > +++ b/drivers/net/i40e/i40e_ethdev.h > @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { > uint32_t session_id; /* Session ID in big endian. */ }; > > +/* A structure used to define the input for l2 dst type flow */ struct l2 dst type flow? > +i40e_eth_l2_flow { Flow other names, use i40e_l2_flow here. > + struct rte_ether_addr dst; > + struct rte_ether_addr src; > + uint16_t ether_type; /**< Ether type in big endian */ > +}; > + > /* > * A union contains the inputs for all types of flow > * items in flows need to be in big endian > */ > union i40e_fdir_flow { > - struct rte_eth_l2_flow l2_flow; > + struct i40e_eth_l2_flow l2_flow; > struct rte_eth_udpv4_flow udp4_flow; > struct rte_eth_tcpv4_flow tcp4_flow; > struct rte_eth_sctpv4_flow sctp4_flow; > @@ -628,6 +635,13 @@ struct i40e_fdir_action { > uint8_t flex_off; > }; > > +/* Ether input set kinds */ > +enum i40e_fdir_eth_inset { > + I40E_ETH_INSET_NULL = 0, > + I40E_ETH_INSET_DMAC, > + I40E_ETH_INSET_SMAC_DMAC, > +}; What's the enumeration's purpose? Could you follow the original code for input set configuration and packet construct?
FVL enable src MAC address and dst MAC address as FDIR's input set for ipv4-other. When OVS-DPDK is working as a pure L2 switch, enable MAC address as FDIR input set with Mark+RSS action would help the performance speed up. And FVL FDIR supports to change input set with MAC address. Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- v3: - Enable MAC address as FDIR's input set v2: - Enable src MAC address as FDIR's input set --- doc/guides/rel_notes/release_20_05.rst | 6 +++ drivers/net/i40e/i40e_ethdev.c | 1 + drivers/net/i40e/i40e_ethdev.h | 9 +++- drivers/net/i40e/i40e_fdir.c | 6 +++ drivers/net/i40e/i40e_flow.c | 65 +++++++++++++++++++------- 5 files changed, 68 insertions(+), 19 deletions(-) diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 000bbf501..7139288d6 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -62,6 +62,12 @@ New Features * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit. +* **Updated Intel i40e driver.** + + Updated i40e PMD with new features and improvements, including: + + * enable MAC address as FDIR input set for ipv4-other. + Removed Items ------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9539b0470..041627ef5 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9373,6 +9373,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..dbb5d594a 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ +struct i40e_l2_flow { + struct rte_ether_addr dst; + struct rte_ether_addr src; + uint16_t ether_type; /**< Ether type in big endian */ +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..2f24615b6 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), + &fdir_input->flow.l2_flow.src, + sizeof(struct rte_ether_addr)); raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..65922b39c 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || - !rte_is_zero_ether_addr(ð_mask->dst)) { + if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_zero_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (rte_is_zero_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= I40E_INSET_SMAC; + } else if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= (I40E_INSET_DMAC | I40E_INSET_SMAC); + } else { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } } - if (eth_spec && eth_mask && eth_mask->type) { + if (eth_spec && eth_mask && + next_type == RTE_FLOW_ITEM_TYPE_END) { if (eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2750,21 +2767,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, frag_off & RTE_IPV4_HDR_MF_FLAG) pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; - /* Get the filter info */ - filter->input.flow.ip4_flow.proto = - ipv4_spec->hdr.next_proto_id; - filter->input.flow.ip4_flow.tos = - ipv4_spec->hdr.type_of_service; - filter->input.flow.ip4_flow.ttl = - ipv4_spec->hdr.time_to_live; - filter->input.flow.ip4_flow.src_ip = - ipv4_spec->hdr.src_addr; - filter->input.flow.ip4_flow.dst_ip = - ipv4_spec->hdr.dst_addr; - - filter->input.flow_ext.inner_ip = false; - filter->input.flow_ext.oip_type = - I40E_FDIR_IPTYPE_IPV4; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & (I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid MAC_addr mask."); + return -rte_errno; + } + } else { + /* Get the filter info */ + filter->input.flow.ip4_flow.proto = + ipv4_spec->hdr.next_proto_id; + filter->input.flow.ip4_flow.tos = + ipv4_spec->hdr.type_of_service; + filter->input.flow.ip4_flow.ttl = + ipv4_spec->hdr.time_to_live; + filter->input.flow.ip4_flow.src_ip = + ipv4_spec->hdr.src_addr; + filter->input.flow.ip4_flow.dst_ip = + ipv4_spec->hdr.dst_addr; + + filter->input.flow_ext.inner_ip = false; + filter->input.flow_ext.oip_type = + I40E_FDIR_IPTYPE_IPV4; + } } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { filter->input.flow_ext.inner_ip = true; filter->input.flow_ext.iip_type = -- 2.17.1
-----Original Message----- From: Cui, LunyuanX <lunyuanx.cui@intel.com> Sent: Monday, March 30, 2020 5:06 PM To: dev@dpdk.org Cc: Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming <qiming.yang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>; Cui, LunyuanX <lunyuanx.cui@intel.com> Subject: [PATCH v3] net/i40e: enable MAC address as FDIR input set FVL enable src MAC address and dst MAC address as FDIR's input set for ipv4-other. When OVS-DPDK is working as a pure L2 switch, enable MAC address as FDIR input set with Mark+RSS action would help the performance speed up. And FVL FDIR supports to change input set with MAC address. Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- v3: - Enable MAC address as FDIR's input set v2: - Enable src MAC address as FDIR's input set --- doc/guides/rel_notes/release_20_05.rst | 6 +++ drivers/net/i40e/i40e_ethdev.c | 1 + drivers/net/i40e/i40e_ethdev.h | 9 +++- drivers/net/i40e/i40e_fdir.c | 6 +++ drivers/net/i40e/i40e_flow.c | 65 +++++++++++++++++++------- 5 files changed, 68 insertions(+), 19 deletions(-) diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 000bbf501..7139288d6 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -62,6 +62,12 @@ New Features * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit. +* **Updated Intel i40e driver.** + + Updated i40e PMD with new features and improvements, including: + + * enable MAC address as FDIR input set for ipv4-other. + Removed Items ------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9539b0470..041627ef5 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9373,6 +9373,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..dbb5d594a 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ struct +i40e_l2_flow { + struct rte_ether_addr dst; + struct rte_ether_addr src; + uint16_t ether_type; /**< Ether type in big endian */ +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..2f24615b6 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), + &fdir_input->flow.l2_flow.src, + sizeof(struct rte_ether_addr)); raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..65922b39c 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || - !rte_is_zero_ether_addr(ð_mask->dst)) { + if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_zero_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (rte_is_zero_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= I40E_INSET_SMAC; + } else if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= (I40E_INSET_DMAC | I40E_INSET_SMAC); + } else { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } } - if (eth_spec && eth_mask && eth_mask->type) { + if (eth_spec && eth_mask && + next_type == RTE_FLOW_ITEM_TYPE_END) { What's the purpose here? if (eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2750,21 +2767,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, frag_off & RTE_IPV4_HDR_MF_FLAG) pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; - /* Get the filter info */ - filter->input.flow.ip4_flow.proto = - ipv4_spec->hdr.next_proto_id; - filter->input.flow.ip4_flow.tos = - ipv4_spec->hdr.type_of_service; - filter->input.flow.ip4_flow.ttl = - ipv4_spec->hdr.time_to_live; - filter->input.flow.ip4_flow.src_ip = - ipv4_spec->hdr.src_addr; - filter->input.flow.ip4_flow.dst_ip = - ipv4_spec->hdr.dst_addr; - - filter->input.flow_ext.inner_ip = false; - filter->input.flow_ext.oip_type = - I40E_FDIR_IPTYPE_IPV4; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & (I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid MAC_addr mask."); + return -rte_errno; + } I don't think it must be exclusive between src mac/dst mac and other IPv4 fields. + } else { + /* Get the filter info */ + filter->input.flow.ip4_flow.proto = + ipv4_spec->hdr.next_proto_id; + filter->input.flow.ip4_flow.tos = + ipv4_spec->hdr.type_of_service; + filter->input.flow.ip4_flow.ttl = + ipv4_spec->hdr.time_to_live; + filter->input.flow.ip4_flow.src_ip = + ipv4_spec->hdr.src_addr; + filter->input.flow.ip4_flow.dst_ip = + ipv4_spec->hdr.dst_addr; + + filter->input.flow_ext.inner_ip = false; + filter->input.flow_ext.oip_type = + I40E_FDIR_IPTYPE_IPV4; + } } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { filter->input.flow_ext.inner_ip = true; filter->input.flow_ext.iip_type = -- 2.17.1
FVL enable src MAC address and dst MAC address as FDIR's input set for ipv4-other, ipv4-udp and ipv4-tcp. When OVS-DPDK is working as a pure L2 switch, enable MAC address as FDIR input set with Mark+RSS action would help the performance speed up. And FVL FDIR supports to change input set with MAC address. Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- v4: - Enable MAC address as FDIR's input set for ipv4-udp and ipv4-tcp v3: - Enable MAC address as FDIR's input set v2: - Enable src MAC address as FDIR's input set --- doc/guides/rel_notes/release_20_05.rst | 6 ++ drivers/net/i40e/i40e_ethdev.c | 3 + drivers/net/i40e/i40e_ethdev.h | 9 +- drivers/net/i40e/i40e_fdir.c | 6 ++ drivers/net/i40e/i40e_flow.c | 131 +++++++++++++++++-------- 5 files changed, 114 insertions(+), 41 deletions(-) diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 000bbf501..9e55955c4 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -62,6 +62,12 @@ New Features * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit. +* **Updated Intel i40e driver.** + + Updated i40e PMD with new features and improvements, including: + + * enable MAC address as FDIR input set for ipv4-other, ipv4-udp and ipv4-tcp. + Removed Items ------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9539b0470..530908b0e 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9342,6 +9342,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9357,6 +9358,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9373,6 +9375,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..dbb5d594a 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ +struct i40e_l2_flow { + struct rte_ether_addr dst; + struct rte_ether_addr src; + uint16_t ether_type; /**< Ether type in big endian */ +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..2f24615b6 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), + &fdir_input->flow.l2_flow.src, + sizeof(struct rte_ether_addr)); raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..42324b208 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || - !rte_is_zero_ether_addr(ð_mask->dst)) { + if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_zero_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (rte_is_zero_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= I40E_INSET_SMAC; + } else if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= (I40E_INSET_DMAC | I40E_INSET_SMAC); + } else { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } } - if (eth_spec && eth_mask && eth_mask->type) { + if (eth_spec && eth_mask && + next_type == RTE_FLOW_ITEM_TYPE_END) { if (eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2750,21 +2767,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, frag_off & RTE_IPV4_HDR_MF_FLAG) pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; - /* Get the filter info */ - filter->input.flow.ip4_flow.proto = - ipv4_spec->hdr.next_proto_id; - filter->input.flow.ip4_flow.tos = - ipv4_spec->hdr.type_of_service; - filter->input.flow.ip4_flow.ttl = - ipv4_spec->hdr.time_to_live; - filter->input.flow.ip4_flow.src_ip = - ipv4_spec->hdr.src_addr; - filter->input.flow.ip4_flow.dst_ip = - ipv4_spec->hdr.dst_addr; - - filter->input.flow_ext.inner_ip = false; - filter->input.flow_ext.oip_type = - I40E_FDIR_IPTYPE_IPV4; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & (I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid MAC_addr mask."); + return -rte_errno; + } + } else { + /* Get the filter info */ + filter->input.flow.ip4_flow.proto = + ipv4_spec->hdr.next_proto_id; + filter->input.flow.ip4_flow.tos = + ipv4_spec->hdr.type_of_service; + filter->input.flow.ip4_flow.ttl = + ipv4_spec->hdr.time_to_live; + filter->input.flow.ip4_flow.src_ip = + ipv4_spec->hdr.src_addr; + filter->input.flow.ip4_flow.dst_ip = + ipv4_spec->hdr.dst_addr; + + filter->input.flow_ext.inner_ip = false; + filter->input.flow_ext.oip_type = + I40E_FDIR_IPTYPE_IPV4; + } } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { filter->input.flow_ext.inner_ip = true; filter->input.flow_ext.iip_type = @@ -2894,17 +2923,28 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, if (tcp_mask->hdr.dst_port == UINT16_MAX) input_set |= I40E_INSET_DST_PORT; - /* Get filter info */ - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { - filter->input.flow.tcp4_flow.src_port = - tcp_spec->hdr.src_port; - filter->input.flow.tcp4_flow.dst_port = - tcp_spec->hdr.dst_port; - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { - filter->input.flow.tcp6_flow.src_port = - tcp_spec->hdr.src_port; - filter->input.flow.tcp6_flow.dst_port = - tcp_spec->hdr.dst_port; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & + (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid MAC_addr mask."); + return -rte_errno; + } + } else { + /* Get filter info */ + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { + filter->input.flow.tcp4_flow.src_port = + tcp_spec->hdr.src_port; + filter->input.flow.tcp4_flow.dst_port = + tcp_spec->hdr.dst_port; + } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { + filter->input.flow.tcp6_flow.src_port = + tcp_spec->hdr.src_port; + filter->input.flow.tcp6_flow.dst_port = + tcp_spec->hdr.dst_port; + } } } @@ -2938,17 +2978,28 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, if (udp_mask->hdr.dst_port == UINT16_MAX) input_set |= I40E_INSET_DST_PORT; - /* Get filter info */ - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { - filter->input.flow.udp4_flow.src_port = - udp_spec->hdr.src_port; - filter->input.flow.udp4_flow.dst_port = - udp_spec->hdr.dst_port; - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { - filter->input.flow.udp6_flow.src_port = - udp_spec->hdr.src_port; - filter->input.flow.udp6_flow.dst_port = - udp_spec->hdr.dst_port; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & + (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "Invalid MAC_addr mask."); + return -rte_errno; + } + } else { + /* Get filter info */ + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { + filter->input.flow.udp4_flow.src_port = + udp_spec->hdr.src_port; + filter->input.flow.udp4_flow.dst_port = + udp_spec->hdr.dst_port; + } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { + filter->input.flow.udp6_flow.src_port = + udp_spec->hdr.src_port; + filter->input.flow.udp6_flow.dst_port = + udp_spec->hdr.dst_port; + } } } filter->input.flow_ext.is_udp = true; -- 2.17.1
> -----Original Message----- > From: Cui, LunyuanX <lunyuanx.cui@intel.com> > Sent: Wednesday, April 1, 2020 3:51 PM > To: dev@dpdk.org > Cc: Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming > <qiming.yang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>; Cui, > LunyuanX <lunyuanx.cui@intel.com> > Subject: [PATCH v4] net/i40e: enable MAC address as FDIR input set > > FVL enable src MAC address and dst MAC address as FDIR's input set for > ipv4-other, ipv4-udp and ipv4-tcp. When OVS-DPDK is working as a pure L2 > switch, enable MAC address as FDIR input set with Mark+RSS action would > help the performance speed up. And FVL FDIR supports to change input set > with MAC address. > > Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> > > --- > v4: > - Enable MAC address as FDIR's input set for ipv4-udp and ipv4-tcp > v3: > - Enable MAC address as FDIR's input set > v2: > - Enable src MAC address as FDIR's input set > --- > doc/guides/rel_notes/release_20_05.rst | 6 ++ > drivers/net/i40e/i40e_ethdev.c | 3 + > drivers/net/i40e/i40e_ethdev.h | 9 +- > drivers/net/i40e/i40e_fdir.c | 6 ++ > drivers/net/i40e/i40e_flow.c | 131 +++++++++++++++++-------- > 5 files changed, 114 insertions(+), 41 deletions(-) > > diff --git a/doc/guides/rel_notes/release_20_05.rst > b/doc/guides/rel_notes/release_20_05.rst > index 000bbf501..9e55955c4 100644 > --- a/doc/guides/rel_notes/release_20_05.rst > +++ b/doc/guides/rel_notes/release_20_05.rst > @@ -62,6 +62,12 @@ New Features > > * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit. > > +* **Updated Intel i40e driver.** > + > + Updated i40e PMD with new features and improvements, including: > + > + * enable MAC address as FDIR input set for ipv4-other, ipv4-udp and ipv4- > tcp. > + > > Removed Items > ------------- > diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c > index 9539b0470..530908b0e 100644 > --- a/drivers/net/i40e/i40e_ethdev.c > +++ b/drivers/net/i40e/i40e_ethdev.c > @@ -9342,6 +9342,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype > pctype, > I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | > I40E_INSET_IPV4_TTL, > [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = > + I40E_INSET_DMAC | I40E_INSET_SMAC | > I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | > I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | > I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9357,6 > +9358,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, > I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | > I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, > [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = > + I40E_INSET_DMAC | I40E_INSET_SMAC | > I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | > I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | > I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9373,6 > +9375,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, > I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | > I40E_INSET_SCTP_VT, > [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = > + I40E_INSET_DMAC | I40E_INSET_SMAC | > I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | > I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | > I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git > a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index > aac89de91..dbb5d594a 100644 > --- a/drivers/net/i40e/i40e_ethdev.h > +++ b/drivers/net/i40e/i40e_ethdev.h > @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { > uint32_t session_id; /* Session ID in big endian. */ }; > > +/* A structure used to define the input for l2 dst type flow */ struct > +i40e_l2_flow { > + struct rte_ether_addr dst; > + struct rte_ether_addr src; > + uint16_t ether_type; /**< Ether type in big endian */ > +}; > + > /* > * A union contains the inputs for all types of flow > * items in flows need to be in big endian > */ > union i40e_fdir_flow { > - struct rte_eth_l2_flow l2_flow; > + struct i40e_l2_flow l2_flow; > struct rte_eth_udpv4_flow udp4_flow; > struct rte_eth_tcpv4_flow tcp4_flow; > struct rte_eth_sctpv4_flow sctp4_flow; > diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index > 931f25976..2f24615b6 100644 > --- a/drivers/net/i40e/i40e_fdir.c > +++ b/drivers/net/i40e/i40e_fdir.c > @@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf > *pf, > [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, > }; > > + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, > + sizeof(struct rte_ether_addr)); > + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), > + &fdir_input->flow.l2_flow.src, > + sizeof(struct rte_ether_addr)); Please help to double check if the dst and src need to be swapped refer to the datasheet: The "source" and "destination" fields in the transmitted packet are presented in a reversed order with respect to the expected received packets. > raw_pkt += 2 * sizeof(struct rte_ether_addr); > + > if (vlan && fdir_input->flow_ext.vlan_tci) { > rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); > rte_memcpy(raw_pkt + sizeof(uint16_t), diff --git > a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index > d877ac250..42324b208 100644 > --- a/drivers/net/i40e/i40e_flow.c > +++ b/drivers/net/i40e/i40e_flow.c > @@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev > *dev, > } > > if (eth_spec && eth_mask) { > - if (!rte_is_zero_ether_addr(ð_mask->src) > || > - !rte_is_zero_ether_addr(ð_mask->dst)) > { > + if (rte_is_broadcast_ether_addr(ð_mask- > >dst) && > + rte_is_zero_ether_addr(ð_mask- > >src)) { > + filter->input.flow.l2_flow.dst = > + eth_spec->dst; > + input_set |= I40E_INSET_DMAC; > + } else if (rte_is_zero_ether_addr(ð_mask- > >dst) && > + > rte_is_broadcast_ether_addr(ð_mask->src)) { > + filter->input.flow.l2_flow.src = > + eth_spec->src; > + input_set |= I40E_INSET_SMAC; > + } else if > (rte_is_broadcast_ether_addr(ð_mask->dst) && > + > rte_is_broadcast_ether_addr(ð_mask->src)) { > + filter->input.flow.l2_flow.dst = > + eth_spec->dst; > + filter->input.flow.l2_flow.src = > + eth_spec->src; > + input_set |= (I40E_INSET_DMAC | > I40E_INSET_SMAC); > + } else { > rte_flow_error_set(error, EINVAL, > > RTE_FLOW_ERROR_TYPE_ITEM, > item, > @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev > *dev, > return -rte_errno; > } > } > - if (eth_spec && eth_mask && eth_mask->type) { > + if (eth_spec && eth_mask && > + next_type == RTE_FLOW_ITEM_TYPE_END) { > if (eth_mask->type != RTE_BE16(0xffff)) { > rte_flow_error_set(error, EINVAL, > > RTE_FLOW_ERROR_TYPE_ITEM, > @@ -2750,21 +2767,33 @@ i40e_flow_parse_fdir_pattern(struct > rte_eth_dev *dev, > frag_off & RTE_IPV4_HDR_MF_FLAG) > pctype = > I40E_FILTER_PCTYPE_FRAG_IPV4; > > - /* Get the filter info */ > - filter->input.flow.ip4_flow.proto = > - ipv4_spec->hdr.next_proto_id; > - filter->input.flow.ip4_flow.tos = > - ipv4_spec->hdr.type_of_service; > - filter->input.flow.ip4_flow.ttl = > - ipv4_spec->hdr.time_to_live; > - filter->input.flow.ip4_flow.src_ip = > - ipv4_spec->hdr.src_addr; > - filter->input.flow.ip4_flow.dst_ip = > - ipv4_spec->hdr.dst_addr; > - > - filter->input.flow_ext.inner_ip = false; > - filter->input.flow_ext.oip_type = > - I40E_FDIR_IPTYPE_IPV4; > + if (input_set & (I40E_INSET_DMAC | > I40E_INSET_SMAC)) { > + if (input_set & (I40E_INSET_IPV4_SRC > | > + I40E_INSET_IPV4_DST | > I40E_INSET_IPV4_TOS | > + I40E_INSET_IPV4_TTL | > I40E_INSET_IPV4_PROTO)) { > + rte_flow_error_set(error, > EINVAL, > + > RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid MAC_addr > mask."); The error info is not correct. This logic means L2 input set are exclusive with L3 input set, right? > + return -rte_errno; > + } > + } else { > + /* Get the filter info */ > + filter->input.flow.ip4_flow.proto = > + ipv4_spec- > >hdr.next_proto_id; > + filter->input.flow.ip4_flow.tos = > + ipv4_spec- > >hdr.type_of_service; > + filter->input.flow.ip4_flow.ttl = > + ipv4_spec->hdr.time_to_live; > + filter->input.flow.ip4_flow.src_ip = > + ipv4_spec->hdr.src_addr; > + filter->input.flow.ip4_flow.dst_ip = > + ipv4_spec->hdr.dst_addr; > + > + filter->input.flow_ext.inner_ip = false; > + filter->input.flow_ext.oip_type = > + I40E_FDIR_IPTYPE_IPV4; > + } > } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { > filter->input.flow_ext.inner_ip = true; > filter->input.flow_ext.iip_type = > @@ -2894,17 +2923,28 @@ i40e_flow_parse_fdir_pattern(struct > rte_eth_dev *dev, > if (tcp_mask->hdr.dst_port == UINT16_MAX) > input_set |= I40E_INSET_DST_PORT; > > - /* Get filter info */ > - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { > - filter->input.flow.tcp4_flow.src_port > = > - tcp_spec->hdr.src_port; > - filter->input.flow.tcp4_flow.dst_port > = > - tcp_spec->hdr.dst_port; > - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { > - filter->input.flow.tcp6_flow.src_port > = > - tcp_spec->hdr.src_port; > - filter->input.flow.tcp6_flow.dst_port > = > - tcp_spec->hdr.dst_port; > + if (input_set & (I40E_INSET_DMAC | > I40E_INSET_SMAC)) { > + if (input_set & > + (I40E_INSET_SRC_PORT | > I40E_INSET_DST_PORT)) { > + rte_flow_error_set(error, > EINVAL, > + > RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid MAC_addr > mask."); Same comment. > + return -rte_errno; > + } > + } else { > + /* Get filter info */ > + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) > { > + filter- > >input.flow.tcp4_flow.src_port = > + tcp_spec- > >hdr.src_port; > + filter- > >input.flow.tcp4_flow.dst_port = > + tcp_spec- > >hdr.dst_port; > + } else if (l3 == > RTE_FLOW_ITEM_TYPE_IPV6) { > + filter- > >input.flow.tcp6_flow.src_port = > + tcp_spec- > >hdr.src_port; > + filter- > >input.flow.tcp6_flow.dst_port = > + tcp_spec- > >hdr.dst_port; > + } > } > } > > @@ -2938,17 +2978,28 @@ i40e_flow_parse_fdir_pattern(struct > rte_eth_dev *dev, > if (udp_mask->hdr.dst_port == UINT16_MAX) > input_set |= I40E_INSET_DST_PORT; > > - /* Get filter info */ > - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { > - filter->input.flow.udp4_flow.src_port > = > - udp_spec->hdr.src_port; > - filter->input.flow.udp4_flow.dst_port > = > - udp_spec->hdr.dst_port; > - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { > - filter->input.flow.udp6_flow.src_port > = > - udp_spec->hdr.src_port; > - filter->input.flow.udp6_flow.dst_port > = > - udp_spec->hdr.dst_port; > + if (input_set & (I40E_INSET_DMAC | > I40E_INSET_SMAC)) { > + if (input_set & > + (I40E_INSET_SRC_PORT | > I40E_INSET_DST_PORT)) { > + rte_flow_error_set(error, > EINVAL, > + > RTE_FLOW_ERROR_TYPE_ITEM, > + item, > + "Invalid MAC_addr > mask."); Same comment. > + return -rte_errno; > + } > + } else { > + /* Get filter info */ > + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) > { > + filter- > >input.flow.udp4_flow.src_port = > + udp_spec- > >hdr.src_port; > + filter- > >input.flow.udp4_flow.dst_port = > + udp_spec- > >hdr.dst_port; > + } else if (l3 == > RTE_FLOW_ITEM_TYPE_IPV6) { > + filter- > >input.flow.udp6_flow.src_port = > + udp_spec- > >hdr.src_port; > + filter- > >input.flow.udp6_flow.dst_port = > + udp_spec- > >hdr.dst_port; > + } > } > } > filter->input.flow_ext.is_udp = true; > -- > 2.17.1
FVL enable src MAC address and dst MAC address as FDIR's input set for ipv4-other, ipv4-udp and ipv4-tcp. When OVS-DPDK is working as a pure L2 switch, enable MAC address as FDIR input set with Mark+RSS action would help the performance speed up. And FVL FDIR supports to change input set with MAC address. Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- v5: - Change error info v4: - Enable MAC address as FDIR's input set for ipv4-udp and ipv4-tcp v3: - Enable MAC address as FDIR's input set v2: - Enable src MAC address as FDIR's input set --- doc/guides/rel_notes/release_20_05.rst | 6 ++ drivers/net/i40e/i40e_ethdev.c | 3 + drivers/net/i40e/i40e_ethdev.h | 9 +- drivers/net/i40e/i40e_fdir.c | 6 ++ drivers/net/i40e/i40e_flow.c | 134 +++++++++++++++++-------- 5 files changed, 117 insertions(+), 41 deletions(-) diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 000bbf501..9e55955c4 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -62,6 +62,12 @@ New Features * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit. +* **Updated Intel i40e driver.** + + Updated i40e PMD with new features and improvements, including: + + * enable MAC address as FDIR input set for ipv4-other, ipv4-udp and ipv4-tcp. + Removed Items ------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9539b0470..530908b0e 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9342,6 +9342,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9357,6 +9358,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9373,6 +9375,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..dbb5d594a 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ +struct i40e_l2_flow { + struct rte_ether_addr dst; + struct rte_ether_addr src; + uint16_t ether_type; /**< Ether type in big endian */ +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..2f24615b6 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), + &fdir_input->flow.l2_flow.src, + sizeof(struct rte_ether_addr)); raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..e376ef632 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || - !rte_is_zero_ether_addr(ð_mask->dst)) { + if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_zero_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (rte_is_zero_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= I40E_INSET_SMAC; + } else if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= (I40E_INSET_DMAC | I40E_INSET_SMAC); + } else { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } } - if (eth_spec && eth_mask && eth_mask->type) { + if (eth_spec && eth_mask && + next_type == RTE_FLOW_ITEM_TYPE_END) { if (eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2750,21 +2767,34 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, frag_off & RTE_IPV4_HDR_MF_FLAG) pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; - /* Get the filter info */ - filter->input.flow.ip4_flow.proto = - ipv4_spec->hdr.next_proto_id; - filter->input.flow.ip4_flow.tos = - ipv4_spec->hdr.type_of_service; - filter->input.flow.ip4_flow.ttl = - ipv4_spec->hdr.time_to_live; - filter->input.flow.ip4_flow.src_ip = - ipv4_spec->hdr.src_addr; - filter->input.flow.ip4_flow.dst_ip = - ipv4_spec->hdr.dst_addr; - - filter->input.flow_ext.inner_ip = false; - filter->input.flow_ext.oip_type = - I40E_FDIR_IPTYPE_IPV4; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & (I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 input set is exclusive with" + " L3 input set."); + return -rte_errno; + } + } else { + /* Get the filter info */ + filter->input.flow.ip4_flow.proto = + ipv4_spec->hdr.next_proto_id; + filter->input.flow.ip4_flow.tos = + ipv4_spec->hdr.type_of_service; + filter->input.flow.ip4_flow.ttl = + ipv4_spec->hdr.time_to_live; + filter->input.flow.ip4_flow.src_ip = + ipv4_spec->hdr.src_addr; + filter->input.flow.ip4_flow.dst_ip = + ipv4_spec->hdr.dst_addr; + + filter->input.flow_ext.inner_ip = false; + filter->input.flow_ext.oip_type = + I40E_FDIR_IPTYPE_IPV4; + } } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { filter->input.flow_ext.inner_ip = true; filter->input.flow_ext.iip_type = @@ -2894,17 +2924,29 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, if (tcp_mask->hdr.dst_port == UINT16_MAX) input_set |= I40E_INSET_DST_PORT; - /* Get filter info */ - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { - filter->input.flow.tcp4_flow.src_port = - tcp_spec->hdr.src_port; - filter->input.flow.tcp4_flow.dst_port = - tcp_spec->hdr.dst_port; - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { - filter->input.flow.tcp6_flow.src_port = - tcp_spec->hdr.src_port; - filter->input.flow.tcp6_flow.dst_port = - tcp_spec->hdr.dst_port; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & + (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 input set is exclusive with" + " L4 input set."); + return -rte_errno; + } + } else { + /* Get filter info */ + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { + filter->input.flow.tcp4_flow.src_port = + tcp_spec->hdr.src_port; + filter->input.flow.tcp4_flow.dst_port = + tcp_spec->hdr.dst_port; + } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { + filter->input.flow.tcp6_flow.src_port = + tcp_spec->hdr.src_port; + filter->input.flow.tcp6_flow.dst_port = + tcp_spec->hdr.dst_port; + } } } @@ -2938,17 +2980,29 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, if (udp_mask->hdr.dst_port == UINT16_MAX) input_set |= I40E_INSET_DST_PORT; - /* Get filter info */ - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { - filter->input.flow.udp4_flow.src_port = - udp_spec->hdr.src_port; - filter->input.flow.udp4_flow.dst_port = - udp_spec->hdr.dst_port; - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { - filter->input.flow.udp6_flow.src_port = - udp_spec->hdr.src_port; - filter->input.flow.udp6_flow.dst_port = - udp_spec->hdr.dst_port; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & + (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 input set is exclusive with" + " L4 input set."); + return -rte_errno; + } + } else { + /* Get filter info */ + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { + filter->input.flow.udp4_flow.src_port = + udp_spec->hdr.src_port; + filter->input.flow.udp4_flow.dst_port = + udp_spec->hdr.dst_port; + } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { + filter->input.flow.udp6_flow.src_port = + udp_spec->hdr.src_port; + filter->input.flow.udp6_flow.dst_port = + udp_spec->hdr.dst_port; + } } } filter->input.flow_ext.is_udp = true; -- 2.17.1
FVL enable source MAC address and destination MAC address as FDIR's input set for ipv4-other, ipv4-udp and ipv4-tcp. When OVS-DPDK is working as a pure L2 switch, enable MAC address as FDIR input set with Mark+RSS action would help the performance speed up. And FVL FDIR supports to change input set with MAC address. Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- v6: - Change commit message v5: - Change error info v4: - Enable MAC address as FDIR's input set for ipv4-udp and ipv4-tcp v3: - Enable MAC address as FDIR's input set v2: - Enable src MAC address as FDIR's input set --- doc/guides/rel_notes/release_20_05.rst | 6 ++ drivers/net/i40e/i40e_ethdev.c | 3 + drivers/net/i40e/i40e_ethdev.h | 9 +- drivers/net/i40e/i40e_fdir.c | 6 ++ drivers/net/i40e/i40e_flow.c | 134 +++++++++++++++++-------- 5 files changed, 117 insertions(+), 41 deletions(-) diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 000bbf501..65f76f001 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -62,6 +62,12 @@ New Features * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit. +* **Updated Intel i40e driver.** + + Updated i40e PMD with new features and improvements, including: + + * Enable MAC address as FDIR input set for ipv4-other, ipv4-udp and ipv4-tcp. + Removed Items ------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9539b0470..530908b0e 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9342,6 +9342,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9357,6 +9358,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9373,6 +9375,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..dbb5d594a 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ +struct i40e_l2_flow { + struct rte_ether_addr dst; + struct rte_ether_addr src; + uint16_t ether_type; /**< Ether type in big endian */ +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..2f24615b6 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), + &fdir_input->flow.l2_flow.src, + sizeof(struct rte_ether_addr)); raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..e376ef632 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || - !rte_is_zero_ether_addr(ð_mask->dst)) { + if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_zero_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (rte_is_zero_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= I40E_INSET_SMAC; + } else if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= (I40E_INSET_DMAC | I40E_INSET_SMAC); + } else { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } } - if (eth_spec && eth_mask && eth_mask->type) { + if (eth_spec && eth_mask && + next_type == RTE_FLOW_ITEM_TYPE_END) { if (eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2750,21 +2767,34 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, frag_off & RTE_IPV4_HDR_MF_FLAG) pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; - /* Get the filter info */ - filter->input.flow.ip4_flow.proto = - ipv4_spec->hdr.next_proto_id; - filter->input.flow.ip4_flow.tos = - ipv4_spec->hdr.type_of_service; - filter->input.flow.ip4_flow.ttl = - ipv4_spec->hdr.time_to_live; - filter->input.flow.ip4_flow.src_ip = - ipv4_spec->hdr.src_addr; - filter->input.flow.ip4_flow.dst_ip = - ipv4_spec->hdr.dst_addr; - - filter->input.flow_ext.inner_ip = false; - filter->input.flow_ext.oip_type = - I40E_FDIR_IPTYPE_IPV4; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & (I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 input set is exclusive with" + " L3 input set."); + return -rte_errno; + } + } else { + /* Get the filter info */ + filter->input.flow.ip4_flow.proto = + ipv4_spec->hdr.next_proto_id; + filter->input.flow.ip4_flow.tos = + ipv4_spec->hdr.type_of_service; + filter->input.flow.ip4_flow.ttl = + ipv4_spec->hdr.time_to_live; + filter->input.flow.ip4_flow.src_ip = + ipv4_spec->hdr.src_addr; + filter->input.flow.ip4_flow.dst_ip = + ipv4_spec->hdr.dst_addr; + + filter->input.flow_ext.inner_ip = false; + filter->input.flow_ext.oip_type = + I40E_FDIR_IPTYPE_IPV4; + } } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { filter->input.flow_ext.inner_ip = true; filter->input.flow_ext.iip_type = @@ -2894,17 +2924,29 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, if (tcp_mask->hdr.dst_port == UINT16_MAX) input_set |= I40E_INSET_DST_PORT; - /* Get filter info */ - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { - filter->input.flow.tcp4_flow.src_port = - tcp_spec->hdr.src_port; - filter->input.flow.tcp4_flow.dst_port = - tcp_spec->hdr.dst_port; - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { - filter->input.flow.tcp6_flow.src_port = - tcp_spec->hdr.src_port; - filter->input.flow.tcp6_flow.dst_port = - tcp_spec->hdr.dst_port; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & + (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 input set is exclusive with" + " L4 input set."); + return -rte_errno; + } + } else { + /* Get filter info */ + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { + filter->input.flow.tcp4_flow.src_port = + tcp_spec->hdr.src_port; + filter->input.flow.tcp4_flow.dst_port = + tcp_spec->hdr.dst_port; + } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { + filter->input.flow.tcp6_flow.src_port = + tcp_spec->hdr.src_port; + filter->input.flow.tcp6_flow.dst_port = + tcp_spec->hdr.dst_port; + } } } @@ -2938,17 +2980,29 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, if (udp_mask->hdr.dst_port == UINT16_MAX) input_set |= I40E_INSET_DST_PORT; - /* Get filter info */ - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { - filter->input.flow.udp4_flow.src_port = - udp_spec->hdr.src_port; - filter->input.flow.udp4_flow.dst_port = - udp_spec->hdr.dst_port; - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { - filter->input.flow.udp6_flow.src_port = - udp_spec->hdr.src_port; - filter->input.flow.udp6_flow.dst_port = - udp_spec->hdr.dst_port; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & + (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 input set is exclusive with" + " L4 input set."); + return -rte_errno; + } + } else { + /* Get filter info */ + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { + filter->input.flow.udp4_flow.src_port = + udp_spec->hdr.src_port; + filter->input.flow.udp4_flow.dst_port = + udp_spec->hdr.dst_port; + } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { + filter->input.flow.udp6_flow.src_port = + udp_spec->hdr.src_port; + filter->input.flow.udp6_flow.dst_port = + udp_spec->hdr.dst_port; + } } } filter->input.flow_ext.is_udp = true; -- 2.17.1
Enable source MAC address and destination MAC address as FDIR's input set for ipv4-other, ipv4-udp and ipv4-tcp. When OVS-DPDK is working as a pure L2 switch, enable MAC address as FDIR input set with Mark+RSS action would help the performance speed up. And FVL FDIR supports to change input set with MAC address. Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com> --- v7: - Change commit message and error info v6: - Change commit message v5: - Change error info v4: - Enable MAC address as FDIR's input set for ipv4-udp and ipv4-tcp v3: - Enable MAC address as FDIR's input set v2: - Enable src MAC address as FDIR's input set --- doc/guides/rel_notes/release_20_05.rst | 6 ++ drivers/net/i40e/i40e_ethdev.c | 3 + drivers/net/i40e/i40e_ethdev.h | 9 +- drivers/net/i40e/i40e_fdir.c | 6 ++ drivers/net/i40e/i40e_flow.c | 131 +++++++++++++++++-------- 5 files changed, 114 insertions(+), 41 deletions(-) diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst index 000bbf501..65f76f001 100644 --- a/doc/guides/rel_notes/release_20_05.rst +++ b/doc/guides/rel_notes/release_20_05.rst @@ -62,6 +62,12 @@ New Features * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit. +* **Updated Intel i40e driver.** + + Updated i40e PMD with new features and improvements, including: + + * Enable MAC address as FDIR input set for ipv4-other, ipv4-udp and ipv4-tcp. + Removed Items ------------- diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 9539b0470..530908b0e 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -9342,6 +9342,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | I40E_INSET_IPV4_TTL, [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9357,6 +9358,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT, [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9373,6 +9375,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT, [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = + I40E_INSET_DMAC | I40E_INSET_SMAC | I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER | I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index aac89de91..dbb5d594a 100644 --- a/drivers/net/i40e/i40e_ethdev.h +++ b/drivers/net/i40e/i40e_ethdev.h @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow { uint32_t session_id; /* Session ID in big endian. */ }; +/* A structure used to define the input for l2 dst type flow */ +struct i40e_l2_flow { + struct rte_ether_addr dst; + struct rte_ether_addr src; + uint16_t ether_type; /**< Ether type in big endian */ +}; + /* * A union contains the inputs for all types of flow * items in flows need to be in big endian */ union i40e_fdir_flow { - struct rte_eth_l2_flow l2_flow; + struct i40e_l2_flow l2_flow; struct rte_eth_udpv4_flow udp4_flow; struct rte_eth_tcpv4_flow tcp4_flow; struct rte_eth_sctpv4_flow sctp4_flow; diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index 931f25976..2f24615b6 100644 --- a/drivers/net/i40e/i40e_fdir.c +++ b/drivers/net/i40e/i40e_fdir.c @@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, }; + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst, + sizeof(struct rte_ether_addr)); + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr), + &fdir_input->flow.l2_flow.src, + sizeof(struct rte_ether_addr)); raw_pkt += 2 * sizeof(struct rte_ether_addr); + if (vlan && fdir_input->flow_ext.vlan_tci) { rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); rte_memcpy(raw_pkt + sizeof(uint16_t), diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index d877ac250..b1861a7db 100644 --- a/drivers/net/i40e/i40e_flow.c +++ b/drivers/net/i40e/i40e_flow.c @@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, } if (eth_spec && eth_mask) { - if (!rte_is_zero_ether_addr(ð_mask->src) || - !rte_is_zero_ether_addr(ð_mask->dst)) { + if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_zero_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + input_set |= I40E_INSET_DMAC; + } else if (rte_is_zero_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= I40E_INSET_SMAC; + } else if (rte_is_broadcast_ether_addr(ð_mask->dst) && + rte_is_broadcast_ether_addr(ð_mask->src)) { + filter->input.flow.l2_flow.dst = + eth_spec->dst; + filter->input.flow.l2_flow.src = + eth_spec->src; + input_set |= (I40E_INSET_DMAC | I40E_INSET_SMAC); + } else { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, return -rte_errno; } } - if (eth_spec && eth_mask && eth_mask->type) { + if (eth_spec && eth_mask && + next_type == RTE_FLOW_ITEM_TYPE_END) { if (eth_mask->type != RTE_BE16(0xffff)) { rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, @@ -2750,21 +2767,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, frag_off & RTE_IPV4_HDR_MF_FLAG) pctype = I40E_FILTER_PCTYPE_FRAG_IPV4; - /* Get the filter info */ - filter->input.flow.ip4_flow.proto = - ipv4_spec->hdr.next_proto_id; - filter->input.flow.ip4_flow.tos = - ipv4_spec->hdr.type_of_service; - filter->input.flow.ip4_flow.ttl = - ipv4_spec->hdr.time_to_live; - filter->input.flow.ip4_flow.src_ip = - ipv4_spec->hdr.src_addr; - filter->input.flow.ip4_flow.dst_ip = - ipv4_spec->hdr.dst_addr; - - filter->input.flow_ext.inner_ip = false; - filter->input.flow_ext.oip_type = - I40E_FDIR_IPTYPE_IPV4; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & (I40E_INSET_IPV4_SRC | + I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS | + I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 and L3 input set are exclusive."); + return -rte_errno; + } + } else { + /* Get the filter info */ + filter->input.flow.ip4_flow.proto = + ipv4_spec->hdr.next_proto_id; + filter->input.flow.ip4_flow.tos = + ipv4_spec->hdr.type_of_service; + filter->input.flow.ip4_flow.ttl = + ipv4_spec->hdr.time_to_live; + filter->input.flow.ip4_flow.src_ip = + ipv4_spec->hdr.src_addr; + filter->input.flow.ip4_flow.dst_ip = + ipv4_spec->hdr.dst_addr; + + filter->input.flow_ext.inner_ip = false; + filter->input.flow_ext.oip_type = + I40E_FDIR_IPTYPE_IPV4; + } } else if (!ipv4_spec && !ipv4_mask && !outer_ip) { filter->input.flow_ext.inner_ip = true; filter->input.flow_ext.iip_type = @@ -2894,17 +2923,28 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, if (tcp_mask->hdr.dst_port == UINT16_MAX) input_set |= I40E_INSET_DST_PORT; - /* Get filter info */ - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { - filter->input.flow.tcp4_flow.src_port = - tcp_spec->hdr.src_port; - filter->input.flow.tcp4_flow.dst_port = - tcp_spec->hdr.dst_port; - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { - filter->input.flow.tcp6_flow.src_port = - tcp_spec->hdr.src_port; - filter->input.flow.tcp6_flow.dst_port = - tcp_spec->hdr.dst_port; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & + (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 and L4 input set are exclusive."); + return -rte_errno; + } + } else { + /* Get filter info */ + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { + filter->input.flow.tcp4_flow.src_port = + tcp_spec->hdr.src_port; + filter->input.flow.tcp4_flow.dst_port = + tcp_spec->hdr.dst_port; + } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { + filter->input.flow.tcp6_flow.src_port = + tcp_spec->hdr.src_port; + filter->input.flow.tcp6_flow.dst_port = + tcp_spec->hdr.dst_port; + } } } @@ -2938,17 +2978,28 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, if (udp_mask->hdr.dst_port == UINT16_MAX) input_set |= I40E_INSET_DST_PORT; - /* Get filter info */ - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { - filter->input.flow.udp4_flow.src_port = - udp_spec->hdr.src_port; - filter->input.flow.udp4_flow.dst_port = - udp_spec->hdr.dst_port; - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { - filter->input.flow.udp6_flow.src_port = - udp_spec->hdr.src_port; - filter->input.flow.udp6_flow.dst_port = - udp_spec->hdr.dst_port; + if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) { + if (input_set & + (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "L2 and L4 input set are exclusive."); + return -rte_errno; + } + } else { + /* Get filter info */ + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) { + filter->input.flow.udp4_flow.src_port = + udp_spec->hdr.src_port; + filter->input.flow.udp4_flow.dst_port = + udp_spec->hdr.dst_port; + } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) { + filter->input.flow.udp6_flow.src_port = + udp_spec->hdr.src_port; + filter->input.flow.udp6_flow.dst_port = + udp_spec->hdr.dst_port; + } } } filter->input.flow_ext.is_udp = true; -- 2.17.1
> -----Original Message-----
> From: Cui, LunyuanX <lunyuanx.cui@intel.com>
> Sent: Thursday, April 2, 2020 3:59 PM
> To: dev@dpdk.org
> Cc: Xing, Beilei <beilei.xing@intel.com>; Yang, Qiming
> <qiming.yang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>; Cui,
> LunyuanX <lunyuanx.cui@intel.com>
> Subject: [PATCH v7] net/i40e: enable MAC address as FDIR input set
>
> Enable source MAC address and destination MAC address as FDIR's input set
> for ipv4-other, ipv4-udp and ipv4-tcp. When OVS-DPDK is working as a pure
> L2 switch, enable MAC address as FDIR input set with Mark+RSS action would
> help the performance speed up. And FVL FDIR supports to change input set
> with MAC address.
>
> Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com>
>
> ---
> v7:
> - Change commit message and error info
> v6:
> - Change commit message
> v5:
> - Change error info
> v4:
> - Enable MAC address as FDIR's input set for ipv4-udp and ipv4-tcp
> v3:
> - Enable MAC address as FDIR's input set
> v2:
> - Enable src MAC address as FDIR's input set
> ---
> doc/guides/rel_notes/release_20_05.rst | 6 ++
> drivers/net/i40e/i40e_ethdev.c | 3 +
> drivers/net/i40e/i40e_ethdev.h | 9 +-
> drivers/net/i40e/i40e_fdir.c | 6 ++
> drivers/net/i40e/i40e_flow.c | 131 +++++++++++++++++--------
> 5 files changed, 114 insertions(+), 41 deletions(-)
>
> diff --git a/doc/guides/rel_notes/release_20_05.rst
> b/doc/guides/rel_notes/release_20_05.rst
> index 000bbf501..65f76f001 100644
> --- a/doc/guides/rel_notes/release_20_05.rst
> +++ b/doc/guides/rel_notes/release_20_05.rst
> @@ -62,6 +62,12 @@ New Features
>
> * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit.
>
> +* **Updated Intel i40e driver.**
> +
> + Updated i40e PMD with new features and improvements, including:
> +
> + * Enable MAC address as FDIR input set for ipv4-other, ipv4-udp and ipv4-
> tcp.
> +
>
> Removed Items
> -------------
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 9539b0470..530908b0e 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -9342,6 +9342,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype
> pctype,
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO |
> I40E_INSET_IPV4_TTL,
> [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] =
> + I40E_INSET_DMAC | I40E_INSET_SMAC |
> I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
> I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9357,6
> +9358,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
> I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
> [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
> + I40E_INSET_DMAC | I40E_INSET_SMAC |
> I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
> I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL | @@ -9373,6
> +9375,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
> I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
> I40E_INSET_SCTP_VT,
> [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] =
> + I40E_INSET_DMAC | I40E_INSET_SMAC |
> I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
> I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO | diff --git
> a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h index
> aac89de91..dbb5d594a 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow {
> uint32_t session_id; /* Session ID in big endian. */ };
>
> +/* A structure used to define the input for l2 dst type flow */ struct
> +i40e_l2_flow {
> + struct rte_ether_addr dst;
> + struct rte_ether_addr src;
> + uint16_t ether_type; /**< Ether type in big endian */
> +};
> +
> /*
> * A union contains the inputs for all types of flow
> * items in flows need to be in big endian
> */
> union i40e_fdir_flow {
> - struct rte_eth_l2_flow l2_flow;
> + struct i40e_l2_flow l2_flow;
> struct rte_eth_udpv4_flow udp4_flow;
> struct rte_eth_tcpv4_flow tcp4_flow;
> struct rte_eth_sctpv4_flow sctp4_flow;
> diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index
> 931f25976..2f24615b6 100644
> --- a/drivers/net/i40e/i40e_fdir.c
> +++ b/drivers/net/i40e/i40e_fdir.c
> @@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf
> *pf,
> [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE,
> };
>
> + rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst,
> + sizeof(struct rte_ether_addr));
> + rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr),
> + &fdir_input->flow.l2_flow.src,
> + sizeof(struct rte_ether_addr));
> raw_pkt += 2 * sizeof(struct rte_ether_addr);
> +
> if (vlan && fdir_input->flow_ext.vlan_tci) {
> rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame));
> rte_memcpy(raw_pkt + sizeof(uint16_t), diff --git
> a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c index
> d877ac250..b1861a7db 100644
> --- a/drivers/net/i40e/i40e_flow.c
> +++ b/drivers/net/i40e/i40e_flow.c
> @@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev
> *dev,
> }
>
> if (eth_spec && eth_mask) {
> - if (!rte_is_zero_ether_addr(ð_mask->src)
> ||
> - !rte_is_zero_ether_addr(ð_mask->dst))
> {
> + if (rte_is_broadcast_ether_addr(ð_mask-
> >dst) &&
> + rte_is_zero_ether_addr(ð_mask-
> >src)) {
> + filter->input.flow.l2_flow.dst =
> + eth_spec->dst;
> + input_set |= I40E_INSET_DMAC;
> + } else if (rte_is_zero_ether_addr(ð_mask-
> >dst) &&
> +
> rte_is_broadcast_ether_addr(ð_mask->src)) {
> + filter->input.flow.l2_flow.src =
> + eth_spec->src;
> + input_set |= I40E_INSET_SMAC;
> + } else if
> (rte_is_broadcast_ether_addr(ð_mask->dst) &&
> +
> rte_is_broadcast_ether_addr(ð_mask->src)) {
> + filter->input.flow.l2_flow.dst =
> + eth_spec->dst;
> + filter->input.flow.l2_flow.src =
> + eth_spec->src;
> + input_set |= (I40E_INSET_DMAC |
> I40E_INSET_SMAC);
> + } else {
> rte_flow_error_set(error, EINVAL,
>
> RTE_FLOW_ERROR_TYPE_ITEM,
> item,
> @@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev
> *dev,
> return -rte_errno;
> }
> }
> - if (eth_spec && eth_mask && eth_mask->type) {
> + if (eth_spec && eth_mask &&
> + next_type == RTE_FLOW_ITEM_TYPE_END) {
> if (eth_mask->type != RTE_BE16(0xffff)) {
> rte_flow_error_set(error, EINVAL,
>
> RTE_FLOW_ERROR_TYPE_ITEM,
> @@ -2750,21 +2767,33 @@ i40e_flow_parse_fdir_pattern(struct
> rte_eth_dev *dev,
> frag_off & RTE_IPV4_HDR_MF_FLAG)
> pctype =
> I40E_FILTER_PCTYPE_FRAG_IPV4;
>
> - /* Get the filter info */
> - filter->input.flow.ip4_flow.proto =
> - ipv4_spec->hdr.next_proto_id;
> - filter->input.flow.ip4_flow.tos =
> - ipv4_spec->hdr.type_of_service;
> - filter->input.flow.ip4_flow.ttl =
> - ipv4_spec->hdr.time_to_live;
> - filter->input.flow.ip4_flow.src_ip =
> - ipv4_spec->hdr.src_addr;
> - filter->input.flow.ip4_flow.dst_ip =
> - ipv4_spec->hdr.dst_addr;
> -
> - filter->input.flow_ext.inner_ip = false;
> - filter->input.flow_ext.oip_type =
> - I40E_FDIR_IPTYPE_IPV4;
> + if (input_set & (I40E_INSET_DMAC |
> I40E_INSET_SMAC)) {
> + if (input_set & (I40E_INSET_IPV4_SRC
> |
> + I40E_INSET_IPV4_DST |
> I40E_INSET_IPV4_TOS |
> + I40E_INSET_IPV4_TTL |
> I40E_INSET_IPV4_PROTO)) {
> + rte_flow_error_set(error,
> EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "L2 and L3 input set
> are exclusive.");
> + return -rte_errno;
> + }
> + } else {
> + /* Get the filter info */
> + filter->input.flow.ip4_flow.proto =
> + ipv4_spec-
> >hdr.next_proto_id;
> + filter->input.flow.ip4_flow.tos =
> + ipv4_spec-
> >hdr.type_of_service;
> + filter->input.flow.ip4_flow.ttl =
> + ipv4_spec->hdr.time_to_live;
> + filter->input.flow.ip4_flow.src_ip =
> + ipv4_spec->hdr.src_addr;
> + filter->input.flow.ip4_flow.dst_ip =
> + ipv4_spec->hdr.dst_addr;
> +
> + filter->input.flow_ext.inner_ip = false;
> + filter->input.flow_ext.oip_type =
> + I40E_FDIR_IPTYPE_IPV4;
> + }
> } else if (!ipv4_spec && !ipv4_mask && !outer_ip) {
> filter->input.flow_ext.inner_ip = true;
> filter->input.flow_ext.iip_type =
> @@ -2894,17 +2923,28 @@ i40e_flow_parse_fdir_pattern(struct
> rte_eth_dev *dev,
> if (tcp_mask->hdr.dst_port == UINT16_MAX)
> input_set |= I40E_INSET_DST_PORT;
>
> - /* Get filter info */
> - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
> - filter->input.flow.tcp4_flow.src_port
> =
> - tcp_spec->hdr.src_port;
> - filter->input.flow.tcp4_flow.dst_port
> =
> - tcp_spec->hdr.dst_port;
> - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
> - filter->input.flow.tcp6_flow.src_port
> =
> - tcp_spec->hdr.src_port;
> - filter->input.flow.tcp6_flow.dst_port
> =
> - tcp_spec->hdr.dst_port;
> + if (input_set & (I40E_INSET_DMAC |
> I40E_INSET_SMAC)) {
> + if (input_set &
> + (I40E_INSET_SRC_PORT |
> I40E_INSET_DST_PORT)) {
> + rte_flow_error_set(error,
> EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "L2 and L4 input set
> are exclusive.");
> + return -rte_errno;
> + }
> + } else {
> + /* Get filter info */
> + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
> {
> + filter-
> >input.flow.tcp4_flow.src_port =
> + tcp_spec-
> >hdr.src_port;
> + filter-
> >input.flow.tcp4_flow.dst_port =
> + tcp_spec-
> >hdr.dst_port;
> + } else if (l3 ==
> RTE_FLOW_ITEM_TYPE_IPV6) {
> + filter-
> >input.flow.tcp6_flow.src_port =
> + tcp_spec-
> >hdr.src_port;
> + filter-
> >input.flow.tcp6_flow.dst_port =
> + tcp_spec-
> >hdr.dst_port;
> + }
> }
> }
>
> @@ -2938,17 +2978,28 @@ i40e_flow_parse_fdir_pattern(struct
> rte_eth_dev *dev,
> if (udp_mask->hdr.dst_port == UINT16_MAX)
> input_set |= I40E_INSET_DST_PORT;
>
> - /* Get filter info */
> - if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
> - filter->input.flow.udp4_flow.src_port
> =
> - udp_spec->hdr.src_port;
> - filter->input.flow.udp4_flow.dst_port
> =
> - udp_spec->hdr.dst_port;
> - } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
> - filter->input.flow.udp6_flow.src_port
> =
> - udp_spec->hdr.src_port;
> - filter->input.flow.udp6_flow.dst_port
> =
> - udp_spec->hdr.dst_port;
> + if (input_set & (I40E_INSET_DMAC |
> I40E_INSET_SMAC)) {
> + if (input_set &
> + (I40E_INSET_SRC_PORT |
> I40E_INSET_DST_PORT)) {
> + rte_flow_error_set(error,
> EINVAL,
> +
> RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "L2 and L4 input set
> are exclusive.");
> + return -rte_errno;
> + }
> + } else {
> + /* Get filter info */
> + if (l3 == RTE_FLOW_ITEM_TYPE_IPV4)
> {
> + filter-
> >input.flow.udp4_flow.src_port =
> + udp_spec-
> >hdr.src_port;
> + filter-
> >input.flow.udp4_flow.dst_port =
> + udp_spec-
> >hdr.dst_port;
> + } else if (l3 ==
> RTE_FLOW_ITEM_TYPE_IPV6) {
> + filter-
> >input.flow.udp6_flow.src_port =
> + udp_spec-
> >hdr.src_port;
> + filter-
> >input.flow.udp6_flow.dst_port =
> + udp_spec-
> >hdr.dst_port;
> + }
> }
> }
> filter->input.flow_ext.is_udp = true;
> --
> 2.17.1
Acked-by: Beilei Xing <beilei.xing@intel.com>
On 04/02, Lunyuan Cui wrote:
>Enable source MAC address and destination MAC address as FDIR's
>input set for ipv4-other, ipv4-udp and ipv4-tcp. When OVS-DPDK is
>working as a pure L2 switch, enable MAC address as FDIR input set
>with Mark+RSS action would help the performance speed up. And FVL
>FDIR supports to change input set with MAC address.
>
>Signed-off-by: Lunyuan Cui <lunyuanx.cui@intel.com>
>
>---
>v7:
> - Change commit message and error info
>v6:
> - Change commit message
>v5:
> - Change error info
>v4:
> - Enable MAC address as FDIR's input set for ipv4-udp and ipv4-tcp
>v3:
> - Enable MAC address as FDIR's input set
>v2:
> - Enable src MAC address as FDIR's input set
>---
> doc/guides/rel_notes/release_20_05.rst | 6 ++
> drivers/net/i40e/i40e_ethdev.c | 3 +
> drivers/net/i40e/i40e_ethdev.h | 9 +-
> drivers/net/i40e/i40e_fdir.c | 6 ++
> drivers/net/i40e/i40e_flow.c | 131 +++++++++++++++++--------
> 5 files changed, 114 insertions(+), 41 deletions(-)
>
>diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
>index 000bbf501..65f76f001 100644
>--- a/doc/guides/rel_notes/release_20_05.rst
>+++ b/doc/guides/rel_notes/release_20_05.rst
>@@ -62,6 +62,12 @@ New Features
>
> * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit.
>
>+* **Updated Intel i40e driver.**
>+
>+ Updated i40e PMD with new features and improvements, including:
>+
>+ * Enable MAC address as FDIR input set for ipv4-other, ipv4-udp and ipv4-tcp.
>+
>
> Removed Items
> -------------
>diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
>index 9539b0470..530908b0e 100644
>--- a/drivers/net/i40e/i40e_ethdev.c
>+++ b/drivers/net/i40e/i40e_ethdev.c
>@@ -9342,6 +9342,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO |
> I40E_INSET_IPV4_TTL,
> [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] =
>+ I40E_INSET_DMAC | I40E_INSET_SMAC |
> I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
> I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
>@@ -9357,6 +9358,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
> I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT,
> [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] =
>+ I40E_INSET_DMAC | I40E_INSET_SMAC |
> I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
> I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_TTL |
>@@ -9373,6 +9375,7 @@ i40e_get_valid_input_set(enum i40e_filter_pctype pctype,
> I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT |
> I40E_INSET_SCTP_VT,
> [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] =
>+ I40E_INSET_DMAC | I40E_INSET_SMAC |
> I40E_INSET_VLAN_OUTER | I40E_INSET_VLAN_INNER |
> I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
> I40E_INSET_IPV4_TOS | I40E_INSET_IPV4_PROTO |
>diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
>index aac89de91..dbb5d594a 100644
>--- a/drivers/net/i40e/i40e_ethdev.h
>+++ b/drivers/net/i40e/i40e_ethdev.h
>@@ -544,12 +544,19 @@ struct i40e_ipv6_l2tpv3oip_flow {
> uint32_t session_id; /* Session ID in big endian. */
> };
>
>+/* A structure used to define the input for l2 dst type flow */
>+struct i40e_l2_flow {
>+ struct rte_ether_addr dst;
>+ struct rte_ether_addr src;
>+ uint16_t ether_type; /**< Ether type in big endian */
>+};
>+
> /*
> * A union contains the inputs for all types of flow
> * items in flows need to be in big endian
> */
> union i40e_fdir_flow {
>- struct rte_eth_l2_flow l2_flow;
>+ struct i40e_l2_flow l2_flow;
> struct rte_eth_udpv4_flow udp4_flow;
> struct rte_eth_tcpv4_flow tcp4_flow;
> struct rte_eth_sctpv4_flow sctp4_flow;
>diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
>index 931f25976..2f24615b6 100644
>--- a/drivers/net/i40e/i40e_fdir.c
>+++ b/drivers/net/i40e/i40e_fdir.c
>@@ -1062,7 +1062,13 @@ i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf,
> [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE,
> };
>
>+ rte_memcpy(raw_pkt, &fdir_input->flow.l2_flow.dst,
>+ sizeof(struct rte_ether_addr));
>+ rte_memcpy(raw_pkt + sizeof(struct rte_ether_addr),
>+ &fdir_input->flow.l2_flow.src,
>+ sizeof(struct rte_ether_addr));
> raw_pkt += 2 * sizeof(struct rte_ether_addr);
>+
> if (vlan && fdir_input->flow_ext.vlan_tci) {
> rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame));
> rte_memcpy(raw_pkt + sizeof(uint16_t),
>diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
>index d877ac250..b1861a7db 100644
>--- a/drivers/net/i40e/i40e_flow.c
>+++ b/drivers/net/i40e/i40e_flow.c
>@@ -2626,8 +2626,24 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
> }
>
> if (eth_spec && eth_mask) {
>- if (!rte_is_zero_ether_addr(ð_mask->src) ||
>- !rte_is_zero_ether_addr(ð_mask->dst)) {
>+ if (rte_is_broadcast_ether_addr(ð_mask->dst) &&
>+ rte_is_zero_ether_addr(ð_mask->src)) {
>+ filter->input.flow.l2_flow.dst =
>+ eth_spec->dst;
>+ input_set |= I40E_INSET_DMAC;
>+ } else if (rte_is_zero_ether_addr(ð_mask->dst) &&
>+ rte_is_broadcast_ether_addr(ð_mask->src)) {
>+ filter->input.flow.l2_flow.src =
>+ eth_spec->src;
>+ input_set |= I40E_INSET_SMAC;
>+ } else if (rte_is_broadcast_ether_addr(ð_mask->dst) &&
>+ rte_is_broadcast_ether_addr(ð_mask->src)) {
>+ filter->input.flow.l2_flow.dst =
>+ eth_spec->dst;
>+ filter->input.flow.l2_flow.src =
>+ eth_spec->src;
>+ input_set |= (I40E_INSET_DMAC | I40E_INSET_SMAC);
>+ } else {
> rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ITEM,
> item,
>@@ -2635,7 +2651,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
> return -rte_errno;
> }
> }
>- if (eth_spec && eth_mask && eth_mask->type) {
>+ if (eth_spec && eth_mask &&
>+ next_type == RTE_FLOW_ITEM_TYPE_END) {
> if (eth_mask->type != RTE_BE16(0xffff)) {
> rte_flow_error_set(error, EINVAL,
> RTE_FLOW_ERROR_TYPE_ITEM,
>@@ -2750,21 +2767,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
> frag_off & RTE_IPV4_HDR_MF_FLAG)
> pctype = I40E_FILTER_PCTYPE_FRAG_IPV4;
>
>- /* Get the filter info */
>- filter->input.flow.ip4_flow.proto =
>- ipv4_spec->hdr.next_proto_id;
>- filter->input.flow.ip4_flow.tos =
>- ipv4_spec->hdr.type_of_service;
>- filter->input.flow.ip4_flow.ttl =
>- ipv4_spec->hdr.time_to_live;
>- filter->input.flow.ip4_flow.src_ip =
>- ipv4_spec->hdr.src_addr;
>- filter->input.flow.ip4_flow.dst_ip =
>- ipv4_spec->hdr.dst_addr;
>-
>- filter->input.flow_ext.inner_ip = false;
>- filter->input.flow_ext.oip_type =
>- I40E_FDIR_IPTYPE_IPV4;
>+ if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) {
>+ if (input_set & (I40E_INSET_IPV4_SRC |
>+ I40E_INSET_IPV4_DST | I40E_INSET_IPV4_TOS |
>+ I40E_INSET_IPV4_TTL | I40E_INSET_IPV4_PROTO)) {
>+ rte_flow_error_set(error, EINVAL,
>+ RTE_FLOW_ERROR_TYPE_ITEM,
>+ item,
>+ "L2 and L3 input set are exclusive.");
>+ return -rte_errno;
>+ }
>+ } else {
>+ /* Get the filter info */
>+ filter->input.flow.ip4_flow.proto =
>+ ipv4_spec->hdr.next_proto_id;
>+ filter->input.flow.ip4_flow.tos =
>+ ipv4_spec->hdr.type_of_service;
>+ filter->input.flow.ip4_flow.ttl =
>+ ipv4_spec->hdr.time_to_live;
>+ filter->input.flow.ip4_flow.src_ip =
>+ ipv4_spec->hdr.src_addr;
>+ filter->input.flow.ip4_flow.dst_ip =
>+ ipv4_spec->hdr.dst_addr;
>+
>+ filter->input.flow_ext.inner_ip = false;
>+ filter->input.flow_ext.oip_type =
>+ I40E_FDIR_IPTYPE_IPV4;
>+ }
> } else if (!ipv4_spec && !ipv4_mask && !outer_ip) {
> filter->input.flow_ext.inner_ip = true;
> filter->input.flow_ext.iip_type =
>@@ -2894,17 +2923,28 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
> if (tcp_mask->hdr.dst_port == UINT16_MAX)
> input_set |= I40E_INSET_DST_PORT;
>
>- /* Get filter info */
>- if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
>- filter->input.flow.tcp4_flow.src_port =
>- tcp_spec->hdr.src_port;
>- filter->input.flow.tcp4_flow.dst_port =
>- tcp_spec->hdr.dst_port;
>- } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
>- filter->input.flow.tcp6_flow.src_port =
>- tcp_spec->hdr.src_port;
>- filter->input.flow.tcp6_flow.dst_port =
>- tcp_spec->hdr.dst_port;
>+ if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) {
>+ if (input_set &
>+ (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) {
>+ rte_flow_error_set(error, EINVAL,
>+ RTE_FLOW_ERROR_TYPE_ITEM,
>+ item,
>+ "L2 and L4 input set are exclusive.");
>+ return -rte_errno;
>+ }
>+ } else {
>+ /* Get filter info */
>+ if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
>+ filter->input.flow.tcp4_flow.src_port =
>+ tcp_spec->hdr.src_port;
>+ filter->input.flow.tcp4_flow.dst_port =
>+ tcp_spec->hdr.dst_port;
>+ } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
>+ filter->input.flow.tcp6_flow.src_port =
>+ tcp_spec->hdr.src_port;
>+ filter->input.flow.tcp6_flow.dst_port =
>+ tcp_spec->hdr.dst_port;
>+ }
> }
> }
>
>@@ -2938,17 +2978,28 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
> if (udp_mask->hdr.dst_port == UINT16_MAX)
> input_set |= I40E_INSET_DST_PORT;
>
>- /* Get filter info */
>- if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
>- filter->input.flow.udp4_flow.src_port =
>- udp_spec->hdr.src_port;
>- filter->input.flow.udp4_flow.dst_port =
>- udp_spec->hdr.dst_port;
>- } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
>- filter->input.flow.udp6_flow.src_port =
>- udp_spec->hdr.src_port;
>- filter->input.flow.udp6_flow.dst_port =
>- udp_spec->hdr.dst_port;
>+ if (input_set & (I40E_INSET_DMAC | I40E_INSET_SMAC)) {
>+ if (input_set &
>+ (I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT)) {
>+ rte_flow_error_set(error, EINVAL,
>+ RTE_FLOW_ERROR_TYPE_ITEM,
>+ item,
>+ "L2 and L4 input set are exclusive.");
>+ return -rte_errno;
>+ }
>+ } else {
>+ /* Get filter info */
>+ if (l3 == RTE_FLOW_ITEM_TYPE_IPV4) {
>+ filter->input.flow.udp4_flow.src_port =
>+ udp_spec->hdr.src_port;
>+ filter->input.flow.udp4_flow.dst_port =
>+ udp_spec->hdr.dst_port;
>+ } else if (l3 == RTE_FLOW_ITEM_TYPE_IPV6) {
>+ filter->input.flow.udp6_flow.src_port =
>+ udp_spec->hdr.src_port;
>+ filter->input.flow.udp6_flow.dst_port =
>+ udp_spec->hdr.dst_port;
>+ }
> }
> }
> filter->input.flow_ext.is_udp = true;
>--
>2.17.1
>
Applied to dpdk-next-net-intel, Thanks.