Instead of FDIR filters RTE flow API should be used.
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
Acked-by: Haiyue Wang <haiyue.wang@intel.com>
Acked-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
"filters:\n"
"--------\n\n"
- "flow_director_filter (port_id) mode IP (add|del|update)"
- " flow (ipv4-other|ipv4-frag|ipv6-other|ipv6-frag)"
- " src (src_ip_address) dst (dst_ip_address)"
- " tos (tos_value) proto (proto_value) ttl (ttl_value)"
- " vlan (vlan_value) flexbytes (flexbytes_value)"
- " (drop|fwd) pf|vf(vf_id) queue (queue_id)"
- " fd_id (fd_id_value)\n"
- " Add/Del an IP type flow director filter.\n\n"
-
- "flow_director_filter (port_id) mode IP (add|del|update)"
- " flow (ipv4-tcp|ipv4-udp|ipv6-tcp|ipv6-udp)"
- " src (src_ip_address) (src_port)"
- " dst (dst_ip_address) (dst_port)"
- " tos (tos_value) ttl (ttl_value)"
- " vlan (vlan_value) flexbytes (flexbytes_value)"
- " (drop|fwd) pf|vf(vf_id) queue (queue_id)"
- " fd_id (fd_id_value)\n"
- " Add/Del an UDP/TCP type flow director filter.\n\n"
-
- "flow_director_filter (port_id) mode IP (add|del|update)"
- " flow (ipv4-sctp|ipv6-sctp)"
- " src (src_ip_address) (src_port)"
- " dst (dst_ip_address) (dst_port)"
- " tag (verification_tag) "
- " tos (tos_value) ttl (ttl_value)"
- " vlan (vlan_value)"
- " flexbytes (flexbytes_value) (drop|fwd)"
- " pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)\n"
- " Add/Del a SCTP type flow director filter.\n\n"
-
- "flow_director_filter (port_id) mode IP (add|del|update)"
- " flow l2_payload ether (ethertype)"
- " flexbytes (flexbytes_value) (drop|fwd)"
- " pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)\n"
- " Add/Del a l2 payload type flow director filter.\n\n"
-
- "flow_director_filter (port_id) mode MAC-VLAN (add|del|update)"
- " mac (mac_address) vlan (vlan_value)"
- " flexbytes (flexbytes_value) (drop|fwd)"
- " queue (queue_id) fd_id (fd_id_value)\n"
- " Add/Del a MAC-VLAN flow director filter.\n\n"
-
- "flow_director_filter (port_id) mode Tunnel (add|del|update)"
- " mac (mac_address) vlan (vlan_value)"
- " tunnel (NVGRE|VxLAN) tunnel-id (tunnel_id_value)"
- " flexbytes (flexbytes_value) (drop|fwd)"
- " queue (queue_id) fd_id (fd_id_value)\n"
- " Add/Del a Tunnel flow director filter.\n\n"
-
+#ifdef RTE_NET_I40E
"flow_director_filter (port_id) mode raw (add|del|update)"
" flow (flow_id) (drop|fwd) queue (queue_id)"
" fd_id (fd_id_value) packet (packet file name)\n"
" Add/Del a raw type flow director filter.\n\n"
-
- "flush_flow_director (port_id)\n"
- " Flush all flow director entries of a device.\n\n"
+#endif
"flow_director_mask (port_id) mode IP vlan (vlan_value)"
" src_mask (ipv4_src) (ipv6_src) (src_port)"
" (raw|l2|l3|l4) (config)\n"
" Configure flex payload selection.\n\n"
- "set_fdir_input_set (port_id) "
- "(ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
- "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|"
- "l2_payload) (ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|"
- "dst-ipv6|ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|"
- "ipv6-next-header|ipv6-hop-limits|udp-src-port|"
- "udp-dst-port|tcp-src-port|tcp-dst-port|"
- "sctp-src-port|sctp-dst-port|sctp-veri-tag|none)"
- " (select|add)\n"
- " Set the input set for FDir.\n\n"
-
"flow validate {port_id}"
" [group {group_id}] [priority {level}]"
" [ingress] [egress]"
else if (!strcmp(res->what, "xstats"))
RTE_ETH_FOREACH_DEV(i)
nic_xstats_display(i);
+#if defined(RTE_NET_I40E) || defined(RTE_NET_IXGBE)
else if (!strcmp(res->what, "fdir"))
RTE_ETH_FOREACH_DEV(i)
fdir_get_infos(i);
+#endif
else if (!strcmp(res->what, "stat_qmap"))
RTE_ETH_FOREACH_DEV(i)
nic_stats_mapping_display(i);
nic_stats_display(res->portnum);
else if (!strcmp(res->what, "xstats"))
nic_xstats_display(res->portnum);
+#if defined(RTE_NET_I40E) || defined(RTE_NET_IXGBE)
else if (!strcmp(res->what, "fdir"))
fdir_get_infos(res->portnum);
+#endif
else if (!strcmp(res->what, "stat_qmap"))
nic_stats_mapping_display(res->portnum);
else if (!strcmp(res->what, "dcb_tc"))
/* *** Filters Control *** */
-/* *** deal with flow director filter *** */
-struct cmd_flow_director_result {
- cmdline_fixed_string_t flow_director_filter;
- portid_t port_id;
- cmdline_fixed_string_t mode;
- cmdline_fixed_string_t mode_value;
- cmdline_fixed_string_t ops;
- cmdline_fixed_string_t flow;
- cmdline_fixed_string_t flow_type;
- cmdline_fixed_string_t ether;
- uint16_t ether_type;
- cmdline_fixed_string_t src;
- cmdline_ipaddr_t ip_src;
- uint16_t port_src;
- cmdline_fixed_string_t dst;
- cmdline_ipaddr_t ip_dst;
- uint16_t port_dst;
- cmdline_fixed_string_t verify_tag;
- uint32_t verify_tag_value;
- cmdline_fixed_string_t tos;
- uint8_t tos_value;
- cmdline_fixed_string_t proto;
- uint8_t proto_value;
- cmdline_fixed_string_t ttl;
- uint8_t ttl_value;
- cmdline_fixed_string_t vlan;
- uint16_t vlan_value;
- cmdline_fixed_string_t flexbytes;
- cmdline_fixed_string_t flexbytes_value;
- cmdline_fixed_string_t pf_vf;
- cmdline_fixed_string_t drop;
- cmdline_fixed_string_t queue;
- uint16_t queue_id;
- cmdline_fixed_string_t fd_id;
- uint32_t fd_id_value;
- cmdline_fixed_string_t mac;
- struct rte_ether_addr mac_addr;
- cmdline_fixed_string_t tunnel;
- cmdline_fixed_string_t tunnel_type;
- cmdline_fixed_string_t tunnel_id;
- uint32_t tunnel_id_value;
- cmdline_fixed_string_t packet;
- char filepath[];
-};
-
static inline int
parse_flexbytes(const char *q_arg, uint8_t *flexbytes, uint16_t max_num)
{
return RTE_ETH_FLOW_UNKNOWN;
}
-static enum rte_eth_fdir_tunnel_type
-str2fdir_tunneltype(char *string)
-{
- uint8_t i = 0;
-
- static const struct {
- char str[32];
- enum rte_eth_fdir_tunnel_type type;
- } tunneltype_str[] = {
- {"NVGRE", RTE_FDIR_TUNNEL_TYPE_NVGRE},
- {"VxLAN", RTE_FDIR_TUNNEL_TYPE_VXLAN},
- };
-
- for (i = 0; i < RTE_DIM(tunneltype_str); i++) {
- if (!strcmp(tunneltype_str[i].str, string))
- return tunneltype_str[i].type;
- }
- return RTE_FDIR_TUNNEL_TYPE_UNKNOWN;
-}
-
#define IPV4_ADDR_TO_UINT(ip_addr, ip) \
do { \
if ((ip_addr).family == AF_INET) \
} \
} while (0)
+#ifdef RTE_NET_I40E
+
+/* *** deal with flow director filter *** */
+struct cmd_flow_director_result {
+ cmdline_fixed_string_t flow_director_filter;
+ portid_t port_id;
+ cmdline_fixed_string_t mode;
+ cmdline_fixed_string_t mode_value;
+ cmdline_fixed_string_t ops;
+ cmdline_fixed_string_t flow;
+ cmdline_fixed_string_t flow_type;
+ cmdline_fixed_string_t drop;
+ cmdline_fixed_string_t queue;
+ uint16_t queue_id;
+ cmdline_fixed_string_t fd_id;
+ uint32_t fd_id_value;
+ cmdline_fixed_string_t packet;
+ char filepath[];
+};
+
static void
cmd_flow_director_filter_parsed(void *parsed_result,
__rte_unused struct cmdline *cl,
__rte_unused void *data)
{
struct cmd_flow_director_result *res = parsed_result;
- struct rte_eth_fdir_filter entry;
- uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN];
- char *end;
- unsigned long vf_id;
int ret = 0;
+ struct rte_pmd_i40e_flow_type_mapping
+ mapping[RTE_PMD_I40E_FLOW_TYPE_MAX];
+ struct rte_pmd_i40e_pkt_template_conf conf;
+ uint16_t flow_type = str2flowtype(res->flow_type);
+ uint16_t i, port = res->port_id;
+ uint8_t add;
- ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
- if (ret < 0) {
- printf("flow director is not supported on port %u.\n",
- res->port_id);
- return;
- }
- memset(flexbytes, 0, sizeof(flexbytes));
- memset(&entry, 0, sizeof(struct rte_eth_fdir_filter));
-
- if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
- if (strcmp(res->mode_value, "MAC-VLAN")) {
- printf("Please set mode to MAC-VLAN.\n");
- return;
- }
- } else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
- if (strcmp(res->mode_value, "Tunnel")) {
- printf("Please set mode to Tunnel.\n");
- return;
- }
- } else {
- if (!strcmp(res->mode_value, "raw")) {
-#ifdef RTE_NET_I40E
- struct rte_pmd_i40e_flow_type_mapping
- mapping[RTE_PMD_I40E_FLOW_TYPE_MAX];
- struct rte_pmd_i40e_pkt_template_conf conf;
- uint16_t flow_type = str2flowtype(res->flow_type);
- uint16_t i, port = res->port_id;
- uint8_t add;
-
- memset(&conf, 0, sizeof(conf));
+ memset(&conf, 0, sizeof(conf));
- if (flow_type == RTE_ETH_FLOW_UNKNOWN) {
- printf("Invalid flow type specified.\n");
- return;
- }
- ret = rte_pmd_i40e_flow_type_mapping_get(res->port_id,
- mapping);
- if (ret)
- return;
- if (mapping[flow_type].pctype == 0ULL) {
- printf("Invalid flow type specified.\n");
- return;
- }
- for (i = 0; i < RTE_PMD_I40E_PCTYPE_MAX; i++) {
- if (mapping[flow_type].pctype & (1ULL << i)) {
- conf.input.pctype = i;
- break;
- }
- }
-
- conf.input.packet = open_file(res->filepath,
- &conf.input.length);
- if (!conf.input.packet)
- return;
- if (!strcmp(res->drop, "drop"))
- conf.action.behavior =
- RTE_PMD_I40E_PKT_TEMPLATE_REJECT;
- else
- conf.action.behavior =
- RTE_PMD_I40E_PKT_TEMPLATE_ACCEPT;
- conf.action.report_status =
- RTE_PMD_I40E_PKT_TEMPLATE_REPORT_ID;
- conf.action.rx_queue = res->queue_id;
- conf.soft_id = res->fd_id_value;
- add = strcmp(res->ops, "del") ? 1 : 0;
- ret = rte_pmd_i40e_flow_add_del_packet_template(port,
- &conf,
- add);
- if (ret < 0)
- printf("flow director config error: (%s)\n",
- strerror(-ret));
- close_file(conf.input.packet);
-#endif
- return;
- } else if (strcmp(res->mode_value, "IP")) {
- printf("Please set mode to IP or raw.\n");
- return;
- }
- entry.input.flow_type = str2flowtype(res->flow_type);
- }
-
- ret = parse_flexbytes(res->flexbytes_value,
- flexbytes,
- RTE_ETH_FDIR_MAX_FLEXLEN);
- if (ret < 0) {
- printf("error: Cannot parse flexbytes input.\n");
+ if (flow_type == RTE_ETH_FLOW_UNKNOWN) {
+ printf("Invalid flow type specified.\n");
return;
}
-
- switch (entry.input.flow_type) {
- case RTE_ETH_FLOW_FRAG_IPV4:
- case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
- entry.input.flow.ip4_flow.proto = res->proto_value;
- /* fall-through */
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- IPV4_ADDR_TO_UINT(res->ip_dst,
- entry.input.flow.ip4_flow.dst_ip);
- IPV4_ADDR_TO_UINT(res->ip_src,
- entry.input.flow.ip4_flow.src_ip);
- entry.input.flow.ip4_flow.tos = res->tos_value;
- entry.input.flow.ip4_flow.ttl = res->ttl_value;
- /* need convert to big endian. */
- entry.input.flow.udp4_flow.dst_port =
- rte_cpu_to_be_16(res->port_dst);
- entry.input.flow.udp4_flow.src_port =
- rte_cpu_to_be_16(res->port_src);
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
- IPV4_ADDR_TO_UINT(res->ip_dst,
- entry.input.flow.sctp4_flow.ip.dst_ip);
- IPV4_ADDR_TO_UINT(res->ip_src,
- entry.input.flow.sctp4_flow.ip.src_ip);
- entry.input.flow.ip4_flow.tos = res->tos_value;
- entry.input.flow.ip4_flow.ttl = res->ttl_value;
- /* need convert to big endian. */
- entry.input.flow.sctp4_flow.dst_port =
- rte_cpu_to_be_16(res->port_dst);
- entry.input.flow.sctp4_flow.src_port =
- rte_cpu_to_be_16(res->port_src);
- entry.input.flow.sctp4_flow.verify_tag =
- rte_cpu_to_be_32(res->verify_tag_value);
- break;
- case RTE_ETH_FLOW_FRAG_IPV6:
- case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
- entry.input.flow.ipv6_flow.proto = res->proto_value;
- /* fall-through */
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- IPV6_ADDR_TO_ARRAY(res->ip_dst,
- entry.input.flow.ipv6_flow.dst_ip);
- IPV6_ADDR_TO_ARRAY(res->ip_src,
- entry.input.flow.ipv6_flow.src_ip);
- entry.input.flow.ipv6_flow.tc = res->tos_value;
- entry.input.flow.ipv6_flow.hop_limits = res->ttl_value;
- /* need convert to big endian. */
- entry.input.flow.udp6_flow.dst_port =
- rte_cpu_to_be_16(res->port_dst);
- entry.input.flow.udp6_flow.src_port =
- rte_cpu_to_be_16(res->port_src);
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
- IPV6_ADDR_TO_ARRAY(res->ip_dst,
- entry.input.flow.sctp6_flow.ip.dst_ip);
- IPV6_ADDR_TO_ARRAY(res->ip_src,
- entry.input.flow.sctp6_flow.ip.src_ip);
- entry.input.flow.ipv6_flow.tc = res->tos_value;
- entry.input.flow.ipv6_flow.hop_limits = res->ttl_value;
- /* need convert to big endian. */
- entry.input.flow.sctp6_flow.dst_port =
- rte_cpu_to_be_16(res->port_dst);
- entry.input.flow.sctp6_flow.src_port =
- rte_cpu_to_be_16(res->port_src);
- entry.input.flow.sctp6_flow.verify_tag =
- rte_cpu_to_be_32(res->verify_tag_value);
- break;
- case RTE_ETH_FLOW_L2_PAYLOAD:
- entry.input.flow.l2_flow.ether_type =
- rte_cpu_to_be_16(res->ether_type);
- break;
- default:
- break;
- }
-
- if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
- rte_memcpy(&entry.input.flow.mac_vlan_flow.mac_addr,
- &res->mac_addr,
- sizeof(struct rte_ether_addr));
-
- if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
- rte_memcpy(&entry.input.flow.tunnel_flow.mac_addr,
- &res->mac_addr,
- sizeof(struct rte_ether_addr));
- entry.input.flow.tunnel_flow.tunnel_type =
- str2fdir_tunneltype(res->tunnel_type);
- entry.input.flow.tunnel_flow.tunnel_id =
- rte_cpu_to_be_32(res->tunnel_id_value);
+ ret = rte_pmd_i40e_flow_type_mapping_get(res->port_id,
+ mapping);
+ if (ret)
+ return;
+ if (mapping[flow_type].pctype == 0ULL) {
+ printf("Invalid flow type specified.\n");
+ return;
}
-
- rte_memcpy(entry.input.flow_ext.flexbytes,
- flexbytes,
- RTE_ETH_FDIR_MAX_FLEXLEN);
-
- entry.input.flow_ext.vlan_tci = rte_cpu_to_be_16(res->vlan_value);
-
- entry.action.flex_off = 0; /*use 0 by default */
- if (!strcmp(res->drop, "drop"))
- entry.action.behavior = RTE_ETH_FDIR_REJECT;
- else
- entry.action.behavior = RTE_ETH_FDIR_ACCEPT;
-
- if (fdir_conf.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN &&
- fdir_conf.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) {
- if (!strcmp(res->pf_vf, "pf"))
- entry.input.flow_ext.is_vf = 0;
- else if (!strncmp(res->pf_vf, "vf", 2)) {
- struct rte_eth_dev_info dev_info;
-
- ret = eth_dev_info_get_print_err(res->port_id,
- &dev_info);
- if (ret != 0)
- return;
-
- errno = 0;
- vf_id = strtoul(res->pf_vf + 2, &end, 10);
- if (errno != 0 || *end != '\0' ||
- vf_id >= dev_info.max_vfs) {
- printf("invalid parameter %s.\n", res->pf_vf);
- return;
- }
- entry.input.flow_ext.is_vf = 1;
- entry.input.flow_ext.dst_id = (uint16_t)vf_id;
- } else {
- printf("invalid parameter %s.\n", res->pf_vf);
- return;
+ for (i = 0; i < RTE_PMD_I40E_PCTYPE_MAX; i++) {
+ if (mapping[flow_type].pctype & (1ULL << i)) {
+ conf.input.pctype = i;
+ break;
}
}
- /* set to report FD ID by default */
- entry.action.report_status = RTE_ETH_FDIR_REPORT_ID;
- entry.action.rx_queue = res->queue_id;
- entry.soft_id = res->fd_id_value;
- if (!strcmp(res->ops, "add"))
- ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_ADD, &entry);
- else if (!strcmp(res->ops, "del"))
- ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_DELETE, &entry);
+ conf.input.packet = open_file(res->filepath,
+ &conf.input.length);
+ if (!conf.input.packet)
+ return;
+ if (!strcmp(res->drop, "drop"))
+ conf.action.behavior =
+ RTE_PMD_I40E_PKT_TEMPLATE_REJECT;
else
- ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_UPDATE, &entry);
+ conf.action.behavior =
+ RTE_PMD_I40E_PKT_TEMPLATE_ACCEPT;
+ conf.action.report_status =
+ RTE_PMD_I40E_PKT_TEMPLATE_REPORT_ID;
+ conf.action.rx_queue = res->queue_id;
+ conf.soft_id = res->fd_id_value;
+ add = strcmp(res->ops, "del") ? 1 : 0;
+ ret = rte_pmd_i40e_flow_add_del_packet_template(port,
+ &conf,
+ add);
if (ret < 0)
- printf("flow director programming error: (%s)\n",
- strerror(-ret));
+ printf("flow director config error: (%s)\n",
+ strerror(-ret));
+ close_file(conf.input.packet);
}
cmdline_parse_token_string_t cmd_flow_director_filter =
cmdline_parse_token_string_t cmd_flow_director_flow_type =
TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
flow_type, NULL);
-cmdline_parse_token_string_t cmd_flow_director_ether =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- ether, "ether");
-cmdline_parse_token_num_t cmd_flow_director_ether_type =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- ether_type, UINT16);
-cmdline_parse_token_string_t cmd_flow_director_src =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- src, "src");
-cmdline_parse_token_ipaddr_t cmd_flow_director_ip_src =
- TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result,
- ip_src);
-cmdline_parse_token_num_t cmd_flow_director_port_src =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- port_src, UINT16);
-cmdline_parse_token_string_t cmd_flow_director_dst =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- dst, "dst");
-cmdline_parse_token_ipaddr_t cmd_flow_director_ip_dst =
- TOKEN_IPADDR_INITIALIZER(struct cmd_flow_director_result,
- ip_dst);
-cmdline_parse_token_num_t cmd_flow_director_port_dst =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- port_dst, UINT16);
-cmdline_parse_token_string_t cmd_flow_director_verify_tag =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- verify_tag, "verify_tag");
-cmdline_parse_token_num_t cmd_flow_director_verify_tag_value =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- verify_tag_value, UINT32);
-cmdline_parse_token_string_t cmd_flow_director_tos =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- tos, "tos");
-cmdline_parse_token_num_t cmd_flow_director_tos_value =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- tos_value, UINT8);
-cmdline_parse_token_string_t cmd_flow_director_proto =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- proto, "proto");
-cmdline_parse_token_num_t cmd_flow_director_proto_value =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- proto_value, UINT8);
-cmdline_parse_token_string_t cmd_flow_director_ttl =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- ttl, "ttl");
-cmdline_parse_token_num_t cmd_flow_director_ttl_value =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- ttl_value, UINT8);
-cmdline_parse_token_string_t cmd_flow_director_vlan =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- vlan, "vlan");
-cmdline_parse_token_num_t cmd_flow_director_vlan_value =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- vlan_value, UINT16);
-cmdline_parse_token_string_t cmd_flow_director_flexbytes =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- flexbytes, "flexbytes");
-cmdline_parse_token_string_t cmd_flow_director_flexbytes_value =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- flexbytes_value, NULL);
cmdline_parse_token_string_t cmd_flow_director_drop =
TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
drop, "drop#fwd");
-cmdline_parse_token_string_t cmd_flow_director_pf_vf =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- pf_vf, NULL);
cmdline_parse_token_string_t cmd_flow_director_queue =
TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
queue, "queue");
cmdline_parse_token_string_t cmd_flow_director_mode =
TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
mode, "mode");
-cmdline_parse_token_string_t cmd_flow_director_mode_ip =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- mode_value, "IP");
-cmdline_parse_token_string_t cmd_flow_director_mode_mac_vlan =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- mode_value, "MAC-VLAN");
-cmdline_parse_token_string_t cmd_flow_director_mode_tunnel =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- mode_value, "Tunnel");
cmdline_parse_token_string_t cmd_flow_director_mode_raw =
TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
mode_value, "raw");
-cmdline_parse_token_string_t cmd_flow_director_mac =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- mac, "mac");
-cmdline_parse_token_etheraddr_t cmd_flow_director_mac_addr =
- TOKEN_ETHERADDR_INITIALIZER(struct cmd_flow_director_result,
- mac_addr);
-cmdline_parse_token_string_t cmd_flow_director_tunnel =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- tunnel, "tunnel");
-cmdline_parse_token_string_t cmd_flow_director_tunnel_type =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- tunnel_type, "NVGRE#VxLAN");
-cmdline_parse_token_string_t cmd_flow_director_tunnel_id =
- TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
- tunnel_id, "tunnel-id");
-cmdline_parse_token_num_t cmd_flow_director_tunnel_id_value =
- TOKEN_NUM_INITIALIZER(struct cmd_flow_director_result,
- tunnel_id_value, UINT32);
cmdline_parse_token_string_t cmd_flow_director_packet =
TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
packet, "packet");
TOKEN_STRING_INITIALIZER(struct cmd_flow_director_result,
filepath, NULL);
-cmdline_parse_inst_t cmd_add_del_ip_flow_director = {
- .f = cmd_flow_director_filter_parsed,
- .data = NULL,
- .help_str = "flow_director_filter <port_id> mode IP add|del|update flow"
- " ipv4-other|ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|"
- "ipv6-other|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|"
- "l2_payload src <src_ip> dst <dst_ip> tos <tos_value> "
- "proto <proto_value> ttl <ttl_value> vlan <vlan_value> "
- "flexbytes <flexbyte_values> drop|fw <pf_vf> queue <queue_id> "
- "fd_id <fd_id_value>: "
- "Add or delete an ip flow director entry on NIC",
- .tokens = {
- (void *)&cmd_flow_director_filter,
- (void *)&cmd_flow_director_port_id,
- (void *)&cmd_flow_director_mode,
- (void *)&cmd_flow_director_mode_ip,
- (void *)&cmd_flow_director_ops,
- (void *)&cmd_flow_director_flow,
- (void *)&cmd_flow_director_flow_type,
- (void *)&cmd_flow_director_src,
- (void *)&cmd_flow_director_ip_src,
- (void *)&cmd_flow_director_dst,
- (void *)&cmd_flow_director_ip_dst,
- (void *)&cmd_flow_director_tos,
- (void *)&cmd_flow_director_tos_value,
- (void *)&cmd_flow_director_proto,
- (void *)&cmd_flow_director_proto_value,
- (void *)&cmd_flow_director_ttl,
- (void *)&cmd_flow_director_ttl_value,
- (void *)&cmd_flow_director_vlan,
- (void *)&cmd_flow_director_vlan_value,
- (void *)&cmd_flow_director_flexbytes,
- (void *)&cmd_flow_director_flexbytes_value,
- (void *)&cmd_flow_director_drop,
- (void *)&cmd_flow_director_pf_vf,
- (void *)&cmd_flow_director_queue,
- (void *)&cmd_flow_director_queue_id,
- (void *)&cmd_flow_director_fd_id,
- (void *)&cmd_flow_director_fd_id_value,
- NULL,
- },
-};
-
-cmdline_parse_inst_t cmd_add_del_udp_flow_director = {
- .f = cmd_flow_director_filter_parsed,
- .data = NULL,
- .help_str = "flow_director_filter ... : Add or delete an udp/tcp flow "
- "director entry on NIC",
- .tokens = {
- (void *)&cmd_flow_director_filter,
- (void *)&cmd_flow_director_port_id,
- (void *)&cmd_flow_director_mode,
- (void *)&cmd_flow_director_mode_ip,
- (void *)&cmd_flow_director_ops,
- (void *)&cmd_flow_director_flow,
- (void *)&cmd_flow_director_flow_type,
- (void *)&cmd_flow_director_src,
- (void *)&cmd_flow_director_ip_src,
- (void *)&cmd_flow_director_port_src,
- (void *)&cmd_flow_director_dst,
- (void *)&cmd_flow_director_ip_dst,
- (void *)&cmd_flow_director_port_dst,
- (void *)&cmd_flow_director_tos,
- (void *)&cmd_flow_director_tos_value,
- (void *)&cmd_flow_director_ttl,
- (void *)&cmd_flow_director_ttl_value,
- (void *)&cmd_flow_director_vlan,
- (void *)&cmd_flow_director_vlan_value,
- (void *)&cmd_flow_director_flexbytes,
- (void *)&cmd_flow_director_flexbytes_value,
- (void *)&cmd_flow_director_drop,
- (void *)&cmd_flow_director_pf_vf,
- (void *)&cmd_flow_director_queue,
- (void *)&cmd_flow_director_queue_id,
- (void *)&cmd_flow_director_fd_id,
- (void *)&cmd_flow_director_fd_id_value,
- NULL,
- },
-};
-
-cmdline_parse_inst_t cmd_add_del_sctp_flow_director = {
- .f = cmd_flow_director_filter_parsed,
- .data = NULL,
- .help_str = "flow_director_filter ... : Add or delete a sctp flow "
- "director entry on NIC",
- .tokens = {
- (void *)&cmd_flow_director_filter,
- (void *)&cmd_flow_director_port_id,
- (void *)&cmd_flow_director_mode,
- (void *)&cmd_flow_director_mode_ip,
- (void *)&cmd_flow_director_ops,
- (void *)&cmd_flow_director_flow,
- (void *)&cmd_flow_director_flow_type,
- (void *)&cmd_flow_director_src,
- (void *)&cmd_flow_director_ip_src,
- (void *)&cmd_flow_director_port_src,
- (void *)&cmd_flow_director_dst,
- (void *)&cmd_flow_director_ip_dst,
- (void *)&cmd_flow_director_port_dst,
- (void *)&cmd_flow_director_verify_tag,
- (void *)&cmd_flow_director_verify_tag_value,
- (void *)&cmd_flow_director_tos,
- (void *)&cmd_flow_director_tos_value,
- (void *)&cmd_flow_director_ttl,
- (void *)&cmd_flow_director_ttl_value,
- (void *)&cmd_flow_director_vlan,
- (void *)&cmd_flow_director_vlan_value,
- (void *)&cmd_flow_director_flexbytes,
- (void *)&cmd_flow_director_flexbytes_value,
- (void *)&cmd_flow_director_drop,
- (void *)&cmd_flow_director_pf_vf,
- (void *)&cmd_flow_director_queue,
- (void *)&cmd_flow_director_queue_id,
- (void *)&cmd_flow_director_fd_id,
- (void *)&cmd_flow_director_fd_id_value,
- NULL,
- },
-};
-
-cmdline_parse_inst_t cmd_add_del_l2_flow_director = {
- .f = cmd_flow_director_filter_parsed,
- .data = NULL,
- .help_str = "flow_director_filter ... : Add or delete a L2 flow "
- "director entry on NIC",
- .tokens = {
- (void *)&cmd_flow_director_filter,
- (void *)&cmd_flow_director_port_id,
- (void *)&cmd_flow_director_mode,
- (void *)&cmd_flow_director_mode_ip,
- (void *)&cmd_flow_director_ops,
- (void *)&cmd_flow_director_flow,
- (void *)&cmd_flow_director_flow_type,
- (void *)&cmd_flow_director_ether,
- (void *)&cmd_flow_director_ether_type,
- (void *)&cmd_flow_director_flexbytes,
- (void *)&cmd_flow_director_flexbytes_value,
- (void *)&cmd_flow_director_drop,
- (void *)&cmd_flow_director_pf_vf,
- (void *)&cmd_flow_director_queue,
- (void *)&cmd_flow_director_queue_id,
- (void *)&cmd_flow_director_fd_id,
- (void *)&cmd_flow_director_fd_id_value,
- NULL,
- },
-};
-
-cmdline_parse_inst_t cmd_add_del_mac_vlan_flow_director = {
- .f = cmd_flow_director_filter_parsed,
- .data = NULL,
- .help_str = "flow_director_filter ... : Add or delete a MAC VLAN flow "
- "director entry on NIC",
- .tokens = {
- (void *)&cmd_flow_director_filter,
- (void *)&cmd_flow_director_port_id,
- (void *)&cmd_flow_director_mode,
- (void *)&cmd_flow_director_mode_mac_vlan,
- (void *)&cmd_flow_director_ops,
- (void *)&cmd_flow_director_mac,
- (void *)&cmd_flow_director_mac_addr,
- (void *)&cmd_flow_director_vlan,
- (void *)&cmd_flow_director_vlan_value,
- (void *)&cmd_flow_director_flexbytes,
- (void *)&cmd_flow_director_flexbytes_value,
- (void *)&cmd_flow_director_drop,
- (void *)&cmd_flow_director_queue,
- (void *)&cmd_flow_director_queue_id,
- (void *)&cmd_flow_director_fd_id,
- (void *)&cmd_flow_director_fd_id_value,
- NULL,
- },
-};
-
-cmdline_parse_inst_t cmd_add_del_tunnel_flow_director = {
- .f = cmd_flow_director_filter_parsed,
- .data = NULL,
- .help_str = "flow_director_filter ... : Add or delete a tunnel flow "
- "director entry on NIC",
- .tokens = {
- (void *)&cmd_flow_director_filter,
- (void *)&cmd_flow_director_port_id,
- (void *)&cmd_flow_director_mode,
- (void *)&cmd_flow_director_mode_tunnel,
- (void *)&cmd_flow_director_ops,
- (void *)&cmd_flow_director_mac,
- (void *)&cmd_flow_director_mac_addr,
- (void *)&cmd_flow_director_vlan,
- (void *)&cmd_flow_director_vlan_value,
- (void *)&cmd_flow_director_tunnel,
- (void *)&cmd_flow_director_tunnel_type,
- (void *)&cmd_flow_director_tunnel_id,
- (void *)&cmd_flow_director_tunnel_id_value,
- (void *)&cmd_flow_director_flexbytes,
- (void *)&cmd_flow_director_flexbytes_value,
- (void *)&cmd_flow_director_drop,
- (void *)&cmd_flow_director_queue,
- (void *)&cmd_flow_director_queue_id,
- (void *)&cmd_flow_director_fd_id,
- (void *)&cmd_flow_director_fd_id_value,
- NULL,
- },
-};
-
cmdline_parse_inst_t cmd_add_del_raw_flow_director = {
.f = cmd_flow_director_filter_parsed,
.data = NULL,
},
};
-struct cmd_flush_flow_director_result {
- cmdline_fixed_string_t flush_flow_director;
- portid_t port_id;
-};
-
-cmdline_parse_token_string_t cmd_flush_flow_director_flush =
- TOKEN_STRING_INITIALIZER(struct cmd_flush_flow_director_result,
- flush_flow_director, "flush_flow_director");
-cmdline_parse_token_num_t cmd_flush_flow_director_port_id =
- TOKEN_NUM_INITIALIZER(struct cmd_flush_flow_director_result,
- port_id, UINT16);
-
-static void
-cmd_flush_flow_director_parsed(void *parsed_result,
- __rte_unused struct cmdline *cl,
- __rte_unused void *data)
-{
- struct cmd_flow_director_result *res = parsed_result;
- int ret = 0;
-
- ret = rte_eth_dev_filter_supported(res->port_id, RTE_ETH_FILTER_FDIR);
- if (ret < 0) {
- printf("flow director is not supported on port %u.\n",
- res->port_id);
- return;
- }
-
- ret = rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_FLUSH, NULL);
- if (ret < 0)
- printf("flow director table flushing error: (%s)\n",
- strerror(-ret));
-}
-
-cmdline_parse_inst_t cmd_flush_flow_director = {
- .f = cmd_flush_flow_director_parsed,
- .data = NULL,
- .help_str = "flush_flow_director <port_id>: "
- "Flush all flow director entries of a device on NIC",
- .tokens = {
- (void *)&cmd_flush_flow_director_flush,
- (void *)&cmd_flush_flow_director_port_id,
- NULL,
- },
-};
+#endif /* RTE_NET_I40E */
/* *** deal with flow director mask *** */
struct cmd_flow_director_mask_result {
/* Generic flow interface command. */
extern cmdline_parse_inst_t cmd_flow;
-/* *** Classification Filters Control *** */
-
-static enum rte_eth_input_set_field
-str2inset(char *string)
-{
- uint16_t i;
-
- static const struct {
- char str[32];
- enum rte_eth_input_set_field inset;
- } inset_table[] = {
- {"ethertype", RTE_ETH_INPUT_SET_L2_ETHERTYPE},
- {"ovlan", RTE_ETH_INPUT_SET_L2_OUTER_VLAN},
- {"ivlan", RTE_ETH_INPUT_SET_L2_INNER_VLAN},
- {"src-ipv4", RTE_ETH_INPUT_SET_L3_SRC_IP4},
- {"dst-ipv4", RTE_ETH_INPUT_SET_L3_DST_IP4},
- {"ipv4-tos", RTE_ETH_INPUT_SET_L3_IP4_TOS},
- {"ipv4-proto", RTE_ETH_INPUT_SET_L3_IP4_PROTO},
- {"ipv4-ttl", RTE_ETH_INPUT_SET_L3_IP4_TTL},
- {"src-ipv6", RTE_ETH_INPUT_SET_L3_SRC_IP6},
- {"dst-ipv6", RTE_ETH_INPUT_SET_L3_DST_IP6},
- {"ipv6-tc", RTE_ETH_INPUT_SET_L3_IP6_TC},
- {"ipv6-next-header", RTE_ETH_INPUT_SET_L3_IP6_NEXT_HEADER},
- {"ipv6-hop-limits", RTE_ETH_INPUT_SET_L3_IP6_HOP_LIMITS},
- {"udp-src-port", RTE_ETH_INPUT_SET_L4_UDP_SRC_PORT},
- {"udp-dst-port", RTE_ETH_INPUT_SET_L4_UDP_DST_PORT},
- {"tcp-src-port", RTE_ETH_INPUT_SET_L4_TCP_SRC_PORT},
- {"tcp-dst-port", RTE_ETH_INPUT_SET_L4_TCP_DST_PORT},
- {"sctp-src-port", RTE_ETH_INPUT_SET_L4_SCTP_SRC_PORT},
- {"sctp-dst-port", RTE_ETH_INPUT_SET_L4_SCTP_DST_PORT},
- {"sctp-veri-tag", RTE_ETH_INPUT_SET_L4_SCTP_VERIFICATION_TAG},
- {"udp-key", RTE_ETH_INPUT_SET_TUNNEL_L4_UDP_KEY},
- {"gre-key", RTE_ETH_INPUT_SET_TUNNEL_GRE_KEY},
- {"fld-1st", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_1ST_WORD},
- {"fld-2nd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_2ND_WORD},
- {"fld-3rd", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_3RD_WORD},
- {"fld-4th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_4TH_WORD},
- {"fld-5th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_5TH_WORD},
- {"fld-6th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_6TH_WORD},
- {"fld-7th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_7TH_WORD},
- {"fld-8th", RTE_ETH_INPUT_SET_FLEX_PAYLOAD_8TH_WORD},
- {"none", RTE_ETH_INPUT_SET_NONE},
- };
-
- for (i = 0; i < RTE_DIM(inset_table); i++) {
- if (!strcmp(string, inset_table[i].str))
- return inset_table[i].inset;
- }
-
- return RTE_ETH_INPUT_SET_UNKNOWN;
-}
-
-/* Set flow director input set */
-struct cmd_set_fdir_input_set_result {
- cmdline_fixed_string_t set_fdir_input_set;
- portid_t port_id;
- cmdline_fixed_string_t flow_type;
- cmdline_fixed_string_t inset_field;
- cmdline_fixed_string_t select;
-};
-
-static void
-cmd_set_fdir_input_set_parsed(void *parsed_result,
- __rte_unused struct cmdline *cl,
- __rte_unused void *data)
-{
- struct cmd_set_fdir_input_set_result *res = parsed_result;
- struct rte_eth_fdir_filter_info info;
-
- memset(&info, 0, sizeof(info));
- info.info_type = RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT;
- info.info.input_set_conf.flow_type = str2flowtype(res->flow_type);
- info.info.input_set_conf.field[0] = str2inset(res->inset_field);
- info.info.input_set_conf.inset_size = 1;
- if (!strcmp(res->select, "select"))
- info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT;
- else if (!strcmp(res->select, "add"))
- info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD;
- rte_eth_dev_filter_ctrl(res->port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_SET, &info);
-}
-
-cmdline_parse_token_string_t cmd_set_fdir_input_set_cmd =
- TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
- set_fdir_input_set, "set_fdir_input_set");
-cmdline_parse_token_num_t cmd_set_fdir_input_set_port_id =
- TOKEN_NUM_INITIALIZER(struct cmd_set_fdir_input_set_result,
- port_id, UINT16);
-cmdline_parse_token_string_t cmd_set_fdir_input_set_flow_type =
- TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
- flow_type,
- "ipv4-frag#ipv4-tcp#ipv4-udp#ipv4-sctp#ipv4-other#"
- "ipv6-frag#ipv6-tcp#ipv6-udp#ipv6-sctp#ipv6-other#l2_payload");
-cmdline_parse_token_string_t cmd_set_fdir_input_set_field =
- TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
- inset_field,
- "ivlan#ethertype#src-ipv4#dst-ipv4#src-ipv6#dst-ipv6#"
- "ipv4-tos#ipv4-proto#ipv4-ttl#ipv6-tc#ipv6-next-header#"
- "ipv6-hop-limits#udp-src-port#udp-dst-port#"
- "tcp-src-port#tcp-dst-port#sctp-src-port#sctp-dst-port#"
- "sctp-veri-tag#none");
-cmdline_parse_token_string_t cmd_set_fdir_input_set_select =
- TOKEN_STRING_INITIALIZER(struct cmd_set_fdir_input_set_result,
- select, "select#add");
-
-cmdline_parse_inst_t cmd_set_fdir_input_set = {
- .f = cmd_set_fdir_input_set_parsed,
- .data = NULL,
- .help_str = "set_fdir_input_set <port_id> "
- "ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp|ipv4-other|"
- "ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other|l2_payload "
- "ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6|"
- "ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|ipv6-next-header|"
- "ipv6-hop-limits|udp-src-port|udp-dst-port|"
- "tcp-src-port|tcp-dst-port|sctp-src-port|sctp-dst-port|"
- "sctp-veri-tag|none select|add",
- .tokens = {
- (void *)&cmd_set_fdir_input_set_cmd,
- (void *)&cmd_set_fdir_input_set_port_id,
- (void *)&cmd_set_fdir_input_set_flow_type,
- (void *)&cmd_set_fdir_input_set_field,
- (void *)&cmd_set_fdir_input_set_select,
- NULL,
- },
-};
-
/* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */
struct cmd_mcast_addr_result {
cmdline_fixed_string_t mcast_addr_cmd;
(cmdline_parse_inst_t *)&cmd_config_rss_hash_key,
(cmdline_parse_inst_t *)&cmd_dump,
(cmdline_parse_inst_t *)&cmd_dump_one,
- (cmdline_parse_inst_t *)&cmd_add_del_ip_flow_director,
- (cmdline_parse_inst_t *)&cmd_add_del_udp_flow_director,
- (cmdline_parse_inst_t *)&cmd_add_del_sctp_flow_director,
- (cmdline_parse_inst_t *)&cmd_add_del_l2_flow_director,
- (cmdline_parse_inst_t *)&cmd_add_del_mac_vlan_flow_director,
- (cmdline_parse_inst_t *)&cmd_add_del_tunnel_flow_director,
+#ifdef RTE_NET_I40E
(cmdline_parse_inst_t *)&cmd_add_del_raw_flow_director,
- (cmdline_parse_inst_t *)&cmd_flush_flow_director,
+#endif
(cmdline_parse_inst_t *)&cmd_set_flow_director_ip_mask,
(cmdline_parse_inst_t *)&cmd_set_flow_director_mac_vlan_mask,
(cmdline_parse_inst_t *)&cmd_set_flow_director_tunnel_mask,
(cmdline_parse_inst_t *)&cmd_set_flow_director_flex_mask,
(cmdline_parse_inst_t *)&cmd_set_flow_director_flex_payload,
- (cmdline_parse_inst_t *)&cmd_set_fdir_input_set,
(cmdline_parse_inst_t *)&cmd_flow,
(cmdline_parse_inst_t *)&cmd_show_port_meter_cap,
(cmdline_parse_inst_t *)&cmd_add_port_meter_profile_srtcm,
return NULL;
}
+#if defined(RTE_NET_I40E) || defined(RTE_NET_IXGBE)
+
static inline void
print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
{
get_fdir_info(portid_t port_id, struct rte_eth_fdir_info *fdir_info,
struct rte_eth_fdir_stats *fdir_stat)
{
- int ret;
-
- ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
- if (!ret) {
- rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_INFO, fdir_info);
- rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
- RTE_ETH_FILTER_STATS, fdir_stat);
- return 0;
- }
+ int ret = -ENOTSUP;
#ifdef RTE_NET_I40E
if (ret == -ENOTSUP) {
fdir_stats_border, fdir_stats_border);
}
+#endif /* RTE_NET_I40E || RTE_NET_IXGBE */
+
void
fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg)
{
int port_is_stopped(portid_t port_id);
int port_is_started(portid_t port_id);
void pmd_test_exit(void);
+#if defined(RTE_NET_I40E) || defined(RTE_NET_IXGBE)
void fdir_get_infos(portid_t port_id);
+#endif
void fdir_set_flex_mask(portid_t port_id,
struct rte_eth_fdir_flex_mask *cfg);
void fdir_set_flex_payload(portid_t port_id,
.. code-block:: console
- testpmd> flow_director_filter 0 mode IP add flow ipv4-udp \
- src 2.2.2.3 32 dst 2.2.2.5 32 vlan 0 flexbytes () \
- fwd pf queue 1 fd_id 1
+ testpmd> flow create 0 ingress pattern eth / ipv4 src is 2.2.2.3 \
+ dst is 2.2.2.5 / udp src is 32 dst is 32 / end \
+ actions mark id 1 / queue index 1 / end
Check the flow director status:
f_add: 0 f_remove: 0
-Delete all flow director rules on a port:
-
-.. code-block:: console
-
- testpmd> flush_flow_director 0
-
Floating VEB
~~~~~~~~~~~~~
* ethdev: the legacy filter API, including
- ``rte_eth_dev_filter_supported()``, ``rte_eth_dev_filter_ctrl()`` as well
- as filter types FDIR, is superseded by the generic flow API (rte_flow) in
+ ``rte_eth_dev_filter_supported()``, ``rte_eth_dev_filter_ctrl()``
+ is superseded by the generic flow API (rte_flow) in
PMDs that implement the latter.
The legacy API will be removed in DPDK 20.11.
.. _testpmd_flow_director:
-flow_director_filter
-~~~~~~~~~~~~~~~~~~~~
-
-The Flow Director works in receive mode to identify specific flows or sets of flows and route them to specific queues.
-
-Four types of filtering are supported which are referred to as Perfect Match, Signature, Perfect-mac-vlan and
-Perfect-tunnel filters, the match mode is set by the ``--pkt-filter-mode`` command-line parameter:
-
-* Perfect match filters.
- The hardware checks a match between the masked fields of the received packets and the programmed filters.
- The masked fields are for IP flow.
-
-* Signature filters.
- The hardware checks a match between a hash-based signature of the masked fields of the received packet.
-
-* Perfect-mac-vlan match filters.
- The hardware checks a match between the masked fields of the received packets and the programmed filters.
- The masked fields are for MAC VLAN flow.
-
-* Perfect-tunnel match filters.
- The hardware checks a match between the masked fields of the received packets and the programmed filters.
- The masked fields are for tunnel flow.
-
-* Perfect-raw-flow-type match filters.
- The hardware checks a match between the masked fields of the received packets and pre-loaded raw (template) packet.
- The masked fields are specified by input sets.
-
-The Flow Director filters can match the different fields for different type of packet: flow type, specific input set
-per flow type and the flexible payload.
-
-The Flow Director can also mask out parts of all of these fields so that filters
-are only applied to certain fields or parts of the fields.
-
-Note that for raw flow type mode the source and destination fields in the
-raw packet buffer need to be presented in a reversed order with respect
-to the expected received packets.
-For example: IP source and destination addresses or TCP/UDP/SCTP
-source and destination ports
-
-Different NICs may have different capabilities, command show port fdir (port_id) can be used to acquire the information.
-
-# Commands to add flow director filters of different flow types::
-
- flow_director_filter (port_id) mode IP (add|del|update) \
- flow (ipv4-other|ipv4-frag|ipv6-other|ipv6-frag) \
- src (src_ip_address) dst (dst_ip_address) \
- tos (tos_value) proto (proto_value) ttl (ttl_value) \
- vlan (vlan_value) flexbytes (flexbytes_value) \
- (drop|fwd) pf|vf(vf_id) queue (queue_id) \
- fd_id (fd_id_value)
-
- flow_director_filter (port_id) mode IP (add|del|update) \
- flow (ipv4-tcp|ipv4-udp|ipv6-tcp|ipv6-udp) \
- src (src_ip_address) (src_port) \
- dst (dst_ip_address) (dst_port) \
- tos (tos_value) ttl (ttl_value) \
- vlan (vlan_value) flexbytes (flexbytes_value) \
- (drop|fwd) queue pf|vf(vf_id) (queue_id) \
- fd_id (fd_id_value)
-
- flow_director_filter (port_id) mode IP (add|del|update) \
- flow (ipv4-sctp|ipv6-sctp) \
- src (src_ip_address) (src_port) \
- dst (dst_ip_address) (dst_port) \
- tos (tos_value) ttl (ttl_value) \
- tag (verification_tag) vlan (vlan_value) \
- flexbytes (flexbytes_value) (drop|fwd) \
- pf|vf(vf_id) queue (queue_id) fd_id (fd_id_value)
-
- flow_director_filter (port_id) mode IP (add|del|update) flow l2_payload \
- ether (ethertype) flexbytes (flexbytes_value) \
- (drop|fwd) pf|vf(vf_id) queue (queue_id)
- fd_id (fd_id_value)
-
- flow_director_filter (port_id) mode MAC-VLAN (add|del|update) \
- mac (mac_address) vlan (vlan_value) \
- flexbytes (flexbytes_value) (drop|fwd) \
- queue (queue_id) fd_id (fd_id_value)
-
- flow_director_filter (port_id) mode Tunnel (add|del|update) \
- mac (mac_address) vlan (vlan_value) \
- tunnel (NVGRE|VxLAN) tunnel-id (tunnel_id_value) \
- flexbytes (flexbytes_value) (drop|fwd) \
- queue (queue_id) fd_id (fd_id_value)
-
- flow_director_filter (port_id) mode raw (add|del|update) flow (flow_id) \
- (drop|fwd) queue (queue_id) fd_id (fd_id_value) \
- packet (packet file name)
-
-For example, to add an ipv4-udp flow type filter::
-
- testpmd> flow_director_filter 0 mode IP add flow ipv4-udp src 2.2.2.3 32 \
- dst 2.2.2.5 33 tos 2 ttl 40 vlan 0x1 flexbytes (0x88,0x48) \
- fwd pf queue 1 fd_id 1
-
-For example, add an ipv4-other flow type filter::
-
- testpmd> flow_director_filter 0 mode IP add flow ipv4-other src 2.2.2.3 \
- dst 2.2.2.5 tos 2 proto 20 ttl 40 vlan 0x1 \
- flexbytes (0x88,0x48) fwd pf queue 1 fd_id 1
-
-flush_flow_director
-~~~~~~~~~~~~~~~~~~~
-
-Flush all flow director filters on a device::
-
- testpmd> flush_flow_director (port_id)
-
-Example, to flush all flow director filter on port 0::
-
- testpmd> flush_flow_director 0
-
flow_director_mask
~~~~~~~~~~~~~~~~~~
testpmd> flow_director_flex_payload 0 l4 \
(4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)
-set_fdir_input_set
-~~~~~~~~~~~~~~~~~~
-
-The Flow Director filters can match the different fields for different type of packet, i.e. specific input set
-on per flow type and the flexible payload. This command can be used to change input set for each flow type.
-
-Set the input set for flow director::
-
- set_fdir_input_set (port_id) (ipv4-frag|ipv4-tcp|ipv4-udp|ipv4-sctp| \
- ipv4-other|ipv6|ipv6-frag|ipv6-tcp|ipv6-udp|ipv6-sctp|ipv6-other| \
- l2_payload|<flow_id>) (ivlan|ethertype|src-ipv4|dst-ipv4|src-ipv6|dst-ipv6| \
- ipv4-tos|ipv4-proto|ipv4-ttl|ipv6-tc|ipv6-next-header|ipv6-hop-limits| \
- tudp-src-port|udp-dst-port|cp-src-port|tcp-dst-port|sctp-src-port| \
- sctp-dst-port|sctp-veri-tag|none) (select|add)
-
-For example to add source IP to FD input set for flow type of ipv4-udp on port 0::
-
- testpmd> set_fdir_input_set 0 ipv4-udp src-ipv4 add
-
.. _testpmd_rte_flow:
return RTE_ETH_TX_DESC_FULL;
}
-static int
-bnxt_parse_fdir_filter(struct bnxt *bp,
- struct rte_eth_fdir_filter *fdir,
- struct bnxt_filter_info *filter)
-{
- enum rte_fdir_mode fdir_mode =
- bp->eth_dev->data->dev_conf.fdir_conf.mode;
- struct bnxt_vnic_info *vnic0, *vnic;
- struct bnxt_filter_info *filter1;
- uint32_t en = 0;
- int i;
-
- if (fdir_mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
- return -EINVAL;
-
- filter->l2_ovlan = fdir->input.flow_ext.vlan_tci;
- en |= EM_FLOW_ALLOC_INPUT_EN_OVLAN_VID;
-
- switch (fdir->input.flow_type) {
- case RTE_ETH_FLOW_IPV4:
- case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
- /* FALLTHROUGH */
- filter->src_ipaddr[0] = fdir->input.flow.ip4_flow.src_ip;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR;
- filter->dst_ipaddr[0] = fdir->input.flow.ip4_flow.dst_ip;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR;
- filter->ip_protocol = fdir->input.flow.ip4_flow.proto;
- en |= NTUPLE_FLTR_ALLOC_IN_EN_IP_PROTO;
- filter->ip_addr_type =
- NTUPLE_FLTR_ALLOC_INPUT_IP_ADDR_TYPE_IPV4;
- filter->src_ipaddr_mask[0] = 0xffffffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
- filter->dst_ipaddr_mask[0] = 0xffffffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
- filter->ethertype = 0x800;
- filter->enables |= NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- filter->src_port = fdir->input.flow.tcp4_flow.src_port;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT;
- filter->dst_port = fdir->input.flow.tcp4_flow.dst_port;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT;
- filter->dst_port_mask = 0xffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT_MASK;
- filter->src_port_mask = 0xffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT_MASK;
- filter->src_ipaddr[0] = fdir->input.flow.tcp4_flow.ip.src_ip;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR;
- filter->dst_ipaddr[0] = fdir->input.flow.tcp4_flow.ip.dst_ip;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR;
- filter->ip_protocol = 6;
- en |= NTUPLE_FLTR_ALLOC_IN_EN_IP_PROTO;
- filter->ip_addr_type =
- NTUPLE_FLTR_ALLOC_INPUT_IP_ADDR_TYPE_IPV4;
- filter->src_ipaddr_mask[0] = 0xffffffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
- filter->dst_ipaddr_mask[0] = 0xffffffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
- filter->ethertype = 0x800;
- filter->enables |= NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- filter->src_port = fdir->input.flow.udp4_flow.src_port;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT;
- filter->dst_port = fdir->input.flow.udp4_flow.dst_port;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT;
- filter->dst_port_mask = 0xffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT_MASK;
- filter->src_port_mask = 0xffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT_MASK;
- filter->src_ipaddr[0] = fdir->input.flow.udp4_flow.ip.src_ip;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR;
- filter->dst_ipaddr[0] = fdir->input.flow.udp4_flow.ip.dst_ip;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR;
- filter->ip_protocol = 17;
- en |= NTUPLE_FLTR_ALLOC_IN_EN_IP_PROTO;
- filter->ip_addr_type =
- NTUPLE_FLTR_ALLOC_INPUT_IP_ADDR_TYPE_IPV4;
- filter->src_ipaddr_mask[0] = 0xffffffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
- filter->dst_ipaddr_mask[0] = 0xffffffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
- filter->ethertype = 0x800;
- filter->enables |= NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE;
- break;
- case RTE_ETH_FLOW_IPV6:
- case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
- /* FALLTHROUGH */
- filter->ip_addr_type =
- NTUPLE_FLTR_ALLOC_INPUT_IP_ADDR_TYPE_IPV6;
- filter->ip_protocol = fdir->input.flow.ipv6_flow.proto;
- en |= NTUPLE_FLTR_ALLOC_IN_EN_IP_PROTO;
- rte_memcpy(filter->src_ipaddr,
- fdir->input.flow.ipv6_flow.src_ip, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR;
- rte_memcpy(filter->dst_ipaddr,
- fdir->input.flow.ipv6_flow.dst_ip, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR;
- memset(filter->dst_ipaddr_mask, 0xff, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
- memset(filter->src_ipaddr_mask, 0xff, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
- filter->ethertype = 0x86dd;
- filter->enables |= NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- filter->src_port = fdir->input.flow.tcp6_flow.src_port;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT;
- filter->dst_port = fdir->input.flow.tcp6_flow.dst_port;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT;
- filter->dst_port_mask = 0xffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT_MASK;
- filter->src_port_mask = 0xffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT_MASK;
- filter->ip_addr_type =
- NTUPLE_FLTR_ALLOC_INPUT_IP_ADDR_TYPE_IPV6;
- filter->ip_protocol = fdir->input.flow.tcp6_flow.ip.proto;
- en |= NTUPLE_FLTR_ALLOC_IN_EN_IP_PROTO;
- rte_memcpy(filter->src_ipaddr,
- fdir->input.flow.tcp6_flow.ip.src_ip, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR;
- rte_memcpy(filter->dst_ipaddr,
- fdir->input.flow.tcp6_flow.ip.dst_ip, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR;
- memset(filter->dst_ipaddr_mask, 0xff, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
- memset(filter->src_ipaddr_mask, 0xff, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
- filter->ethertype = 0x86dd;
- filter->enables |= NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- filter->src_port = fdir->input.flow.udp6_flow.src_port;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT;
- filter->dst_port = fdir->input.flow.udp6_flow.dst_port;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT;
- filter->dst_port_mask = 0xffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_PORT_MASK;
- filter->src_port_mask = 0xffff;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_PORT_MASK;
- filter->ip_addr_type =
- NTUPLE_FLTR_ALLOC_INPUT_IP_ADDR_TYPE_IPV6;
- filter->ip_protocol = fdir->input.flow.udp6_flow.ip.proto;
- en |= NTUPLE_FLTR_ALLOC_IN_EN_IP_PROTO;
- rte_memcpy(filter->src_ipaddr,
- fdir->input.flow.udp6_flow.ip.src_ip, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR;
- rte_memcpy(filter->dst_ipaddr,
- fdir->input.flow.udp6_flow.ip.dst_ip, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR;
- memset(filter->dst_ipaddr_mask, 0xff, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_IPADDR_MASK;
- memset(filter->src_ipaddr_mask, 0xff, 16);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_SRC_IPADDR_MASK;
- filter->ethertype = 0x86dd;
- filter->enables |= NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE;
- break;
- case RTE_ETH_FLOW_L2_PAYLOAD:
- filter->ethertype = fdir->input.flow.l2_flow.ether_type;
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_ETHERTYPE;
- break;
- case RTE_ETH_FLOW_VXLAN:
- if (fdir->action.behavior == RTE_ETH_FDIR_REJECT)
- return -EINVAL;
- filter->vni = fdir->input.flow.tunnel_flow.tunnel_id;
- filter->tunnel_type =
- CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_VXLAN;
- en |= HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_TUNNEL_TYPE;
- break;
- case RTE_ETH_FLOW_NVGRE:
- if (fdir->action.behavior == RTE_ETH_FDIR_REJECT)
- return -EINVAL;
- filter->vni = fdir->input.flow.tunnel_flow.tunnel_id;
- filter->tunnel_type =
- CFA_NTUPLE_FILTER_ALLOC_REQ_TUNNEL_TYPE_NVGRE;
- en |= HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_TUNNEL_TYPE;
- break;
- case RTE_ETH_FLOW_UNKNOWN:
- case RTE_ETH_FLOW_RAW:
- case RTE_ETH_FLOW_FRAG_IPV4:
- case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
- case RTE_ETH_FLOW_FRAG_IPV6:
- case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
- case RTE_ETH_FLOW_IPV6_EX:
- case RTE_ETH_FLOW_IPV6_TCP_EX:
- case RTE_ETH_FLOW_IPV6_UDP_EX:
- case RTE_ETH_FLOW_GENEVE:
- /* FALLTHROUGH */
- default:
- return -EINVAL;
- }
-
- vnic0 = BNXT_GET_DEFAULT_VNIC(bp);
- vnic = &bp->vnic_info[fdir->action.rx_queue];
- if (vnic == NULL) {
- PMD_DRV_LOG(ERR, "Invalid queue %d\n", fdir->action.rx_queue);
- return -EINVAL;
- }
-
- if (fdir_mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
- rte_memcpy(filter->dst_macaddr,
- fdir->input.flow.mac_vlan_flow.mac_addr.addr_bytes, 6);
- en |= NTUPLE_FLTR_ALLOC_INPUT_EN_DST_MACADDR;
- }
-
- if (fdir->action.behavior == RTE_ETH_FDIR_REJECT) {
- filter->flags = HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_FLAGS_DROP;
- filter1 = STAILQ_FIRST(&vnic0->filter);
- //filter1 = bnxt_get_l2_filter(bp, filter, vnic0);
- } else {
- filter->dst_id = vnic->fw_vnic_id;
- for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
- if (filter->dst_macaddr[i] == 0x00)
- filter1 = STAILQ_FIRST(&vnic0->filter);
- else
- filter1 = bnxt_get_l2_filter(bp, filter, vnic);
- }
-
- if (filter1 == NULL)
- return -EINVAL;
-
- en |= HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID;
- filter->fw_l2_filter_id = filter1->fw_l2_filter_id;
-
- filter->enables = en;
-
- return 0;
-}
-
-static struct bnxt_filter_info *
-bnxt_match_fdir(struct bnxt *bp, struct bnxt_filter_info *nf,
- struct bnxt_vnic_info **mvnic)
-{
- struct bnxt_filter_info *mf = NULL;
- int i;
-
- for (i = bp->nr_vnics - 1; i >= 0; i--) {
- struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
-
- STAILQ_FOREACH(mf, &vnic->filter, next) {
- if (mf->filter_type == nf->filter_type &&
- mf->flags == nf->flags &&
- mf->src_port == nf->src_port &&
- mf->src_port_mask == nf->src_port_mask &&
- mf->dst_port == nf->dst_port &&
- mf->dst_port_mask == nf->dst_port_mask &&
- mf->ip_protocol == nf->ip_protocol &&
- mf->ip_addr_type == nf->ip_addr_type &&
- mf->ethertype == nf->ethertype &&
- mf->vni == nf->vni &&
- mf->tunnel_type == nf->tunnel_type &&
- mf->l2_ovlan == nf->l2_ovlan &&
- mf->l2_ovlan_mask == nf->l2_ovlan_mask &&
- mf->l2_ivlan == nf->l2_ivlan &&
- mf->l2_ivlan_mask == nf->l2_ivlan_mask &&
- !memcmp(mf->l2_addr, nf->l2_addr,
- RTE_ETHER_ADDR_LEN) &&
- !memcmp(mf->l2_addr_mask, nf->l2_addr_mask,
- RTE_ETHER_ADDR_LEN) &&
- !memcmp(mf->src_macaddr, nf->src_macaddr,
- RTE_ETHER_ADDR_LEN) &&
- !memcmp(mf->dst_macaddr, nf->dst_macaddr,
- RTE_ETHER_ADDR_LEN) &&
- !memcmp(mf->src_ipaddr, nf->src_ipaddr,
- sizeof(nf->src_ipaddr)) &&
- !memcmp(mf->src_ipaddr_mask, nf->src_ipaddr_mask,
- sizeof(nf->src_ipaddr_mask)) &&
- !memcmp(mf->dst_ipaddr, nf->dst_ipaddr,
- sizeof(nf->dst_ipaddr)) &&
- !memcmp(mf->dst_ipaddr_mask, nf->dst_ipaddr_mask,
- sizeof(nf->dst_ipaddr_mask))) {
- if (mvnic)
- *mvnic = vnic;
- return mf;
- }
- }
- }
- return NULL;
-}
-
-static int
-bnxt_fdir_filter(struct rte_eth_dev *dev,
- enum rte_filter_op filter_op,
- void *arg)
-{
- struct bnxt *bp = dev->data->dev_private;
- struct rte_eth_fdir_filter *fdir = (struct rte_eth_fdir_filter *)arg;
- struct bnxt_filter_info *filter, *match;
- struct bnxt_vnic_info *vnic, *mvnic;
- int ret = 0, i;
-
- if (filter_op == RTE_ETH_FILTER_NOP)
- return 0;
-
- if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
- return -EINVAL;
-
- switch (filter_op) {
- case RTE_ETH_FILTER_ADD:
- case RTE_ETH_FILTER_DELETE:
- /* FALLTHROUGH */
- filter = bnxt_get_unused_filter(bp);
- if (filter == NULL) {
- PMD_DRV_LOG(ERR,
- "Not enough resources for a new flow.\n");
- return -ENOMEM;
- }
-
- ret = bnxt_parse_fdir_filter(bp, fdir, filter);
- if (ret != 0)
- goto free_filter;
- filter->filter_type = HWRM_CFA_NTUPLE_FILTER;
-
- if (fdir->action.behavior == RTE_ETH_FDIR_REJECT)
- vnic = &bp->vnic_info[0];
- else
- vnic = &bp->vnic_info[fdir->action.rx_queue];
-
- match = bnxt_match_fdir(bp, filter, &mvnic);
- if (match != NULL && filter_op == RTE_ETH_FILTER_ADD) {
- if (match->dst_id == vnic->fw_vnic_id) {
- PMD_DRV_LOG(ERR, "Flow already exists.\n");
- ret = -EEXIST;
- goto free_filter;
- } else {
- match->dst_id = vnic->fw_vnic_id;
- ret = bnxt_hwrm_set_ntuple_filter(bp,
- match->dst_id,
- match);
- STAILQ_REMOVE(&mvnic->filter, match,
- bnxt_filter_info, next);
- STAILQ_INSERT_TAIL(&vnic->filter, match, next);
- PMD_DRV_LOG(ERR,
- "Filter with matching pattern exist\n");
- PMD_DRV_LOG(ERR,
- "Updated it to new destination q\n");
- goto free_filter;
- }
- }
- if (match == NULL && filter_op == RTE_ETH_FILTER_DELETE) {
- PMD_DRV_LOG(ERR, "Flow does not exist.\n");
- ret = -ENOENT;
- goto free_filter;
- }
-
- if (filter_op == RTE_ETH_FILTER_ADD) {
- ret = bnxt_hwrm_set_ntuple_filter(bp,
- filter->dst_id,
- filter);
- if (ret)
- goto free_filter;
- STAILQ_INSERT_TAIL(&vnic->filter, filter, next);
- } else {
- ret = bnxt_hwrm_clear_ntuple_filter(bp, match);
- STAILQ_REMOVE(&vnic->filter, match,
- bnxt_filter_info, next);
- bnxt_free_filter(bp, match);
- bnxt_free_filter(bp, filter);
- }
- break;
- case RTE_ETH_FILTER_FLUSH:
- for (i = bp->nr_vnics - 1; i >= 0; i--) {
- struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
-
- STAILQ_FOREACH(filter, &vnic->filter, next) {
- if (filter->filter_type ==
- HWRM_CFA_NTUPLE_FILTER) {
- ret =
- bnxt_hwrm_clear_ntuple_filter(bp,
- filter);
- STAILQ_REMOVE(&vnic->filter, filter,
- bnxt_filter_info, next);
- }
- }
- }
- return ret;
- case RTE_ETH_FILTER_UPDATE:
- case RTE_ETH_FILTER_STATS:
- case RTE_ETH_FILTER_INFO:
- PMD_DRV_LOG(ERR, "operation %u not implemented", filter_op);
- break;
- default:
- PMD_DRV_LOG(ERR, "unknown operation %u", filter_op);
- ret = -EINVAL;
- break;
- }
- return ret;
-
-free_filter:
- bnxt_free_filter(bp, filter);
- return ret;
-}
-
int
bnxt_filter_ctrl_op(struct rte_eth_dev *dev,
enum rte_filter_type filter_type,
return ret;
switch (filter_type) {
- case RTE_ETH_FILTER_FDIR:
- ret = bnxt_fdir_filter(dev, filter_op, arg);
- break;
case RTE_ETH_FILTER_GENERIC:
if (filter_op != RTE_ETH_FILTER_GET)
return -EINVAL;
}
int dev_is_enic(struct rte_eth_dev *dev);
-void enic_fdir_stats_get(struct enic *enic,
- struct rte_eth_fdir_stats *stats);
-int enic_fdir_add_fltr(struct enic *enic,
- struct rte_eth_fdir_filter *params);
-int enic_fdir_del_fltr(struct enic *enic,
- struct rte_eth_fdir_filter *params);
void enic_free_wq(void *txq);
int enic_alloc_intr_resources(struct enic *enic);
int enic_setup_finish(struct enic *enic);
void enic_pick_rx_handler(struct rte_eth_dev *eth_dev);
void enic_pick_tx_handler(struct rte_eth_dev *eth_dev);
void enic_fdir_info(struct enic *enic);
-void enic_fdir_info_get(struct enic *enic, struct rte_eth_fdir_info *stats);
int enic_vf_representor_init(struct rte_eth_dev *eth_dev, void *init_params);
int enic_vf_representor_uninit(struct rte_eth_dev *ethdev);
int enic_fm_allocate_switch_domain(struct enic *pf);
const struct rte_eth_fdir_input *input,
const struct rte_eth_fdir_masks *masks);
-void enic_fdir_stats_get(struct enic *enic, struct rte_eth_fdir_stats *stats)
-{
- *stats = enic->fdir.stats;
-}
-
-void enic_fdir_info_get(struct enic *enic, struct rte_eth_fdir_info *info)
-{
- info->mode = (enum rte_fdir_mode)enic->fdir.modes;
- info->flow_types_mask[0] = enic->fdir.types_mask;
-}
-
void enic_fdir_info(struct enic *enic)
{
enic->fdir.modes = (uint32_t)RTE_FDIR_MODE_PERFECT;
}
}
-int enic_fdir_del_fltr(struct enic *enic, struct rte_eth_fdir_filter *params)
-{
- int32_t pos;
- struct enic_fdir_node *key;
- /* See if the key is in the table */
- pos = rte_hash_del_key(enic->fdir.hash, params);
- switch (pos) {
- case -EINVAL:
- case -ENOENT:
- enic->fdir.stats.f_remove++;
- return -EINVAL;
- default:
- /* The entry is present in the table */
- key = enic->fdir.nodes[pos];
-
- /* Delete the filter */
- vnic_dev_classifier(enic->vdev, CLSF_DEL,
- &key->fltr_id, NULL, NULL);
- rte_free(key);
- enic->fdir.nodes[pos] = NULL;
- enic->fdir.stats.free++;
- enic->fdir.stats.remove++;
- break;
- }
- return 0;
-}
-
-int enic_fdir_add_fltr(struct enic *enic, struct rte_eth_fdir_filter *params)
-{
- struct enic_fdir_node *key;
- struct filter_v2 fltr;
- int32_t pos;
- uint8_t do_free = 0;
- uint16_t old_fltr_id = 0;
- uint32_t flowtype_supported;
- uint16_t flex_bytes;
- uint16_t queue;
- struct filter_action_v2 action;
-
- memset(&fltr, 0, sizeof(fltr));
- memset(&action, 0, sizeof(action));
- flowtype_supported = enic->fdir.types_mask
- & (1 << params->input.flow_type);
-
- flex_bytes = ((params->input.flow_ext.flexbytes[1] << 8 & 0xFF00) |
- (params->input.flow_ext.flexbytes[0] & 0xFF));
-
- if (!enic->fdir.hash ||
- (params->input.flow_ext.vlan_tci & 0xFFF) ||
- !flowtype_supported || flex_bytes ||
- params->action.behavior /* drop */) {
- enic->fdir.stats.f_add++;
- return -ENOTSUP;
- }
-
- /* Get the enicpmd RQ from the DPDK Rx queue */
- queue = enic_rte_rq_idx_to_sop_idx(params->action.rx_queue);
-
- if (!enic->rq[queue].in_use)
- return -EINVAL;
-
- /* See if the key is already there in the table */
- pos = rte_hash_del_key(enic->fdir.hash, params);
- switch (pos) {
- case -EINVAL:
- enic->fdir.stats.f_add++;
- return -EINVAL;
- case -ENOENT:
- /* Add a new classifier entry */
- if (!enic->fdir.stats.free) {
- enic->fdir.stats.f_add++;
- return -ENOSPC;
- }
- key = rte_zmalloc("enic_fdir_node",
- sizeof(struct enic_fdir_node), 0);
- if (!key) {
- enic->fdir.stats.f_add++;
- return -ENOMEM;
- }
- break;
- default:
- /* The entry is already present in the table.
- * Check if there is a change in queue
- */
- key = enic->fdir.nodes[pos];
- enic->fdir.nodes[pos] = NULL;
- if (unlikely(key->rq_index == queue)) {
- /* Nothing to be done */
- enic->fdir.stats.f_add++;
- pos = rte_hash_add_key(enic->fdir.hash, params);
- if (pos < 0) {
- dev_err(enic, "Add hash key failed\n");
- return pos;
- }
- enic->fdir.nodes[pos] = key;
- dev_warning(enic,
- "FDIR rule is already present\n");
- return 0;
- }
-
- if (likely(enic->fdir.stats.free)) {
- /* Add the filter and then delete the old one.
- * This is to avoid packets from going into the
- * default queue during the window between
- * delete and add
- */
- do_free = 1;
- old_fltr_id = key->fltr_id;
- } else {
- /* No free slots in the classifier.
- * Delete the filter and add the modified one later
- */
- vnic_dev_classifier(enic->vdev, CLSF_DEL,
- &key->fltr_id, NULL, NULL);
- enic->fdir.stats.free++;
- }
-
- break;
- }
-
- key->filter = *params;
- key->rq_index = queue;
-
- enic->fdir.copy_fltr_fn(&fltr, ¶ms->input,
- &enic->rte_dev->data->dev_conf.fdir_conf.mask);
- action.type = FILTER_ACTION_RQ_STEERING;
- action.rq_idx = queue;
-
- if (!vnic_dev_classifier(enic->vdev, CLSF_ADD, &queue, &fltr,
- &action)) {
- key->fltr_id = queue;
- } else {
- dev_err(enic, "Add classifier entry failed\n");
- enic->fdir.stats.f_add++;
- rte_free(key);
- return -1;
- }
-
- if (do_free)
- vnic_dev_classifier(enic->vdev, CLSF_DEL, &old_fltr_id, NULL,
- NULL);
- else{
- enic->fdir.stats.free--;
- enic->fdir.stats.add++;
- }
-
- pos = rte_hash_add_key(enic->fdir.hash, params);
- if (pos < 0) {
- enic->fdir.stats.f_add++;
- dev_err(enic, "Add hash key failed\n");
- return pos;
- }
-
- enic->fdir.nodes[pos] = key;
- return 0;
-}
-
void enic_clsf_destroy(struct enic *enic)
{
uint32_t index;
RTE_LOG_REGISTER(enic_pmd_logtype, pmd.net.enic, INFO);
-static int
-enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev,
- enum rte_filter_op filter_op, void *arg)
-{
- struct enic *enic = pmd_priv(eth_dev);
- int ret = 0;
-
- ENICPMD_FUNC_TRACE();
- if (filter_op == RTE_ETH_FILTER_NOP)
- return 0;
-
- if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
- return -EINVAL;
-
- switch (filter_op) {
- case RTE_ETH_FILTER_ADD:
- case RTE_ETH_FILTER_UPDATE:
- ret = enic_fdir_add_fltr(enic,
- (struct rte_eth_fdir_filter *)arg);
- break;
-
- case RTE_ETH_FILTER_DELETE:
- ret = enic_fdir_del_fltr(enic,
- (struct rte_eth_fdir_filter *)arg);
- break;
-
- case RTE_ETH_FILTER_STATS:
- enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg);
- break;
-
- case RTE_ETH_FILTER_FLUSH:
- dev_warning(enic, "unsupported operation %u", filter_op);
- ret = -ENOTSUP;
- break;
- case RTE_ETH_FILTER_INFO:
- enic_fdir_info_get(enic, (struct rte_eth_fdir_info *)arg);
- break;
- default:
- dev_err(enic, "unknown operation %u", filter_op);
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
static int
enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,
enum rte_filter_type filter_type,
else
*(const void **)arg = &enic_flow_ops;
break;
- case RTE_ETH_FILTER_FDIR:
- ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg);
- break;
default:
dev_warning(enic, "Filter type (%d) not supported",
filter_type);
return 0;
}
-int
-i40e_fdir_filter_inset_select(struct i40e_pf *pf,
- struct rte_eth_input_set_conf *conf)
-{
- struct i40e_hw *hw = I40E_PF_TO_HW(pf);
- enum i40e_filter_pctype pctype;
- uint64_t input_set, inset_reg = 0;
- uint32_t mask_reg[I40E_INSET_MASK_NUM_REG] = {0};
- int ret, i, num;
-
- if (!hw || !conf) {
- PMD_DRV_LOG(ERR, "Invalid pointer");
- return -EFAULT;
- }
- if (conf->op != RTE_ETH_INPUT_SET_SELECT &&
- conf->op != RTE_ETH_INPUT_SET_ADD) {
- PMD_DRV_LOG(ERR, "Unsupported input set operation");
- return -EINVAL;
- }
-
- pctype = i40e_flowtype_to_pctype(pf->adapter, conf->flow_type);
-
- if (pctype == I40E_FILTER_PCTYPE_INVALID) {
- PMD_DRV_LOG(ERR, "invalid flow_type input.");
- return -EINVAL;
- }
-
- ret = i40e_parse_input_set(&input_set, pctype, conf->field,
- conf->inset_size);
- if (ret) {
- PMD_DRV_LOG(ERR, "Failed to parse input set");
- return -EINVAL;
- }
-
- /* get inset value in register */
- inset_reg = i40e_read_rx_ctl(hw, I40E_PRTQF_FD_INSET(pctype, 1));
- inset_reg <<= I40E_32_BIT_WIDTH;
- inset_reg |= i40e_read_rx_ctl(hw, I40E_PRTQF_FD_INSET(pctype, 0));
-
- /* Can not change the inset reg for flex payload for fdir,
- * it is done by writing I40E_PRTQF_FD_FLXINSET
- * in i40e_set_flex_mask_on_pctype.
- */
- if (conf->op == RTE_ETH_INPUT_SET_SELECT)
- inset_reg &= I40E_REG_INSET_FLEX_PAYLOAD_WORDS;
- else
- input_set |= pf->fdir.input_set[pctype];
- num = i40e_generate_inset_mask_reg(input_set, mask_reg,
- I40E_INSET_MASK_NUM_REG);
- if (num < 0)
- return -EINVAL;
- if (pf->support_multi_driver && num > 0) {
- PMD_DRV_LOG(ERR, "FDIR bit mask is not supported.");
- return -ENOTSUP;
- }
-
- inset_reg |= i40e_translate_input_set_reg(hw->mac.type, input_set);
-
- i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 0),
- (uint32_t)(inset_reg & UINT32_MAX));
- i40e_check_write_reg(hw, I40E_PRTQF_FD_INSET(pctype, 1),
- (uint32_t)((inset_reg >>
- I40E_32_BIT_WIDTH) & UINT32_MAX));
-
- if (!pf->support_multi_driver) {
- for (i = 0; i < num; i++)
- i40e_check_write_global_reg(hw,
- I40E_GLQF_FD_MSK(i, pctype),
- mask_reg[i]);
- /*clear unused mask registers of the pctype */
- for (i = num; i < I40E_INSET_MASK_NUM_REG; i++)
- i40e_check_write_global_reg(hw,
- I40E_GLQF_FD_MSK(i, pctype),
- 0);
- } else {
- PMD_DRV_LOG(ERR, "FDIR bit mask is not supported.");
- }
- I40E_WRITE_FLUSH(hw);
-
- pf->fdir.input_set[pctype] = input_set;
- return 0;
-}
-
/* Convert ethertype filter structure */
static int
i40e_ethertype_filter_convert(const struct rte_eth_ethertype_filter *input,
return -EINVAL;
switch (filter_type) {
- case RTE_ETH_FILTER_FDIR:
- ret = i40e_fdir_ctrl_func(dev, filter_op, arg);
- break;
case RTE_ETH_FILTER_GENERIC:
if (filter_op != RTE_ETH_FILTER_GET)
return -EINVAL;
};
/* 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.
+ * It supports RTE_ETH_FILTER_FDIR data representation.
*/
struct i40e_fdir_filter_conf {
uint32_t soft_id;
struct rte_eth_fdir_info *fdir);
void i40e_fdir_stats_get(struct rte_eth_dev *dev,
struct rte_eth_fdir_stats *stat);
-int i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
- enum rte_filter_op filter_op,
- void *arg);
int i40e_select_filter_input_set(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf,
enum rte_filter_type filter);
void i40e_fdir_filter_restore(struct i40e_pf *pf);
int i40e_hash_filter_inset_select(struct i40e_hw *hw,
struct rte_eth_input_set_conf *conf);
-int i40e_fdir_filter_inset_select(struct i40e_pf *pf,
- struct rte_eth_input_set_conf *conf);
int i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf, uint32_t opcode,
uint32_t retval, uint8_t *msg,
uint16_t msglen);
int i40e_ethertype_filter_set(struct i40e_pf *pf,
struct rte_eth_ethertype_filter *filter,
bool add);
-int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *filter,
- bool add);
struct rte_flow *
i40e_fdir_entry_pool_get(struct i40e_fdir_info *fdir_info);
void i40e_fdir_entry_pool_put(struct i40e_fdir_info *fdir_info,
(1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \
(1ULL << RTE_ETH_FLOW_L2_PAYLOAD))
-static int i40e_fdir_filter_programming(struct i40e_pf *pf,
- enum i40e_filter_pctype pctype,
- const struct rte_eth_fdir_filter *filter,
- bool add);
static int i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input,
struct i40e_fdir_filter *filter);
static struct i40e_fdir_filter *
return ret;
}
-static inline int
-i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input,
- unsigned char *raw_pkt,
- bool vlan)
-{
- static uint8_t vlan_frame[] = {0x81, 0, 0, 0};
- uint16_t *ether_type;
- uint8_t len = 2 * sizeof(struct rte_ether_addr);
- struct rte_ipv4_hdr *ip;
- struct rte_ipv6_hdr *ip6;
- static const uint8_t next_proto[] = {
- [RTE_ETH_FLOW_FRAG_IPV4] = IPPROTO_IP,
- [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = IPPROTO_TCP,
- [RTE_ETH_FLOW_NONFRAG_IPV4_UDP] = IPPROTO_UDP,
- [RTE_ETH_FLOW_NONFRAG_IPV4_SCTP] = IPPROTO_SCTP,
- [RTE_ETH_FLOW_NONFRAG_IPV4_OTHER] = IPPROTO_IP,
- [RTE_ETH_FLOW_FRAG_IPV6] = IPPROTO_NONE,
- [RTE_ETH_FLOW_NONFRAG_IPV6_TCP] = IPPROTO_TCP,
- [RTE_ETH_FLOW_NONFRAG_IPV6_UDP] = IPPROTO_UDP,
- [RTE_ETH_FLOW_NONFRAG_IPV6_SCTP] = IPPROTO_SCTP,
- [RTE_ETH_FLOW_NONFRAG_IPV6_OTHER] = IPPROTO_NONE,
- };
-
- 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),
- &fdir_input->flow_ext.vlan_tci,
- sizeof(uint16_t));
- raw_pkt += sizeof(vlan_frame);
- len += sizeof(vlan_frame);
- }
- ether_type = (uint16_t *)raw_pkt;
- raw_pkt += sizeof(uint16_t);
- len += sizeof(uint16_t);
-
- switch (fdir_input->flow_type) {
- case RTE_ETH_FLOW_L2_PAYLOAD:
- *ether_type = fdir_input->flow.l2_flow.ether_type;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
- case RTE_ETH_FLOW_FRAG_IPV4:
- ip = (struct rte_ipv4_hdr *)raw_pkt;
-
- *ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
- ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
- /* set len to by default */
- ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
- ip->next_proto_id = fdir_input->flow.ip4_flow.proto ?
- fdir_input->flow.ip4_flow.proto :
- next_proto[fdir_input->flow_type];
- ip->time_to_live = fdir_input->flow.ip4_flow.ttl ?
- fdir_input->flow.ip4_flow.ttl :
- I40E_FDIR_IP_DEFAULT_TTL;
- ip->type_of_service = fdir_input->flow.ip4_flow.tos;
- /*
- * The source and destination fields in the transmitted packet
- * need to be presented in a reversed order with respect
- * to the expected received packets.
- */
- ip->src_addr = fdir_input->flow.ip4_flow.dst_ip;
- ip->dst_addr = fdir_input->flow.ip4_flow.src_ip;
- len += sizeof(struct rte_ipv4_hdr);
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
- case RTE_ETH_FLOW_FRAG_IPV6:
- ip6 = (struct rte_ipv6_hdr *)raw_pkt;
-
- *ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
- ip6->vtc_flow =
- rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW |
- (fdir_input->flow.ipv6_flow.tc <<
- I40E_FDIR_IPv6_TC_OFFSET));
- ip6->payload_len =
- rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
- ip6->proto = fdir_input->flow.ipv6_flow.proto ?
- fdir_input->flow.ipv6_flow.proto :
- next_proto[fdir_input->flow_type];
- ip6->hop_limits = fdir_input->flow.ipv6_flow.hop_limits ?
- fdir_input->flow.ipv6_flow.hop_limits :
- I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
- /*
- * The source and destination fields in the transmitted packet
- * need to be presented in a reversed order with respect
- * to the expected received packets.
- */
- rte_memcpy(&(ip6->src_addr),
- &(fdir_input->flow.ipv6_flow.dst_ip),
- IPV6_ADDR_LEN);
- rte_memcpy(&(ip6->dst_addr),
- &(fdir_input->flow.ipv6_flow.src_ip),
- IPV6_ADDR_LEN);
- len += sizeof(struct rte_ipv6_hdr);
- break;
- default:
- PMD_DRV_LOG(ERR, "unknown flow type %u.",
- fdir_input->flow_type);
- return -1;
- }
- return len;
-}
-
-
-/*
- * i40e_fdir_construct_pkt - construct packet based on fields in input
- * @pf: board private structure
- * @fdir_input: input set of the flow director entry
- * @raw_pkt: a packet to be constructed
- */
-static int
-i40e_fdir_construct_pkt(struct i40e_pf *pf,
- const struct rte_eth_fdir_input *fdir_input,
- unsigned char *raw_pkt)
-{
- unsigned char *payload, *ptr;
- struct rte_udp_hdr *udp;
- struct rte_tcp_hdr *tcp;
- struct rte_sctp_hdr *sctp;
- uint8_t size, dst = 0;
- uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/
- int len;
-
- /* fill the ethernet and IP head */
- len = i40e_fdir_fill_eth_ip_head(fdir_input, raw_pkt,
- !!fdir_input->flow_ext.vlan_tci);
- if (len < 0)
- return -EINVAL;
-
- /* fill the L4 head */
- switch (fdir_input->flow_type) {
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- udp = (struct rte_udp_hdr *)(raw_pkt + len);
- payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr);
- /*
- * The source and destination fields in the transmitted packet
- * need to be presented in a reversed order with respect
- * to the expected received packets.
- */
- udp->src_port = fdir_input->flow.udp4_flow.dst_port;
- udp->dst_port = fdir_input->flow.udp4_flow.src_port;
- udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
- break;
-
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- tcp = (struct rte_tcp_hdr *)(raw_pkt + len);
- payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr);
- /*
- * The source and destination fields in the transmitted packet
- * need to be presented in a reversed order with respect
- * to the expected received packets.
- */
- tcp->src_port = fdir_input->flow.tcp4_flow.dst_port;
- tcp->dst_port = fdir_input->flow.tcp4_flow.src_port;
- tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
- break;
-
- case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
- sctp = (struct rte_sctp_hdr *)(raw_pkt + len);
- payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr);
- /*
- * The source and destination fields in the transmitted packet
- * need to be presented in a reversed order with respect
- * to the expected received packets.
- */
- sctp->src_port = fdir_input->flow.sctp4_flow.dst_port;
- sctp->dst_port = fdir_input->flow.sctp4_flow.src_port;
- sctp->tag = fdir_input->flow.sctp4_flow.verify_tag;
- break;
-
- case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
- case RTE_ETH_FLOW_FRAG_IPV4:
- payload = raw_pkt + len;
- set_idx = I40E_FLXPLD_L3_IDX;
- break;
-
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- udp = (struct rte_udp_hdr *)(raw_pkt + len);
- payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr);
- /*
- * The source and destination fields in the transmitted packet
- * need to be presented in a reversed order with respect
- * to the expected received packets.
- */
- udp->src_port = fdir_input->flow.udp6_flow.dst_port;
- udp->dst_port = fdir_input->flow.udp6_flow.src_port;
- udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
- break;
-
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- tcp = (struct rte_tcp_hdr *)(raw_pkt + len);
- payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr);
- /*
- * The source and destination fields in the transmitted packet
- * need to be presented in a reversed order with respect
- * to the expected received packets.
- */
- tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
- tcp->src_port = fdir_input->flow.udp6_flow.dst_port;
- tcp->dst_port = fdir_input->flow.udp6_flow.src_port;
- break;
-
- case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
- sctp = (struct rte_sctp_hdr *)(raw_pkt + len);
- payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr);
- /*
- * The source and destination fields in the transmitted packet
- * need to be presented in a reversed order with respect
- * to the expected received packets.
- */
- sctp->src_port = fdir_input->flow.sctp6_flow.dst_port;
- sctp->dst_port = fdir_input->flow.sctp6_flow.src_port;
- sctp->tag = fdir_input->flow.sctp6_flow.verify_tag;
- break;
-
- case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
- case RTE_ETH_FLOW_FRAG_IPV6:
- payload = raw_pkt + len;
- set_idx = I40E_FLXPLD_L3_IDX;
- break;
- case RTE_ETH_FLOW_L2_PAYLOAD:
- payload = raw_pkt + len;
- /*
- * ARP packet is a special case on which the payload
- * starts after the whole ARP header
- */
- if (fdir_input->flow.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;
- break;
- default:
- PMD_DRV_LOG(ERR, "unknown flow type %u.", fdir_input->flow_type);
- return -EINVAL;
- }
-
- /* fill the flexbytes to payload */
- for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) {
- pit_idx = set_idx * I40E_MAX_FLXPLD_FIED + i;
- size = pf->fdir.flex_set[pit_idx].size;
- if (size == 0)
- continue;
- dst = pf->fdir.flex_set[pit_idx].dst_offset * sizeof(uint16_t);
- ptr = payload +
- pf->fdir.flex_set[pit_idx].src_offset * sizeof(uint16_t);
- rte_memcpy(ptr,
- &fdir_input->flow_ext.flexbytes[dst],
- size * sizeof(uint16_t));
- }
-
- return 0;
-}
static struct i40e_customized_pctype *
i40e_flow_fdir_find_customized_pctype(struct i40e_pf *pf, uint8_t pctype)
rte_bitmap_set(fdir_info->fdir_flow_pool.bitmap, f->idx);
}
-/*
- * i40e_add_del_fdir_filter - add or remove a flow director filter.
- * @pf: board private structure
- * @filter: fdir filter entry
- * @add: 0 - delete, 1 - add
- */
-int
-i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *filter,
- bool add)
-{
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt[0];
- enum i40e_filter_pctype pctype;
- int ret = 0;
-
- if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
- PMD_DRV_LOG(ERR, "FDIR is not enabled, please"
- " check the mode in fdir_conf.");
- return -ENOTSUP;
- }
-
- pctype = i40e_flowtype_to_pctype(pf->adapter, filter->input.flow_type);
- if (pctype == I40E_FILTER_PCTYPE_INVALID) {
- PMD_DRV_LOG(ERR, "invalid flow_type input.");
- return -EINVAL;
- }
- if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) {
- PMD_DRV_LOG(ERR, "Invalid queue ID");
- return -EINVAL;
- }
- if (filter->input.flow_ext.is_vf &&
- filter->input.flow_ext.dst_id >= pf->vf_num) {
- PMD_DRV_LOG(ERR, "Invalid VF ID");
- return -EINVAL;
- }
-
- memset(pkt, 0, I40E_FDIR_PKT_LEN);
-
- ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt);
- if (ret < 0) {
- PMD_DRV_LOG(ERR, "construct packet for fdir fails.");
- return ret;
- }
-
- if (hw->mac.type == I40E_MAC_X722) {
- /* get translated pctype value in fd pctype register */
- pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
- hw, I40E_GLQF_FD_PCTYPES((int)pctype));
- }
-
- ret = i40e_fdir_filter_programming(pf, pctype, filter, add);
- if (ret < 0) {
- PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).",
- pctype);
- return ret;
- }
-
- return ret;
-}
-
static inline unsigned char *
i40e_find_available_buffer(struct rte_eth_dev *dev)
{
return ret;
}
-/*
- * i40e_fdir_filter_programming - Program a flow director filter rule.
- * Is done by Flow Director Programming Descriptor followed by packet
- * structure that contains the filter fields need to match.
- * @pf: board private structure
- * @pctype: pctype
- * @filter: fdir filter entry
- * @add: 0 - delete, 1 - add
- */
-static int
-i40e_fdir_filter_programming(struct i40e_pf *pf,
- enum i40e_filter_pctype pctype,
- const struct rte_eth_fdir_filter *filter,
- bool add)
-{
- struct i40e_tx_queue *txq = pf->fdir.txq;
- struct i40e_rx_queue *rxq = pf->fdir.rxq;
- const struct rte_eth_fdir_action *fdir_action = &filter->action;
- volatile struct i40e_tx_desc *txdp;
- volatile struct i40e_filter_program_desc *fdirdp;
- uint32_t td_cmd;
- uint16_t vsi_id, i;
- uint8_t dest;
-
- PMD_DRV_LOG(INFO, "filling filter programming descriptor.");
- fdirdp = (volatile struct i40e_filter_program_desc *)
- (&(txq->tx_ring[txq->tx_tail]));
-
- fdirdp->qindex_flex_ptype_vsi =
- rte_cpu_to_le_32((fdir_action->rx_queue <<
- I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
- I40E_TXD_FLTR_QW0_QINDEX_MASK);
-
- fdirdp->qindex_flex_ptype_vsi |=
- rte_cpu_to_le_32((fdir_action->flex_off <<
- I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT) &
- I40E_TXD_FLTR_QW0_FLEXOFF_MASK);
-
- fdirdp->qindex_flex_ptype_vsi |=
- rte_cpu_to_le_32((pctype <<
- I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) &
- I40E_TXD_FLTR_QW0_PCTYPE_MASK);
-
- if (filter->input.flow_ext.is_vf)
- vsi_id = pf->vfs[filter->input.flow_ext.dst_id].vsi->vsi_id;
- else
- /* Use LAN VSI Id by default */
- vsi_id = pf->main_vsi->vsi_id;
- fdirdp->qindex_flex_ptype_vsi |=
- rte_cpu_to_le_32(((uint32_t)vsi_id <<
- I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
- I40E_TXD_FLTR_QW0_DEST_VSI_MASK);
-
- fdirdp->dtype_cmd_cntindex =
- rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG);
-
- if (add)
- fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
- I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE <<
- I40E_TXD_FLTR_QW1_PCMD_SHIFT);
- else
- fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
- I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE <<
- I40E_TXD_FLTR_QW1_PCMD_SHIFT);
-
- if (fdir_action->behavior == RTE_ETH_FDIR_REJECT)
- dest = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
- else if (fdir_action->behavior == RTE_ETH_FDIR_ACCEPT)
- dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
- else if (fdir_action->behavior == RTE_ETH_FDIR_PASSTHRU)
- dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER;
- else {
- PMD_DRV_LOG(ERR, "Failed to program FDIR filter:"
- " unsupported fdir behavior.");
- return -EINVAL;
- }
-
- fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((dest <<
- I40E_TXD_FLTR_QW1_DEST_SHIFT) &
- I40E_TXD_FLTR_QW1_DEST_MASK);
-
- fdirdp->dtype_cmd_cntindex |=
- rte_cpu_to_le_32((fdir_action->report_status<<
- I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT) &
- I40E_TXD_FLTR_QW1_FD_STATUS_MASK);
-
- fdirdp->dtype_cmd_cntindex |=
- rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK);
- fdirdp->dtype_cmd_cntindex |=
- rte_cpu_to_le_32(
- ((uint32_t)pf->fdir.match_counter_index <<
- I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
- I40E_TXD_FLTR_QW1_CNTINDEX_MASK);
-
- fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id);
-
- PMD_DRV_LOG(INFO, "filling transmit descriptor.");
- txdp = &(txq->tx_ring[txq->tx_tail + 1]);
- txdp->buffer_addr = rte_cpu_to_le_64(pf->fdir.dma_addr[0]);
- td_cmd = I40E_TX_DESC_CMD_EOP |
- I40E_TX_DESC_CMD_RS |
- I40E_TX_DESC_CMD_DUMMY;
-
- txdp->cmd_type_offset_bsz =
- i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0);
-
- txq->tx_tail += 2; /* set 2 descriptors above, fdirdp and txdp */
- if (txq->tx_tail >= txq->nb_tx_desc)
- txq->tx_tail = 0;
- /* Update the tx tail register */
- rte_wmb();
- I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail);
- for (i = 0; i < I40E_FDIR_MAX_WAIT_US; i++) {
- if ((txdp->cmd_type_offset_bsz &
- rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) ==
- rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
- break;
- rte_delay_us(1);
- }
- if (i >= I40E_FDIR_MAX_WAIT_US) {
- PMD_DRV_LOG(ERR, "Failed to program FDIR filter:"
- " time out to get DD on tx queue.");
- return -ETIMEDOUT;
- }
- /* totally delay 10 ms to check programming status*/
- for (; i < I40E_FDIR_MAX_WAIT_US; i++) {
- if (i40e_check_fdir_programming_status(rxq) >= 0)
- return 0;
- rte_delay_us(1);
- }
- PMD_DRV_LOG(ERR,
- "Failed to program FDIR filter: programming status reported.");
- return -ETIMEDOUT;
-}
-
/*
* i40e_flow_fdir_filter_programming - Program a flow director filter rule.
* Is done by Flow Director Programming Descriptor followed by packet
I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
}
-static int
-i40e_fdir_filter_set(struct rte_eth_dev *dev,
- struct rte_eth_fdir_filter_info *info)
-{
- struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- int ret = 0;
-
- if (!info) {
- PMD_DRV_LOG(ERR, "Invalid pointer");
- return -EFAULT;
- }
-
- switch (info->info_type) {
- case RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT:
- ret = i40e_fdir_filter_inset_select(pf,
- &(info->info.input_set_conf));
- break;
- default:
- PMD_DRV_LOG(ERR, "FD filter info type (%d) not supported",
- info->info_type);
- return -EINVAL;
- }
-
- return ret;
-}
-
-/*
- * i40e_fdir_ctrl_func - deal with all operations on flow director.
- * @pf: board private structure
- * @filter_op:operation will be taken.
- * @arg: a pointer to specific structure corresponding to the filter_op
- */
-int
-i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
- enum rte_filter_op filter_op,
- void *arg)
-{
- struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- int ret = 0;
-
- if ((pf->flags & I40E_FLAG_FDIR) == 0)
- return -ENOTSUP;
-
- if (filter_op == RTE_ETH_FILTER_NOP)
- return 0;
-
- if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
- return -EINVAL;
-
- switch (filter_op) {
- case RTE_ETH_FILTER_ADD:
- ret = i40e_add_del_fdir_filter(dev,
- (struct rte_eth_fdir_filter *)arg,
- TRUE);
- break;
- case RTE_ETH_FILTER_DELETE:
- ret = i40e_add_del_fdir_filter(dev,
- (struct rte_eth_fdir_filter *)arg,
- FALSE);
- break;
- case RTE_ETH_FILTER_FLUSH:
- ret = i40e_fdir_flush(dev);
- break;
- case RTE_ETH_FILTER_INFO:
- i40e_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg);
- break;
- case RTE_ETH_FILTER_SET:
- ret = i40e_fdir_filter_set(dev,
- (struct rte_eth_fdir_filter_info *)arg);
- break;
- case RTE_ETH_FILTER_STATS:
- i40e_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg);
- break;
- default:
- PMD_DRV_LOG(ERR, "unknown operation %u.", filter_op);
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
/* Restore flow director filter */
void
i40e_fdir_filter_restore(struct i40e_pf *pf)
}
static int
-ixgbe_dev_filter_ctrl(struct rte_eth_dev *dev,
+ixgbe_dev_filter_ctrl(__rte_unused struct rte_eth_dev *dev,
enum rte_filter_type filter_type,
enum rte_filter_op filter_op,
void *arg)
int ret = 0;
switch (filter_type) {
- case RTE_ETH_FILTER_FDIR:
- ret = ixgbe_fdir_ctrl_func(dev, filter_op, arg);
- break;
case RTE_ETH_FILTER_GENERIC:
if (filter_op != RTE_ETH_FILTER_GET)
return -EINVAL;
uint32_t ixgbe_convert_vm_rx_mask_to_val(uint16_t rx_mask, uint32_t orig_val);
-int ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev,
- enum rte_filter_op filter_op, void *arg);
void ixgbe_fdir_filter_restore(struct rte_eth_dev *dev);
int ixgbe_clear_all_fdir_filter(struct rte_eth_dev *dev);
static int ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev,
const struct rte_eth_fdir_flex_conf *conf, uint32_t *fdirctrl);
static int fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl);
-static int ixgbe_fdir_filter_to_atr_input(
- const struct rte_eth_fdir_filter *fdir_filter,
- union ixgbe_atr_input *input,
- enum rte_fdir_mode mode);
static uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
uint32_t key);
static uint32_t atr_compute_sig_hash_82599(union ixgbe_atr_input *input,
static int fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd,
uint32_t fdirhash);
-static int ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *fdir_filter,
- bool del,
- bool update);
static int ixgbe_fdir_flush(struct rte_eth_dev *dev);
/**
return 0;
}
-/*
- * Convert DPDK rte_eth_fdir_filter struct to ixgbe_atr_input union that is used
- * by the IXGBE driver code.
- */
-static int
-ixgbe_fdir_filter_to_atr_input(const struct rte_eth_fdir_filter *fdir_filter,
- union ixgbe_atr_input *input, enum rte_fdir_mode mode)
-{
- input->formatted.vlan_id = fdir_filter->input.flow_ext.vlan_tci;
- input->formatted.flex_bytes = (uint16_t)(
- (fdir_filter->input.flow_ext.flexbytes[1] << 8 & 0xFF00) |
- (fdir_filter->input.flow_ext.flexbytes[0] & 0xFF));
-
- switch (fdir_filter->input.flow_type) {
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
- input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
- input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV6;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV6;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
- input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV6;
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
- input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV6;
- break;
- default:
- break;
- }
-
- switch (fdir_filter->input.flow_type) {
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- input->formatted.src_port =
- fdir_filter->input.flow.udp4_flow.src_port;
- input->formatted.dst_port =
- fdir_filter->input.flow.udp4_flow.dst_port;
- /* fall-through */
- /*for SCTP flow type, port and verify_tag are meaningless in ixgbe.*/
- case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
- input->formatted.src_ip[0] =
- fdir_filter->input.flow.ip4_flow.src_ip;
- input->formatted.dst_ip[0] =
- fdir_filter->input.flow.ip4_flow.dst_ip;
- break;
-
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- input->formatted.src_port =
- fdir_filter->input.flow.udp6_flow.src_port;
- input->formatted.dst_port =
- fdir_filter->input.flow.udp6_flow.dst_port;
- /* fall-through */
- /*for SCTP flow type, port and verify_tag are meaningless in ixgbe.*/
- case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
- rte_memcpy(input->formatted.src_ip,
- fdir_filter->input.flow.ipv6_flow.src_ip,
- sizeof(input->formatted.src_ip));
- rte_memcpy(input->formatted.dst_ip,
- fdir_filter->input.flow.ipv6_flow.dst_ip,
- sizeof(input->formatted.dst_ip));
- break;
- default:
- break;
- }
-
- if (mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
- rte_memcpy(
- input->formatted.inner_mac,
- fdir_filter->input.flow.mac_vlan_flow.mac_addr.addr_bytes,
- sizeof(input->formatted.inner_mac));
- } else if (mode == RTE_FDIR_MODE_PERFECT_TUNNEL) {
- rte_memcpy(
- input->formatted.inner_mac,
- fdir_filter->input.flow.tunnel_flow.mac_addr.addr_bytes,
- sizeof(input->formatted.inner_mac));
- if (fdir_filter->input.flow.tunnel_flow.tunnel_type ==
- RTE_FDIR_TUNNEL_TYPE_VXLAN)
- input->formatted.tunnel_type =
- IXGBE_FDIR_VXLAN_TUNNEL_TYPE;
- else if (fdir_filter->input.flow.tunnel_flow.tunnel_type ==
- RTE_FDIR_TUNNEL_TYPE_NVGRE)
- input->formatted.tunnel_type =
- IXGBE_FDIR_NVGRE_TUNNEL_TYPE;
- else
- PMD_DRV_LOG(ERR, " invalid tunnel type arguments.");
-
- input->formatted.tni_vni =
- fdir_filter->input.flow.tunnel_flow.tunnel_id >> 8;
- }
-
- return 0;
-}
-
/*
* The below function is taken from the FreeBSD IXGBE drivers release
* 2.3.8. The only change is not to mask hash_result with IXGBE_ATR_HASH_MASK
return 0;
}
-static int
-ixgbe_interpret_fdir_filter(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *fdir_filter,
- struct ixgbe_fdir_rule *rule)
-{
- enum rte_fdir_mode fdir_mode = dev->data->dev_conf.fdir_conf.mode;
- int err;
-
- memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
-
- err = ixgbe_fdir_filter_to_atr_input(fdir_filter,
- &rule->ixgbe_fdir,
- fdir_mode);
- if (err)
- return err;
-
- rule->mode = fdir_mode;
- if (fdir_filter->action.behavior == RTE_ETH_FDIR_REJECT)
- rule->fdirflags = IXGBE_FDIRCMD_DROP;
- rule->queue = fdir_filter->action.rx_queue;
- rule->soft_id = fdir_filter->soft_id;
-
- return 0;
-}
-
int
ixgbe_fdir_filter_program(struct rte_eth_dev *dev,
struct ixgbe_fdir_rule *rule,
return err;
}
-/* ixgbe_add_del_fdir_filter - add or remove a flow diretor filter.
- * @dev: pointer to the structure rte_eth_dev
- * @fdir_filter: fdir filter entry
- * @del: 1 - delete, 0 - add
- * @update: 1 - update
- */
-static int
-ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *fdir_filter,
- bool del,
- bool update)
-{
- struct ixgbe_fdir_rule rule;
- int err;
-
- err = ixgbe_interpret_fdir_filter(dev, fdir_filter, &rule);
-
- if (err)
- return err;
-
- return ixgbe_fdir_filter_program(dev, &rule, del, update);
-}
-
static int
ixgbe_fdir_flush(struct rte_eth_dev *dev)
{
}
-/*
- * ixgbe_fdir_ctrl_func - deal with all operations on flow director.
- * @dev: pointer to the structure rte_eth_dev
- * @filter_op:operation will be taken
- * @arg: a pointer to specific structure corresponding to the filter_op
- */
-int
-ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev,
- enum rte_filter_op filter_op, void *arg)
-{
- struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- int ret = 0;
-
- if (hw->mac.type != ixgbe_mac_82599EB &&
- hw->mac.type != ixgbe_mac_X540 &&
- hw->mac.type != ixgbe_mac_X550 &&
- hw->mac.type != ixgbe_mac_X550EM_x &&
- hw->mac.type != ixgbe_mac_X550EM_a)
- return -ENOTSUP;
-
- if (filter_op == RTE_ETH_FILTER_NOP)
- return 0;
-
- if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
- return -EINVAL;
-
- switch (filter_op) {
- case RTE_ETH_FILTER_ADD:
- ret = ixgbe_add_del_fdir_filter(dev,
- (struct rte_eth_fdir_filter *)arg, FALSE, FALSE);
- break;
- case RTE_ETH_FILTER_UPDATE:
- ret = ixgbe_add_del_fdir_filter(dev,
- (struct rte_eth_fdir_filter *)arg, FALSE, TRUE);
- break;
- case RTE_ETH_FILTER_DELETE:
- ret = ixgbe_add_del_fdir_filter(dev,
- (struct rte_eth_fdir_filter *)arg, TRUE, FALSE);
- break;
- case RTE_ETH_FILTER_FLUSH:
- ret = ixgbe_fdir_flush(dev);
- break;
- case RTE_ETH_FILTER_INFO:
- ixgbe_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg);
- break;
- case RTE_ETH_FILTER_STATS:
- ixgbe_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg);
- break;
- default:
- PMD_DRV_LOG(ERR, "unknown operation %u", filter_op);
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
/* restore flow director filter */
void
ixgbe_fdir_filter_restore(struct rte_eth_dev *dev)
.get_restore_info = mlx5_flow_tunnel_get_restore_info,
};
-/* Convert FDIR request to Generic flow. */
-struct mlx5_fdir {
- struct rte_flow_attr attr;
- struct rte_flow_item items[4];
- struct rte_flow_item_eth l2;
- struct rte_flow_item_eth l2_mask;
- union {
- struct rte_flow_item_ipv4 ipv4;
- struct rte_flow_item_ipv6 ipv6;
- } l3;
- union {
- struct rte_flow_item_ipv4 ipv4;
- struct rte_flow_item_ipv6 ipv6;
- } l3_mask;
- union {
- struct rte_flow_item_udp udp;
- struct rte_flow_item_tcp tcp;
- } l4;
- union {
- struct rte_flow_item_udp udp;
- struct rte_flow_item_tcp tcp;
- } l4_mask;
- struct rte_flow_action actions[2];
- struct rte_flow_action_queue queue;
-};
-
/* Tunnel information. */
struct mlx5_flow_tunnel_info {
uint64_t tunnel; /**< Tunnel bit (see MLX5_FLOW_*). */
uint32_t flow_idx)
{
struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_fdir_flow *priv_fdir_flow = NULL;
struct rte_flow *flow = mlx5_ipool_get(priv->sh->ipool
[MLX5_IPOOL_RTE_FLOW], flow_idx);
rte_spinlock_unlock(&priv->flow_list_lock);
}
flow_mreg_del_copy_action(dev, flow);
- if (flow->fdir) {
- LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
- if (priv_fdir_flow->rix_flow == flow_idx)
- break;
- }
- if (priv_fdir_flow) {
- LIST_REMOVE(priv_fdir_flow, next);
- mlx5_free(priv_fdir_flow->fdir);
- mlx5_free(priv_fdir_flow);
- }
- }
mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], flow_idx);
if (flow->tunnel) {
struct mlx5_flow_tunnel *tunnel;
return 0;
}
-/**
- * Convert a flow director filter to a generic flow.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param fdir_filter
- * Flow director filter to add.
- * @param attributes
- * Generic flow parameters structure.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_fdir_filter_convert(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *fdir_filter,
- struct mlx5_fdir *attributes)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- const struct rte_eth_fdir_input *input = &fdir_filter->input;
- const struct rte_eth_fdir_masks *mask =
- &dev->data->dev_conf.fdir_conf.mask;
-
- /* Validate queue number. */
- if (fdir_filter->action.rx_queue >= priv->rxqs_n) {
- DRV_LOG(ERR, "port %u invalid queue number %d",
- dev->data->port_id, fdir_filter->action.rx_queue);
- rte_errno = EINVAL;
- return -rte_errno;
- }
- attributes->attr.ingress = 1;
- attributes->items[0] = (struct rte_flow_item) {
- .type = RTE_FLOW_ITEM_TYPE_ETH,
- .spec = &attributes->l2,
- .mask = &attributes->l2_mask,
- };
- switch (fdir_filter->action.behavior) {
- case RTE_ETH_FDIR_ACCEPT:
- attributes->actions[0] = (struct rte_flow_action){
- .type = RTE_FLOW_ACTION_TYPE_QUEUE,
- .conf = &attributes->queue,
- };
- break;
- case RTE_ETH_FDIR_REJECT:
- attributes->actions[0] = (struct rte_flow_action){
- .type = RTE_FLOW_ACTION_TYPE_DROP,
- };
- break;
- default:
- DRV_LOG(ERR, "port %u invalid behavior %d",
- dev->data->port_id,
- fdir_filter->action.behavior);
- rte_errno = ENOTSUP;
- return -rte_errno;
- }
- attributes->queue.index = fdir_filter->action.rx_queue;
- /* Handle L3. */
- switch (fdir_filter->input.flow_type) {
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
- attributes->l3.ipv4.hdr = (struct rte_ipv4_hdr){
- .src_addr = input->flow.ip4_flow.src_ip,
- .dst_addr = input->flow.ip4_flow.dst_ip,
- .time_to_live = input->flow.ip4_flow.ttl,
- .type_of_service = input->flow.ip4_flow.tos,
- };
- attributes->l3_mask.ipv4.hdr = (struct rte_ipv4_hdr){
- .src_addr = mask->ipv4_mask.src_ip,
- .dst_addr = mask->ipv4_mask.dst_ip,
- .time_to_live = mask->ipv4_mask.ttl,
- .type_of_service = mask->ipv4_mask.tos,
- .next_proto_id = mask->ipv4_mask.proto,
- };
- attributes->items[1] = (struct rte_flow_item){
- .type = RTE_FLOW_ITEM_TYPE_IPV4,
- .spec = &attributes->l3,
- .mask = &attributes->l3_mask,
- };
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
- attributes->l3.ipv6.hdr = (struct rte_ipv6_hdr){
- .hop_limits = input->flow.ipv6_flow.hop_limits,
- .proto = input->flow.ipv6_flow.proto,
- };
-
- memcpy(attributes->l3.ipv6.hdr.src_addr,
- input->flow.ipv6_flow.src_ip,
- RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
- memcpy(attributes->l3.ipv6.hdr.dst_addr,
- input->flow.ipv6_flow.dst_ip,
- RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
- memcpy(attributes->l3_mask.ipv6.hdr.src_addr,
- mask->ipv6_mask.src_ip,
- RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr));
- memcpy(attributes->l3_mask.ipv6.hdr.dst_addr,
- mask->ipv6_mask.dst_ip,
- RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr));
- attributes->items[1] = (struct rte_flow_item){
- .type = RTE_FLOW_ITEM_TYPE_IPV6,
- .spec = &attributes->l3,
- .mask = &attributes->l3_mask,
- };
- break;
- default:
- DRV_LOG(ERR, "port %u invalid flow type%d",
- dev->data->port_id, fdir_filter->input.flow_type);
- rte_errno = ENOTSUP;
- return -rte_errno;
- }
- /* Handle L4. */
- switch (fdir_filter->input.flow_type) {
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- attributes->l4.udp.hdr = (struct rte_udp_hdr){
- .src_port = input->flow.udp4_flow.src_port,
- .dst_port = input->flow.udp4_flow.dst_port,
- };
- attributes->l4_mask.udp.hdr = (struct rte_udp_hdr){
- .src_port = mask->src_port_mask,
- .dst_port = mask->dst_port_mask,
- };
- attributes->items[2] = (struct rte_flow_item){
- .type = RTE_FLOW_ITEM_TYPE_UDP,
- .spec = &attributes->l4,
- .mask = &attributes->l4_mask,
- };
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- attributes->l4.tcp.hdr = (struct rte_tcp_hdr){
- .src_port = input->flow.tcp4_flow.src_port,
- .dst_port = input->flow.tcp4_flow.dst_port,
- };
- attributes->l4_mask.tcp.hdr = (struct rte_tcp_hdr){
- .src_port = mask->src_port_mask,
- .dst_port = mask->dst_port_mask,
- };
- attributes->items[2] = (struct rte_flow_item){
- .type = RTE_FLOW_ITEM_TYPE_TCP,
- .spec = &attributes->l4,
- .mask = &attributes->l4_mask,
- };
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- attributes->l4.udp.hdr = (struct rte_udp_hdr){
- .src_port = input->flow.udp6_flow.src_port,
- .dst_port = input->flow.udp6_flow.dst_port,
- };
- attributes->l4_mask.udp.hdr = (struct rte_udp_hdr){
- .src_port = mask->src_port_mask,
- .dst_port = mask->dst_port_mask,
- };
- attributes->items[2] = (struct rte_flow_item){
- .type = RTE_FLOW_ITEM_TYPE_UDP,
- .spec = &attributes->l4,
- .mask = &attributes->l4_mask,
- };
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- attributes->l4.tcp.hdr = (struct rte_tcp_hdr){
- .src_port = input->flow.tcp6_flow.src_port,
- .dst_port = input->flow.tcp6_flow.dst_port,
- };
- attributes->l4_mask.tcp.hdr = (struct rte_tcp_hdr){
- .src_port = mask->src_port_mask,
- .dst_port = mask->dst_port_mask,
- };
- attributes->items[2] = (struct rte_flow_item){
- .type = RTE_FLOW_ITEM_TYPE_TCP,
- .spec = &attributes->l4,
- .mask = &attributes->l4_mask,
- };
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
- case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
- break;
- default:
- DRV_LOG(ERR, "port %u invalid flow type%d",
- dev->data->port_id, fdir_filter->input.flow_type);
- rte_errno = ENOTSUP;
- return -rte_errno;
- }
- return 0;
-}
-
-#define FLOW_FDIR_CMP(f1, f2, fld) \
- memcmp(&(f1)->fld, &(f2)->fld, sizeof(f1->fld))
-
-/**
- * Compare two FDIR flows. If items and actions are identical, the two flows are
- * regarded as same.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param f1
- * FDIR flow to compare.
- * @param f2
- * FDIR flow to compare.
- *
- * @return
- * Zero on match, 1 otherwise.
- */
-static int
-flow_fdir_cmp(const struct mlx5_fdir *f1, const struct mlx5_fdir *f2)
-{
- if (FLOW_FDIR_CMP(f1, f2, attr) ||
- FLOW_FDIR_CMP(f1, f2, l2) ||
- FLOW_FDIR_CMP(f1, f2, l2_mask) ||
- FLOW_FDIR_CMP(f1, f2, l3) ||
- FLOW_FDIR_CMP(f1, f2, l3_mask) ||
- FLOW_FDIR_CMP(f1, f2, l4) ||
- FLOW_FDIR_CMP(f1, f2, l4_mask) ||
- FLOW_FDIR_CMP(f1, f2, actions[0].type))
- return 1;
- if (f1->actions[0].type == RTE_FLOW_ACTION_TYPE_QUEUE &&
- FLOW_FDIR_CMP(f1, f2, queue))
- return 1;
- return 0;
-}
-
-/**
- * Search device flow list to find out a matched FDIR flow.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param fdir_flow
- * FDIR flow to lookup.
- *
- * @return
- * Index of flow if found, 0 otherwise.
- */
-static uint32_t
-flow_fdir_filter_lookup(struct rte_eth_dev *dev, struct mlx5_fdir *fdir_flow)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- uint32_t flow_idx = 0;
- struct mlx5_fdir_flow *priv_fdir_flow = NULL;
-
- MLX5_ASSERT(fdir_flow);
- LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
- if (!flow_fdir_cmp(priv_fdir_flow->fdir, fdir_flow)) {
- DRV_LOG(DEBUG, "port %u found FDIR flow %u",
- dev->data->port_id, flow_idx);
- flow_idx = priv_fdir_flow->rix_flow;
- break;
- }
- }
- return flow_idx;
-}
-
-/**
- * Add new flow director filter and store it in list.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param fdir_filter
- * Flow director filter to add.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_fdir_filter_add(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *fdir_filter)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_fdir *fdir_flow;
- struct rte_flow *flow;
- struct mlx5_fdir_flow *priv_fdir_flow = NULL;
- uint32_t flow_idx;
- int ret;
-
- fdir_flow = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*fdir_flow), 0,
- SOCKET_ID_ANY);
- if (!fdir_flow) {
- rte_errno = ENOMEM;
- return -rte_errno;
- }
- ret = flow_fdir_filter_convert(dev, fdir_filter, fdir_flow);
- if (ret)
- goto error;
- flow_idx = flow_fdir_filter_lookup(dev, fdir_flow);
- if (flow_idx) {
- rte_errno = EEXIST;
- goto error;
- }
- priv_fdir_flow = mlx5_malloc(MLX5_MEM_ZERO,
- sizeof(struct mlx5_fdir_flow),
- 0, SOCKET_ID_ANY);
- if (!priv_fdir_flow) {
- rte_errno = ENOMEM;
- goto error;
- }
- flow_idx = flow_list_create(dev, &priv->flows, &fdir_flow->attr,
- fdir_flow->items, fdir_flow->actions, true,
- NULL);
- flow = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], flow_idx);
- if (!flow)
- goto error;
- flow->fdir = 1;
- priv_fdir_flow->fdir = fdir_flow;
- priv_fdir_flow->rix_flow = flow_idx;
- LIST_INSERT_HEAD(&priv->fdir_flows, priv_fdir_flow, next);
- DRV_LOG(DEBUG, "port %u created FDIR flow %p",
- dev->data->port_id, (void *)flow);
- return 0;
-error:
- mlx5_free(priv_fdir_flow);
- mlx5_free(fdir_flow);
- return -rte_errno;
-}
-
-/**
- * Delete specific filter.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param fdir_filter
- * Filter to be deleted.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_fdir_filter_delete(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *fdir_filter)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- uint32_t flow_idx;
- struct mlx5_fdir fdir_flow = {
- .attr.group = 0,
- };
- struct mlx5_fdir_flow *priv_fdir_flow = NULL;
- int ret;
-
- ret = flow_fdir_filter_convert(dev, fdir_filter, &fdir_flow);
- if (ret)
- return -rte_errno;
- LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
- /* Find the fdir in priv list */
- if (!flow_fdir_cmp(priv_fdir_flow->fdir, &fdir_flow))
- break;
- }
- if (!priv_fdir_flow)
- return 0;
- LIST_REMOVE(priv_fdir_flow, next);
- flow_idx = priv_fdir_flow->rix_flow;
- flow_list_destroy(dev, &priv->flows, flow_idx);
- mlx5_free(priv_fdir_flow->fdir);
- mlx5_free(priv_fdir_flow);
- DRV_LOG(DEBUG, "port %u deleted FDIR flow %u",
- dev->data->port_id, flow_idx);
- return 0;
-}
-
-/**
- * Update queue for specific filter.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param fdir_filter
- * Filter to be updated.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_fdir_filter_update(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *fdir_filter)
-{
- int ret;
-
- ret = flow_fdir_filter_delete(dev, fdir_filter);
- if (ret)
- return ret;
- return flow_fdir_filter_add(dev, fdir_filter);
-}
-
-/**
- * Flush all filters.
- *
- * @param dev
- * Pointer to Ethernet device.
- */
-static void
-flow_fdir_filter_flush(struct rte_eth_dev *dev)
-{
- struct mlx5_priv *priv = dev->data->dev_private;
- struct mlx5_fdir_flow *priv_fdir_flow = NULL;
-
- while (!LIST_EMPTY(&priv->fdir_flows)) {
- priv_fdir_flow = LIST_FIRST(&priv->fdir_flows);
- LIST_REMOVE(priv_fdir_flow, next);
- flow_list_destroy(dev, &priv->flows, priv_fdir_flow->rix_flow);
- mlx5_free(priv_fdir_flow->fdir);
- mlx5_free(priv_fdir_flow);
- }
-}
-
-/**
- * Get flow director information.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param[out] fdir_info
- * Resulting flow director information.
- */
-static void
-flow_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir_info)
-{
- struct rte_eth_fdir_masks *mask =
- &dev->data->dev_conf.fdir_conf.mask;
-
- fdir_info->mode = dev->data->dev_conf.fdir_conf.mode;
- fdir_info->guarant_spc = 0;
- rte_memcpy(&fdir_info->mask, mask, sizeof(fdir_info->mask));
- fdir_info->max_flexpayload = 0;
- fdir_info->flow_types_mask[0] = 0;
- fdir_info->flex_payload_unit = 0;
- fdir_info->max_flex_payload_segment_num = 0;
- fdir_info->flex_payload_limit = 0;
- memset(&fdir_info->flex_conf, 0, sizeof(fdir_info->flex_conf));
-}
-
-/**
- * Deal with flow director operations.
- *
- * @param dev
- * Pointer to Ethernet device.
- * @param filter_op
- * Operation to perform.
- * @param arg
- * Pointer to operation-specific structure.
- *
- * @return
- * 0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op,
- void *arg)
-{
- enum rte_fdir_mode fdir_mode =
- dev->data->dev_conf.fdir_conf.mode;
-
- if (filter_op == RTE_ETH_FILTER_NOP)
- return 0;
- if (fdir_mode != RTE_FDIR_MODE_PERFECT &&
- fdir_mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
- DRV_LOG(ERR, "port %u flow director mode %d not supported",
- dev->data->port_id, fdir_mode);
- rte_errno = EINVAL;
- return -rte_errno;
- }
- switch (filter_op) {
- case RTE_ETH_FILTER_ADD:
- return flow_fdir_filter_add(dev, arg);
- case RTE_ETH_FILTER_UPDATE:
- return flow_fdir_filter_update(dev, arg);
- case RTE_ETH_FILTER_DELETE:
- return flow_fdir_filter_delete(dev, arg);
- case RTE_ETH_FILTER_FLUSH:
- flow_fdir_filter_flush(dev);
- break;
- case RTE_ETH_FILTER_INFO:
- flow_fdir_info_get(dev, arg);
- break;
- default:
- DRV_LOG(DEBUG, "port %u unknown operation %u",
- dev->data->port_id, filter_op);
- rte_errno = EINVAL;
- return -rte_errno;
- }
- return 0;
-}
-
/**
* Manage filter operations.
*
}
*(const void **)arg = &mlx5_flow_ops;
return 0;
- case RTE_ETH_FILTER_FDIR:
- return flow_fdir_ctrl_func(dev, filter_op, arg);
default:
DRV_LOG(ERR, "port %u filter type (%d) not supported",
dev->data->port_id, filter_type);
uint32_t ref_cnt; /**< Use count. */
};
-/* Fdir flow structure */
-struct mlx5_fdir_flow {
- LIST_ENTRY(mlx5_fdir_flow) next; /* Pointer to the next element. */
- struct mlx5_fdir *fdir; /* Pointer to fdir. */
- uint32_t rix_flow; /* Index to flow. */
-};
-
#define MLX5_MAX_TUNNELS 256
#define MLX5_TNL_MISS_RULE_PRIORITY 3
#define MLX5_TNL_MISS_FDB_JUMP_GRP 0x1234faac
uint32_t dev_handles;
/**< Device flow handles that are part of the flow. */
uint32_t drv_type:2; /**< Driver type. */
- uint32_t fdir:1; /**< Identifier of associated FDIR if any. */
uint32_t tunnel:1;
uint32_t meter:16; /**< Holds flow meter id. */
uint32_t rix_mreg_copy;
int qede_check_fdir_support(struct rte_eth_dev *eth_dev);
-uint16_t qede_fdir_construct_pkt(struct rte_eth_dev *eth_dev,
- struct rte_eth_fdir_filter *fdir,
- void *buff,
- struct ecore_arfs_config_params *params);
-
void qede_fdir_dealloc_resc(struct rte_eth_dev *eth_dev);
int qede_activate_vport(struct rte_eth_dev *eth_dev, bool flg);
*/
#define QEDE_MAX_FDIR_PKT_LEN (86)
-static inline bool qede_valid_flow(uint16_t flow_type)
-{
- return ((flow_type == RTE_ETH_FLOW_NONFRAG_IPV4_TCP) ||
- (flow_type == RTE_ETH_FLOW_NONFRAG_IPV4_UDP) ||
- (flow_type == RTE_ETH_FLOW_NONFRAG_IPV6_TCP) ||
- (flow_type == RTE_ETH_FLOW_NONFRAG_IPV6_UDP));
-}
-
static uint16_t
qede_arfs_construct_pkt(struct rte_eth_dev *eth_dev,
struct qede_arfs_entry *arfs,
}
}
-static int
-qede_fdir_to_arfs_filter(struct rte_eth_dev *eth_dev,
- struct rte_eth_fdir_filter *fdir,
- struct qede_arfs_entry *arfs)
-{
- struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
- struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
- struct rte_eth_fdir_input *input;
-
- static const uint8_t next_proto[] = {
- [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = IPPROTO_TCP,
- [RTE_ETH_FLOW_NONFRAG_IPV4_UDP] = IPPROTO_UDP,
- [RTE_ETH_FLOW_NONFRAG_IPV6_TCP] = IPPROTO_TCP,
- [RTE_ETH_FLOW_NONFRAG_IPV6_UDP] = IPPROTO_UDP,
- };
-
- input = &fdir->input;
-
- DP_INFO(edev, "flow_type %d\n", input->flow_type);
-
- switch (input->flow_type) {
- case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
- case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
- /* fill the common ip header */
- arfs->tuple.eth_proto = RTE_ETHER_TYPE_IPV4;
- arfs->tuple.dst_ipv4 = input->flow.ip4_flow.dst_ip;
- arfs->tuple.src_ipv4 = input->flow.ip4_flow.src_ip;
- arfs->tuple.ip_proto = next_proto[input->flow_type];
-
- /* UDP */
- if (input->flow_type == RTE_ETH_FLOW_NONFRAG_IPV4_UDP) {
- arfs->tuple.dst_port = input->flow.udp4_flow.dst_port;
- arfs->tuple.src_port = input->flow.udp4_flow.src_port;
- } else { /* TCP */
- arfs->tuple.dst_port = input->flow.tcp4_flow.dst_port;
- arfs->tuple.src_port = input->flow.tcp4_flow.src_port;
- }
- break;
- case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
- case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
- arfs->tuple.eth_proto = RTE_ETHER_TYPE_IPV6;
- arfs->tuple.ip_proto = next_proto[input->flow_type];
- rte_memcpy(arfs->tuple.dst_ipv6,
- &input->flow.ipv6_flow.dst_ip,
- IPV6_ADDR_LEN);
- rte_memcpy(arfs->tuple.src_ipv6,
- &input->flow.ipv6_flow.src_ip,
- IPV6_ADDR_LEN);
-
- /* UDP */
- if (input->flow_type == RTE_ETH_FLOW_NONFRAG_IPV6_UDP) {
- arfs->tuple.dst_port = input->flow.udp6_flow.dst_port;
- arfs->tuple.src_port = input->flow.udp6_flow.src_port;
- } else { /* TCP */
- arfs->tuple.dst_port = input->flow.tcp6_flow.dst_port;
- arfs->tuple.src_port = input->flow.tcp6_flow.src_port;
- }
- break;
- default:
- DP_ERR(edev, "Unsupported flow_type %u\n",
- input->flow_type);
- return -ENOTSUP;
- }
-
- arfs->rx_queue = fdir->action.rx_queue;
- return 0;
-}
-
static int
qede_config_arfs_filter(struct rte_eth_dev *eth_dev,
struct qede_arfs_entry *arfs,
return rc;
}
-static int
-qede_config_cmn_fdir_filter(struct rte_eth_dev *eth_dev,
- struct rte_eth_fdir_filter *fdir_filter,
- bool add)
-{
- struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
- struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
- struct qede_arfs_entry *arfs = NULL;
- int rc = 0;
-
- arfs = rte_malloc(NULL, sizeof(struct qede_arfs_entry),
- RTE_CACHE_LINE_SIZE);
- if (!arfs) {
- DP_ERR(edev, "Did not allocate memory for arfs\n");
- return -ENOMEM;
- }
-
- rc = qede_fdir_to_arfs_filter(eth_dev, fdir_filter, arfs);
- if (rc < 0)
- return rc;
-
- rc = qede_config_arfs_filter(eth_dev, arfs, add);
- if (rc < 0)
- rte_free(arfs);
-
- return rc;
-}
-
-static int
-qede_fdir_filter_add(struct rte_eth_dev *eth_dev,
- struct rte_eth_fdir_filter *fdir,
- bool add)
-{
- struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
- struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
-
- if (!qede_valid_flow(fdir->input.flow_type)) {
- DP_ERR(edev, "invalid flow_type input\n");
- return -EINVAL;
- }
-
- if (fdir->action.rx_queue >= QEDE_RSS_COUNT(eth_dev)) {
- DP_ERR(edev, "invalid queue number %u\n",
- fdir->action.rx_queue);
- return -EINVAL;
- }
-
- if (fdir->input.flow_ext.is_vf) {
- DP_ERR(edev, "flowdir is not supported over VF\n");
- return -EINVAL;
- }
-
- return qede_config_cmn_fdir_filter(eth_dev, fdir, add);
-}
-
/* Fills the L3/L4 headers and returns the actual length of flowdir packet */
static uint16_t
qede_arfs_construct_pkt(struct rte_eth_dev *eth_dev,
return len;
}
-static int
-qede_fdir_filter_conf(struct rte_eth_dev *eth_dev,
- enum rte_filter_op filter_op,
- void *arg)
-{
- struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
- struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
- struct rte_eth_fdir_filter *fdir;
- int ret;
-
- fdir = (struct rte_eth_fdir_filter *)arg;
- switch (filter_op) {
- case RTE_ETH_FILTER_NOP:
- /* Typically used to query flowdir support */
- if (ECORE_IS_CMT(edev)) {
- DP_ERR(edev, "flowdir is not supported in 100G mode\n");
- return -ENOTSUP;
- }
- return 0; /* means supported */
- case RTE_ETH_FILTER_ADD:
- ret = qede_fdir_filter_add(eth_dev, fdir, 1);
- break;
- case RTE_ETH_FILTER_DELETE:
- ret = qede_fdir_filter_add(eth_dev, fdir, 0);
- break;
- case RTE_ETH_FILTER_FLUSH:
- case RTE_ETH_FILTER_UPDATE:
- case RTE_ETH_FILTER_INFO:
- return -ENOTSUP;
- break;
- default:
- DP_ERR(edev, "unknown operation %u", filter_op);
- ret = -EINVAL;
- }
-
- return ret;
-}
-
static int
qede_tunnel_update(struct qede_dev *qdev,
struct ecore_tunnel_info *tunn_info)
struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
switch (filter_type) {
- case RTE_ETH_FILTER_FDIR:
- return qede_fdir_filter_conf(eth_dev, filter_op, arg);
case RTE_ETH_FILTER_GENERIC:
if (ECORE_IS_CMT(edev)) {
DP_ERR(edev, "flowdir is not supported in 100G mode\n");
sfc_log_init(sa, "entry");
switch (filter_type) {
- case RTE_ETH_FILTER_FDIR:
- sfc_err(sa, "Flow Director filters not supported");
- break;
case RTE_ETH_FILTER_GENERIC:
if (filter_op != RTE_ETH_FILTER_GET) {
rc = EINVAL;
};
/**
- * 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.
+ * A structure used to define the flow director filter entry by filter_ctrl API.
*/
struct rte_eth_fdir_filter {
uint32_t soft_id;
uint32_t best_cnt; /**< Number of filters in best effort spaces. */
};
-/**
- * Flow Director filter information types.
- */
-enum rte_eth_fdir_filter_info_type {
- RTE_ETH_FDIR_FILTER_INFO_TYPE_UNKNOWN = 0,
- /** Flow Director filter input set configuration */
- RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT,
- RTE_ETH_FDIR_FILTER_INFO_TYPE_MAX,
-};
-
-/**
- * A structure used to set FDIR filter information, to support filter type
- * of 'RTE_ETH_FILTER_FDIR' RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT operation.
- */
-struct rte_eth_fdir_filter_info {
- enum rte_eth_fdir_filter_info_type info_type; /**< Information type */
- /** Details of fdir filter information */
- union {
- /** Flow Director input set configuration per port */
- struct rte_eth_input_set_conf input_set_conf;
- } info;
-};
-
/**
* l2 tunnel configuration.
*/