i40e: Enable cloud filters via tc-flower
This patch enables tc-flower based hardware offloads. tc flower filter provided by the kernel is configured as driver specific cloud filter. The patch implements functions and admin queue commands needed to support cloud filters in the driver and adds cloud filters to configure these tc-flower filters. The classification function of the filter is to direct matched packets to a traffic class. The hardware traffic class is set based on the the classid reserved in the range :ffe0 - :ffef. Match Dst MAC and route to TC0: prio 1 flower dst_mac 3c:fd:fe:a0:d6:70 skip_sw\ hw_tc 1 Match Dst IPv4,Dst Port and route to TC1: prio 2 flower dst_ip 192.168.3.5/32\ ip_proto udp dst_port 25 skip_sw\ hw_tc 2 Match Dst IPv6,Dst Port and route to TC1: prio 3 flower dst_ip fe8::200:1\ ip_proto udp dst_port 66 skip_sw\ hw_tc 2 Delete tc flower filter: Example: Flow Director Sideband is disabled while configuring cloud filters via tc-flower and until any cloud filter exists. Unsupported matches when cloud filters are added using enhanced big buffer cloud filter mode of underlying switch include: 1. source port and source IP 2. Combined MAC address and IP fields. 3. Not specifying L4 port These filter matches can however be used to redirect traffic to the main VSI (tc 0) which does not require the enhanced big buffer cloud filter support. Signed-off-by: Amritha Nambiar <amritha.nambiar@intel.com> Signed-off-by: Kiran Patil <kiran.patil@intel.com> Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com> Signed-off-by: Jingjing Wu <jingjing.wu@intel.com> Acked-by: Shannon Nelson <shannon.nelson@oracle.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
aaf66502b6
commit
2f4b411a3d
|
@ -55,6 +55,8 @@
|
|||
#include <linux/net_tstamp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/tc_act/tc_gact.h>
|
||||
#include <net/tc_act/tc_mirred.h>
|
||||
#include "i40e_type.h"
|
||||
#include "i40e_prototype.h"
|
||||
#include "i40e_client.h"
|
||||
|
@ -253,10 +255,56 @@ struct i40e_fdir_filter {
|
|||
u32 fd_id;
|
||||
};
|
||||
|
||||
#define I40E_CLOUD_FIELD_OMAC 0x01
|
||||
#define I40E_CLOUD_FIELD_IMAC 0x02
|
||||
#define I40E_CLOUD_FIELD_IVLAN 0x04
|
||||
#define I40E_CLOUD_FIELD_TEN_ID 0x08
|
||||
#define I40E_CLOUD_FIELD_IIP 0x10
|
||||
|
||||
#define I40E_CLOUD_FILTER_FLAGS_OMAC I40E_CLOUD_FIELD_OMAC
|
||||
#define I40E_CLOUD_FILTER_FLAGS_IMAC I40E_CLOUD_FIELD_IMAC
|
||||
#define I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN (I40E_CLOUD_FIELD_IMAC | \
|
||||
I40E_CLOUD_FIELD_IVLAN)
|
||||
#define I40E_CLOUD_FILTER_FLAGS_IMAC_TEN_ID (I40E_CLOUD_FIELD_IMAC | \
|
||||
I40E_CLOUD_FIELD_TEN_ID)
|
||||
#define I40E_CLOUD_FILTER_FLAGS_OMAC_TEN_ID_IMAC (I40E_CLOUD_FIELD_OMAC | \
|
||||
I40E_CLOUD_FIELD_IMAC | \
|
||||
I40E_CLOUD_FIELD_TEN_ID)
|
||||
#define I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN_TEN_ID (I40E_CLOUD_FIELD_IMAC | \
|
||||
I40E_CLOUD_FIELD_IVLAN | \
|
||||
I40E_CLOUD_FIELD_TEN_ID)
|
||||
#define I40E_CLOUD_FILTER_FLAGS_IIP I40E_CLOUD_FIELD_IIP
|
||||
|
||||
struct i40e_cloud_filter {
|
||||
struct hlist_node cloud_node;
|
||||
unsigned long cookie;
|
||||
u16 seid; /* filter control */
|
||||
/* cloud filter input set follows */
|
||||
u8 dst_mac[ETH_ALEN];
|
||||
u8 src_mac[ETH_ALEN];
|
||||
__be16 vlan_id;
|
||||
u16 seid; /* filter control */
|
||||
__be16 dst_port;
|
||||
__be16 src_port;
|
||||
u32 tenant_id;
|
||||
union {
|
||||
struct {
|
||||
struct in_addr dst_ip;
|
||||
struct in_addr src_ip;
|
||||
} v4;
|
||||
struct {
|
||||
struct in6_addr dst_ip6;
|
||||
struct in6_addr src_ip6;
|
||||
} v6;
|
||||
} ip;
|
||||
#define dst_ipv6 ip.v6.dst_ip6.s6_addr32
|
||||
#define src_ipv6 ip.v6.src_ip6.s6_addr32
|
||||
#define dst_ipv4 ip.v4.dst_ip.s_addr
|
||||
#define src_ipv4 ip.v4.src_ip.s_addr
|
||||
u16 n_proto; /* Ethernet Protocol */
|
||||
u8 ip_proto; /* IPPROTO value */
|
||||
u8 flags;
|
||||
#define I40E_CLOUD_TNL_TYPE_NONE 0xff
|
||||
u8 tunnel_type;
|
||||
};
|
||||
|
||||
#define I40E_ETH_P_LLDP 0x88cc
|
||||
|
@ -492,6 +540,8 @@ struct i40e_pf {
|
|||
#define I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED BIT(27)
|
||||
#define I40E_FLAG_SOURCE_PRUNING_DISABLED BIT(28)
|
||||
#define I40E_FLAG_TC_MQPRIO BIT(29)
|
||||
#define I40E_FLAG_FD_SB_INACTIVE BIT(30)
|
||||
#define I40E_FLAG_FD_SB_TO_CLOUD_FILTER BIT(31)
|
||||
|
||||
struct i40e_client_instance *cinst;
|
||||
bool stat_offsets_loaded;
|
||||
|
@ -574,6 +624,8 @@ struct i40e_pf {
|
|||
u16 phy_led_val;
|
||||
|
||||
u16 override_q_count;
|
||||
u16 last_sw_conf_flags;
|
||||
u16 last_sw_conf_valid_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1392,6 +1392,9 @@ struct i40e_aqc_cloud_filters_element_data {
|
|||
struct {
|
||||
u8 data[16];
|
||||
} v6;
|
||||
struct {
|
||||
__le16 data[8];
|
||||
} raw_v6;
|
||||
} ipaddr;
|
||||
__le16 flags;
|
||||
#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0
|
||||
|
|
|
@ -5436,5 +5436,194 @@ i40e_add_pinfo_to_list(struct i40e_hw *hw,
|
|||
|
||||
status = i40e_aq_write_ppp(hw, (void *)sec, sec->data_end,
|
||||
track_id, &offset, &info, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_aq_add_cloud_filters
|
||||
* @hw: pointer to the hardware structure
|
||||
* @seid: VSI seid to add cloud filters from
|
||||
* @filters: Buffer which contains the filters to be added
|
||||
* @filter_count: number of filters contained in the buffer
|
||||
*
|
||||
* Set the cloud filters for a given VSI. The contents of the
|
||||
* i40e_aqc_cloud_filters_element_data are filled in by the caller
|
||||
* of the function.
|
||||
*
|
||||
**/
|
||||
enum i40e_status_code
|
||||
i40e_aq_add_cloud_filters(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_aqc_cloud_filters_element_data *filters,
|
||||
u8 filter_count)
|
||||
{
|
||||
struct i40e_aq_desc desc;
|
||||
struct i40e_aqc_add_remove_cloud_filters *cmd =
|
||||
(struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
|
||||
enum i40e_status_code status;
|
||||
u16 buff_len;
|
||||
|
||||
i40e_fill_default_direct_cmd_desc(&desc,
|
||||
i40e_aqc_opc_add_cloud_filters);
|
||||
|
||||
buff_len = filter_count * sizeof(*filters);
|
||||
desc.datalen = cpu_to_le16(buff_len);
|
||||
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
|
||||
cmd->num_filters = filter_count;
|
||||
cmd->seid = cpu_to_le16(seid);
|
||||
|
||||
status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_aq_add_cloud_filters_bb
|
||||
* @hw: pointer to the hardware structure
|
||||
* @seid: VSI seid to add cloud filters from
|
||||
* @filters: Buffer which contains the filters in big buffer to be added
|
||||
* @filter_count: number of filters contained in the buffer
|
||||
*
|
||||
* Set the big buffer cloud filters for a given VSI. The contents of the
|
||||
* i40e_aqc_cloud_filters_element_bb are filled in by the caller of the
|
||||
* function.
|
||||
*
|
||||
**/
|
||||
i40e_status
|
||||
i40e_aq_add_cloud_filters_bb(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_aqc_cloud_filters_element_bb *filters,
|
||||
u8 filter_count)
|
||||
{
|
||||
struct i40e_aq_desc desc;
|
||||
struct i40e_aqc_add_remove_cloud_filters *cmd =
|
||||
(struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
|
||||
i40e_status status;
|
||||
u16 buff_len;
|
||||
int i;
|
||||
|
||||
i40e_fill_default_direct_cmd_desc(&desc,
|
||||
i40e_aqc_opc_add_cloud_filters);
|
||||
|
||||
buff_len = filter_count * sizeof(*filters);
|
||||
desc.datalen = cpu_to_le16(buff_len);
|
||||
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
|
||||
cmd->num_filters = filter_count;
|
||||
cmd->seid = cpu_to_le16(seid);
|
||||
cmd->big_buffer_flag = I40E_AQC_ADD_CLOUD_CMD_BB;
|
||||
|
||||
for (i = 0; i < filter_count; i++) {
|
||||
u16 tnl_type;
|
||||
u32 ti;
|
||||
|
||||
tnl_type = (le16_to_cpu(filters[i].element.flags) &
|
||||
I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK) >>
|
||||
I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT;
|
||||
|
||||
/* Due to hardware eccentricities, the VNI for Geneve is shifted
|
||||
* one more byte further than normally used for Tenant ID in
|
||||
* other tunnel types.
|
||||
*/
|
||||
if (tnl_type == I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE) {
|
||||
ti = le32_to_cpu(filters[i].element.tenant_id);
|
||||
filters[i].element.tenant_id = cpu_to_le32(ti << 8);
|
||||
}
|
||||
}
|
||||
|
||||
status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_aq_rem_cloud_filters
|
||||
* @hw: pointer to the hardware structure
|
||||
* @seid: VSI seid to remove cloud filters from
|
||||
* @filters: Buffer which contains the filters to be removed
|
||||
* @filter_count: number of filters contained in the buffer
|
||||
*
|
||||
* Remove the cloud filters for a given VSI. The contents of the
|
||||
* i40e_aqc_cloud_filters_element_data are filled in by the caller
|
||||
* of the function.
|
||||
*
|
||||
**/
|
||||
enum i40e_status_code
|
||||
i40e_aq_rem_cloud_filters(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_aqc_cloud_filters_element_data *filters,
|
||||
u8 filter_count)
|
||||
{
|
||||
struct i40e_aq_desc desc;
|
||||
struct i40e_aqc_add_remove_cloud_filters *cmd =
|
||||
(struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
|
||||
enum i40e_status_code status;
|
||||
u16 buff_len;
|
||||
|
||||
i40e_fill_default_direct_cmd_desc(&desc,
|
||||
i40e_aqc_opc_remove_cloud_filters);
|
||||
|
||||
buff_len = filter_count * sizeof(*filters);
|
||||
desc.datalen = cpu_to_le16(buff_len);
|
||||
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
|
||||
cmd->num_filters = filter_count;
|
||||
cmd->seid = cpu_to_le16(seid);
|
||||
|
||||
status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_aq_rem_cloud_filters_bb
|
||||
* @hw: pointer to the hardware structure
|
||||
* @seid: VSI seid to remove cloud filters from
|
||||
* @filters: Buffer which contains the filters in big buffer to be removed
|
||||
* @filter_count: number of filters contained in the buffer
|
||||
*
|
||||
* Remove the big buffer cloud filters for a given VSI. The contents of the
|
||||
* i40e_aqc_cloud_filters_element_bb are filled in by the caller of the
|
||||
* function.
|
||||
*
|
||||
**/
|
||||
i40e_status
|
||||
i40e_aq_rem_cloud_filters_bb(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_aqc_cloud_filters_element_bb *filters,
|
||||
u8 filter_count)
|
||||
{
|
||||
struct i40e_aq_desc desc;
|
||||
struct i40e_aqc_add_remove_cloud_filters *cmd =
|
||||
(struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
|
||||
i40e_status status;
|
||||
u16 buff_len;
|
||||
int i;
|
||||
|
||||
i40e_fill_default_direct_cmd_desc(&desc,
|
||||
i40e_aqc_opc_remove_cloud_filters);
|
||||
|
||||
buff_len = filter_count * sizeof(*filters);
|
||||
desc.datalen = cpu_to_le16(buff_len);
|
||||
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
|
||||
cmd->num_filters = filter_count;
|
||||
cmd->seid = cpu_to_le16(seid);
|
||||
cmd->big_buffer_flag = I40E_AQC_ADD_CLOUD_CMD_BB;
|
||||
|
||||
for (i = 0; i < filter_count; i++) {
|
||||
u16 tnl_type;
|
||||
u32 ti;
|
||||
|
||||
tnl_type = (le16_to_cpu(filters[i].element.flags) &
|
||||
I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK) >>
|
||||
I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT;
|
||||
|
||||
/* Due to hardware eccentricities, the VNI for Geneve is shifted
|
||||
* one more byte further than normally used for Tenant ID in
|
||||
* other tunnel types.
|
||||
*/
|
||||
if (tnl_type == I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE) {
|
||||
ti = le32_to_cpu(filters[i].element.tenant_id);
|
||||
filters[i].element.tenant_id = cpu_to_le32(ti << 8);
|
||||
}
|
||||
}
|
||||
|
||||
status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -283,6 +283,22 @@ i40e_status i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw,
|
|||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_resume_port_tx(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status
|
||||
i40e_aq_add_cloud_filters_bb(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_aqc_cloud_filters_element_bb *filters,
|
||||
u8 filter_count);
|
||||
enum i40e_status_code
|
||||
i40e_aq_add_cloud_filters(struct i40e_hw *hw, u16 vsi,
|
||||
struct i40e_aqc_cloud_filters_element_data *filters,
|
||||
u8 filter_count);
|
||||
enum i40e_status_code
|
||||
i40e_aq_rem_cloud_filters(struct i40e_hw *hw, u16 vsi,
|
||||
struct i40e_aqc_cloud_filters_element_data *filters,
|
||||
u8 filter_count);
|
||||
i40e_status
|
||||
i40e_aq_rem_cloud_filters_bb(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_aqc_cloud_filters_element_bb *filters,
|
||||
u8 filter_count);
|
||||
i40e_status i40e_read_lldp_cfg(struct i40e_hw *hw,
|
||||
struct i40e_lldp_variables *lldp_cfg);
|
||||
/* i40e_common */
|
||||
|
|
|
@ -291,6 +291,7 @@ struct i40e_hw_capabilities {
|
|||
#define I40E_CLOUD_FILTER_MODE1 0x6
|
||||
#define I40E_CLOUD_FILTER_MODE2 0x7
|
||||
#define I40E_CLOUD_FILTER_MODE3 0x8
|
||||
#define I40E_SWITCH_MODE_MASK 0xF
|
||||
|
||||
u32 management_mode;
|
||||
u32 mng_protocols_over_mctp;
|
||||
|
|
|
@ -1360,6 +1360,9 @@ struct i40e_aqc_cloud_filters_element_data {
|
|||
struct {
|
||||
u8 data[16];
|
||||
} v6;
|
||||
struct {
|
||||
__le16 data[8];
|
||||
} raw_v6;
|
||||
} ipaddr;
|
||||
__le16 flags;
|
||||
#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0
|
||||
|
|
Loading…
Reference in New Issue