Skip to content

Commit 3a0b5a2

Browse files
pgardocxanguy11
authored andcommitted
iavf: Introduce new state machines for flow director
New states introduced: IAVF_FDIR_FLTR_DIS_REQUEST IAVF_FDIR_FLTR_DIS_PENDING IAVF_FDIR_FLTR_INACTIVE Current FDIR state machines (SM) are not adequate to handle a few scenarios in the link DOWN/UP event, reset event and ntuple-feature. For example, when VF link goes DOWN and comes back UP administratively, the expectation is that previously installed filters should also be restored. But with current SM, filters are not restored. So with new SM, during link DOWN filters are marked as INACTIVE in the iavf list but removed from PF. After link UP, SM will transition from INACTIVE to ADD_REQUEST to restore the filter. Similarly, with VF reset, filters will be removed from the PF, but marked as INACTIVE in the iavf list. Filters will be restored after reset completion. Steps to reproduce: ------------------- 1. Create a VF. Here VF is enp8s0. 2. Assign IP addresses to VF and link partner and ping continuously from remote. Here remote IP is 1.1.1.1. 3. Check default RX Queue of traffic. ethtool -S enp8s0 | grep -E "rx-[[:digit:]]+\.packets" 4. Add filter - change default RX Queue (to 15 here) ethtool -U ens8s0 flow-type ip4 src-ip 1.1.1.1 action 15 loc 5 5. Ensure filter gets added and traffic is received on RX queue 15 now. Link event testing: ------------------- 6. Bring VF link down and up. If traffic flows to configured queue 15, test is success, otherwise it is a failure. Reset event testing: -------------------- 7. Reset the VF. If traffic flows to configured queue 15, test is success, otherwise it is a failure. Fixes: 0dbfbab ("iavf: Add framework to enable ethtool ntuple filters") Signed-off-by: Piotr Gardocki <piotrx.gardocki@intel.com> Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com> Signed-off-by: Ranganatha Rao <ranganatha.rao@intel.com> Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent 810c38a commit 3a0b5a2

5 files changed

