mask_type_name(ingress_port_mask_type));
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 0;
}
match->value.recirc_id);
MCDI_STRUCT_SET_BYTE(match_crit, MAE_FIELD_MASK_VALUE_PAIRS_V2_RECIRC_ID_MASK,
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;
}
#define MCDI_WORD(_buf, _field) \
((u16)BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \
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) \
EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value)
#define MCDI_STRUCT_SET_DWORD(_buf, _field, _value) \
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,
struct flow_rule *rule,
struct efx_tc_match *match,
}
if (dissector->used_keys &
~(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",
dissector->used_keys);
return -EOPNOTSUPP;
}
+ MAP_KEY_AND_MASK(BASIC, basic, n_proto, eth_proto);
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
struct flow_match_basic 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) {
NL_SET_ERR_MSG_MOD(extack, "Unsupported ip_proto match");
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;
}
/* L1 */
u32 ingress_port;
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 {