net/hns3: support flow director

This patch adds support for rte_flow_ops operation and flow
director of hns3 PMD driver.
Flow director feature is only supported in hns3 PF driver.
It supports the network L2\L3\L4 and tunnel packet creation,
deletion, flushing, and querying hit statistics.

Signed-off-by: Chunsong Feng <fengchunsong@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
Signed-off-by: Hao Chen <chenhao164@huawei.com>
Signed-off-by: Min Hu (Connor) <humin29@huawei.com>
Signed-off-by: Huisong Li <lihuisong@huawei.com>
Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
Wei Hu (Xavier) 2019-09-26 22:01:56 +08:00 committed by Ferruh Yigit
parent 59fad0f321
commit fcba820d9b
8 changed files with 2751 additions and 3 deletions

View File

@ -8,6 +8,8 @@ Link status = Y
MTU update = Y
Unicast MAC filter = Y
Multicast MAC filter = Y
Flow director = Y
Flow API = Y
FW version = Y
Linux UIO = Y
Linux VFIO = Y

View File

@ -12,7 +12,7 @@ CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
LDLIBS += -lrte_eal
LDLIBS += -lrte_ethdev -lrte_net
LDLIBS += -lrte_ethdev -lrte_net -lrte_hash
LDLIBS += -lrte_bus_pci
EXPORT_MAP := rte_pmd_hns3_version.map
@ -24,5 +24,7 @@ LIBABIVER := 1
#
SRCS-$(CONFIG_RTE_LIBRTE_HNS3_PMD) += hns3_ethdev.c
SRCS-$(CONFIG_RTE_LIBRTE_HNS3_PMD) += hns3_cmd.c
SRCS-$(CONFIG_RTE_LIBRTE_HNS3_PMD) += hns3_flow.c
SRCS-$(CONFIG_RTE_LIBRTE_HNS3_PMD) += hns3_fdir.c
include $(RTE_SDK)/mk/rte.lib.mk

View File

@ -2500,6 +2500,12 @@ hns3_init_hardware(struct hns3_adapter *hns)
goto err_mac_init;
}
ret = hns3_init_fd_config(hns);
if (ret) {
PMD_INIT_LOG(ERR, "Failed to init flow director: %d", ret);
goto err_mac_init;
}
ret = hns3_config_tso(hw, HNS3_TSO_MSS_MIN, HNS3_TSO_MSS_MAX);
if (ret) {
PMD_INIT_LOG(ERR, "Failed to config tso: %d", ret);
@ -2559,8 +2565,18 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
goto err_get_config;
}
/* Initialize flow director filter list & hash */
ret = hns3_fdir_filter_init(hns);
if (ret) {
PMD_INIT_LOG(ERR, "Failed to alloc hashmap for fdir: %d", ret);
goto err_hw_init;
}
return 0;
err_hw_init:
hns3_uninit_umv_space(hw);
err_get_config:
hns3_cmd_uninit(hw);
@ -2581,6 +2597,7 @@ hns3_uninit_pf(struct rte_eth_dev *eth_dev)
PMD_INIT_FUNC_TRACE();
hns3_fdir_filter_uninit(hns);
hns3_uninit_umv_space(hw);
hns3_cmd_uninit(hw);
hns3_cmd_destroy_queue(hw);
@ -2598,6 +2615,8 @@ hns3_dev_close(struct rte_eth_dev *eth_dev)
hns3_configure_all_mc_mac_addr(hns, true);
hns3_uninit_pf(eth_dev);
rte_free(eth_dev->process_private);
eth_dev->process_private = NULL;
hw->adapter_state = HNS3_NIC_CLOSED;
}
@ -2611,6 +2630,7 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
.mac_addr_set = hns3_set_default_mac_addr,
.set_mc_addr_list = hns3_set_mc_mac_addr_list,
.link_update = hns3_dev_link_update,
.filter_ctrl = hns3_dev_filter_ctrl,
};
static int
@ -2621,6 +2641,16 @@ hns3_dev_init(struct rte_eth_dev *eth_dev)
int ret;
PMD_INIT_FUNC_TRACE();
eth_dev->process_private = (struct hns3_process_private *)
rte_zmalloc_socket("hns3_filter_list",
sizeof(struct hns3_process_private),
RTE_CACHE_LINE_SIZE, eth_dev->device->numa_node);
if (eth_dev->process_private == NULL) {
PMD_INIT_LOG(ERR, "Failed to alloc memory for process private");
return -ENOMEM;
}
/* initialize flow filter lists */
hns3_filterlist_init(eth_dev);
eth_dev->dev_ops = &hns3_eth_dev_ops;
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
@ -2677,6 +2707,8 @@ err_init_pf:
eth_dev->rx_pkt_burst = NULL;
eth_dev->tx_pkt_burst = NULL;
eth_dev->tx_pkt_prepare = NULL;
rte_free(eth_dev->process_private);
eth_dev->process_private = NULL;
return ret;
}

