mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
i40evf: Add support to apply cloud filters
This patch enables a tc filter to be applied as a cloud filter for the VF. This patch adds functions which parse the tc filter, extract the necessary fields needed to configure the filter and package them in a virtchnl message to be sent to the PF to apply them. Signed-off-by: Harshitha Ramamurthy <harshitha.ramamurthy@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
1 parent
3872c8d44c
commit
0075fa0fad
3 files changed
+810
-5
No files matched your search
@@ -54,6 +54,8 @@
|
|||||||
#include <net/ip6_checksum.h>
|
#include <net/ip6_checksum.h>
|
||||||
#include <net/pkt_cls.h>
|
#include <net/pkt_cls.h>
|
||||||
#include <net/udp.h>
|
#include <net/udp.h>
|
||||||
|
#include <net/tc_act/tc_gact.h>
|
||||||
|
#include <net/tc_act/tc_mirred.h>
|
||||||
|
|
||||||
#include "i40e_type.h"
|
#include "i40e_type.h"
|
||||||
#include <linux/avf/virtchnl.h>
|
#include <linux/avf/virtchnl.h>
|
||||||
@@ -184,6 +186,14 @@ struct i40evf_channel_config {
|
|||||||
u8 total_qps;
|
u8 total_qps;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* State of cloud filter */
|
||||||
|
enum i40evf_cloud_filter_state_t {
|
||||||
|
__I40EVF_CF_INVALID, /* cloud filter not added */
|
||||||
|
__I40EVF_CF_ADD_PENDING, /* cloud filter pending add by the PF */
|
||||||
|
__I40EVF_CF_DEL_PENDING, /* cloud filter pending del by the PF */
|
||||||
|
__I40EVF_CF_ACTIVE, /* cloud filter is active */
|
||||||
|
};
|
||||||
|
|
||||||
/* Driver state. The order of these is important! */
|
/* Driver state. The order of these is important! */
|
||||||
enum i40evf_state_t {
|
enum i40evf_state_t {
|
||||||
__I40EVF_STARTUP, /* driver loaded, probe complete */
|
__I40EVF_STARTUP, /* driver loaded, probe complete */
|
||||||
@@ -205,6 +215,36 @@ enum i40evf_critical_section_t {
|
|||||||
__I40EVF_IN_REMOVE_TASK, /* device being removed */
|
__I40EVF_IN_REMOVE_TASK, /* device being removed */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define I40EVF_CLOUD_FIELD_OMAC 0x01
|
||||||
|
#define I40EVF_CLOUD_FIELD_IMAC 0x02
|
||||||
|
#define I40EVF_CLOUD_FIELD_IVLAN 0x04
|
||||||
|
#define I40EVF_CLOUD_FIELD_TEN_ID 0x08
|
||||||
|
#define I40EVF_CLOUD_FIELD_IIP 0x10
|
||||||
|
|
||||||
|
#define I40EVF_CF_FLAGS_OMAC I40EVF_CLOUD_FIELD_OMAC
|
||||||
|
#define I40EVF_CF_FLAGS_IMAC I40EVF_CLOUD_FIELD_IMAC
|
||||||
|
#define I40EVF_CF_FLAGS_IMAC_IVLAN (I40EVF_CLOUD_FIELD_IMAC |\
|
||||||
|
I40EVF_CLOUD_FIELD_IVLAN)
|
||||||
|
#define I40EVF_CF_FLAGS_IMAC_TEN_ID (I40EVF_CLOUD_FIELD_IMAC |\
|
||||||
|
I40EVF_CLOUD_FIELD_TEN_ID)
|
||||||
|
#define I40EVF_CF_FLAGS_OMAC_TEN_ID_IMAC (I40EVF_CLOUD_FIELD_OMAC |\
|
||||||
|
I40EVF_CLOUD_FIELD_IMAC |\
|
||||||
|
I40EVF_CLOUD_FIELD_TEN_ID)
|
||||||
|
#define I40EVF_CF_FLAGS_IMAC_IVLAN_TEN_ID (I40EVF_CLOUD_FIELD_IMAC |\
|
||||||
|
I40EVF_CLOUD_FIELD_IVLAN |\
|
||||||
|
I40EVF_CLOUD_FIELD_TEN_ID)
|
||||||
|
#define I40EVF_CF_FLAGS_IIP I40E_CLOUD_FIELD_IIP
|
||||||
|
|
||||||
|
/* bookkeeping of cloud filters */
|
||||||
|
struct i40evf_cloud_filter {
|
||||||
|
enum i40evf_cloud_filter_state_t state;
|
||||||
|
struct list_head list;
|
||||||
|
struct virtchnl_filter f;
|
||||||
|
unsigned long cookie;
|
||||||
|
bool del; /* filter needs to be deleted */
|
||||||
|
bool add; /* filter needs to be added */
|
||||||
|
};
|
||||||
|
|
||||||
/* board specific private data structure */
|
/* board specific private data structure */
|
||||||
struct i40evf_adapter {
|
struct i40evf_adapter {
|
||||||
struct timer_list watchdog_timer;
|
struct timer_list watchdog_timer;
|
||||||
@@ -287,6 +327,8 @@ struct i40evf_adapter {
|
|||||||
#define I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING BIT(20)
|
#define I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING BIT(20)
|
||||||
#define I40EVF_FLAG_AQ_ENABLE_CHANNELS BIT(21)
|
#define I40EVF_FLAG_AQ_ENABLE_CHANNELS BIT(21)
|
||||||
#define I40EVF_FLAG_AQ_DISABLE_CHANNELS BIT(22)
|
#define I40EVF_FLAG_AQ_DISABLE_CHANNELS BIT(22)
|
||||||
|
#define I40EVF_FLAG_AQ_ADD_CLOUD_FILTER BIT(23)
|
||||||
|
#define I40EVF_FLAG_AQ_DEL_CLOUD_FILTER BIT(24)
|
||||||
|
|
||||||
/* OS defined structs */
|
/* OS defined structs */
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
@@ -335,6 +377,10 @@ struct i40evf_adapter {
|
|||||||
/* ADQ related members */
|
/* ADQ related members */
|
||||||
struct i40evf_channel_config ch_config;
|
struct i40evf_channel_config ch_config;
|
||||||
u8 num_tc;
|
u8 num_tc;
|
||||||
|
struct list_head cloud_filter_list;
|
||||||
|
/* lock to protest access to the cloud filter list */
|
||||||
|
spinlock_t cloud_filter_list_lock;
|
||||||
|
u16 num_cloud_filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -403,4 +449,6 @@ void i40evf_notify_client_open(struct i40e_vsi *vsi);
|
|||||||
void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset);
|
void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset);
|
||||||
void i40evf_enable_channels(struct i40evf_adapter *adapter);
|
void i40evf_enable_channels(struct i40evf_adapter *adapter);
|
||||||
void i40evf_disable_channels(struct i40evf_adapter *adapter);
|
void i40evf_disable_channels(struct i40evf_adapter *adapter);
|
||||||
|
void i40evf_add_cloud_filter(struct i40evf_adapter *adapter);
|
||||||
|
void i40evf_del_cloud_filter(struct i40evf_adapter *adapter);
|
||||||
#endif /* _I40EVF_H_ */
|
#endif /* _I40EVF_H_ */
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -1040,6 +1040,134 @@ void i40evf_disable_channels(struct i40evf_adapter *adapter)
|
|||||||
NULL, 0);
|
NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i40evf_print_cloud_filter
|
||||||
|
* @adapter: adapter structure
|
||||||
|
* @f: cloud filter to print
|
||||||
|
*
|
||||||
|
* Print the cloud filter
|
||||||
|
**/
|
||||||
|
static void i40evf_print_cloud_filter(struct i40evf_adapter *adapter,
|
||||||
|
struct virtchnl_filter f)
|
||||||
|
{
|
||||||
|
switch (f.flow_type) {
|
||||||
|
case VIRTCHNL_TCP_V4_FLOW:
|
||||||
|
dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI4 src_ip %pI4 dst_port %hu src_port %hu\n",
|
||||||
|
&f.data.tcp_spec.dst_mac, &f.data.tcp_spec.src_mac,
|
||||||
|
ntohs(f.data.tcp_spec.vlan_id),
|
||||||
|
&f.data.tcp_spec.dst_ip[0], &f.data.tcp_spec.src_ip[0],
|
||||||
|
ntohs(f.data.tcp_spec.dst_port),
|
||||||
|
ntohs(f.data.tcp_spec.src_port));
|
||||||
|
break;
|
||||||
|
case VIRTCHNL_TCP_V6_FLOW:
|
||||||
|
dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI6 src_ip %pI6 dst_port %hu src_port %hu\n",
|
||||||
|
&f.data.tcp_spec.dst_mac, &f.data.tcp_spec.src_mac,
|
||||||
|
ntohs(f.data.tcp_spec.vlan_id),
|
||||||
|
&f.data.tcp_spec.dst_ip, &f.data.tcp_spec.src_ip,
|
||||||
|
ntohs(f.data.tcp_spec.dst_port),
|
||||||
|
ntohs(f.data.tcp_spec.src_port));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i40evf_add_cloud_filter
|
||||||
|
* @adapter: adapter structure
|
||||||
|
*
|
||||||
|
* Request that the PF add cloud filters as specified
|
||||||
|
* by the user via tc tool.
|
||||||
|
**/
|
||||||
|
void i40evf_add_cloud_filter(struct i40evf_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct i40evf_cloud_filter *cf;
|
||||||
|
struct virtchnl_filter *f;
|
||||||
|
int len = 0, count = 0;
|
||||||
|
|
||||||
|
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
|
||||||
|
/* bail because we already have a command pending */
|
||||||
|
dev_err(&adapter->pdev->dev, "Cannot add cloud filter, command %d pending\n",
|
||||||
|
adapter->current_op);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
|
||||||
|
if (cf->add) {
|
||||||
|
count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!count) {
|
||||||
|
adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
adapter->current_op = VIRTCHNL_OP_ADD_CLOUD_FILTER;
|
||||||
|
|
||||||
|
len = sizeof(struct virtchnl_filter);
|
||||||
|
f = kzalloc(len, GFP_KERNEL);
|
||||||
|
if (!f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
|
||||||
|
if (cf->add) {
|
||||||
|
memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
|
||||||
|
cf->add = false;
|
||||||
|
cf->state = __I40EVF_CF_ADD_PENDING;
|
||||||
|
i40evf_send_pf_msg(adapter,
|
||||||
|
VIRTCHNL_OP_ADD_CLOUD_FILTER,
|
||||||
|
(u8 *)f, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kfree(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i40evf_del_cloud_filter
|
||||||
|
* @adapter: adapter structure
|
||||||
|
*
|
||||||
|
* Request that the PF delete cloud filters as specified
|
||||||
|
* by the user via tc tool.
|
||||||
|
**/
|
||||||
|
void i40evf_del_cloud_filter(struct i40evf_adapter *adapter)
|
||||||
|
{
|
||||||
|
struct i40evf_cloud_filter *cf, *cftmp;
|
||||||
|
struct virtchnl_filter *f;
|
||||||
|
int len = 0, count = 0;
|
||||||
|
|
||||||
|
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
|
||||||
|
/* bail because we already have a command pending */
|
||||||
|
dev_err(&adapter->pdev->dev, "Cannot remove cloud filter, command %d pending\n",
|
||||||
|
adapter->current_op);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
|
||||||
|
if (cf->del) {
|
||||||
|
count++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!count) {
|
||||||
|
adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
adapter->current_op = VIRTCHNL_OP_DEL_CLOUD_FILTER;
|
||||||
|
|
||||||
|
len = sizeof(struct virtchnl_filter);
|
||||||
|
f = kzalloc(len, GFP_KERNEL);
|
||||||
|
if (!f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
|
||||||
|
if (cf->del) {
|
||||||
|
memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
|
||||||
|
cf->del = false;
|
||||||
|
cf->state = __I40EVF_CF_DEL_PENDING;
|
||||||
|
i40evf_send_pf_msg(adapter,
|
||||||
|
VIRTCHNL_OP_DEL_CLOUD_FILTER,
|
||||||
|
(u8 *)f, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kfree(f);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i40evf_request_reset
|
* i40evf_request_reset
|
||||||
* @adapter: adapter structure
|
* @adapter: adapter structure
|
||||||
@@ -1163,6 +1291,42 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
|
|||||||
adapter->ch_config.state = __I40EVF_TC_RUNNING;
|
adapter->ch_config.state = __I40EVF_TC_RUNNING;
|
||||||
netif_tx_start_all_queues(netdev);
|
netif_tx_start_all_queues(netdev);
|
||||||
break;
|
break;
|
||||||
|
case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
|
||||||
|
struct i40evf_cloud_filter *cf, *cftmp;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(cf, cftmp,
|
||||||
|
&adapter->cloud_filter_list,
|
||||||
|
list) {
|
||||||
|
if (cf->state == __I40EVF_CF_ADD_PENDING) {
|
||||||
|
cf->state = __I40EVF_CF_INVALID;
|
||||||
|
dev_info(&adapter->pdev->dev, "Failed to add cloud filter, error %s\n",
|
||||||
|
i40evf_stat_str(&adapter->hw,
|
||||||
|
v_retval));
|
||||||
|
i40evf_print_cloud_filter(adapter,
|
||||||
|
cf->f);
|
||||||
|
list_del(&cf->list);
|
||||||
|
kfree(cf);
|
||||||
|
adapter->num_cloud_filters--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
|
||||||
|
struct i40evf_cloud_filter *cf;
|
||||||
|
|
||||||
|
list_for_each_entry(cf, &adapter->cloud_filter_list,
|
||||||
|
list) {
|
||||||
|
if (cf->state == __I40EVF_CF_DEL_PENDING) {
|
||||||
|
cf->state = __I40EVF_CF_ACTIVE;
|
||||||
|
dev_info(&adapter->pdev->dev, "Failed to del cloud filter, error %s\n",
|
||||||
|
i40evf_stat_str(&adapter->hw,
|
||||||
|
v_retval));
|
||||||
|
i40evf_print_cloud_filter(adapter,
|
||||||
|
cf->f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
|
dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
|
||||||
v_retval,
|
v_retval,
|
||||||
@@ -1257,6 +1421,29 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
|
||||||
|
struct i40evf_cloud_filter *cf;
|
||||||
|
|
||||||
|
list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
|
||||||
|
if (cf->state == __I40EVF_CF_ADD_PENDING)
|
||||||
|
cf->state = __I40EVF_CF_ACTIVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
|
||||||
|
struct i40evf_cloud_filter *cf, *cftmp;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,
|
||||||
|
list) {
|
||||||
|
if (cf->state == __I40EVF_CF_DEL_PENDING) {
|
||||||
|
cf->state = __I40EVF_CF_INVALID;
|
||||||
|
list_del(&cf->list);
|
||||||
|
kfree(cf);
|
||||||
|
adapter->num_cloud_filters--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (adapter->current_op && (v_opcode != adapter->current_op))
|
if (adapter->current_op && (v_opcode != adapter->current_op))
|
||||||
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
|
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
|
||||||
|
|||||||
Reference in new issue
Block a user