Skip to content

Commit 2f4b411

Browse files
anambiarinJeff Kirsher
authored andcommitted
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 <[email protected]> Signed-off-by: Kiran Patil <[email protected]> Signed-off-by: Anjali Singhai Jain <[email protected]> Signed-off-by: Jingjing Wu <[email protected]> Acked-by: Shannon Nelson <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent aaf6650 commit 2f4b411

File tree

7 files changed

+1192
-31
lines changed

7 files changed

+1192
-31
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
#include <linux/net_tstamp.h>
5656
#include <linux/ptp_clock_kernel.h>
5757
#include <net/pkt_cls.h>
58+
#include <net/tc_act/tc_gact.h>
59+
#include <net/tc_act/tc_mirred.h>
5860
#include "i40e_type.h"
5961
#include "i40e_prototype.h"
6062
#include "i40e_client.h"
@@ -253,10 +255,56 @@ struct i40e_fdir_filter {
253255
u32 fd_id;
254256
};
255257

258+
#define I40E_CLOUD_FIELD_OMAC 0x01
259+
#define I40E_CLOUD_FIELD_IMAC 0x02
260+
#define I40E_CLOUD_FIELD_IVLAN 0x04
261+
#define I40E_CLOUD_FIELD_TEN_ID 0x08
262+
#define I40E_CLOUD_FIELD_IIP 0x10
263+
264+
#define I40E_CLOUD_FILTER_FLAGS_OMAC I40E_CLOUD_FIELD_OMAC
265+
#define I40E_CLOUD_FILTER_FLAGS_IMAC I40E_CLOUD_FIELD_IMAC
266+
#define I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN (I40E_CLOUD_FIELD_IMAC | \
267+
I40E_CLOUD_FIELD_IVLAN)
268+
#define I40E_CLOUD_FILTER_FLAGS_IMAC_TEN_ID (I40E_CLOUD_FIELD_IMAC | \
269+
I40E_CLOUD_FIELD_TEN_ID)
270+
#define I40E_CLOUD_FILTER_FLAGS_OMAC_TEN_ID_IMAC (I40E_CLOUD_FIELD_OMAC | \
271+
I40E_CLOUD_FIELD_IMAC | \
272+
I40E_CLOUD_FIELD_TEN_ID)
273+
#define I40E_CLOUD_FILTER_FLAGS_IMAC_IVLAN_TEN_ID (I40E_CLOUD_FIELD_IMAC | \
274+
I40E_CLOUD_FIELD_IVLAN | \
275+
I40E_CLOUD_FIELD_TEN_ID)
276+
#define I40E_CLOUD_FILTER_FLAGS_IIP I40E_CLOUD_FIELD_IIP
277+
256278
struct i40e_cloud_filter {
257279
struct hlist_node cloud_node;
258280
unsigned long cookie;
259-
u16 seid; /* filter control */
281+
/* cloud filter input set follows */
282+
u8 dst_mac[ETH_ALEN];
283+
u8 src_mac[ETH_ALEN];
284+
__be16 vlan_id;
285+
u16 seid; /* filter control */
286+
__be16 dst_port;
287+
__be16 src_port;
288+
u32 tenant_id;
289+
union {
290+
struct {
291+
struct in_addr dst_ip;
292+
struct in_addr src_ip;
293+
} v4;
294+
struct {
295+
struct in6_addr dst_ip6;
296+
struct in6_addr src_ip6;
297+
} v6;
298+
} ip;
299+
#define dst_ipv6 ip.v6.dst_ip6.s6_addr32
300+
#define src_ipv6 ip.v6.src_ip6.s6_addr32
301+
#define dst_ipv4 ip.v4.dst_ip.s_addr
302+
#define src_ipv4 ip.v4.src_ip.s_addr
303+
u16 n_proto; /* Ethernet Protocol */
304+
u8 ip_proto; /* IPPROTO value */
305+
u8 flags;
306+
#define I40E_CLOUD_TNL_TYPE_NONE 0xff
307+
u8 tunnel_type;
260308
};
261309

