net/enic: add flow implementation based on Flow Manager API
Flow Manager API is the new firmware interface that exposes match action capabilities in 1400 series VIC adapters. It is intended for virtual switch offloads and enables more advanced features than the existing filter API. For example, it supports VXLAN encap and decap actions, and exposes TCAM and exact match tables. Add the new flow implementation using Flow Manager and use it when available. When Flow Manager is not available, the driver will continue to use the old filter-based flow implementation. Signed-off-by: John Daley <johndale@cisco.com> Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
This commit is contained in:
parent
c02a96fc4a
commit
ea7768b5bb
@ -248,6 +248,15 @@ selected via CIMC or UCSM followed by a reboot of the server.
|
||||
- Selectors: 'is', 'spec' and 'mask'. 'last' is not supported
|
||||
- In total, up to 64 bytes of mask is allowed across all headers
|
||||
|
||||
- **1400 and later series VICs with Flow Manager API enabled**
|
||||
|
||||
- Attributes: ingress, egress
|
||||
- Items: eth, vlan, ipv4, ipv6, sctp, udp, tcp, vxlan, raw, inner eth, vlan, ipv4, ipv6, sctp, udp, tcp
|
||||
- Ingress Actions: count, drop, flag, jump, mark, port_id, passthru, queue, rss, vxlan_decap, vxlan_encap, and void
|
||||
- Egress Actions: count, drop, jump, passthru, vxlan_encap, and void
|
||||
- Selectors: 'is', 'spec' and 'mask'. 'last' is not supported
|
||||
- In total, up to 64 bytes of mask is allowed across all headers
|
||||
|
||||
The VIC performs packet matching after applying VLAN strip. If VLAN
|
||||
stripping is enabled, EtherType in the ETH item corresponds to the
|
||||
stripped VLAN header's EtherType. Stripping does not affect the VLAN
|
||||
|
@ -68,6 +68,7 @@ New Features
|
||||
* **Updated the enic driver.**
|
||||
|
||||
* Added support for Geneve with options offload.
|
||||
* Added flow API implementation based on VIC Flow Manager API.
|
||||
|
||||
* **Added Hisilicon hns3 PMD.**
|
||||
|
||||
|
@ -32,6 +32,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_rxtx.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_clsf.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_res.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_flow.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += enic_fm_flow.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_cq.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_wq.c
|
||||
SRCS-$(CONFIG_RTE_LIBRTE_ENIC_PMD) += base/vnic_dev.c
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "vnic_devcmd.h"
|
||||
#include "vnic_nic.h"
|
||||
#include "vnic_stats.h"
|
||||
#include "vnic_flowman.h"
|
||||
|
||||
|
||||
enum vnic_proxy_type {
|
||||
@ -47,6 +48,8 @@ struct vnic_dev {
|
||||
dma_addr_t stats_pa;
|
||||
struct vnic_devcmd_fw_info *fw_info;
|
||||
dma_addr_t fw_info_pa;
|
||||
struct fm_info *flowman_info;
|
||||
dma_addr_t flowman_info_pa;
|
||||
enum vnic_proxy_type proxy;
|
||||
u32 proxy_index;
|
||||
u64 args[VNIC_DEVCMD_NARGS];
|
||||
@ -500,8 +503,74 @@ int vnic_dev_capable_adv_filters(struct vnic_dev *vdev)
|
||||
return (a1 >= (u32)FILTER_DPDK_1);
|
||||
}
|
||||
|
||||
/* Determine the "best" filtering mode VIC is capaible of. Returns one of 3
|
||||
int vnic_dev_flowman_cmd(struct vnic_dev *vdev, u64 *args, int nargs)
|
||||
{
|
||||
int wait = 1000;
|
||||
|
||||
return vnic_dev_cmd_args(vdev, CMD_FLOW_MANAGER_OP, args, nargs, wait);
|
||||
}
|
||||
|
||||
static int vnic_dev_flowman_enable(struct vnic_dev *vdev, u32 *mode,
|
||||
u8 *filter_actions)
|
||||
{
|
||||
char name[NAME_MAX];
|
||||
u64 args[3];
|
||||
u64 ops;
|
||||
static u32 instance;
|
||||
|
||||
/* flowman devcmd available? */
|
||||
if (!vnic_dev_capable(vdev, CMD_FLOW_MANAGER_OP))
|
||||
return 0;
|
||||
/* Have the version we are using? */
|
||||
args[0] = FM_API_VERSION_QUERY;
|
||||
if (vnic_dev_flowman_cmd(vdev, args, 1))
|
||||
return 0;
|
||||
if ((args[0] & (1ULL << FM_VERSION)) == 0)
|
||||
return 0;
|
||||
/* Select the version */
|
||||
args[0] = FM_API_VERSION_SELECT;
|
||||
args[1] = FM_VERSION;
|
||||
if (vnic_dev_flowman_cmd(vdev, args, 2))
|
||||
return 0;
|
||||
/* Can we get fm_info? */
|
||||
if (!vdev->flowman_info) {
|
||||
snprintf((char *)name, sizeof(name), "vnic_flowman_info-%u",
|
||||
instance++);
|
||||
vdev->flowman_info = vdev->alloc_consistent(vdev->priv,
|
||||
sizeof(struct fm_info),
|
||||
&vdev->flowman_info_pa, (u8 *)name);
|
||||
if (!vdev->flowman_info)
|
||||
return 0;
|
||||
}
|
||||
args[0] = FM_INFO_QUERY;
|
||||
args[1] = vdev->flowman_info_pa;
|
||||
args[2] = sizeof(struct fm_info);
|
||||
if (vnic_dev_flowman_cmd(vdev, args, 3))
|
||||
return 0;
|
||||
/* Have required operations? */
|
||||
ops = (1ULL << FMOP_END) |
|
||||
(1ULL << FMOP_DROP) |
|
||||
(1ULL << FMOP_RQ_STEER) |
|
||||
(1ULL << FMOP_EXACT_MATCH) |
|
||||
(1ULL << FMOP_MARK) |
|
||||
(1ULL << FMOP_TAG) |
|
||||
(1ULL << FMOP_EG_HAIRPIN) |
|
||||
(1ULL << FMOP_ENCAP) |
|
||||
(1ULL << FMOP_DECAP_NOSTRIP);
|
||||
if ((vdev->flowman_info->fm_op_mask & ops) != ops)
|
||||
return 0;
|
||||
/* Good to use flowman now */
|
||||
*mode = FILTER_FLOWMAN;
|
||||
*filter_actions = FILTER_ACTION_RQ_STEERING_FLAG |
|
||||
FILTER_ACTION_FILTER_ID_FLAG |
|
||||
FILTER_ACTION_COUNTER_FLAG |
|
||||
FILTER_ACTION_DROP_FLAG;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Determine the "best" filtering mode VIC is capaible of. Returns one of 4
|
||||
* value or 0 on error:
|
||||
* FILTER_FLOWMAN- flowman api capable
|
||||
* FILTER_DPDK_1- advanced filters availabile
|
||||
* FILTER_USNIC_IP_FLAG - advanced filters but with the restriction that
|
||||
* the IP layer must explicitly specified. I.e. cannot have a UDP
|
||||
@ -517,6 +586,10 @@ int vnic_dev_capable_filter_mode(struct vnic_dev *vdev, u32 *mode,
|
||||
int err;
|
||||
u32 max_level = 0;
|
||||
|
||||
/* If flowman is available, use it as it is the most capable API */
|
||||
if (vnic_dev_flowman_enable(vdev, mode, filter_actions))
|
||||
return 0;
|
||||
|
||||
err = vnic_dev_advanced_filters_cap(vdev, args, 4);
|
||||
|
||||
/* determine supported filter actions */
|
||||
@ -977,6 +1050,10 @@ void vnic_dev_unregister(struct vnic_dev *vdev)
|
||||
vdev->free_consistent(vdev->priv,
|
||||
sizeof(struct vnic_stats),
|
||||
vdev->stats, vdev->stats_pa);
|
||||
if (vdev->flowman_info)
|
||||
vdev->free_consistent(vdev->priv,
|
||||
sizeof(struct fm_info),
|
||||
vdev->flowman_info, vdev->flowman_info_pa);
|
||||
if (vdev->fw_info)
|
||||
vdev->free_consistent(vdev->priv,
|
||||
sizeof(struct vnic_devcmd_fw_info),
|
||||
|
@ -182,6 +182,7 @@ int vnic_dev_deinit_done(struct vnic_dev *vdev, int *status);
|
||||
int vnic_dev_set_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
|
||||
int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry,
|
||||
struct filter_v2 *data, struct filter_action_v2 *action_v2);
|
||||
int vnic_dev_flowman_cmd(struct vnic_dev *vdev, u64 *args, int nargs);
|
||||
int vnic_dev_overlay_offload_ctrl(struct vnic_dev *vdev,
|
||||
u8 overlay, u8 config);
|
||||
int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, u8 overlay,
|
||||
|
@ -600,6 +600,16 @@ enum vnic_devcmd_cmd {
|
||||
* a3 = bitmask of supported actions
|
||||
*/
|
||||
CMD_ADD_ADV_FILTER = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 77),
|
||||
|
||||
/*
|
||||
* Perform a Flow Manager Operation (see flowman_api.h)
|
||||
* in: (u32) a0 = sub-command
|
||||
* (u64) a1..15 = (sub-command specific)
|
||||
*
|
||||
* All arguments that have not been assigned a meaning should be
|
||||
* initialized to 0 to allow for better driver forward compatibility.
|
||||
*/
|
||||
CMD_FLOW_MANAGER_OP = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 88),
|
||||
};
|
||||
|
||||
/* Modes for exchanging advanced filter capabilities. The modes supported by
|
||||
@ -865,6 +875,7 @@ struct filter_action {
|
||||
#define FILTER_ACTION_RQ_STEERING_FLAG (1 << 0)
|
||||
#define FILTER_ACTION_FILTER_ID_FLAG (1 << 1)
|
||||
#define FILTER_ACTION_DROP_FLAG (1 << 2)
|
||||
#define FILTER_ACTION_COUNTER_FLAG (1 << 3)
|
||||
#define FILTER_ACTION_V2_ALL (FILTER_ACTION_RQ_STEERING_FLAG \
|
||||
| FILTER_ACTION_DROP_FLAG \
|
||||
| FILTER_ACTION_FILTER_ID_FLAG)
|
||||
@ -889,6 +900,7 @@ enum filter_type {
|
||||
FILTER_NVGRE_VMQ = 4,
|
||||
FILTER_USNIC_IP = 5,
|
||||
FILTER_DPDK_1 = 6,
|
||||
FILTER_FLOWMAN = 7,
|
||||
FILTER_MAX
|
||||
};
|
||||
|
||||
|
365
drivers/net/enic/base/vnic_flowman.h
Normal file
365
drivers/net/enic/base/vnic_flowman.h
Normal file
@ -0,0 +1,365 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright 2018-2019 Cisco Systems, Inc. All rights reserved.
|
||||
*/
|
||||
#ifndef _VNIC_FLOWMAN_H_
|
||||
#define _VNIC_FLOWMAN_H_
|
||||
|
||||
/* This file contains Flow Manager (FM) API of the firmware */
|
||||
|
||||
/* Flow manager sub-ops */
|
||||
enum {
|
||||
FM_EXACT_TABLE_ALLOC,
|
||||
FM_TCAM_TABLE_ALLOC,
|
||||
FM_MATCH_TABLE_FREE,
|
||||
FM_COUNTER_BRK,
|
||||
FM_COUNTER_QUERY,
|
||||
FM_COUNTER_CLEAR_ALL,
|
||||
FM_COUNTER_DMA,
|
||||
FM_ACTION_ALLOC,
|
||||
FM_ACTION_FREE,
|
||||
FM_EXACT_ENTRY_INSTALL,
|
||||
FM_TCAM_ENTRY_INSTALL,
|
||||
FM_MATCH_ENTRY_REMOVE,
|
||||
FM_VNIC_FIND,
|
||||
FM_API_VERSION_QUERY,
|
||||
FM_API_VERSION_SELECT,
|
||||
FM_INFO_QUERY
|
||||
};
|
||||
|
||||
/*
|
||||
* FKM (flow key metadata) flags used to match packet metadata
|
||||
* (e.g. packet is tcp)
|
||||
*/
|
||||
#define FKM_BITS \
|
||||
FBIT(FKM_QTAG) \
|
||||
FBIT(FKM_CMD) \
|
||||
FBIT(FKM_IPV4) \
|
||||
FBIT(FKM_IPV6) \
|
||||
FBIT(FKM_ROCE) \
|
||||
FBIT(FKM_UDP) \
|
||||
FBIT(FKM_TCP) \
|
||||
FBIT(FKM_TCPORUDP) \
|
||||
FBIT(FKM_IPFRAG) \
|
||||
FBIT(FKM_NVGRE) \
|
||||
FBIT(FKM_VXLAN) \
|
||||
FBIT(FKM_GENEVE) \
|
||||
FBIT(FKM_NSH) \
|
||||
FBIT(FKM_ROCEV2) \
|
||||
FBIT(FKM_VLAN_PRES) \
|
||||
FBIT(FKM_IPOK) \
|
||||
FBIT(FKM_L4OK) \
|
||||
FBIT(FKM_ROCEOK) \
|
||||
FBIT(FKM_FCSOK) \
|
||||
FBIT(FKM_EG_SPAN) \
|
||||
FBIT(FKM_IG_SPAN) \
|
||||
FBIT(FKM_EG_HAIRPINNED)
|
||||
|
||||
/*
|
||||
* FKH (flow key header) flags.
|
||||
* This selects which headers are valid in the struct.
|
||||
* This is distinct from metadata in that metadata is requesting actual
|
||||
* selection criteria. If, for example, a TCAM match with metadata "FKM_UDP"
|
||||
* is feeding into an exact match table, there may be no need for the
|
||||
* exact match table to also specify FKM_UDP, so FKH_UDP is used to
|
||||
* specify that the UDP header fields should be used in the match.
|
||||
*/
|
||||
#define FKH_BITS \
|
||||
FBIT(FKH_ETHER) \
|
||||
FBIT(FKH_QTAG) \
|
||||
FBIT(FKH_L2RAW) \
|
||||
FBIT(FKH_IPV4) \
|
||||
FBIT(FKH_IPV6) \
|
||||
FBIT(FKH_L3RAW) \
|
||||
FBIT(FKH_UDP) \
|
||||
FBIT(FKH_TCP) \
|
||||
FBIT(FKH_ICMP) \
|
||||
FBIT(FKH_VXLAN) \
|
||||
FBIT(FKH_L4RAW)
|
||||
|
||||
#define FBIT(X) X##_BIT,
|
||||
enum {
|
||||
FKM_BITS
|
||||
FKM_BIT_COUNT
|
||||
};
|
||||
|
||||
enum {
|
||||
FKH_BITS
|
||||
FKH_BIT_COUNT
|
||||
};
|
||||
#undef FBIT
|
||||
#define FBIT(X) X = (1 << X##_BIT),
|
||||
enum {
|
||||
FKM_BITS
|
||||
};
|
||||
enum {
|
||||
FKH_BITS
|
||||
};
|
||||
#undef FBIT
|
||||
|
||||
#define FM_ETH_ALEN 6
|
||||
#define FM_LAYER_SIZE 64
|
||||
|
||||
/* Header match pattern */
|
||||
struct fm_header_set {
|
||||
uint32_t fk_metadata; /* FKM flags */
|
||||
uint32_t fk_header_select; /* FKH flags */
|
||||
uint16_t fk_vlan;
|
||||
/* L2: Ethernet Header (valid if FKH_ETHER) */
|
||||
union {
|
||||
struct {
|
||||
uint8_t fk_dstmac[FM_ETH_ALEN];
|
||||
uint8_t fk_srcmac[FM_ETH_ALEN];
|
||||
uint16_t fk_ethtype;
|
||||
} __rte_packed eth;
|
||||
uint8_t rawdata[FM_LAYER_SIZE];
|
||||
} __rte_packed l2;
|
||||
/* L3: IPv4 or IPv6 (valid if FKH_IPV4,6) */
|
||||
union {
|
||||
/* Valid if FKH_IPV4 */
|
||||
struct {
|
||||
uint8_t fk_ihl_vers;
|
||||
uint8_t fk_tos;
|
||||
uint16_t fk_tot_len;
|
||||
uint16_t fk_id;
|
||||
uint16_t fk_frag_off;
|
||||
uint8_t fk_ttl;
|
||||
uint8_t fk_proto;
|
||||
uint16_t fk_check;
|
||||
uint32_t fk_saddr;
|
||||
uint32_t fk_daddr;
|
||||
} __rte_packed ip4;
|
||||
/* Valid if FKH_IPV6 */
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
uint32_t fk_un1_flow;
|
||||
uint16_t fk_un1_plen;
|
||||
uint8_t fk_un1_nxt;
|
||||
uint8_t fk_un1_hlim;
|
||||
} unl;
|
||||
uint8_t fk_un2_vfc;
|
||||
} ctl;
|
||||
uint8_t fk_srcip[16];
|
||||
uint8_t fk_dstip[16];
|
||||
} __rte_packed ip6;
|
||||
uint8_t rawdata[FM_LAYER_SIZE];
|
||||
} __rte_packed l3;
|
||||
/* L4: UDP, TCP, or ICMP (valid if FKH_UDP,TCP,ICMP) */
|
||||
union {
|
||||
struct {
|
||||
uint16_t fk_source;
|
||||
uint16_t fk_dest;
|
||||
uint16_t fk_len;
|
||||
uint16_t fk_check;
|
||||
} __rte_packed udp;
|
||||
struct {
|
||||
uint16_t fk_source;
|
||||
uint16_t fk_dest;
|
||||
uint32_t fk_seq;
|
||||
uint32_t fk_ack_seq;
|
||||
uint16_t fk_flags;
|
||||
uint16_t fk_window;
|
||||
uint16_t fk_check;
|
||||
uint16_t fk_urg_ptr;
|
||||
} __rte_packed tcp;
|
||||
struct {
|
||||
uint8_t fk_code;
|
||||
uint8_t fk_type;
|
||||
} __rte_packed icmp;
|
||||
uint8_t rawdata[FM_LAYER_SIZE];
|
||||
} __rte_packed l4;
|
||||
/* VXLAN (valid if FKH_VXLAN) */
|
||||
struct {
|
||||
uint8_t fkvx_flags;
|
||||
uint8_t fkvx_res0[3];
|
||||
uint8_t fkvx_vni[3];
|
||||
uint8_t fkvx_res1;
|
||||
} __rte_packed vxlan;
|
||||
/* Payload or unknown inner-most protocol */
|
||||
uint8_t fk_l5_data[64];
|
||||
} __rte_packed;
|
||||
|
||||
/*
|
||||
* FK (flow key) template.
|
||||
* fk_hdrset specifies a set of headers per layer of encapsulation.
|
||||
* Currently FM supports two header sets: outer (0) and inner(1)
|
||||
*/
|
||||
#define FM_HDRSET_MAX 2
|
||||
|
||||
struct fm_key_template {
|
||||
struct fm_header_set fk_hdrset[FM_HDRSET_MAX];
|
||||
uint32_t fk_flags;
|
||||
uint16_t fk_packet_tag;
|
||||
uint16_t fk_packet_size;
|
||||
uint16_t fk_port_id;
|
||||
uint32_t fk_wq_id; /* WQ index */
|
||||
uint64_t fk_wq_vnic; /* VNIC handle for WQ index */
|
||||
} __rte_packed;
|
||||
|
||||
/* Action operation types */
|
||||
enum {
|
||||
FMOP_NOP = 0,
|
||||
/* End the action chain. */
|
||||
FMOP_END,
|
||||
/* Drop packet and end the action chain. */
|
||||
FMOP_DROP,
|
||||
/* Steer packet to an RQ. */
|
||||
FMOP_RQ_STEER,
|
||||
/*
|
||||
* Jump to an exact match table.
|
||||
* arg1: exact match table handle
|
||||
*/
|
||||
FMOP_EXACT_MATCH,
|
||||
/* Apply CQ-visible mark on packet. Mark is written to RSS HASH. */
|
||||
FMOP_MARK,
|
||||
/*
|
||||
* Apply CQ-visible mark on packet. Mark is written to a field in
|
||||
* extended CQ. RSS HASH is preserved.
|
||||
*/
|
||||
FMOP_EXT_MARK,
|
||||
/*
|
||||
* Apply internal tag which can be matched in subsequent
|
||||
* stages or hairpin.
|
||||
*/
|
||||
FMOP_TAG,
|
||||
/* Hairpin packet from EG -> IG */
|
||||
FMOP_EG_HAIRPIN,
|
||||
/* Hairpin packet from IG -> EG */
|
||||
FMOP_IG_HAIRPIN,
|
||||
/* Encap with VXLAN and inner VLAN from metadata. */
|
||||
FMOP_ENCAP_IVLAN,
|
||||
/* Encap, no inner VLAN. */
|
||||
FMOP_ENCAP_NOIVLAN,
|
||||
/* Encap, add inner VLAN if present. */
|
||||
FMOP_ENCAP,
|
||||
/* Set outer VLAN. */
|
||||
FMOP_SET_OVLAN,
|
||||
/* Decap when vlan_strip is off */
|
||||
FMOP_DECAP_NOSTRIP,
|
||||
FMOP_OP_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* Action operation.
|
||||
* Complex actions are achieved by a series of "transform operations"
|
||||
* We can have complex transform operations like "decap" or "vxlan
|
||||
* encap" and also simple ops like insert this data, add PACKET_LEN to
|
||||
* this address, etc.
|
||||
*/
|
||||
struct fm_action_op {
|
||||
uint32_t fa_op; /* FMOP flags */
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint8_t len1_offset;
|
||||
uint8_t len1_delta;
|
||||
uint8_t len2_offset;
|
||||
uint8_t len2_delta;
|
||||
uint16_t outer_vlan;
|
||||
uint8_t template_offset;
|
||||
uint8_t template_len;
|
||||
} __rte_packed encap;
|
||||
struct {
|
||||
uint32_t rq_index;
|
||||
uint64_t vnic_handle;
|
||||
} __rte_packed rq_steer;
|
||||
struct {
|
||||
uint16_t vlan;
|
||||
} __rte_packed ovlan;
|
||||
struct {
|
||||
uint16_t mark;
|
||||
} __rte_packed mark;
|
||||
struct {
|
||||
uint32_t ext_mark;
|
||||
} __rte_packed ext_mark;
|
||||
struct {
|
||||
uint8_t tag;
|
||||
} __rte_packed tag;
|
||||
struct {
|
||||
uint64_t handle;
|
||||
} __rte_packed exact;
|
||||
} __rte_packed;
|
||||
} __rte_packed;
|
||||
|
||||
#define FM_ACTION_OP_MAX 64
|
||||
#define FM_ACTION_DATA_MAX 96
|
||||
|
||||
/*
|
||||
* Action is a series of action operations applied to matched
|
||||
* packet. FMA (flowman action).
|
||||
*/
|
||||
struct fm_action {
|
||||
struct fm_action_op fma_action_ops[FM_ACTION_OP_MAX];
|
||||
uint8_t fma_data[FM_ACTION_DATA_MAX];
|
||||
} __rte_packed;
|
||||
|
||||
/* Match entry flags. FMEF (flow match entry flag) */
|
||||
#define FMEF_COUNTER 0x0001 /* counter index is valid */
|
||||
|
||||
/* FEM (flow exact match) entry */
|
||||
struct fm_exact_match_entry {
|
||||
struct fm_key_template fem_data; /* Match data. Mask is per table */
|
||||
uint32_t fem_flags; /* FMEF_xxx */
|
||||
uint64_t fem_action; /* Action handle */
|
||||
uint32_t fem_counter; /* Counter index */
|
||||
} __rte_packed;
|
||||
|
||||
/* FTM (flow TCAM match) entry */
|
||||
struct fm_tcam_match_entry {
|
||||
struct fm_key_template ftm_mask; /* Key mask */
|
||||
struct fm_key_template ftm_data; /* Match data */
|
||||
uint32_t ftm_flags; /* FMEF_xxx */
|
||||
uint32_t ftm_position; /* Entry position */
|
||||
uint64_t ftm_action; /* Action handle */
|
||||
uint32_t ftm_counter; /* Counter index */
|
||||
} __rte_packed;
|
||||
|
||||
/* Match directions */
|
||||
enum {
|
||||
FM_INGRESS,
|
||||
FM_EGRESS,
|
||||
FM_DIR_CNT
|
||||
};
|
||||
|
||||
/* Last stage ID, independent of the number of stages in hardware */
|
||||
#define FM_STAGE_LAST 0xff
|
||||
|
||||
/* Hash based exact match table. FET (flow exact match table) */
|
||||
struct fm_exact_match_table {
|
||||
uint8_t fet_direction; /* FM_INGRESS or EGRESS*/
|
||||
uint8_t fet_stage;
|
||||
uint8_t pad[2];
|
||||
uint32_t fet_max_entries;
|
||||
uint64_t fet_dflt_action;
|
||||
struct fm_key_template fet_key;
|
||||
} __rte_packed;
|
||||
|
||||
/* TCAM based match table. FTT (flow TCAM match table) */
|
||||
struct fm_tcam_match_table {
|
||||
uint8_t ftt_direction;
|
||||
uint8_t ftt_stage;
|
||||
uint8_t pad[2];
|
||||
uint32_t ftt_max_entries;
|
||||
} __rte_packed;
|
||||
|
||||
struct fm_counter_counts {
|
||||
uint64_t fcc_packets;
|
||||
uint64_t fcc_bytes;
|
||||
} __rte_packed;
|
||||
|
||||
/*
|
||||
* Return structure for FM_INFO_QUERY devcmd
|
||||
*/
|
||||
#define FM_VERSION 1 /* This header file is for version 1 */
|
||||
|
||||
struct fm_info {
|
||||
uint64_t fm_op_mask; /* Bitmask of action supported ops */
|
||||
uint64_t fm_current_ts; /* Current VIC timestamp */
|
||||
uint64_t fm_clock_freq; /* Timestamp clock frequency */
|
||||
uint16_t fm_max_ops; /* Max ops in an action */
|
||||
uint8_t fm_stages; /* Number of match-action stages */
|
||||
uint8_t pad[5];
|
||||
uint32_t fm_counter_count; /* Number of allocated counters */
|
||||
} __rte_packed;
|
||||
|
||||
#endif /* _VNIC_FLOWMAN_H_ */
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "vnic_enet.h"
|
||||
#include "vnic_dev.h"
|
||||
#include "vnic_flowman.h"
|
||||
#include "vnic_wq.h"
|
||||
#include "vnic_rq.h"
|
||||
#include "vnic_cq.h"
|
||||
@ -90,10 +91,17 @@ struct enic_memzone_entry {
|
||||
LIST_ENTRY(enic_memzone_entry) entries;
|
||||
};
|
||||
|
||||
/* Defined in enic_fm_flow.c */
|
||||
struct enic_flowman;
|
||||
struct enic_fm_flow;
|
||||
|
||||
struct rte_flow {
|
||||
LIST_ENTRY(rte_flow) next;
|
||||
u16 enic_filter_id;
|
||||
/* Data for filter API based flow (enic_flow.c) */
|
||||
uint16_t enic_filter_id;
|
||||
struct filter_v2 enic_filter;
|
||||
/* Data for flow manager based flow (enic_fm_flow.c) */
|
||||
struct enic_fm_flow *fm;
|
||||
};
|
||||
|
||||
/* Per-instance private data structure */
|
||||
@ -199,6 +207,9 @@ struct enic {
|
||||
/* Multicast MAC addresses added to the NIC */
|
||||
uint32_t mc_count;
|
||||
struct rte_ether_addr mc_addrs[ENIC_MULTICAST_PERFECT_FILTERS];
|
||||
|
||||
/* Flow manager API */
|
||||
struct enic_flowman *fm;
|
||||
};
|
||||
|
||||
/* Compute ethdev's max packet size from MTU */
|
||||
@ -280,6 +291,7 @@ enic_ring_incr(uint32_t n_descriptors, uint32_t idx)
|
||||
return idx;
|
||||
}
|
||||
|
||||
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,
|
||||
@ -325,6 +337,12 @@ void enic_post_wq_index(struct vnic_wq *wq);
|
||||
int enic_probe(struct enic *enic);
|
||||
int enic_clsf_init(struct enic *enic);
|
||||
void enic_clsf_destroy(struct enic *enic);
|
||||
int enic_fm_init(struct enic *enic);
|
||||
void enic_fm_destroy(struct enic *enic);
|
||||
void *enic_alloc_consistent(void *priv, size_t size, dma_addr_t *dma_handle,
|
||||
u8 *name);
|
||||
void enic_free_consistent(void *priv, size_t size, void *vaddr,
|
||||
dma_addr_t dma_handle);
|
||||
uint16_t enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
|
||||
uint16_t nb_pkts);
|
||||
uint16_t enic_noscatter_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
|
||||
@ -346,4 +364,5 @@ 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);
|
||||
extern const struct rte_flow_ops enic_flow_ops;
|
||||
extern const struct rte_flow_ops enic_fm_flow_ops;
|
||||
#endif /* _ENIC_H_ */
|
||||
|
@ -144,7 +144,10 @@ enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,
|
||||
case RTE_ETH_FILTER_GENERIC:
|
||||
if (filter_op != RTE_ETH_FILTER_GET)
|
||||
return -EINVAL;
|
||||
*(const void **)arg = &enic_flow_ops;
|
||||
if (enic->flow_filter_mode == FILTER_FLOWMAN)
|
||||
*(const void **)arg = &enic_fm_flow_ops;
|
||||
else
|
||||
*(const void **)arg = &enic_flow_ops;
|
||||
break;
|
||||
case RTE_ETH_FILTER_FDIR:
|
||||
ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg);
|
||||
@ -1288,6 +1291,11 @@ static struct rte_pci_driver rte_enic_pmd = {
|
||||
.remove = eth_enic_pci_remove,
|
||||
};
|
||||
|
||||
int dev_is_enic(struct rte_eth_dev *dev)
|
||||
{
|
||||
return dev->device->driver == &rte_enic_pmd.driver;
|
||||
}
|
||||
|
||||
RTE_PMD_REGISTER_PCI(net_enic, rte_enic_pmd);
|
||||
RTE_PMD_REGISTER_PCI_TABLE(net_enic, pci_id_enic_map);
|
||||
RTE_PMD_REGISTER_KMOD_DEP(net_enic, "* igb_uio | uio_pci_generic | vfio-pci");
|
||||
|
2459
drivers/net/enic/enic_fm_flow.c
Normal file
2459
drivers/net/enic/enic_fm_flow.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -357,7 +357,7 @@ enic_initial_post_rx(struct enic *enic, struct vnic_rq *rq)
|
||||
rq->need_initial_post = false;
|
||||
}
|
||||
|
||||
static void *
|
||||
void *
|
||||
enic_alloc_consistent(void *priv, size_t size,
|
||||
dma_addr_t *dma_handle, u8 *name)
|
||||
{
|
||||
@ -397,7 +397,7 @@ enic_alloc_consistent(void *priv, size_t size,
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
enic_free_consistent(void *priv,
|
||||
__rte_unused size_t size,
|
||||
void *vaddr,
|
||||
@ -607,6 +607,9 @@ int enic_enable(struct enic *enic)
|
||||
dev_warning(enic, "Init of hash table for clsf failed."\
|
||||
"Flow director feature will not work\n");
|
||||
|
||||
if (enic_fm_init(enic))
|
||||
dev_warning(enic, "Init of flowman failed.\n");
|
||||
|
||||
for (index = 0; index < enic->rq_count; index++) {
|
||||
err = enic_alloc_rx_queue_mbufs(enic,
|
||||
&enic->rq[enic_rte_rq_idx_to_sop_idx(index)]);
|
||||
@ -1064,6 +1067,7 @@ int enic_disable(struct enic *enic)
|
||||
vnic_dev_disable(enic->vdev);
|
||||
|
||||
enic_clsf_destroy(enic);
|
||||
enic_fm_destroy(enic);
|
||||
|
||||
if (!enic_is_sriov_vf(enic))
|
||||
vnic_dev_del_addr(enic->vdev, enic->mac_addr);
|
||||
|
@ -85,17 +85,20 @@ int enic_get_vnic_config(struct enic *enic)
|
||||
vnic_dev_capable_udp_rss_weak(enic->vdev, &enic->nic_cfg_chk,
|
||||
&enic->udp_rss_weak);
|
||||
|
||||
dev_info(enic, "Flow api filter mode: %s Actions: %s%s%s\n",
|
||||
dev_info(enic, "Flow api filter mode: %s Actions: %s%s%s%s\n",
|
||||
((enic->flow_filter_mode == FILTER_FLOWMAN) ? "FLOWMAN" :
|
||||
((enic->flow_filter_mode == FILTER_DPDK_1) ? "DPDK" :
|
||||
((enic->flow_filter_mode == FILTER_USNIC_IP) ? "USNIC" :
|
||||
((enic->flow_filter_mode == FILTER_IPV4_5TUPLE) ? "5TUPLE" :
|
||||
"NONE"))),
|
||||
"NONE")))),
|
||||
((enic->filter_actions & FILTER_ACTION_RQ_STEERING_FLAG) ?
|
||||
"steer " : ""),
|
||||
((enic->filter_actions & FILTER_ACTION_FILTER_ID_FLAG) ?
|
||||
"tag " : ""),
|
||||
((enic->filter_actions & FILTER_ACTION_DROP_FLAG) ?
|
||||
"drop " : ""));
|
||||
"drop " : ""),
|
||||
((enic->filter_actions & FILTER_ACTION_COUNTER_FLAG) ?
|
||||
"count " : ""));
|
||||
|
||||
c->wq_desc_count =
|
||||
min_t(u32, ENIC_MAX_WQ_DESCS,
|
||||
|
@ -10,6 +10,7 @@ sources = files(
|
||||
'enic_clsf.c',
|
||||
'enic_ethdev.c',
|
||||
'enic_flow.c',
|
||||
'enic_fm_flow.c',
|
||||
'enic_main.c',
|
||||
'enic_res.c',
|
||||
'enic_rxtx.c',
|
||||
|
Loading…
Reference in New Issue
Block a user