Commit 6d1c604d authored by Edward Cree's avatar Edward Cree Committed by Jakub Kicinski

sfc: add Layer 2 matches to ef100 TC offload

Support matching on EtherType, VLANs and ethernet source/destination
 addresses, with masking if supported by the hardware.
Signed-off-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f0b59ad1
...@@ -283,7 +283,14 @@ int efx_mae_match_check_caps(struct efx_nic *efx, ...@@ -283,7 +283,14 @@ int efx_mae_match_check_caps(struct efx_nic *efx,
mask_type_name(ingress_port_mask_type)); mask_type_name(ingress_port_mask_type));
return rc; return rc;
} }
if (CHECK(RECIRC_ID, recirc_id)) if (CHECK(ETHER_TYPE, eth_proto) ||
CHECK(VLAN0_TCI, vlan_tci[0]) ||
CHECK(VLAN0_PROTO, vlan_proto[0]) ||
CHECK(VLAN1_TCI, vlan_tci[1]) ||
CHECK(VLAN1_PROTO, vlan_proto[1]) ||
CHECK(ETH_SADDR, eth_saddr) ||
CHECK(ETH_DADDR, eth_daddr) ||
CHECK(RECIRC_ID, recirc_id))
return rc; return rc;
return 0; return 0;
} }
...@@ -460,6 +467,34 @@ static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit), ...@@ -460,6 +467,34 @@ static int efx_mae_populate_match_criteria(MCDI_DECLARE_STRUCT_PTR(match_crit),
match->value.recirc_id); match->value.recirc_id);
MCDI_STRUCT_SET_BYTE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK, MCDI_STRUCT_SET_BYTE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK,
match->mask.recirc_id); match->mask.recirc_id);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE,
match->value.eth_proto);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETHER_TYPE_BE_MASK,
match->mask.eth_proto);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE,
match->value.vlan_tci[0]);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_TCI_BE_MASK,
match->mask.vlan_tci[0]);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE,
match->value.vlan_proto[0]);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN0_PROTO_BE_MASK,
match->mask.vlan_proto[0]);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE,
match->value.vlan_tci[1]);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_TCI_BE_MASK,
match->mask.vlan_tci[1]);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE,
match->value.vlan_proto[1]);
MCDI_STRUCT_SET_WORD_BE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_VLAN1_PROTO_BE_MASK,
match->mask.vlan_proto[1]);
memcpy(MCDI_STRUCT_PTR(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE),
match->value.eth_saddr, ETH_ALEN);
memcpy(MCDI_STRUCT_PTR(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_SADDR_BE_MASK),
match->mask.eth_saddr, ETH_ALEN);
memcpy(MCDI_STRUCT_PTR(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE),
match->value.eth_daddr, ETH_ALEN);
memcpy(MCDI_STRUCT_PTR(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_ETH_DADDR_BE_MASK),
match->mask.eth_daddr, ETH_ALEN);
return 0; return 0;
} }
......
...@@ -224,6 +224,12 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); ...@@ -224,6 +224,12 @@ void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define MCDI_WORD(_buf, _field) \ #define MCDI_WORD(_buf, _field) \
((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \ ((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \
le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field))) le16_to_cpu(*(__force const __le16 *)MCDI_PTR(_buf, _field)))
/* Write a 16-bit field defined in the protocol as being big-endian. */
#define MCDI_STRUCT_SET_WORD_BE(_buf, _field, _value) do { \
BUILD_BUG_ON(_field ## _LEN != 2); \
BUILD_BUG_ON(_field ## _OFST & 1); \
*(__force __be16 *)MCDI_STRUCT_PTR(_buf, _field) = (_value); \
} while (0)
#define MCDI_SET_DWORD(_buf, _field, _value) \ #define MCDI_SET_DWORD(_buf, _field, _value) \
EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value) EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value)
#define MCDI_STRUCT_SET_DWORD(_buf, _field, _value) \ #define MCDI_STRUCT_SET_DWORD(_buf, _field, _value) \
......
...@@ -124,6 +124,20 @@ static void efx_tc_flow_free(void *ptr, void *arg) ...@@ -124,6 +124,20 @@ static void efx_tc_flow_free(void *ptr, void *arg)
kfree(rule); kfree(rule);
} }
/* Boilerplate for the simple 'copy a field' cases */
#define _MAP_KEY_AND_MASK(_name, _type, _tcget, _tcfield, _field) \
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_##_name)) { \
struct flow_match_##_type fm; \
\
flow_rule_match_##_tcget(rule, &fm); \
match->value._field = fm.key->_tcfield; \
match->mask._field = fm.mask->_tcfield; \
}
#define MAP_KEY_AND_MASK(_name, _type, _tcfield, _field) \
_MAP_KEY_AND_MASK(_name, _type, _type, _tcfield, _field)
#define MAP_ENC_KEY_AND_MASK(_name, _type, _tcget, _tcfield, _field) \
_MAP_KEY_AND_MASK(ENC_##_name, _type, _tcget, _tcfield, _field)
static int efx_tc_flower_parse_match(struct efx_nic *efx, static int efx_tc_flower_parse_match(struct efx_nic *efx,
struct flow_rule *rule, struct flow_rule *rule,
struct efx_tc_match *match, struct efx_tc_match *match,
...@@ -144,26 +158,64 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx, ...@@ -144,26 +158,64 @@ static int efx_tc_flower_parse_match(struct efx_nic *efx,
} }
if (dissector->used_keys & if (dissector->used_keys &
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) | ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_BASIC))) { BIT(FLOW_DISSECTOR_KEY_BASIC) |
BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_VLAN) |
BIT(FLOW_DISSECTOR_KEY_CVLAN))) {
NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported flower keys %#x", NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported flower keys %#x",
dissector->used_keys); dissector->used_keys);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
MAP_KEY_AND_MASK(BASIC, basic, n_proto, eth_proto);
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
struct flow_match_basic fm; struct flow_match_basic fm;
flow_rule_match_basic(rule, &fm); flow_rule_match_basic(rule, &fm);
if (fm.mask->n_proto) {
NL_SET_ERR_MSG_MOD(extack, "Unsupported eth_proto match");
return -EOPNOTSUPP;
}
if (fm.mask->ip_proto) { if (fm.mask->ip_proto) {
NL_SET_ERR_MSG_MOD(extack, "Unsupported ip_proto match"); NL_SET_ERR_MSG_MOD(extack, "Unsupported ip_proto match");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
} }
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
struct flow_match_vlan fm;
flow_rule_match_vlan(rule, &fm);
if (fm.mask->vlan_id || fm.mask->vlan_priority || fm.mask->vlan_tpid) {
match->value.vlan_proto[0] = fm.key->vlan_tpid;
match->mask.vlan_proto[0] = fm.mask->vlan_tpid;
match->value.vlan_tci[0] = cpu_to_be16(fm.key->vlan_priority << 13 |
fm.key->vlan_id);
match->mask.vlan_tci[0] = cpu_to_be16(fm.mask->vlan_priority << 13 |
fm.mask->vlan_id);
}
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
struct flow_match_vlan fm;
flow_rule_match_cvlan(rule, &fm);
if (fm.mask->vlan_id || fm.mask->vlan_priority || fm.mask->vlan_tpid) {
match->value.vlan_proto[1] = fm.key->vlan_tpid;
match->mask.vlan_proto[1] = fm.mask->vlan_tpid;
match->value.vlan_tci[1] = cpu_to_be16(fm.key->vlan_priority << 13 |
fm.key->vlan_id);
match->mask.vlan_tci[1] = cpu_to_be16(fm.mask->vlan_priority << 13 |
fm.mask->vlan_id);
}
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
struct flow_match_eth_addrs fm;
flow_rule_match_eth_addrs(rule, &fm);
ether_addr_copy(match->value.eth_saddr, fm.key->src);
ether_addr_copy(match->value.eth_daddr, fm.key->dst);
ether_addr_copy(match->mask.eth_saddr, fm.mask->src);
ether_addr_copy(match->mask.eth_daddr, fm.mask->dst);
}
return 0; return 0;
} }
......
...@@ -26,6 +26,10 @@ struct efx_tc_match_fields { ...@@ -26,6 +26,10 @@ struct efx_tc_match_fields {
/* L1 */ /* L1 */
u32 ingress_port; u32 ingress_port;
u8 recirc_id; u8 recirc_id;
/* L2 (inner when encap) */
__be16 eth_proto;
__be16 vlan_tci[2], vlan_proto[2];
u8 eth_saddr[ETH_ALEN], eth_daddr[ETH_ALEN];
}; };
struct efx_tc_match { struct efx_tc_match {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment