Skip to content

Commit 0dbfbab

Browse files
Haiyue Wanganguy11
authored andcommitted
iavf: Add framework to enable ethtool ntuple filters
Enable ethtool ntuple filter support on the VF driver using the virtchnl interface to the PF driver and the Flow director functionality in the hardware. Signed-off-by: Haiyue Wang <haiyue.wang@intel.com> Tested-by: Chen Bo <BoX.C.Chen@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent d621831 commit 0dbfbab

File tree

4 files changed

+257
-1
lines changed

4 files changed

+257
-1
lines changed

drivers/net/ethernet/intel/iavf/iavf.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "iavf_type.h"
3838
#include <linux/avf/virtchnl.h>
3939
#include "iavf_txrx.h"
40+
#include "iavf_fdir.h"
4041

4142
#define DEFAULT_DEBUG_LEVEL_SHIFT 3
4243
#define PFX "iavf: "
@@ -300,6 +301,8 @@ struct iavf_adapter {
300301
#define IAVF_FLAG_AQ_DISABLE_CHANNELS BIT(22)
301302
#define IAVF_FLAG_AQ_ADD_CLOUD_FILTER BIT(23)
302303
#define IAVF_FLAG_AQ_DEL_CLOUD_FILTER BIT(24)
304+
#define IAVF_FLAG_AQ_ADD_FDIR_FILTER BIT(25)
305+
#define IAVF_FLAG_AQ_DEL_FDIR_FILTER BIT(26)
303306

304307
/* OS defined structs */
305308
struct net_device *netdev;
@@ -340,6 +343,8 @@ struct iavf_adapter {
340343
VIRTCHNL_VF_OFFLOAD_VLAN)
341344
#define ADV_LINK_SUPPORT(_a) ((_a)->vf_res->vf_cap_flags & \
342345
VIRTCHNL_VF_CAP_ADV_LINK_SPEED)
346+
#define FDIR_FLTR_SUPPORT(_a) ((_a)->vf_res->vf_cap_flags & \
347+
VIRTCHNL_VF_OFFLOAD_FDIR_PF)
343348
struct virtchnl_vf_resource *vf_res; /* incl. all VSIs */
344349
struct virtchnl_vsi_resource *vsi_res; /* our LAN VSI */
345350
struct virtchnl_version_info pf_version;
@@ -362,6 +367,11 @@ struct iavf_adapter {
362367
/* lock to protect access to the cloud filter list */
363368
spinlock_t cloud_filter_list_lock;
364369
u16 num_cloud_filters;
370+
371+
#define IAVF_MAX_FDIR_FILTERS 128 /* max allowed Flow Director filters */
372+
u16 fdir_active_fltr;
373+
struct list_head fdir_list_head;
374+
spinlock_t fdir_fltr_lock; /* protect the Flow Director filter list */
365375
};
366376

367377

@@ -432,6 +442,8 @@ void iavf_enable_channels(struct iavf_adapter *adapter);
432442
void iavf_disable_channels(struct iavf_adapter *adapter);
433443
void iavf_add_cloud_filter(struct iavf_adapter *adapter);
434444
void iavf_del_cloud_filter(struct iavf_adapter *adapter);
445+
void iavf_add_fdir_filter(struct iavf_adapter *adapter);
446+
void iavf_del_fdir_filter(struct iavf_adapter *adapter);
435447
struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
436448
const u8 *macaddr);
437449
#endif /* _IAVF_H_ */
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2021, Intel Corporation. */
3+
4+
#ifndef _IAVF_FDIR_H_
5+
#define _IAVF_FDIR_H_
6+
7+
struct iavf_adapter;
8+
9+
/* State of Flow Director filter */
10+
enum iavf_fdir_fltr_state_t {
11+
IAVF_FDIR_FLTR_ADD_REQUEST, /* User requests to add filter */
12+
IAVF_FDIR_FLTR_ADD_PENDING, /* Filter pending add by the PF */
13+
IAVF_FDIR_FLTR_DEL_REQUEST, /* User requests to delete filter */
14+
IAVF_FDIR_FLTR_DEL_PENDING, /* Filter pending delete by the PF */
15+
IAVF_FDIR_FLTR_ACTIVE, /* Filter is active */
16+
};
17+
18+
/* bookkeeping of Flow Director filters */
19+
struct iavf_fdir_fltr {
20+
enum iavf_fdir_fltr_state_t state;
21+
struct list_head list;
22+
23+
u32 flow_id;
24+
25+
struct virtchnl_fdir_add vc_add_msg;
26+
};
27+
28+
int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
29+
void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
30+
bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
31+
void iavf_fdir_list_add_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
32+
struct iavf_fdir_fltr *iavf_find_fdir_fltr_by_loc(struct iavf_adapter *adapter, u32 loc);
33+
#endif /* _IAVF_FDIR_H_ */