Lines changed: 139 additions & 23 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ struct iavf_adapter {
292292
#define IAVF_FLAG_QUEUES_DISABLED BIT(17)
293293
#define IAVF_FLAG_SETUP_NETDEV_FEATURES BIT(18)
294294
#define IAVF_FLAG_REINIT_MSIX_NEEDED BIT(20)
295+
#define IAVF_FLAG_FDIR_ENABLED BIT(21)
295296
/* duplicates for common code */
296297
#define IAVF_FLAG_DCB_ENABLED 0
297298
/* flags for admin queue service task */

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

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ iavf_get_ethtool_fdir_entry(struct iavf_adapter *adapter,
10611061
struct iavf_fdir_fltr *rule = NULL;
10621062
int ret = 0;
10631063

1064-
if (!FDIR_FLTR_SUPPORT(adapter))
1064+
if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
10651065
return -EOPNOTSUPP;
10661066

10671067
spin_lock_bh(&adapter->fdir_fltr_lock);
@@ -1203,7 +1203,7 @@ iavf_get_fdir_fltr_ids(struct iavf_adapter *adapter, struct ethtool_rxnfc *cmd,
12031203
unsigned int cnt = 0;
12041204
int val = 0;
12051205

1206-
if (!FDIR_FLTR_SUPPORT(adapter))
1206+
if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
12071207
return -EOPNOTSUPP;
12081208

12091209
cmd->data = IAVF_MAX_FDIR_FILTERS;
@@ -1395,7 +1395,7 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
13951395
int count = 50;
13961396
int err;
13971397

1398-
if (!FDIR_FLTR_SUPPORT(adapter))
1398+
if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
13991399
return -EOPNOTSUPP;
14001400

14011401
if (fsp->flow_type & FLOW_MAC_EXT)
@@ -1436,12 +1436,16 @@ static int iavf_add_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
14361436
spin_lock_bh(&adapter->fdir_fltr_lock);
14371437
iavf_fdir_list_add_fltr(adapter, fltr);
14381438
adapter->fdir_active_fltr++;
1439-
fltr->state = IAVF_FDIR_FLTR_ADD_REQUEST;
1440-
adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
1439+
if (adapter->link_up) {
1440+
fltr->state = IAVF_FDIR_FLTR_ADD_REQUEST;
1441+
adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
1442+
} else {
1443+
fltr->state = IAVF_FDIR_FLTR_INACTIVE;
1444+
}
14411445
spin_unlock_bh(&adapter->fdir_fltr_lock);
14421446

1443-
mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
1444-
1447+
if (adapter->link_up)
1448+
mod_delayed_work(adapter->wq, &adapter->watchdog_task, 0);
14451449
ret:
14461450
if (err && fltr)
14471451
kfree(fltr);
@@ -1463,7 +1467,7 @@ static int iavf_del_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
14631467
struct iavf_fdir_fltr *fltr = NULL;
14641468
int err = 0;
14651469

1466-
if (!FDIR_FLTR_SUPPORT(adapter))
1470+
if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
14671471
return -EOPNOTSUPP;
14681472

14691473
spin_lock_bh(&adapter->fdir_fltr_lock);
@@ -1472,6 +1476,11 @@ static int iavf_del_fdir_ethtool(struct iavf_adapter *adapter, struct ethtool_rx
14721476
if (fltr->state == IAVF_FDIR_FLTR_ACTIVE) {
14731477
fltr->state = IAVF_FDIR_FLTR_DEL_REQUEST;
14741478
adapter->aq_required |= IAVF_FLAG_AQ_DEL_FDIR_FILTER;
1479+
} else if (fltr->state == IAVF_FDIR_FLTR_INACTIVE) {
1480+
list_del(&fltr->list);
1481+
kfree(fltr);
1482+
adapter->fdir_active_fltr--;
1483+
fltr = NULL;
14751484
} else {
14761485
err = -EBUSY;
14771486
}
@@ -1780,7 +1789,7 @@ static int iavf_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
17801789
ret = 0;
17811790
break;
17821791
case ETHTOOL_GRXCLSRLCNT:
1783-
if (!FDIR_FLTR_SUPPORT(adapter))
1792+
if (!(adapter->flags & IAVF_FLAG_FDIR_ENABLED))
17841793
break;
17851794
spin_lock_bh(&adapter->fdir_fltr_lock);
17861795
cmd->rule_cnt = adapter->fdir_active_fltr;

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,25 @@
66

77
struct iavf_adapter;
88

9-
/* State of Flow Director filter */
9+
/* State of Flow Director filter
10+
*
11+
* *_REQUEST states are used to mark filter to be sent to PF driver to perform
12+
* an action (either add or delete filter). *_PENDING states are an indication
13+
* that request was sent to PF and the driver is waiting for response.
14+
*
15+
* Both DELETE and DISABLE states are being used to delete a filter in PF.
16+
* The difference is that after a successful response filter in DEL_PENDING
17+
* state is being deleted from VF driver as well and filter in DIS_PENDING state
18+
* is being changed to INACTIVE state.
19+
*/
1020
enum iavf_fdir_fltr_state_t {
1121
IAVF_FDIR_FLTR_ADD_REQUEST, /* User requests to add filter */
1222
IAVF_FDIR_FLTR_ADD_PENDING, /* Filter pending add by the PF */
1323
IAVF_FDIR_FLTR_DEL_REQUEST, /* User requests to delete filter */
1424
IAVF_FDIR_FLTR_DEL_PENDING, /* Filter pending delete by the PF */
25+
IAVF_FDIR_FLTR_DIS_REQUEST, /* Filter scheduled to be disabled */
26+
IAVF_FDIR_FLTR_DIS_PENDING, /* Filter pending disable by the PF */
27+
IAVF_FDIR_FLTR_INACTIVE, /* Filter inactive on link down */
1528
IAVF_FDIR_FLTR_ACTIVE, /* Filter is active */
1629
};
1730

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

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,18 +1353,20 @@ static void iavf_clear_cloud_filters(struct iavf_adapter *adapter)
13531353
**/
13541354
static void iavf_clear_fdir_filters(struct iavf_adapter *adapter)
13551355
{
1356-
struct iavf_fdir_fltr *fdir, *fdirtmp;
1356+
struct iavf_fdir_fltr *fdir;
13571357

13581358
/* remove all Flow Director filters */
13591359
spin_lock_bh(&adapter->fdir_fltr_lock);
1360-
list_for_each_entry_safe(fdir, fdirtmp, &adapter->fdir_list_head,
1361-
list) {
1360+
list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
13621361
if (fdir->state == IAVF_FDIR_FLTR_ADD_REQUEST) {
1363-
list_del(&fdir->list);
1364-
kfree(fdir);
1365-
adapter->fdir_active_fltr--;
1366-
} else {
1367-
fdir->state = IAVF_FDIR_FLTR_DEL_REQUEST;
1362+
/* Cancel a request, keep filter as inactive */
1363+
fdir->state = IAVF_FDIR_FLTR_INACTIVE;
1364+
} else if (fdir->state == IAVF_FDIR_FLTR_ADD_PENDING ||
1365+
fdir->state == IAVF_FDIR_FLTR_ACTIVE) {
1366+
/* Disable filters which are active or have a pending
1367+
* request to PF to be added
1368+
*/
1369+
fdir->state = IAVF_FDIR_FLTR_DIS_REQUEST;
13681370
}
13691371
}
13701372
spin_unlock_bh(&adapter->fdir_fltr_lock);
@@ -4112,6 +4114,33 @@ static int iavf_setup_tc(struct net_device *netdev, enum tc_setup_type type,
41124114
}
41134115
}
41144116

4117+
/**
4118+
* iavf_restore_fdir_filters
4119+
* @adapter: board private structure
4120+
*
4121+
* Restore existing FDIR filters when VF netdev comes back up.
4122+
**/
4123+
static void iavf_restore_fdir_filters(struct iavf_adapter *adapter)
4124+
{
4125+
struct iavf_fdir_fltr *f;
4126+
4127+
spin_lock_bh(&adapter->fdir_fltr_lock);
4128+
list_for_each_entry(f, &adapter->fdir_list_head, list) {
4129+
if (f->state == IAVF_FDIR_FLTR_DIS_REQUEST) {
4130+
/* Cancel a request, keep filter as active */
4131+
f->state = IAVF_FDIR_FLTR_ACTIVE;
4132+
} else if (f->state == IAVF_FDIR_FLTR_DIS_PENDING ||
4133+
f->state == IAVF_FDIR_FLTR_INACTIVE) {
4134+
/* Add filters which are inactive or have a pending
4135+
* request to PF to be deleted
4136+
*/
4137+
f->state = IAVF_FDIR_FLTR_ADD_REQUEST;
4138+
adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
4139+
}
4140+
}
4141+
spin_unlock_bh(&adapter->fdir_fltr_lock);
4142+
}
4143+
41154144
/**
41164145
* iavf_open - Called when a network interface is made active
41174146
* @netdev: network interface device structure
@@ -4179,8 +4208,9 @@ static int iavf_open(struct net_device *netdev)
41794208

41804209
spin_unlock_bh(&adapter->mac_vlan_list_lock);
41814210

4182-
/* Restore VLAN filters that were removed with IFF_DOWN */
4211+
/* Restore filters that were removed with IFF_DOWN */
41834212
iavf_restore_filters(adapter);
4213+
iavf_restore_fdir_filters(adapter);
41844214

41854215
iavf_configure(adapter);
41864216

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

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,8 +1735,8 @@ void iavf_add_fdir_filter(struct iavf_adapter *adapter)
17351735
**/
17361736
void iavf_del_fdir_filter(struct iavf_adapter *adapter)
17371737
{
1738+
struct virtchnl_fdir_del f = {};
17381739
struct iavf_fdir_fltr *fdir;
1739-
struct virtchnl_fdir_del f;
17401740
bool process_fltr = false;
17411741
int len;
17421742

@@ -1753,11 +1753,16 @@ void iavf_del_fdir_filter(struct iavf_adapter *adapter)
17531753
list_for_each_entry(fdir, &adapter->fdir_list_head, list) {
17541754
if (fdir->state == IAVF_FDIR_FLTR_DEL_REQUEST) {
17551755
process_fltr = true;
1756-
memset(&f, 0, len);
17571756
f.vsi_id = fdir->vc_add_msg.vsi_id;
17581757
f.flow_id = fdir->flow_id;
17591758
fdir->state = IAVF_FDIR_FLTR_DEL_PENDING;
17601759
break;
1760+
} else if (fdir->state == IAVF_FDIR_FLTR_DIS_REQUEST) {
1761+
process_fltr = true;
1762+
f.vsi_id = fdir->vc_add_msg.vsi_id;
1763+
f.flow_id = fdir->flow_id;
1764+
fdir->state = IAVF_FDIR_FLTR_DIS_PENDING;
1765+
break;
17611766
}
17621767
}
17631768
spin_unlock_bh(&adapter->fdir_fltr_lock);
@@ -1901,6 +1906,48 @@ static void iavf_netdev_features_vlan_strip_set(struct net_device *netdev,
19011906
netdev->features &= ~NETIF_F_HW_VLAN_CTAG_RX;
19021907
}
19031908

1909+
/**
1910+
* iavf_activate_fdir_filters - Reactivate all FDIR filters after a reset
1911+
* @adapter: private adapter structure
1912+
*
1913+
* Called after a reset to re-add all FDIR filters and delete some of them
1914+
* if they were pending to be deleted.
1915+
*/
1916+
static void iavf_activate_fdir_filters(struct iavf_adapter *adapter)
1917+
{
1918+
struct iavf_fdir_fltr *f, *ftmp;
1919+
bool add_filters = false;
1920+
1921+
spin_lock_bh(&adapter->fdir_fltr_lock);
1922+
list_for_each_entry_safe(f, ftmp, &adapter->fdir_list_head, list) {
1923+
if (f->state == IAVF_FDIR_FLTR_ADD_REQUEST ||
1924+
f->state == IAVF_FDIR_FLTR_ADD_PENDING ||
1925+
f->state == IAVF_FDIR_FLTR_ACTIVE) {
1926+
/* All filters and requests have been removed in PF,
1927+
* restore them
1928+
*/
1929+
f->state = IAVF_FDIR_FLTR_ADD_REQUEST;
1930+
add_filters = true;
1931+
} else if (f->state == IAVF_FDIR_FLTR_DIS_REQUEST ||
1932+
f->state == IAVF_FDIR_FLTR_DIS_PENDING) {
1933+
/* Link down state, leave filters as inactive */
1934+
f->state = IAVF_FDIR_FLTR_INACTIVE;
1935+
} else if (f->state == IAVF_FDIR_FLTR_DEL_REQUEST ||
1936+
f->state == IAVF_FDIR_FLTR_DEL_PENDING) {
1937+
/* Delete filters that were pending to be deleted, the
1938+
* list on PF is already cleared after a reset
1939+
*/
1940+
list_del(&f->list);
1941+
kfree(f);
1942+
adapter->fdir_active_fltr--;
1943+
}
1944+
}
1945+
spin_unlock_bh(&adapter->fdir_fltr_lock);
1946+
1947+
if (add_filters)
1948+
adapter->aq_required |= IAVF_FLAG_AQ_ADD_FDIR_FILTER;
1949+
}
1950+
19041951
/**
19051952
* iavf_virtchnl_completion
19061953
* @adapter: adapter structure
@@ -2078,7 +2125,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
20782125
spin_lock_bh(&adapter->fdir_fltr_lock);
20792126
list_for_each_entry(fdir, &adapter->fdir_list_head,
20802127
list) {
2081-
if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING) {
2128+
if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING ||
2129+
fdir->state == IAVF_FDIR_FLTR_DIS_PENDING) {
20822130
fdir->state = IAVF_FDIR_FLTR_ACTIVE;
20832131
dev_info(&adapter->pdev->dev, "Failed to del Flow Director filter, error %s\n",
20842132
iavf_stat_str(&adapter->hw,
@@ -2214,6 +2262,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
22142262

22152263
spin_unlock_bh(&adapter->mac_vlan_list_lock);
22162264

2265+
iavf_activate_fdir_filters(adapter);
2266+
22172267
iavf_parse_vf_resource_msg(adapter);
22182268

22192269
/* negotiated VIRTCHNL_VF_OFFLOAD_VLAN_V2, so wait for the
@@ -2390,7 +2440,9 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
23902440
list_for_each_entry_safe(fdir, fdir_tmp, &adapter->fdir_list_head,
23912441
list) {
23922442
if (fdir->state == IAVF_FDIR_FLTR_DEL_PENDING) {
2393-
if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS) {
2443+
if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS ||
2444+
del_fltr->status ==
2445+
VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST) {
23942446
dev_info(&adapter->pdev->dev, "Flow Director filter with location %u is deleted\n",
23952447
fdir->loc);
23962448
list_del(&fdir->list);
@@ -2402,6 +2454,17 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
24022454
del_fltr->status);
24032455
iavf_print_fdir_fltr(adapter, fdir);
24042456
}
2457+
} else if (fdir->state == IAVF_FDIR_FLTR_DIS_PENDING) {
2458+
if (del_fltr->status == VIRTCHNL_FDIR_SUCCESS ||
2459+
del_fltr->status ==
2460+
VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST) {
2461+
fdir->state = IAVF_FDIR_FLTR_INACTIVE;
2462+
} else {
2463+
fdir->state = IAVF_FDIR_FLTR_ACTIVE;
2464+
dev_info(&adapter->pdev->dev, "Failed to disable Flow Director filter with status: %d\n",
2465+
del_fltr->status);
2466+
iavf_print_fdir_fltr(adapter, fdir);
2467+
}
24052468
}
24062469
}
24072470
spin_unlock_bh(&adapter->fdir_fltr_lock);

0 commit comments

Comments
 (0)