Skip to content

Commit ae67389

Browse files
jbuchocxanguy11
authored andcommitted
ice: Implement 'flow-type ether' rules
Add support for 'flow-type ether' Flow Director rules via ethtool. Create packet segment info for filter configuration based on ethtool command parameters. Reuse infrastructure already created for ipv4 and ipv6 flows to convert packet segment into extraction sequence, which is later used to program the filter inside Flow Director block of the Rx pipeline. Rules not containing masks are processed by the Flow Director, and support the following set of input parameters in all combinations: src, dst, proto, vlan-etype, vlan, action. It is possible to specify address mask in ethtool parameters but only 00:00:00:00:00 and FF:FF:FF:FF:FF are valid. The same applies to proto, vlan-etype and vlan masks: only 0x0000 and 0xffff masks are valid. Testing: (DUT) iperf3 -s (DUT) ethtool -U ens785f0np0 flow-type ether dst <ens785f0np0 mac> \ action 10 (DUT) watch 'ethtool -S ens785f0np0 | grep rx_queue' (LP) iperf3 -c ${DUT_IP} Counters increase only for: 'rx_queue_10_packets' 'rx_queue_10_bytes' Signed-off-by: Jakub Buchocki <[email protected]> Co-developed-by: Mateusz Pacuszka <[email protected]> Signed-off-by: Mateusz Pacuszka <[email protected]> Reviewed-by: Przemek Kitszel <[email protected]> Signed-off-by: Lukasz Plachno <[email protected]> Reviewed-by: Jacob Keller <[email protected]> Reviewed-by: Simon Horman <[email protected]> Tested-by: Pucha Himasekhar Reddy <[email protected]> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <[email protected]>
1 parent 0a66e97 commit ae67389

File tree

4 files changed

+171
-1
lines changed

4 files changed

+171
-1
lines changed

drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ static struct in6_addr zero_ipv6_addr_mask = {
4141
static int ice_fltr_to_ethtool_flow(enum ice_fltr_ptype flow)
4242
{
4343
switch (flow) {
44+
case ICE_FLTR_PTYPE_NONF_ETH:
45+
return ETHER_FLOW;
4446
case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
4547
return TCP_V4_FLOW;
4648
case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
@@ -72,6 +74,8 @@ static int ice_fltr_to_ethtool_flow(enum ice_fltr_ptype flow)
7274
static enum ice_fltr_ptype ice_ethtool_flow_to_fltr(int eth)
7375
{
7476
switch (eth) {
77+
case ETHER_FLOW:
78+
return ICE_FLTR_PTYPE_NONF_ETH;
7579
case TCP_V4_FLOW:
7680
return ICE_FLTR_PTYPE_NONF_IPV4_TCP;
7781
case UDP_V4_FLOW:
@@ -137,6 +141,10 @@ int ice_get_ethtool_fdir_entry(struct ice_hw *hw, struct ethtool_rxnfc *cmd)
137141
memset(&fsp->m_ext, 0, sizeof(fsp->m_ext));
138142

139143
switch (fsp->flow_type) {
144+
case ETHER_FLOW:
145+
fsp->h_u.ether_spec = rule->eth;
146+
fsp->m_u.ether_spec = rule->eth_mask;
147+
break;
140148
case IPV4_USER_FLOW:
141149
fsp->h_u.usr_ip4_spec.ip_ver = ETH_RX_NFC_IP4;
142150
fsp->h_u.usr_ip4_spec.proto = 0;
@@ -1193,6 +1201,122 @@ ice_set_fdir_ip6_usr_seg(struct ice_flow_seg_info *seg,
11931201
return 0;
11941202
}
11951203

1204+
/**
1205+
* ice_fdir_vlan_valid - validate VLAN data for Flow Director rule
1206+
* @dev: network interface device structure
1207+
* @fsp: pointer to ethtool Rx flow specification
1208+
*
1209+
* Return: true if vlan data is valid, false otherwise
1210+
*/
1211+
static bool ice_fdir_vlan_valid(struct device *dev,
1212+
struct ethtool_rx_flow_spec *fsp)
1213+
{
1214+
if (fsp->m_ext.vlan_etype && !eth_type_vlan(fsp->h_ext.vlan_etype))
1215+
return false;
1216+
1217+
if (fsp->m_ext.vlan_tci && ntohs(fsp->h_ext.vlan_tci) >= VLAN_N_VID)
1218+
return false;
1219+
1220+
/* proto and vlan must have vlan-etype defined */
1221+
if (fsp->m_u.ether_spec.h_proto && fsp->m_ext.vlan_tci &&
1222+
!fsp->m_ext.vlan_etype) {
1223+
dev_warn(dev, "Filter with proto and vlan require also vlan-etype");
1224+
return false;
1225+
}
1226+
1227+
return true;
1228+
}
1229+
1230+
/**
1231+
* ice_set_ether_flow_seg - set address and protocol segments for ether flow
1232+
* @dev: network interface device structure
1233+
* @seg: flow segment for programming
1234+
* @eth_spec: mask data from ethtool
1235+
*
1236+
* Return: 0 on success and errno in case of error.
1237+
*/
1238+
static int ice_set_ether_flow_seg(struct device *dev,
1239+
struct ice_flow_seg_info *seg,
1240+
struct ethhdr *eth_spec)
1241+
{
1242+
ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ETH);
1243+
1244+
/* empty rules are not valid */
1245+
if (is_zero_ether_addr(eth_spec->h_source) &&
1246+
is_zero_ether_addr(eth_spec->h_dest) &&
1247+
!eth_spec->h_proto)
1248+
return -EINVAL;
1249+
1250+
/* Ethertype */
1251+
if (eth_spec->h_proto == htons(0xFFFF)) {
1252+
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_TYPE,
1253+
ICE_FLOW_FLD_OFF_INVAL,
1254+
ICE_FLOW_FLD_OFF_INVAL,
1255+
ICE_FLOW_FLD_OFF_INVAL, false);
1256+
} else if (eth_spec->h_proto) {
1257+
dev_warn(dev, "Only 0x0000 or 0xffff proto mask is allowed for flow-type ether");
1258+
return -EOPNOTSUPP;
1259+
}
1260+
1261+
/* Source MAC address */
1262+
if (is_broadcast_ether_addr(eth_spec->h_source))
1263+
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_SA,
1264+
ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1265+
ICE_FLOW_FLD_OFF_INVAL, false);
1266+
else if (!is_zero_ether_addr(eth_spec->h_source))
1267+
goto err_mask;
1268+
1269+
/* Destination MAC address */
1270+
if (is_broadcast_ether_addr(eth_spec->h_dest))
1271+
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_ETH_DA,
1272+
ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
1273+
ICE_FLOW_FLD_OFF_INVAL, false);
1274+
else if (!is_zero_ether_addr(eth_spec->h_dest))
1275+
goto err_mask;
1276+
1277+
return 0;
1278+
1279+
err_mask:
1280+
dev_warn(dev, "Only 00:00:00:00:00:00 or ff:ff:ff:ff:ff:ff MAC address mask is allowed for flow-type ether");
1281+
return -EOPNOTSUPP;
1282+
}
1283+
1284+
/**
1285+
* ice_set_fdir_vlan_seg - set vlan segments for ether flow
1286+
* @seg: flow segment for programming
1287+
* @ext_masks: masks for additional RX flow fields
1288+
*
1289+
* Return: 0 on success and errno in case of error.
1290+
*/
1291+
static int
1292+
ice_set_fdir_vlan_seg(struct ice_flow_seg_info *seg,
1293+
struct ethtool_flow_ext *ext_masks)
1294+
{
1295+
ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_VLAN);
1296+
1297+
if (ext_masks->vlan_etype) {
1298+
if (ext_masks->vlan_etype != htons(0xFFFF))
1299+
return -EOPNOTSUPP;
1300+
1301+
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_S_VLAN,
1302+
ICE_FLOW_FLD_OFF_INVAL,
1303+
ICE_FLOW_FLD_OFF_INVAL,
1304+
ICE_FLOW_FLD_OFF_INVAL, false);
1305+
}
1306+
1307+
if (ext_masks->vlan_tci) {
1308+
if (ext_masks->vlan_tci != htons(0xFFFF))
1309+
return -EOPNOTSUPP;
1310+
1311+
ice_flow_set_fld(seg, ICE_FLOW_FIELD_IDX_C_VLAN,
1312+
ICE_FLOW_FLD_OFF_INVAL,
1313+
ICE_FLOW_FLD_OFF_INVAL,
1314+
ICE_FLOW_FLD_OFF_INVAL, false);
1315+
}
1316+
1317+
return 0;
1318+
}
1319+
11961320
/**
11971321
* ice_cfg_fdir_xtrct_seq - Configure extraction sequence for the given filter
11981322
* @pf: PF structure
@@ -1209,7 +1333,7 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
12091333
struct device *dev = ice_pf_to_dev(pf);
12101334
enum ice_fltr_ptype fltr_idx;
12111335
struct ice_hw *hw = &pf->hw;
1212-
bool perfect_filter;
1336+
bool perfect_filter = false;
12131337
int ret;
12141338

12151339
seg = devm_kzalloc(dev, sizeof(*seg), GFP_KERNEL);
@@ -1262,6 +1386,16 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
12621386
ret = ice_set_fdir_ip6_usr_seg(seg, &fsp->m_u.usr_ip6_spec,
12631387
&perfect_filter);
12641388
break;
1389+
case ETHER_FLOW:
1390+
ret = ice_set_ether_flow_seg(dev, seg, &fsp->m_u.ether_spec);
1391+
if (!ret && (fsp->m_ext.vlan_etype || fsp->m_ext.vlan_tci)) {
1392+
if (!ice_fdir_vlan_valid(dev, fsp)) {
1393+
ret = -EINVAL;
1394+
break;
1395+
}
1396+
ret = ice_set_fdir_vlan_seg(seg, &fsp->m_ext);
1397+
}
1398+
break;
12651399
default:
12661400
ret = -EINVAL;
12671401
}
@@ -1823,6 +1957,10 @@ ice_set_fdir_input_set(struct ice_vsi *vsi, struct ethtool_rx_flow_spec *fsp,
18231957
input->mask.v6.tc = fsp->m_u.usr_ip6_spec.tclass;
18241958
input->mask.v6.proto = fsp->m_u.usr_ip6_spec.l4_proto;
18251959
break;
1960+
case ETHER_FLOW:
1961+
input->eth = fsp->h_u.ether_spec;
1962+
input->eth_mask = fsp->m_u.ether_spec;
1963+
break;
18261964
default:
18271965
/* not doing un-parsed flow types */
18281966
return -EINVAL;

