Commit 242df4f7 authored by Steen Hegelund's avatar Steen Hegelund Committed by David S. Miller

net: microchip: sparx5: Let VCAP API validate added key- and actionfields

Add support for validating keyfields and actionfields when they are added
to a VCAP rule.
We need to ensure that the field is not already present and that the field
is in the key- or actionset, if the client has added a key- or actionset to
the rule at this point.
Signed-off-by: default avatarSteen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent abc4010d
...@@ -790,6 +790,13 @@ const char *vcap_keyfield_name(struct vcap_control *vctrl, ...@@ -790,6 +790,13 @@ const char *vcap_keyfield_name(struct vcap_control *vctrl,
} }
EXPORT_SYMBOL_GPL(vcap_keyfield_name); EXPORT_SYMBOL_GPL(vcap_keyfield_name);
/* map action field id to a string with the action name */
static const char *vcap_actionfield_name(struct vcap_control *vctrl,
enum vcap_action_field action)
{
return vctrl->stats->actionfield_names[action];
}
/* Return the keyfield that matches a key in a keyset */ /* Return the keyfield that matches a key in a keyset */
static const struct vcap_field * static const struct vcap_field *
vcap_find_keyset_keyfield(struct vcap_control *vctrl, vcap_find_keyset_keyfield(struct vcap_control *vctrl,
...@@ -1162,14 +1169,60 @@ static void vcap_copy_from_client_keyfield(struct vcap_rule *rule, ...@@ -1162,14 +1169,60 @@ static void vcap_copy_from_client_keyfield(struct vcap_rule *rule,
memcpy(&field->data, data, sizeof(field->data)); memcpy(&field->data, data, sizeof(field->data));
} }
/* Check if the keyfield is already in the rule */
static bool vcap_keyfield_unique(struct vcap_rule *rule,
enum vcap_key_field key)
{
struct vcap_rule_internal *ri = to_intrule(rule);
const struct vcap_client_keyfield *ckf;
list_for_each_entry(ckf, &ri->data.keyfields, ctrl.list)
if (ckf->ctrl.key == key)
return false;
return true;
}
/* Check if the keyfield is in the keyset */
static bool vcap_keyfield_match_keyset(struct vcap_rule *rule,
enum vcap_key_field key)
{
struct vcap_rule_internal *ri = to_intrule(rule);
enum vcap_keyfield_set keyset = rule->keyset;
enum vcap_type vt = ri->admin->vtype;
const struct vcap_field *fields;
/* the field is accepted if the rule has no keyset yet */
if (keyset == VCAP_KFS_NO_VALUE)
return true;
fields = vcap_keyfields(ri->vctrl, vt, keyset);
if (!fields)
return false;
/* if there is a width there is a way */
return fields[key].width > 0;
}
static int vcap_rule_add_key(struct vcap_rule *rule, static int vcap_rule_add_key(struct vcap_rule *rule,
enum vcap_key_field key, enum vcap_key_field key,
enum vcap_field_type ftype, enum vcap_field_type ftype,
struct vcap_client_keyfield_data *data) struct vcap_client_keyfield_data *data)
{ {
struct vcap_rule_internal *ri = to_intrule(rule);
struct vcap_client_keyfield *field; struct vcap_client_keyfield *field;
/* More validation will be added here later */ if (!vcap_keyfield_unique(rule, key)) {
pr_warn("%s:%d: keyfield %s is already in the rule\n",
__func__, __LINE__,
vcap_keyfield_name(ri->vctrl, key));
return -EINVAL;
}
if (!vcap_keyfield_match_keyset(rule, key)) {
pr_err("%s:%d: keyfield %s does not belong in the rule keyset\n",
__func__, __LINE__,
vcap_keyfield_name(ri->vctrl, key));
return -EINVAL;
}
field = kzalloc(sizeof(*field), GFP_KERNEL); field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field) if (!field)
return -ENOMEM; return -ENOMEM;
...@@ -1262,14 +1315,60 @@ static void vcap_copy_from_client_actionfield(struct vcap_rule *rule, ...@@ -1262,14 +1315,60 @@ static void vcap_copy_from_client_actionfield(struct vcap_rule *rule,
memcpy(&field->data, data, sizeof(field->data)); memcpy(&field->data, data, sizeof(field->data));
} }
/* Check if the actionfield is already in the rule */
static bool vcap_actionfield_unique(struct vcap_rule *rule,
enum vcap_action_field act)
{
struct vcap_rule_internal *ri = to_intrule(rule);
const struct vcap_client_actionfield *caf;
list_for_each_entry(caf, &ri->data.actionfields, ctrl.list)
if (caf->ctrl.action == act)
return false;
return true;
}
/* Check if the actionfield is in the actionset */
static bool vcap_actionfield_match_actionset(struct vcap_rule *rule,
enum vcap_action_field action)
{
enum vcap_actionfield_set actionset = rule->actionset;
struct vcap_rule_internal *ri = to_intrule(rule);
enum vcap_type vt = ri->admin->vtype;
const struct vcap_field *fields;
/* the field is accepted if the rule has no actionset yet */
if (actionset == VCAP_AFS_NO_VALUE)
return true;
fields = vcap_actionfields(ri->vctrl, vt, actionset);
if (!fields)
return false;
/* if there is a width there is a way */
return fields[action].width > 0;
}
static int vcap_rule_add_action(struct vcap_rule *rule, static int vcap_rule_add_action(struct vcap_rule *rule,
enum vcap_action_field action, enum vcap_action_field action,
enum vcap_field_type ftype, enum vcap_field_type ftype,
struct vcap_client_actionfield_data *data) struct vcap_client_actionfield_data *data)
{ {
struct vcap_rule_internal *ri = to_intrule(rule);
struct vcap_client_actionfield *field; struct vcap_client_actionfield *field;
/* More validation will be added here later */ if (!vcap_actionfield_unique(rule, action)) {
pr_warn("%s:%d: actionfield %s is already in the rule\n",
__func__, __LINE__,
vcap_actionfield_name(ri->vctrl, action));
return -EINVAL;
}
if (!vcap_actionfield_match_actionset(rule, action)) {
pr_err("%s:%d: actionfield %s does not belong in the rule actionset\n",
__func__, __LINE__,
vcap_actionfield_name(ri->vctrl, action));
return -EINVAL;
}
field = kzalloc(sizeof(*field), GFP_KERNEL); field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field) if (!field)
return -ENOMEM; return -ENOMEM;
......
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