drivers/net/ethernet/intel/iavf/iavf_main.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,9 @@ void iavf_down(struct iavf_adapter *adapter)
959959
{
960960
struct net_device *netdev = adapter->netdev;
961961
struct iavf_vlan_filter *vlf;
962-
struct iavf_mac_filter *f;
963962
struct iavf_cloud_filter *cf;
963+
struct iavf_fdir_fltr *fdir;
964+
struct iavf_mac_filter *f;
964965

965966
if (adapter->state <= __IAVF_DOWN_PENDING)
966967
return;
@@ -996,6 +997,13 @@ void iavf_down(struct iavf_adapter *adapter)
996997
}
997998
spin_unlock_bh(&adapter->cloud_filter_list_lock);
998999

1000+
/* remove all Flow Director filters */
1001+
spin_lock_bh(&adapter->fdir_fltr_lock);
1002+
list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
1003+
fdir->state = IAVF_FDIR_FLTR_DEL_REQUEST;
1004+
}
1005+
spin_unlock_bh(&adapter->fdir_fltr_lock);
1006+
9991007
if (!(adapter->flags & IAVF_FLAG_PF_COMMS_FAILED) &&
10001008
adapter->state != __IAVF_RESETTING) {
10011009
/* cancel any current operation */
@@ -1007,6 +1015,7 @@ void iavf_down(struct iavf_adapter *adapter)
10071015
adapter->aq_required = IAVF_FLAG_AQ_DEL_MAC_FILTER;
10081016
adapter->aq_required |= IAVF_FLAG_AQ_DEL_VLAN_FILTER;
10091017
adapter->aq_required |= IAVF_FLAG_AQ_DEL_CLOUD_FILTER;
1018+
adapter->aq_required |= IAVF_FLAG_AQ_DEL_FDIR_FILTER;
10101019
adapter->aq_required |= IAVF_FLAG_AQ_DISABLE_QUEUES;
10111020
}
10121021

@@ -1629,6 +1638,14 @@ static int iavf_process_aq_command(struct iavf_adapter *adapter)
16291638
iavf_add_cloud_filter(adapter);
16301639
return 0;
16311640
}
1641+
if (adapter->aq_required & IAVF_FLAG_AQ_ADD_FDIR_FILTER) {
1642+
iavf_add_fdir_filter(adapter);
1643+
return IAVF_SUCCESS;
1644+
}
1645+
if (adapter->aq_required & IAVF_FLAG_AQ_DEL_FDIR_FILTER) {
1646+
iavf_del_fdir_filter(adapter);
1647+
return IAVF_SUCCESS;
1648+
}
16321649
return -EAGAIN;
16331650
}
16341651

@@ -3738,10 +3755,12 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
37383755

37393756
spin_lock_init(&adapter->mac_vlan_list_lock);
37403757
spin_lock_init(&adapter->cloud_filter_list_lock);
3758+
spin_lock_init(&adapter->fdir_fltr_lock);
37413759

37423760
INIT_LIST_HEAD(&adapter->mac_filter_list);
37433761
INIT_LIST_HEAD(&adapter->vlan_filter_list);
37443762
INIT_LIST_HEAD(&adapter->cloud_filter_list);
3763+
INIT_LIST_HEAD(&adapter->fdir_list_head);
37453764

37463765
INIT_WORK(&adapter->reset_task, iavf_reset_task);
37473766
INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
@@ -3845,6 +3864,7 @@ static void iavf_remove(struct pci_dev *pdev)
38453864
{
38463865
struct net_device *netdev = pci_get_drvdata(pdev);
38473866
struct iavf_adapter *adapter = netdev_priv(netdev);
3867+
struct iavf_fdir_fltr *fdir, *fdirtmp;
38483868
struct iavf_vlan_filter *vlf, *vlftmp;
38493869
struct iavf_mac_filter *f, *ftmp;
38503870
struct iavf_cloud_filter *cf, *cftmp;
@@ -3926,6 +3946,13 @@ static void iavf_remove(struct pci_dev *pdev)
39263946
}
39273947
spin_unlock_bh(&adapter->cloud_filter_list_lock);
39283948

3949+
spin_lock_bh(&adapter->fdir_fltr_lock);
3950+
list_for_each_entry_safe(fdir, fdirtmp, &adapter->fdir_list_head, list) {
3951+
list_del(&fdir->list);
3952+
kfree(fdir);
3953+
}
3954+
spin_unlock_bh(&adapter->fdir_fltr_lock);
3955+
39293956
free_netdev(netdev);
39303957

