You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08: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:
committed by
Jeff Kirsher
parent
3872c8d44c
commit
0075fa0fad
@@ -54,6 +54,8 @@
|
||||
#include <net/ip6_checksum.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/tc_act/tc_gact.h>
|
||||
#include <net/tc_act/tc_mirred.h>
|
||||
|
||||
#include "i40e_type.h"
|
||||
#include <linux/avf/virtchnl.h>
|
||||
@@ -184,6 +186,14 @@ struct i40evf_channel_config {
|
||||
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! */
|
||||
enum i40evf_state_t {
|
||||
__I40EVF_STARTUP, /* driver loaded, probe complete */
|
||||
@@ -205,6 +215,36 @@ enum i40evf_critical_section_t {
|
||||
__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 */
|
||||
struct i40evf_adapter {
|
||||
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_ENABLE_CHANNELS BIT(21)
|
||||
#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 */
|
||||
struct net_device *netdev;
|
||||
@@ -335,6 +377,10 @@ struct i40evf_adapter {
|
||||
/* ADQ related members */
|
||||
struct i40evf_channel_config ch_config;
|
||||
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_enable_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_ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1040,6 +1040,134 @@ void i40evf_disable_channels(struct i40evf_adapter *adapter)
|
||||
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
|
||||
* @adapter: adapter structure
|
||||
@@ -1163,6 +1291,42 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
|
||||
adapter->ch_config.state = __I40EVF_TC_RUNNING;
|
||||
netif_tx_start_all_queues(netdev);
|
||||
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:
|
||||
dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
|
||||
v_retval,
|
||||
@@ -1257,6 +1421,29 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
|
||||
}
|
||||
}
|
||||
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:
|
||||
if (adapter->current_op && (v_opcode != adapter->current_op))
|
||||
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
|
||||
|
||||
Reference in New Issue
Block a user