262310
#define I40E_ETH_P_LLDP 0x88cc
@@ -492,6 +540,8 @@ struct i40e_pf {
492540
#define I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED BIT(27)
493541
#define I40E_FLAG_SOURCE_PRUNING_DISABLED BIT(28)
494542
#define I40E_FLAG_TC_MQPRIO BIT(29)
543+
#define I40E_FLAG_FD_SB_INACTIVE BIT(30)
544+
#define I40E_FLAG_FD_SB_TO_CLOUD_FILTER BIT(31)
495545

496546
struct i40e_client_instance *cinst;
497547
bool stat_offsets_loaded;
@@ -574,6 +624,8 @@ struct i40e_pf {
574624
u16 phy_led_val;
575625

576626
u16 override_q_count;
627+
u16 last_sw_conf_flags;
628+
u16 last_sw_conf_valid_flags;
577629
};
578630

579631
/**

drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,9 @@ struct i40e_aqc_cloud_filters_element_data {
13921392
struct {
13931393
u8 data[16];
13941394
} v6;
1395+
struct {
1396+
__le16 data[8];
1397+
} raw_v6;
13951398
} ipaddr;
13961399
__le16 flags;
13971400
#define I40E_AQC_ADD_CLOUD_FILTER_SHIFT 0

drivers/net/ethernet/intel/i40e/i40e_common.c

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5436,5 +5436,194 @@ i40e_add_pinfo_to_list(struct i40e_hw *hw,
54365436

54375437
status = i40e_aq_write_ppp(hw, (void *)sec, sec->data_end,
54385438
track_id, &offset, &info, NULL);
5439+
5440+
return status;
5441+
}
5442+
5443+
/**
5444+
* i40e_aq_add_cloud_filters
5445+
* @hw: pointer to the hardware structure
5446+
* @seid: VSI seid to add cloud filters from
5447+
* @filters: Buffer which contains the filters to be added
5448+
* @filter_count: number of filters contained in the buffer
5449+
*
5450+
* Set the cloud filters for a given VSI. The contents of the
5451+
* i40e_aqc_cloud_filters_element_data are filled in by the caller
5452+
* of the function.
5453+
*
5454+
**/
5455+
enum i40e_status_code
5456+
i40e_aq_add_cloud_filters(struct i40e_hw *hw, u16 seid,
5457+
struct i40e_aqc_cloud_filters_element_data *filters,
5458+
u8 filter_count)
5459+
{
5460+
struct i40e_aq_desc desc;
5461+
struct i40e_aqc_add_remove_cloud_filters *cmd =
5462+
(struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
5463+
enum i40e_status_code status;
5464+
u16 buff_len;
5465+
5466+
i40e_fill_default_direct_cmd_desc(&desc,
5467+
i40e_aqc_opc_add_cloud_filters);
5468+
5469+
buff_len = filter_count * sizeof(*filters);
5470+
desc.datalen = cpu_to_le16(buff_len);
5471+
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
5472+
cmd->num_filters = filter_count;
5473+
cmd->seid = cpu_to_le16(seid);
5474+
5475+
status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
5476+
5477+
return status;
5478+
}
5479+
5480+
/**
5481+
* i40e_aq_add_cloud_filters_bb
5482+
* @hw: pointer to the hardware structure
5483+
* @seid: VSI seid to add cloud filters from
5484+
* @filters: Buffer which contains the filters in big buffer to be added
5485+
* @filter_count: number of filters contained in the buffer
5486+
*
5487+
* Set the big buffer cloud filters for a given VSI. The contents of the
5488+
* i40e_aqc_cloud_filters_element_bb are filled in by the caller of the
5489+
* function.
5490+
*
5491+
**/
5492+
i40e_status
5493+
i40e_aq_add_cloud_filters_bb(struct i40e_hw *hw, u16 seid,
5494+
struct i40e_aqc_cloud_filters_element_bb *filters,
5495+
u8 filter_count)
5496+
{
5497+
struct i40e_aq_desc desc;
5498+
struct i40e_aqc_add_remove_cloud_filters *cmd =
5499+
(struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
5500+
i40e_status status;
5501+
u16 buff_len;
5502+
int i;
5503+
5504+
i40e_fill_default_direct_cmd_desc(&desc,
5505+
i40e_aqc_opc_add_cloud_filters);
5506+
5507+
buff_len = filter_count * sizeof(*filters);
5508+
desc.datalen = cpu_to_le16(buff_len);
5509+
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
5510+
cmd->num_filters = filter_count;
5511+
cmd->seid = cpu_to_le16(seid);
5512+
cmd->big_buffer_flag = I40E_AQC_ADD_CLOUD_CMD_BB;
5513+
5514+
for (i = 0; i < filter_count; i++) {
5515+
u16 tnl_type;
5516+
u32 ti;
5517+
5518+
tnl_type = (le16_to_cpu(filters[i].element.flags) &
5519+
I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK) >>
5520+
I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT;
5521+
5522+
/* Due to hardware eccentricities, the VNI for Geneve is shifted
5523+
* one more byte further than normally used for Tenant ID in
5524+
* other tunnel types.
5525+
*/
5526+
if (tnl_type == I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE) {
5527+
ti = le32_to_cpu(filters[i].element.tenant_id);
5528+
filters[i].element.tenant_id = cpu_to_le32(ti << 8);
5529+
}
5530+
}
5531+
5532+
status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
5533+
5534+
return status;
5535+
}
5536+
5537+
/**
5538+
* i40e_aq_rem_cloud_filters
5539+
* @hw: pointer to the hardware structure
5540+
* @seid: VSI seid to remove cloud filters from
5541+
* @filters: Buffer which contains the filters to be removed
5542+
* @filter_count: number of filters contained in the buffer
5543+
*
5544+
* Remove the cloud filters for a given VSI. The contents of the
5545+
* i40e_aqc_cloud_filters_element_data are filled in by the caller
5546+
* of the function.
5547+
*
5548+
**/
5549+
enum i40e_status_code
5550+
i40e_aq_rem_cloud_filters(struct i40e_hw *hw, u16 seid,
5551+
struct i40e_aqc_cloud_filters_element_data *filters,
5552+
u8 filter_count)
5553+
{
5554+
struct i40e_aq_desc desc;
5555+
struct i40e_aqc_add_remove_cloud_filters *cmd =
5556+
(struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
5557+
enum i40e_status_code status;
5558+
u16 buff_len;
5559+
5560+
i40e_fill_default_direct_cmd_desc(&desc,
5561+
i40e_aqc_opc_remove_cloud_filters);
5562+
5563+
buff_len = filter_count * sizeof(*filters);
5564+
desc.datalen = cpu_to_le16(buff_len);
5565+
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
5566+
cmd->num_filters = filter_count;
5567+
cmd->seid = cpu_to_le16(seid);
5568+
5569+
status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
5570+
5571+
return status;
5572+
}
5573+
5574+
/**
5575+
* i40e_aq_rem_cloud_filters_bb
5576+
* @hw: pointer to the hardware structure
5577+
* @seid: VSI seid to remove cloud filters from
5578+
* @filters: Buffer which contains the filters in big buffer to be removed
5579+
* @filter_count: number of filters contained in the buffer
5580+
*
5581+
* Remove the big buffer cloud filters for a given VSI. The contents of the
5582+
* i40e_aqc_cloud_filters_element_bb are filled in by the caller of the
5583+
* function.
5584+
*
5585+
**/
5586+
i40e_status
5587+
i40e_aq_rem_cloud_filters_bb(struct i40e_hw *hw, u16 seid,
5588+
struct i40e_aqc_cloud_filters_element_bb *filters,
5589+
u8 filter_count)
5590+
{
5591+
struct i40e_aq_desc desc;
5592+
struct i40e_aqc_add_remove_cloud_filters *cmd =
5593+
(struct i40e_aqc_add_remove_cloud_filters *)&desc.params.raw;
5594+
i40e_status status;
5595+
u16 buff_len;
5596+
int i;
5597+
5598+
i40e_fill_default_direct_cmd_desc(&desc,
5599+
i40e_aqc_opc_remove_cloud_filters);
5600+
5601+
buff_len = filter_count * sizeof(*filters);
5602+
desc.datalen = cpu_to_le16(buff_len);
5603+
desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
5604+
cmd->num_filters = filter_count;
5605+
cmd->seid = cpu_to_le16(seid);
5606+
cmd->big_buffer_flag = I40E_AQC_ADD_CLOUD_CMD_BB;
5607+
5608+
for (i = 0; i < filter_count; i++) {
5609+
u16 tnl_type;
5610+
u32 ti;
5611+
5612+
tnl_type = (le16_to_cpu(filters[i].element.flags) &
5613+
I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK) >>
5614+
I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT;
5615+
5616+
/* Due to hardware eccentricities, the VNI for Geneve is shifted
5617+
* one more byte further than normally used for Tenant ID in
5618+
* other tunnel types.
5619+
*/
5620+
if (tnl_type == I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE) {
5621+
ti = le32_to_cpu(filters[i].element.tenant_id);
5622+
filters[i].element.tenant_id = cpu_to_le32(ti << 8);
5623+
}
5624+
}
5625+
5626+
status = i40e_asq_send_command(hw, &desc, filters, buff_len, NULL);
5627+
54395628
return status;
54405629
}

0 commit comments

Comments
 (0)