39313958
pci_disable_pcie_error_reporting(pdev);

drivers/net/ethernet/intel/iavf/iavf_virtchnl.c

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ int iavf_send_vf_config_msg(struct iavf_adapter *adapter)
140140
VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
141141
VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
142142
VIRTCHNL_VF_OFFLOAD_ADQ |
143+
VIRTCHNL_VF_OFFLOAD_FDIR_PF |
143144
VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
144145

145146
adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
@@ -1197,6 +1198,101 @@ void iavf_del_cloud_filter(struct iavf_adapter *adapter)
11971198
kfree(f);
11981199
}
11991200

1201+
/**
1202+
* iavf_add_fdir_filter
1203+
* @adapter: the VF adapter structure
1204+
*
1205+
* Request that the PF add Flow Director filters as specified
1206+
* by the user via ethtool.
1207+
**/
1208+
void iavf_add_fdir_filter(struct iavf_adapter *adapter)
1209+
{
1210+
struct iavf_fdir_fltr *fdir;
1211+
struct virtchnl_fdir_add *f;
1212+
bool process_fltr = false;
1213+
int len;
1214+
1215+
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
1216+
/* bail because we already have a command pending */
1217+
dev_err(&adapter->pdev->dev, "Cannot add Flow Director filter, command %d pending\n",
1218+
adapter->current_op);
1219+
return;
1220+
}
1221+
1222+
len = sizeof(struct virtchnl_fdir_add);
1223+
f = kzalloc(len, GFP_KERNEL);
1224+
if (!f)
1225+
return;
1226+
1227+
spin_lock_bh(&adapter->fdir_fltr_lock);
1228+
list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
1229+
if (fdir->state == IAVF_FDIR_FLTR_ADD_REQUEST) {
1230+
process_fltr = true;
1231+
fdir->state = IAVF_FDIR_FLTR_ADD_PENDING;
1232+
memcpy(f, &fdir->vc_add_msg, len);
1233+
break;
1234+
}
1235+
}
1236+
spin_unlock_bh(&adapter->fdir_fltr_lock);
1237+
1238+
if (!process_fltr) {
1239+
/* prevent iavf_add_fdir_filter() from being called when there
1240+
* are no filters to add
1241+
*/
1242+
adapter->aq_required &= ~IAVF_FLAG_AQ_ADD_FDIR_FILTER;
1243+
kfree(f);
1244+
return;
1245+
}
1246+
adapter->current_op = VIRTCHNL_OP_ADD_FDIR_FILTER;
1247+
iavf_send_pf_msg(adapter, VIRTCHNL_OP_ADD_FDIR_FILTER, (u8 *)f, len);
1248+
kfree(f);
1249+
}
1250+
1251+
/**
1252+
* iavf_del_fdir_filter
1253+
* @adapter: the VF adapter structure
1254+
*
1255+
* Request that the PF delete Flow Director filters as specified
1256+
* by the user via ethtool.
1257+
**/
1258+
void iavf_del_fdir_filter(struct iavf_adapter *adapter)
1259+
{
1260+
struct iavf_fdir_fltr *fdir;
1261+
struct virtchnl_fdir_del f;
1262+
bool process_fltr = false;
1263+
int len;
1264+
1265+
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
1266+
/* bail because we already have a command pending */
1267+
dev_err(&adapter->pdev->dev, "Cannot remove Flow Director filter, command %d pending\n",
1268+
adapter->current_op);
1269+
return;
1270+
}
1271+
1272+
len = sizeof(struct virtchnl_fdir_del);
1273+
1274+
spin_lock_bh(&adapter->fdir_fltr_lock);
1275+
list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
1276+
if (fdir->state == IAVF_FDIR_FLTR_DEL_REQUEST) {
1277+
process_fltr = true;
1278+
memset(&f, 0, len);
1279+
f.vsi_id = fdir->vc_add_msg.vsi_id;
1280+
f.flow_id = fdir->flow_id;
1281+
fdir->state = IAVF_FDIR_FLTR_DEL_PENDING;
1282+
break;
1283+
}
1284+
}
1285+
spin_unlock_bh(&adapter->fdir_fltr_lock);
1286+
1287+
if (!process_fltr) {
1288+
adapter->aq_required &= ~IAVF_FLAG_AQ_DEL_FDIR_FILTER;
1289+
return;
1290+
}
1291+
1292+
adapter->current_op = VIRTCHNL_OP_DEL_FDIR_FILTER;
1293+
iavf_send_pf_msg(adapter, VIRTCHNL_OP_DEL_FDIR_FILTER, (u8 *)&f, len);
1294+
}
1295+
12001296
/**
12011297
* iavf_request_reset
12021298
* @adapter: adapter structure
@@ -1357,6 +1453,48 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
13571453
}
13581454
}
13591455
break;
1456+
case VIRTCHNL_OP_ADD_FDIR_FILTER: {
1457+
struct iavf_fdir_fltr *fdir, *fdir_tmp;
1458+
1459+
spin_lock_bh(&adapter->fdir_fltr_lock);
1460+
list_for_each_entry_safe(fdir, fdir_tmp,
1461+
&adapter->fdir_list_head,
1462+
list) {
1463+
if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING) {
1464+
dev_info(&adapter->pdev->dev, "Failed to add Flow Director filter, error %s\n",
1465+
iavf_stat_str(&adapter->hw,
1466+
v_retval));
1467+
if (msglen)
1468+
dev_err(&adapter->pdev->dev,
1469+
"%s\n", msg);
1470+
list_del(&fdir->list);
1471+
kfree(fdir);
1472+
adapter->fdir_active_fltr--;
1473+
}
1474+
}
1475+
spin_unlock_bh(&adapter->fdir_fltr_lock);
1476+
}
1477+
break;
1478+
case VIRTCHNL_OP_DEL_FDIR_FILTER: {
1479+
struct iavf_fdir_fltr *fdir;
1480+
1481+
spin_lock_bh(&adapter->fdir_fltr_lock);
1482+
list_for_each_entry(fdir, &adapter->fdir_list_head,
1483+
list) {
1484+
if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING) {
1485+
fdir->state = IAVF_FDIR_FLTR_ACTIVE;
1486+
dev_info(&adapter->pdev->dev, "Failed to del Flow Director filter, error %s\n",
1487+
iavf_stat_str(&adapter->hw,
1488+
v_retval));
1489+
}
1490+
}
1491+
spin_unlock_bh(&adapter->fdir_fltr_lock);
1492+
}
1493+
break;
1494+
case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
1495+
case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
1496+
dev_warn(&adapter->pdev->dev, "Changing VLAN Stripping is not allowed when Port VLAN is configured\n");
1497+
break;
13601498
default:
13611499
dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
13621500
v_retval, iavf_stat_str(&adapter->hw, v_retval),
@@ -1490,6 +1628,52 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
14901628
}
14911629
}
14921630
break;
1631+
case VIRTCHNL_OP_ADD_FDIR_FILTER: {
1632+
struct virtchnl_fdir_add *add_fltr = (struct virtchnl_fdir_add *)msg;
1633+
struct iavf_fdir_fltr *fdir, *fdir_tmp;
1634+
1635+
spin_lock_bh(&adapter->fdir_fltr_lock);
1636+
list_for_each_entry_safe(fdir, fdir_tmp,
1637+
&adapter->fdir_list_head,
1638+
list) {
1639+
if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING) {
1640+
if (add_fltr->status == VIRTCHNL_FDIR_SUCCESS) {
1641+
fdir->state = IAVF_FDIR_FLTR_ACTIVE;
1642+
fdir->flow_id = add_fltr->flow_id;
1643+
} else {
1644+
dev_info(&adapter->pdev->dev, "Failed to add Flow Director filter with status: %d\n",
1645+
add_fltr->status);
1646+
list_del(&fdir->list);
1647+
kfree(fdir);
1648+
adapter->fdir_active_fltr--;
1649+
}
1650+
}
1651+
}
1652+
spin_unlock_bh(&adapter->fdir_fltr_lock);
1653+
}
1654+
break;
1655+
case VIRTCHNL_OP_DEL_FDIR_FILTER: {
1656+
struct virtchnl_fdir_del *del_fltr = (struct virtchnl_fdir_del *)msg;
1657+
struct iavf_fdir_fltr *fdir, *fdir_tmp;
1658+
1659+
spin_lock_bh(&adapter->fdir_fltr_lock);
1660+
list_for_each_entry_safe(fdir, fdir_tmp, &adapter->fdir_list_head,
1661+
list) {
1662+
if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING) {
1663+
if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS) {
1664+
list_del(&fdir->list);
1665+
kfree(fdir);
1666+
adapter->fdir_active_fltr--;
1667+
} else {
1668+
fdir->state = IAVF_FDIR_FLTR_ACTIVE;
1669+
dev_info(&adapter->pdev->dev, "Failed to delete Flow Director filter with status: %d\n",
1670+
del_fltr->status);
1671+
}
1672+
}
1673+
}
1674+
spin_unlock_bh(&adapter->fdir_fltr_lock);
1675+
}
1676+
break;
14931677
default:
14941678
if (adapter->current_op && (v_opcode != adapter->current_op))
14951679
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",

0 commit comments

Comments
 (0)