nfp: flower-ct: fill in ct merge check function
Replace merge check stub code with the actual implementation. This checks that the match parts of two tc flows does not conflict. Only overlapping keys needs to be checked, and only the narrowest masked parts needs to be checked, so each key is masked with the AND'd result of both masks before comparing. Signed-off-by: Louis Peens <louis.peens@corigine.com> Signed-off-by: Yinjun Zhang <yinjun.zhang@corigine.com> Signed-off-by: Simon Horman <simon.horman@corigine.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a6ffdd3a0e
commit
c698e2adcc
|
@ -75,7 +75,177 @@ bool is_post_ct_flow(struct flow_cls_offload *flow)
|
|||
static int nfp_ct_merge_check(struct nfp_fl_ct_flow_entry *entry1,
|
||||
struct nfp_fl_ct_flow_entry *entry2)
|
||||
{
|
||||
unsigned int ovlp_keys = entry1->rule->match.dissector->used_keys &
|
||||
entry2->rule->match.dissector->used_keys;
|
||||
bool out;
|
||||
|
||||
/* check the overlapped fields one by one, the unmasked part
|
||||
* should not conflict with each other.
|
||||
*/
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL)) {
|
||||
struct flow_match_control match1, match2;
|
||||
|
||||
flow_rule_match_control(entry1->rule, &match1);
|
||||
flow_rule_match_control(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_BASIC)) {
|
||||
struct flow_match_basic match1, match2;
|
||||
|
||||
flow_rule_match_basic(entry1->rule, &match1);
|
||||
flow_rule_match_basic(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
|
||||
struct flow_match_ipv4_addrs match1, match2;
|
||||
|
||||
flow_rule_match_ipv4_addrs(entry1->rule, &match1);
|
||||
flow_rule_match_ipv4_addrs(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
|
||||
struct flow_match_ipv6_addrs match1, match2;
|
||||
|
||||
flow_rule_match_ipv6_addrs(entry1->rule, &match1);
|
||||
flow_rule_match_ipv6_addrs(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_PORTS)) {
|
||||
struct flow_match_ports match1, match2;
|
||||
|
||||
flow_rule_match_ports(entry1->rule, &match1);
|
||||
flow_rule_match_ports(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
|
||||
struct flow_match_eth_addrs match1, match2;
|
||||
|
||||
flow_rule_match_eth_addrs(entry1->rule, &match1);
|
||||
flow_rule_match_eth_addrs(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_VLAN)) {
|
||||
struct flow_match_vlan match1, match2;
|
||||
|
||||
flow_rule_match_vlan(entry1->rule, &match1);
|
||||
flow_rule_match_vlan(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_MPLS)) {
|
||||
struct flow_match_mpls match1, match2;
|
||||
|
||||
flow_rule_match_mpls(entry1->rule, &match1);
|
||||
flow_rule_match_mpls(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_TCP)) {
|
||||
struct flow_match_tcp match1, match2;
|
||||
|
||||
flow_rule_match_tcp(entry1->rule, &match1);
|
||||
flow_rule_match_tcp(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_IP)) {
|
||||
struct flow_match_ip match1, match2;
|
||||
|
||||
flow_rule_match_ip(entry1->rule, &match1);
|
||||
flow_rule_match_ip(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_KEYID)) {
|
||||
struct flow_match_enc_keyid match1, match2;
|
||||
|
||||
flow_rule_match_enc_keyid(entry1->rule, &match1);
|
||||
flow_rule_match_enc_keyid(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
|
||||
struct flow_match_ipv4_addrs match1, match2;
|
||||
|
||||
flow_rule_match_enc_ipv4_addrs(entry1->rule, &match1);
|
||||
flow_rule_match_enc_ipv4_addrs(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
|
||||
struct flow_match_ipv6_addrs match1, match2;
|
||||
|
||||
flow_rule_match_enc_ipv6_addrs(entry1->rule, &match1);
|
||||
flow_rule_match_enc_ipv6_addrs(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
|
||||
struct flow_match_control match1, match2;
|
||||
|
||||
flow_rule_match_enc_control(entry1->rule, &match1);
|
||||
flow_rule_match_enc_control(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_IP)) {
|
||||
struct flow_match_ip match1, match2;
|
||||
|
||||
flow_rule_match_enc_ip(entry1->rule, &match1);
|
||||
flow_rule_match_enc_ip(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
if (ovlp_keys & BIT(FLOW_DISSECTOR_KEY_ENC_OPTS)) {
|
||||
struct flow_match_enc_opts match1, match2;
|
||||
|
||||
flow_rule_match_enc_opts(entry1->rule, &match1);
|
||||
flow_rule_match_enc_opts(entry2->rule, &match2);
|
||||
COMPARE_UNMASKED_FIELDS(match1, match2, &out);
|
||||
if (out)
|
||||
goto check_failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
check_failed:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int nfp_ct_merge_act_check(struct nfp_fl_ct_flow_entry *pre_ct_entry,
|
||||
|
|
|
@ -9,6 +9,26 @@
|
|||
|
||||
#define NFP_FL_CT_NO_TUN 0xff
|
||||
|
||||
#define COMPARE_UNMASKED_FIELDS(__match1, __match2, __out) \
|
||||
do { \
|
||||
typeof(__match1) _match1 = (__match1); \
|
||||
typeof(__match2) _match2 = (__match2); \
|
||||
bool *_out = (__out); \
|
||||
int i, size = sizeof(*(_match1).key); \
|
||||
char *k1, *m1, *k2, *m2; \
|
||||
*_out = false; \
|
||||
k1 = (char *)_match1.key; \
|
||||
m1 = (char *)_match1.mask; \
|
||||
k2 = (char *)_match2.key; \
|
||||
m2 = (char *)_match2.mask; \
|
||||
for (i = 0; i < size; i++) \
|
||||
if ((k1[i] & m1[i] & m2[i]) ^ \
|
||||
(k2[i] & m1[i] & m2[i])) { \
|
||||
*_out = true; \
|
||||
break; \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
extern const struct rhashtable_params nfp_zone_table_params;
|
||||
extern const struct rhashtable_params nfp_ct_map_params;
|
||||
extern const struct rhashtable_params nfp_tc_ct_merge_params;
|
||||
|
|
Loading…
Reference in New Issue