drivers/net/ethernet/intel/ice/ice_fdir.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include "ice_common.h"
55

66
/* These are training packet headers used to program flow director filters. */
7+
static const u8 ice_fdir_eth_pkt[22];
8+
79
static const u8 ice_fdir_tcpv4_pkt[] = {
810
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
911
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
@@ -416,6 +418,11 @@ static const u8 ice_fdir_ip6_tun_pkt[] = {
416418

417419
/* Flow Director no-op training packet table */
418420
static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {
421+
{
422+
ICE_FLTR_PTYPE_NONF_ETH,
423+
sizeof(ice_fdir_eth_pkt), ice_fdir_eth_pkt,
424+
sizeof(ice_fdir_eth_pkt), ice_fdir_eth_pkt,
425+
},
419426
{
420427
ICE_FLTR_PTYPE_NONF_IPV4_TCP,
421428
sizeof(ice_fdir_tcpv4_pkt), ice_fdir_tcpv4_pkt,
@@ -914,6 +921,21 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
914921
* perspective. The input from user is from Rx filter perspective.
915922
*/
916923
switch (flow) {
924+
case ICE_FLTR_PTYPE_NONF_ETH:
925+
ice_pkt_insert_mac_addr(loc, input->eth.h_dest);
926+
ice_pkt_insert_mac_addr(loc + ETH_ALEN, input->eth.h_source);
927+
if (input->ext_data.vlan_tag || input->ext_data.vlan_type) {
928+
ice_pkt_insert_u16(loc, ICE_ETH_TYPE_F_OFFSET,
929+
input->ext_data.vlan_type);
930+
ice_pkt_insert_u16(loc, ICE_ETH_VLAN_TCI_OFFSET,
931+
input->ext_data.vlan_tag);
932+
ice_pkt_insert_u16(loc, ICE_ETH_TYPE_VLAN_OFFSET,
933+
input->eth.h_proto);
934+
} else {
935+
ice_pkt_insert_u16(loc, ICE_ETH_TYPE_F_OFFSET,
936+
input->eth.h_proto);
937+
}
938+
break;
917939
case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
918940
ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
919941
input->ip.v4.src_ip);
@@ -1201,6 +1223,10 @@ ice_fdir_comp_rules(struct ice_fdir_fltr *a, struct ice_fdir_fltr *b)
12011223
* same flow_type.
12021224
*/
12031225
switch (flow_type) {
1226+
case ICE_FLTR_PTYPE_NONF_ETH:
1227+
if (!memcmp(&a->eth, &b->eth, sizeof(a->eth)))
1228+
return true;
1229+
break;
12041230
case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
12051231
case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
12061232
case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:

drivers/net/ethernet/intel/ice/ice_fdir.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#define ICE_FDIR_MAX_RAW_PKT_SIZE (512 + ICE_FDIR_TUN_PKT_OFF)
99

1010
/* macros for offsets into packets for flow director programming */
11+
#define ICE_ETH_TYPE_F_OFFSET 12
12+
#define ICE_ETH_VLAN_TCI_OFFSET 14
13+
#define ICE_ETH_TYPE_VLAN_OFFSET 16
1114
#define ICE_IPV4_SRC_ADDR_OFFSET 26
1215
#define ICE_IPV4_DST_ADDR_OFFSET 30
1316
#define ICE_IPV4_TCP_SRC_PORT_OFFSET 34
@@ -159,6 +162,8 @@ struct ice_fdir_fltr {
159162
struct list_head fltr_node;
160163
enum ice_fltr_ptype flow_type;
161164

165+
struct ethhdr eth, eth_mask;
166+
162167
union {
163168
struct ice_fdir_v4 v4;
164169
struct ice_fdir_v6 v6;

drivers/net/ethernet/intel/ice/ice_type.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ struct ice_phy_info {
203203
enum ice_fltr_ptype {
204204
/* NONE - used for undef/error */
205205
ICE_FLTR_PTYPE_NONF_NONE = 0,
206+
ICE_FLTR_PTYPE_NONF_ETH,
206207
ICE_FLTR_PTYPE_NONF_IPV4_UDP,
207208
ICE_FLTR_PTYPE_NONF_IPV4_TCP,
208209
ICE_FLTR_PTYPE_NONF_IPV4_SCTP,

0 commit comments

Comments
 (0)