Commit 465a38a2 authored by Steen Hegelund's avatar Steen Hegelund Committed by David S. Miller

net: microchip: sparx5: Support for copying and modifying rules in the API

This adds support for making a copy of a rule and modify keys and actions
to differentiate the copy.
Signed-off-by: default avatarSteen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b084f6cc
...@@ -173,6 +173,7 @@ const struct vcap_set *vcap_keyfieldset(struct vcap_control *vctrl, ...@@ -173,6 +173,7 @@ const struct vcap_set *vcap_keyfieldset(struct vcap_control *vctrl,
return NULL; return NULL;
return kset; return kset;
} }
EXPORT_SYMBOL_GPL(vcap_keyfieldset);
/* Return the typegroup table for the matching keyset (using subword size) */ /* Return the typegroup table for the matching keyset (using subword size) */
const struct vcap_typegroup * const struct vcap_typegroup *
...@@ -824,7 +825,7 @@ vcap_find_keyset_keyfield(struct vcap_control *vctrl, ...@@ -824,7 +825,7 @@ vcap_find_keyset_keyfield(struct vcap_control *vctrl,
} }
/* Match a list of keys against the keysets available in a vcap type */ /* Match a list of keys against the keysets available in a vcap type */
static bool vcap_rule_find_keysets(struct vcap_rule_internal *ri, static bool _vcap_rule_find_keysets(struct vcap_rule_internal *ri,
struct vcap_keyset_list *matches) struct vcap_keyset_list *matches)
{ {
const struct vcap_client_keyfield *ckf; const struct vcap_client_keyfield *ckf;
...@@ -864,6 +865,16 @@ static bool vcap_rule_find_keysets(struct vcap_rule_internal *ri, ...@@ -864,6 +865,16 @@ static bool vcap_rule_find_keysets(struct vcap_rule_internal *ri,
return matches->cnt > 0; return matches->cnt > 0;
} }
/* Match a list of keys against the keysets available in a vcap type */
bool vcap_rule_find_keysets(struct vcap_rule *rule,
struct vcap_keyset_list *matches)
{
struct vcap_rule_internal *ri = to_intrule(rule);
return _vcap_rule_find_keysets(ri, matches);
}
EXPORT_SYMBOL_GPL(vcap_rule_find_keysets);
/* Validate a rule with respect to available port keys */ /* Validate a rule with respect to available port keys */
int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto) int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto)
{ {
...@@ -888,7 +899,7 @@ int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto) ...@@ -888,7 +899,7 @@ int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto)
matches.max = ARRAY_SIZE(keysets); matches.max = ARRAY_SIZE(keysets);
if (ri->data.keyset == VCAP_KFS_NO_VALUE) { if (ri->data.keyset == VCAP_KFS_NO_VALUE) {
/* Iterate over rule keyfields and select keysets that fits */ /* Iterate over rule keyfields and select keysets that fits */
if (!vcap_rule_find_keysets(ri, &matches)) { if (!_vcap_rule_find_keysets(ri, &matches)) {
ri->data.exterr = VCAP_ERR_NO_KEYSET_MATCH; ri->data.exterr = VCAP_ERR_NO_KEYSET_MATCH;
return -EINVAL; return -EINVAL;
} }
...@@ -1270,6 +1281,19 @@ int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin) ...@@ -1270,6 +1281,19 @@ int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin)
} }
EXPORT_SYMBOL_GPL(vcap_del_rules); EXPORT_SYMBOL_GPL(vcap_del_rules);
/* Find a client key field in a rule */
static struct vcap_client_keyfield *
vcap_find_keyfield(struct vcap_rule *rule, enum vcap_key_field key)
{
struct vcap_rule_internal *ri = to_intrule(rule);
struct vcap_client_keyfield *ckf;
list_for_each_entry(ckf, &ri->data.keyfields, ctrl.list)
if (ckf->ctrl.key == key)
return ckf;
return NULL;
}
/* Find information on a key field in a rule */ /* Find information on a key field in a rule */
const struct vcap_field *vcap_lookup_keyfield(struct vcap_rule *rule, const struct vcap_field *vcap_lookup_keyfield(struct vcap_rule *rule,
enum vcap_key_field key) enum vcap_key_field key)
...@@ -1434,6 +1458,19 @@ int vcap_rule_add_key_u128(struct vcap_rule *rule, enum vcap_key_field key, ...@@ -1434,6 +1458,19 @@ int vcap_rule_add_key_u128(struct vcap_rule *rule, enum vcap_key_field key,
} }
EXPORT_SYMBOL_GPL(vcap_rule_add_key_u128); EXPORT_SYMBOL_GPL(vcap_rule_add_key_u128);
/* Find a client action field in a rule */
static struct vcap_client_actionfield *
vcap_find_actionfield(struct vcap_rule *rule, enum vcap_action_field act)
{
struct vcap_rule_internal *ri = (struct vcap_rule_internal *)rule;
struct vcap_client_actionfield *caf;
list_for_each_entry(caf, &ri->data.actionfields, ctrl.list)
if (caf->ctrl.action == act)
return caf;
return NULL;
}
static void vcap_copy_from_client_actionfield(struct vcap_rule *rule, static void vcap_copy_from_client_actionfield(struct vcap_rule *rule,
struct vcap_client_actionfield *field, struct vcap_client_actionfield *field,
struct vcap_client_actionfield_data *data) struct vcap_client_actionfield_data *data)
...@@ -1772,6 +1809,148 @@ int vcap_rule_get_counter(struct vcap_rule *rule, struct vcap_counter *ctr) ...@@ -1772,6 +1809,148 @@ int vcap_rule_get_counter(struct vcap_rule *rule, struct vcap_counter *ctr)
} }
EXPORT_SYMBOL_GPL(vcap_rule_get_counter); EXPORT_SYMBOL_GPL(vcap_rule_get_counter);
static int vcap_rule_mod_key(struct vcap_rule *rule,
enum vcap_key_field key,
enum vcap_field_type ftype,
struct vcap_client_keyfield_data *data)
{
struct vcap_client_keyfield *field;
field = vcap_find_keyfield(rule, key);
if (!field)
return vcap_rule_add_key(rule, key, ftype, data);
vcap_copy_from_client_keyfield(rule, field, data);
return 0;
}
/* Modify a 32 bit key field with value and mask in the rule */
int vcap_rule_mod_key_u32(struct vcap_rule *rule, enum vcap_key_field key,
u32 value, u32 mask)
{
struct vcap_client_keyfield_data data;
data.u32.value = value;
data.u32.mask = mask;
return vcap_rule_mod_key(rule, key, VCAP_FIELD_U32, &data);
}
EXPORT_SYMBOL_GPL(vcap_rule_mod_key_u32);
static int vcap_rule_mod_action(struct vcap_rule *rule,
enum vcap_action_field action,
enum vcap_field_type ftype,
struct vcap_client_actionfield_data *data)
{
struct vcap_client_actionfield *field;
field = vcap_find_actionfield(rule, action);
if (!field)
return vcap_rule_add_action(rule, action, ftype, data);
vcap_copy_from_client_actionfield(rule, field, data);
return 0;
}
/* Modify a 32 bit action field with value in the rule */
int vcap_rule_mod_action_u32(struct vcap_rule *rule,
enum vcap_action_field action,
u32 value)
{
struct vcap_client_actionfield_data data;
data.u32.value = value;
return vcap_rule_mod_action(rule, action, VCAP_FIELD_U32, &data);
}
EXPORT_SYMBOL_GPL(vcap_rule_mod_action_u32);
/* Drop keys in a keylist and any keys that are not supported by the keyset */
int vcap_filter_rule_keys(struct vcap_rule *rule,
enum vcap_key_field keylist[], int length,
bool drop_unsupported)
{
struct vcap_rule_internal *ri = to_intrule(rule);
struct vcap_client_keyfield *ckf, *next_ckf;
const struct vcap_field *fields;
enum vcap_key_field key;
int err = 0;
int idx;
if (length > 0) {
err = -EEXIST;
list_for_each_entry_safe(ckf, next_ckf,
&ri->data.keyfields, ctrl.list) {
key = ckf->ctrl.key;
for (idx = 0; idx < length; ++idx)
if (key == keylist[idx]) {
list_del(&ckf->ctrl.list);
kfree(ckf);
idx++;
err = 0;
}
}
}
if (drop_unsupported) {
err = -EEXIST;
fields = vcap_keyfields(ri->vctrl, ri->admin->vtype,
rule->keyset);
if (!fields)
return err;
list_for_each_entry_safe(ckf, next_ckf,
&ri->data.keyfields, ctrl.list) {
key = ckf->ctrl.key;
if (fields[key].width == 0) {
list_del(&ckf->ctrl.list);
kfree(ckf);
err = 0;
}
}
}
return err;
}
EXPORT_SYMBOL_GPL(vcap_filter_rule_keys);
/* Make a full copy of an existing rule with a new rule id */
struct vcap_rule *vcap_copy_rule(struct vcap_rule *erule)
{
struct vcap_rule_internal *ri = to_intrule(erule);
struct vcap_client_actionfield *caf;
struct vcap_client_keyfield *ckf;
struct vcap_rule *rule;
int err;
err = vcap_api_check(ri->vctrl);
if (err)
return ERR_PTR(err);
rule = vcap_alloc_rule(ri->vctrl, ri->ndev, ri->data.vcap_chain_id,
ri->data.user, ri->data.priority, 0);
if (IS_ERR(rule))
return rule;
list_for_each_entry(ckf, &ri->data.keyfields, ctrl.list) {
/* Add a key duplicate in the new rule */
err = vcap_rule_add_key(rule,
ckf->ctrl.key,
ckf->ctrl.type,
&ckf->data);
if (err)
goto err;
}
list_for_each_entry(caf, &ri->data.actionfields, ctrl.list) {
/* Add a action duplicate in the new rule */
err = vcap_rule_add_action(rule,
caf->ctrl.action,
caf->ctrl.type,
&caf->data);
if (err)
goto err;
}
return rule;
err:
vcap_free_rule(rule);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(vcap_copy_rule);
#ifdef CONFIG_VCAP_KUNIT_TEST #ifdef CONFIG_VCAP_KUNIT_TEST
#include "vcap_api_kunit.c" #include "vcap_api_kunit.c"
#endif #endif
...@@ -168,6 +168,8 @@ int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto); ...@@ -168,6 +168,8 @@ int vcap_val_rule(struct vcap_rule *rule, u16 l3_proto);
int vcap_add_rule(struct vcap_rule *rule); int vcap_add_rule(struct vcap_rule *rule);
/* Delete rule in a VCAP instance */ /* Delete rule in a VCAP instance */
int vcap_del_rule(struct vcap_control *vctrl, struct net_device *ndev, u32 id); int vcap_del_rule(struct vcap_control *vctrl, struct net_device *ndev, u32 id);
/* Make a full copy of an existing rule with a new rule id */
struct vcap_rule *vcap_copy_rule(struct vcap_rule *rule);
/* Update the keyset for the rule */ /* Update the keyset for the rule */
int vcap_set_rule_set_keyset(struct vcap_rule *rule, int vcap_set_rule_set_keyset(struct vcap_rule *rule,
...@@ -213,7 +215,13 @@ bool vcap_is_next_lookup(struct vcap_control *vctrl, int cur_cid, int next_cid); ...@@ -213,7 +215,13 @@ bool vcap_is_next_lookup(struct vcap_control *vctrl, int cur_cid, int next_cid);
/* Provide all rules via a callback interface */ /* Provide all rules via a callback interface */
int vcap_rule_iter(struct vcap_control *vctrl, int vcap_rule_iter(struct vcap_control *vctrl,
int (*callback)(void *, struct vcap_rule *), void *arg); int (*callback)(void *, struct vcap_rule *), void *arg);
/* Match a list of keys against the keysets available in a vcap type */
bool vcap_rule_find_keysets(struct vcap_rule *rule,
struct vcap_keyset_list *matches);
/* Return the keyset information for the keyset */
const struct vcap_set *vcap_keyfieldset(struct vcap_control *vctrl,
enum vcap_type vt,
enum vcap_keyfield_set keyset);
/* Copy to host byte order */ /* Copy to host byte order */
void vcap_netbytes_copy(u8 *dst, u8 *src, int count); void vcap_netbytes_copy(u8 *dst, u8 *src, int count);
...@@ -226,6 +234,10 @@ int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin); ...@@ -226,6 +234,10 @@ int vcap_del_rules(struct vcap_control *vctrl, struct vcap_admin *admin);
/* Add a keyset to a keyset list */ /* Add a keyset to a keyset list */
bool vcap_keyset_list_add(struct vcap_keyset_list *keysetlist, bool vcap_keyset_list_add(struct vcap_keyset_list *keysetlist,
enum vcap_keyfield_set keyset); enum vcap_keyfield_set keyset);
/* Drop keys in a keylist and any keys that are not supported by the keyset */
int vcap_filter_rule_keys(struct vcap_rule *rule,
enum vcap_key_field keylist[], int length,
bool drop_unsupported);
/* map keyset id to a string with the keyset name */ /* map keyset id to a string with the keyset name */
const char *vcap_keyset_name(struct vcap_control *vctrl, const char *vcap_keyset_name(struct vcap_control *vctrl,
...@@ -234,4 +246,12 @@ const char *vcap_keyset_name(struct vcap_control *vctrl, ...@@ -234,4 +246,12 @@ const char *vcap_keyset_name(struct vcap_control *vctrl,
const char *vcap_keyfield_name(struct vcap_control *vctrl, const char *vcap_keyfield_name(struct vcap_control *vctrl,
enum vcap_key_field key); enum vcap_key_field key);
/* Modify a 32 bit key field with value and mask in the rule */
int vcap_rule_mod_key_u32(struct vcap_rule *rule, enum vcap_key_field key,
u32 value, u32 mask);
/* Modify a 32 bit action field with value in the rule */
int vcap_rule_mod_action_u32(struct vcap_rule *rule,
enum vcap_action_field action,
u32 value);
#endif /* __VCAP_API_CLIENT__ */ #endif /* __VCAP_API_CLIENT__ */
...@@ -1197,7 +1197,7 @@ static void vcap_api_rule_find_keyset_basic_test(struct kunit *test) ...@@ -1197,7 +1197,7 @@ static void vcap_api_rule_find_keyset_basic_test(struct kunit *test)
for (idx = 0; idx < ARRAY_SIZE(ckf); idx++) for (idx = 0; idx < ARRAY_SIZE(ckf); idx++)
list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields); list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields);
ret = vcap_rule_find_keysets(&ri, &matches); ret = vcap_rule_find_keysets(&ri.data, &matches);
KUNIT_EXPECT_EQ(test, true, ret); KUNIT_EXPECT_EQ(test, true, ret);
KUNIT_EXPECT_EQ(test, 1, matches.cnt); KUNIT_EXPECT_EQ(test, 1, matches.cnt);
...@@ -1244,7 +1244,7 @@ static void vcap_api_rule_find_keyset_failed_test(struct kunit *test) ...@@ -1244,7 +1244,7 @@ static void vcap_api_rule_find_keyset_failed_test(struct kunit *test)
for (idx = 0; idx < ARRAY_SIZE(ckf); idx++) for (idx = 0; idx < ARRAY_SIZE(ckf); idx++)
list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields); list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields);
ret = vcap_rule_find_keysets(&ri, &matches); ret = vcap_rule_find_keysets(&ri.data, &matches);
KUNIT_EXPECT_EQ(test, false, ret); KUNIT_EXPECT_EQ(test, false, ret);
KUNIT_EXPECT_EQ(test, 0, matches.cnt); KUNIT_EXPECT_EQ(test, 0, matches.cnt);
...@@ -1291,7 +1291,7 @@ static void vcap_api_rule_find_keyset_many_test(struct kunit *test) ...@@ -1291,7 +1291,7 @@ static void vcap_api_rule_find_keyset_many_test(struct kunit *test)
for (idx = 0; idx < ARRAY_SIZE(ckf); idx++) for (idx = 0; idx < ARRAY_SIZE(ckf); idx++)
list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields); list_add_tail(&ckf[idx].ctrl.list, &ri.data.keyfields);
ret = vcap_rule_find_keysets(&ri, &matches); ret = vcap_rule_find_keysets(&ri.data, &matches);
KUNIT_EXPECT_EQ(test, true, ret); KUNIT_EXPECT_EQ(test, true, ret);
KUNIT_EXPECT_EQ(test, 6, matches.cnt); KUNIT_EXPECT_EQ(test, 6, matches.cnt);
......
...@@ -59,10 +59,6 @@ void vcap_iter_update(struct vcap_stream_iter *itr); ...@@ -59,10 +59,6 @@ void vcap_iter_update(struct vcap_stream_iter *itr);
/* Keyset and keyfield functionality */ /* Keyset and keyfield functionality */
/* Return the keyset information for the keyset */
const struct vcap_set *vcap_keyfieldset(struct vcap_control *vctrl,
enum vcap_type vt,
enum vcap_keyfield_set keyset);
/* Return the number of keyfields in the keyset */ /* Return the number of keyfields in the keyset */
int vcap_keyfield_count(struct vcap_control *vctrl, int vcap_keyfield_count(struct vcap_control *vctrl,
enum vcap_type vt, enum vcap_keyfield_set keyset); enum vcap_type vt, enum vcap_keyfield_set keyset);
......
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