View File

@ -9,6 +9,7 @@
#include <rte_alarm.h>
#include "hns3_cmd.h"
#include "hns3_fdir.h"
/* Vendor ID */
#define PCI_VENDOR_ID_HUAWEI 0x19e5
@ -269,8 +270,6 @@ struct hns3_reset_stats {
uint64_t merge_cnt; /* Total merged in high reset times */
};
struct hns3_adapter;
typedef bool (*check_completion_func)(struct hns3_hw *hw);
struct hns3_wait_data {
@ -468,6 +467,9 @@ struct hns3_pf {
struct hns3_vtag_cfg vtag_config;
struct hns3_port_base_vlan_config port_base_vlan_cfg;
LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
struct hns3_fdir_info fdir; /* flow director info */
LIST_HEAD(counters, hns3_flow_counter) flow_counters;
};
struct hns3_vf {
@ -611,5 +613,8 @@ hns3_test_and_clear_bit(unsigned int nr, volatile uint64_t *addr)
int hns3_buffer_alloc(struct hns3_hw *hw);
int hns3_config_gro(struct hns3_hw *hw, bool en);
int hns3_dev_filter_ctrl(struct rte_eth_dev *dev,
enum rte_filter_type filter_type,
enum rte_filter_op filter_op, void *arg);
#endif /* _HNS3_ETHDEV_H_ */

1059
drivers/net/hns3/hns3_fdir.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2018-2019 Hisilicon Limited.
*/
#ifndef _HNS3_FDIR_H_
#define _HNS3_FDIR_H_
#include <rte_flow.h>
struct hns3_fd_key_cfg {
uint8_t key_sel;
uint8_t inner_sipv6_word_en;
uint8_t inner_dipv6_word_en;
uint8_t outer_sipv6_word_en;
uint8_t outer_dipv6_word_en;
uint32_t tuple_active;
uint32_t meta_data_active;
};
enum HNS3_FD_STAGE {
HNS3_FD_STAGE_1,
HNS3_FD_STAGE_2,
HNS3_FD_STAGE_NUM,
};
enum HNS3_FD_ACTION {
HNS3_FD_ACTION_ACCEPT_PACKET,
HNS3_FD_ACTION_DROP_PACKET,
};
struct hns3_fd_cfg {
uint8_t fd_mode;
uint16_t max_key_length;
uint32_t rule_num[HNS3_FD_STAGE_NUM]; /* rule entry number */
uint16_t cnt_num[HNS3_FD_STAGE_NUM]; /* rule hit counter number */
struct hns3_fd_key_cfg key_cfg[HNS3_FD_STAGE_NUM];
};
/* OUTER_XXX indicates tuples in tunnel header of tunnel packet
* INNER_XXX indicate tuples in tunneled header of tunnel packet or
* tuples of non-tunnel packet
*/
enum HNS3_FD_TUPLE {
OUTER_DST_MAC,
OUTER_SRC_MAC,
OUTER_VLAN_TAG_FST,
OUTER_VLAN_TAG_SEC,
OUTER_ETH_TYPE,
OUTER_L2_RSV,
OUTER_IP_TOS,
OUTER_IP_PROTO,
OUTER_SRC_IP,
OUTER_DST_IP,
OUTER_L3_RSV,
OUTER_SRC_PORT,
OUTER_DST_PORT,
OUTER_L4_RSV,
OUTER_TUN_VNI,
OUTER_TUN_FLOW_ID,
INNER_DST_MAC,
INNER_SRC_MAC,
INNER_VLAN_TAG1,
INNER_VLAN_TAG2,
INNER_ETH_TYPE,
INNER_L2_RSV,
INNER_IP_TOS,
INNER_IP_PROTO,
INNER_SRC_IP,
INNER_DST_IP,
INNER_L3_RSV,
INNER_SRC_PORT,
INNER_DST_PORT,
INNER_SCTP_TAG,
MAX_TUPLE,
};
#define VLAN_TAG_NUM_MAX 2
#define VNI_OR_TNI_LEN 3
#define IP_ADDR_LEN 4 /* Length of IPv6 address. */
#define IP_ADDR_KEY_ID 3 /* The last 32bit of IP address as FDIR search key */
#define IPV6_ADDR_WORD_MASK 3 /* The last two word of IPv6 as FDIR search key */
struct hns3_fd_rule_tuples {
uint8_t src_mac[RTE_ETHER_ADDR_LEN];
uint8_t dst_mac[RTE_ETHER_ADDR_LEN];
uint32_t src_ip[IP_ADDR_LEN];
uint32_t dst_ip[IP_ADDR_LEN];
uint16_t src_port;
uint16_t dst_port;
uint16_t vlan_tag1;
uint16_t vlan_tag2;
uint16_t ether_type;
uint8_t ip_tos;
uint8_t ip_proto;
uint32_t sctp_tag;
uint16_t outer_src_port;
uint16_t tunnel_type;
uint16_t outer_ether_type;
uint8_t outer_proto;
uint8_t outer_tun_vni[VNI_OR_TNI_LEN];
uint8_t outer_tun_flow_id;
};
struct hns3_fd_ad_data {
uint16_t ad_id;
uint8_t drop_packet;
uint8_t forward_to_direct_queue;
uint16_t queue_id;
uint8_t use_counter;
uint8_t counter_id;
uint8_t use_next_stage;
uint8_t write_rule_id_to_bd;
uint8_t next_input_key;
uint16_t rule_id;
};
struct hns3_flow_counter {
LIST_ENTRY(hns3_flow_counter) next; /* Pointer to the next counter. */
uint32_t shared:1; /* Share counter ID with other flow rules. */
uint32_t ref_cnt:31; /* Reference counter. */
uint16_t id; /* Counter ID. */
uint64_t hits; /* Number of packets matched by the rule. */
};
#define HNS3_RULE_FLAG_FDID 0x1
#define HNS3_RULE_FLAG_VF_ID 0x2
#define HNS3_RULE_FLAG_COUNTER 0x4
struct hns3_fdir_key_conf {
struct hns3_fd_rule_tuples spec;
struct hns3_fd_rule_tuples mask;
uint8_t vlan_num;
uint8_t outer_vlan_num;
};
struct hns3_fdir_rule {
struct hns3_fdir_key_conf key_conf;
uint32_t input_set;
uint32_t flags;
uint32_t fd_id; /* APP marked unique value for this rule. */
uint8_t action;
/* VF id, avaiblable when flags with HNS3_RULE_FLAG_VF_ID. */
uint8_t vf_id;
uint16_t queue_id;
uint16_t location;
struct rte_flow_action_count act_cnt;
};
/* FDIR filter list structure */
struct hns3_fdir_rule_ele {
TAILQ_ENTRY(hns3_fdir_rule_ele) entries;
struct hns3_fdir_rule fdir_conf;
};
/* hns3_flow memory list structure */
struct hns3_flow_mem {
TAILQ_ENTRY(hns3_flow_mem) entries;
struct rte_flow *flow;
};
TAILQ_HEAD(hns3_fdir_rule_list, hns3_fdir_rule_ele);
TAILQ_HEAD(hns3_flow_mem_list, hns3_flow_mem);
struct hns3_process_private {
struct hns3_fdir_rule_list fdir_list;
struct hns3_flow_mem_list flow_list;
};
/*
* A structure used to define fields of a FDIR related info.
*/
struct hns3_fdir_info {
rte_spinlock_t flows_lock;
struct hns3_fdir_rule_list fdir_list;
struct hns3_fdir_rule_ele **hash_map;
struct rte_hash *hash_handle;
struct hns3_fd_cfg fd_cfg;
};
struct rte_flow {
enum rte_filter_type filter_type;
void *rule;
uint32_t counter_id;
};
struct hns3_adapter;
int hns3_init_fd_config(struct hns3_adapter *hns);
int hns3_fdir_filter_init(struct hns3_adapter *hns);
void hns3_fdir_filter_uninit(struct hns3_adapter *hns);
int hns3_fdir_filter_program(struct hns3_adapter *hns,
struct hns3_fdir_rule *rule, bool del);
int hns3_clear_all_fdir_filter(struct hns3_adapter *hns);
int hns3_get_count(struct hns3_hw *hw, uint32_t id, uint64_t *value);
void hns3_filterlist_init(struct rte_eth_dev *dev);
int hns3_restore_all_fdir_filter(struct hns3_adapter *hns);
#endif /* _HNS3_FDIR_H_ */

1449
drivers/net/hns3/hns3_flow.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -15,5 +15,7 @@ endif
sources = files('hns3_cmd.c',
'hns3_ethdev.c',
'hns3_fdir.c',
'hns3_flow.c',
)
deps += ['hash']