Commit 33e3a273 authored by Steen Hegelund's avatar Steen Hegelund Committed by David S. Miller

net: microchip: vcap api: Convert multi-word keys/actions when encoding

The conversion to the platform specific multi-word format is moved from the
key/action add functions to the encoding key/action.
This allows rules that are disabled (not in VCAP HW) to use the same format
for keys/actions as rules that have just been read from VCAP HW.
Signed-off-by: default avatarHoratiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: default avatarSteen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 01ef75a2
...@@ -508,10 +508,133 @@ static void vcap_encode_keyfield_typegroups(struct vcap_control *vctrl, ...@@ -508,10 +508,133 @@ static void vcap_encode_keyfield_typegroups(struct vcap_control *vctrl,
vcap_encode_typegroups(cache->maskstream, sw_width, tgt, true); vcap_encode_typegroups(cache->maskstream, sw_width, tgt, true);
} }
/* Copy data from src to dst but reverse the data in chunks of 32bits.
* For example if src is 00:11:22:33:44:55 where 55 is LSB the dst will
* have the value 22:33:44:55:00:11.
*/
static void vcap_copy_to_w32be(u8 *dst, const u8 *src, int size)
{
for (int idx = 0; idx < size; ++idx) {
int first_byte_index = 0;
int nidx;
first_byte_index = size - (((idx >> 2) + 1) << 2);
if (first_byte_index < 0)
first_byte_index = 0;
nidx = idx + first_byte_index - (idx & ~0x3);
dst[nidx] = src[idx];
}
}
static void
vcap_copy_from_client_keyfield(struct vcap_rule *rule,
struct vcap_client_keyfield *dst,
const struct vcap_client_keyfield *src)
{
struct vcap_rule_internal *ri = to_intrule(rule);
const struct vcap_client_keyfield_data *sdata;
struct vcap_client_keyfield_data *ddata;
int size;
dst->ctrl.type = src->ctrl.type;
dst->ctrl.key = src->ctrl.key;
INIT_LIST_HEAD(&dst->ctrl.list);
sdata = &src->data;
ddata = &dst->data;
if (!ri->admin->w32be) {
memcpy(ddata, sdata, sizeof(dst->data));
return;
}
size = keyfield_size_table[dst->ctrl.type] / 2;
switch (dst->ctrl.type) {
case VCAP_FIELD_BIT:
case VCAP_FIELD_U32:
memcpy(ddata, sdata, sizeof(dst->data));
break;
case VCAP_FIELD_U48:
vcap_copy_to_w32be(ddata->u48.value, src->data.u48.value, size);
vcap_copy_to_w32be(ddata->u48.mask, src->data.u48.mask, size);
break;
case VCAP_FIELD_U56:
vcap_copy_to_w32be(ddata->u56.value, sdata->u56.value, size);
vcap_copy_to_w32be(ddata->u56.mask, sdata->u56.mask, size);
break;
case VCAP_FIELD_U64:
vcap_copy_to_w32be(ddata->u64.value, sdata->u64.value, size);
vcap_copy_to_w32be(ddata->u64.mask, sdata->u64.mask, size);
break;
case VCAP_FIELD_U72:
vcap_copy_to_w32be(ddata->u72.value, sdata->u72.value, size);
vcap_copy_to_w32be(ddata->u72.mask, sdata->u72.mask, size);
break;
case VCAP_FIELD_U112:
vcap_copy_to_w32be(ddata->u112.value, sdata->u112.value, size);
vcap_copy_to_w32be(ddata->u112.mask, sdata->u112.mask, size);
break;
case VCAP_FIELD_U128:
vcap_copy_to_w32be(ddata->u128.value, sdata->u128.value, size);
vcap_copy_to_w32be(ddata->u128.mask, sdata->u128.mask, size);
break;
}
}
static void
vcap_copy_from_client_actionfield(struct vcap_rule *rule,
struct vcap_client_actionfield *dst,
const struct vcap_client_actionfield *src)
{
struct vcap_rule_internal *ri = to_intrule(rule);
const struct vcap_client_actionfield_data *sdata;
struct vcap_client_actionfield_data *ddata;
int size;
dst->ctrl.type = src->ctrl.type;
dst->ctrl.action = src->ctrl.action;
INIT_LIST_HEAD(&dst->ctrl.list);
sdata = &src->data;
ddata = &dst->data;
if (!ri->admin->w32be) {
memcpy(ddata, sdata, sizeof(dst->data));
return;
}
size = actionfield_size_table[dst->ctrl.type];
switch (dst->ctrl.type) {
case VCAP_FIELD_BIT:
case VCAP_FIELD_U32:
memcpy(ddata, sdata, sizeof(dst->data));
break;
case VCAP_FIELD_U48:
vcap_copy_to_w32be(ddata->u48.value, sdata->u48.value, size);
break;
case VCAP_FIELD_U56:
vcap_copy_to_w32be(ddata->u56.value, sdata->u56.value, size);
break;
case VCAP_FIELD_U64:
vcap_copy_to_w32be(ddata->u64.value, sdata->u64.value, size);
break;
case VCAP_FIELD_U72:
vcap_copy_to_w32be(ddata->u72.value, sdata->u72.value, size);
break;
case VCAP_FIELD_U112:
vcap_copy_to_w32be(ddata->u112.value, sdata->u112.value, size);
break;
case VCAP_FIELD_U128:
vcap_copy_to_w32be(ddata->u128.value, sdata->u128.value, size);
break;
}
}
static int vcap_encode_rule_keyset(struct vcap_rule_internal *ri) static int vcap_encode_rule_keyset(struct vcap_rule_internal *ri)
{ {
const struct vcap_client_keyfield *ckf; const struct vcap_client_keyfield *ckf;
const struct vcap_typegroup *tg_table; const struct vcap_typegroup *tg_table;
struct vcap_client_keyfield tempkf;
const struct vcap_field *kf_table; const struct vcap_field *kf_table;
int keyset_size; int keyset_size;
...@@ -552,7 +675,9 @@ static int vcap_encode_rule_keyset(struct vcap_rule_internal *ri) ...@@ -552,7 +675,9 @@ static int vcap_encode_rule_keyset(struct vcap_rule_internal *ri)
__func__, __LINE__, ckf->ctrl.key); __func__, __LINE__, ckf->ctrl.key);
return -EINVAL; return -EINVAL;
} }
vcap_encode_keyfield(ri, ckf, &kf_table[ckf->ctrl.key], tg_table); vcap_copy_from_client_keyfield(&ri->data, &tempkf, ckf);
vcap_encode_keyfield(ri, &tempkf, &kf_table[ckf->ctrl.key],
tg_table);
} }
/* Add typegroup bits to the key/mask bitstreams */ /* Add typegroup bits to the key/mask bitstreams */
vcap_encode_keyfield_typegroups(ri->vctrl, ri, tg_table); vcap_encode_keyfield_typegroups(ri->vctrl, ri, tg_table);
...@@ -667,6 +792,7 @@ static int vcap_encode_rule_actionset(struct vcap_rule_internal *ri) ...@@ -667,6 +792,7 @@ static int vcap_encode_rule_actionset(struct vcap_rule_internal *ri)
{ {
const struct vcap_client_actionfield *caf; const struct vcap_client_actionfield *caf;
const struct vcap_typegroup *tg_table; const struct vcap_typegroup *tg_table;
struct vcap_client_actionfield tempaf;
const struct vcap_field *af_table; const struct vcap_field *af_table;
int actionset_size; int actionset_size;
...@@ -707,8 +833,9 @@ static int vcap_encode_rule_actionset(struct vcap_rule_internal *ri) ...@@ -707,8 +833,9 @@ static int vcap_encode_rule_actionset(struct vcap_rule_internal *ri)
__func__, __LINE__, caf->ctrl.action); __func__, __LINE__, caf->ctrl.action);
return -EINVAL; return -EINVAL;
} }
vcap_encode_actionfield(ri, caf, &af_table[caf->ctrl.action], vcap_copy_from_client_actionfield(&ri->data, &tempaf, caf);
tg_table); vcap_encode_actionfield(ri, &tempaf,
&af_table[caf->ctrl.action], tg_table);
} }
/* Add typegroup bits to the entry bitstreams */ /* Add typegroup bits to the entry bitstreams */
vcap_encode_actionfield_typegroups(ri, tg_table); vcap_encode_actionfield_typegroups(ri, tg_table);
...@@ -2142,69 +2269,6 @@ const struct vcap_field *vcap_lookup_keyfield(struct vcap_rule *rule, ...@@ -2142,69 +2269,6 @@ const struct vcap_field *vcap_lookup_keyfield(struct vcap_rule *rule,
} }
EXPORT_SYMBOL_GPL(vcap_lookup_keyfield); EXPORT_SYMBOL_GPL(vcap_lookup_keyfield);
/* Copy data from src to dst but reverse the data in chunks of 32bits.
* For example if src is 00:11:22:33:44:55 where 55 is LSB the dst will
* have the value 22:33:44:55:00:11.
*/
static void vcap_copy_to_w32be(u8 *dst, u8 *src, int size)
{
for (int idx = 0; idx < size; ++idx) {
int first_byte_index = 0;
int nidx;
first_byte_index = size - (((idx >> 2) + 1) << 2);
if (first_byte_index < 0)
first_byte_index = 0;
nidx = idx + first_byte_index - (idx & ~0x3);
dst[nidx] = src[idx];
}
}
static void vcap_copy_from_client_keyfield(struct vcap_rule *rule,
struct vcap_client_keyfield *field,
struct vcap_client_keyfield_data *data)
{
struct vcap_rule_internal *ri = to_intrule(rule);
int size;
if (!ri->admin->w32be) {
memcpy(&field->data, data, sizeof(field->data));
return;
}
size = keyfield_size_table[field->ctrl.type] / 2;
switch (field->ctrl.type) {
case VCAP_FIELD_BIT:
case VCAP_FIELD_U32:
memcpy(&field->data, data, sizeof(field->data));
break;
case VCAP_FIELD_U48:
vcap_copy_to_w32be(field->data.u48.value, data->u48.value, size);
vcap_copy_to_w32be(field->data.u48.mask, data->u48.mask, size);
break;
case VCAP_FIELD_U56:
vcap_copy_to_w32be(field->data.u56.value, data->u56.value, size);
vcap_copy_to_w32be(field->data.u56.mask, data->u56.mask, size);
break;
case VCAP_FIELD_U64:
vcap_copy_to_w32be(field->data.u64.value, data->u64.value, size);
vcap_copy_to_w32be(field->data.u64.mask, data->u64.mask, size);
break;
case VCAP_FIELD_U72:
vcap_copy_to_w32be(field->data.u72.value, data->u72.value, size);
vcap_copy_to_w32be(field->data.u72.mask, data->u72.mask, size);
break;
case VCAP_FIELD_U112:
vcap_copy_to_w32be(field->data.u112.value, data->u112.value, size);
vcap_copy_to_w32be(field->data.u112.mask, data->u112.mask, size);
break;
case VCAP_FIELD_U128:
vcap_copy_to_w32be(field->data.u128.value, data->u128.value, size);
vcap_copy_to_w32be(field->data.u128.mask, data->u128.mask, size);
break;
}
}
/* Check if the keyfield is already in the rule */ /* Check if the keyfield is already in the rule */
static bool vcap_keyfield_unique(struct vcap_rule *rule, static bool vcap_keyfield_unique(struct vcap_rule *rule,
enum vcap_key_field key) enum vcap_key_field key)
...@@ -2262,9 +2326,9 @@ static int vcap_rule_add_key(struct vcap_rule *rule, ...@@ -2262,9 +2326,9 @@ static int vcap_rule_add_key(struct vcap_rule *rule,
field = kzalloc(sizeof(*field), GFP_KERNEL); field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field) if (!field)
return -ENOMEM; return -ENOMEM;
memcpy(&field->data, data, sizeof(field->data));
field->ctrl.key = key; field->ctrl.key = key;
field->ctrl.type = ftype; field->ctrl.type = ftype;
vcap_copy_from_client_keyfield(rule, field, data);
list_add_tail(&field->ctrl.list, &rule->keyfields); list_add_tail(&field->ctrl.list, &rule->keyfields);
return 0; return 0;
} }
...@@ -2372,45 +2436,6 @@ vcap_find_actionfield(struct vcap_rule *rule, enum vcap_action_field act) ...@@ -2372,45 +2436,6 @@ vcap_find_actionfield(struct vcap_rule *rule, enum vcap_action_field act)
return NULL; return NULL;
} }
static void vcap_copy_from_client_actionfield(struct vcap_rule *rule,
struct vcap_client_actionfield *field,
struct vcap_client_actionfield_data *data)
{
struct vcap_rule_internal *ri = to_intrule(rule);
int size;
if (!ri->admin->w32be) {
memcpy(&field->data, data, sizeof(field->data));
return;
}
size = actionfield_size_table[field->ctrl.type];
switch (field->ctrl.type) {
case VCAP_FIELD_BIT:
case VCAP_FIELD_U32:
memcpy(&field->data, data, sizeof(field->data));
break;
case VCAP_FIELD_U48:
vcap_copy_to_w32be(field->data.u48.value, data->u48.value, size);
break;
case VCAP_FIELD_U56:
vcap_copy_to_w32be(field->data.u56.value, data->u56.value, size);
break;
case VCAP_FIELD_U64:
vcap_copy_to_w32be(field->data.u64.value, data->u64.value, size);
break;
case VCAP_FIELD_U72:
vcap_copy_to_w32be(field->data.u72.value, data->u72.value, size);
break;
case VCAP_FIELD_U112:
vcap_copy_to_w32be(field->data.u112.value, data->u112.value, size);
break;
case VCAP_FIELD_U128:
vcap_copy_to_w32be(field->data.u128.value, data->u128.value, size);
break;
}
}
/* Check if the actionfield is already in the rule */ /* Check if the actionfield is already in the rule */
static bool vcap_actionfield_unique(struct vcap_rule *rule, static bool vcap_actionfield_unique(struct vcap_rule *rule,
enum vcap_action_field act) enum vcap_action_field act)
...@@ -2468,9 +2493,9 @@ static int vcap_rule_add_action(struct vcap_rule *rule, ...@@ -2468,9 +2493,9 @@ static int vcap_rule_add_action(struct vcap_rule *rule,
field = kzalloc(sizeof(*field), GFP_KERNEL); field = kzalloc(sizeof(*field), GFP_KERNEL);
if (!field) if (!field)
return -ENOMEM; return -ENOMEM;
memcpy(&field->data, data, sizeof(field->data));
field->ctrl.action = action; field->ctrl.action = action;
field->ctrl.type = ftype; field->ctrl.type = ftype;
vcap_copy_from_client_actionfield(rule, field, data);
list_add_tail(&field->ctrl.list, &rule->actionfields); list_add_tail(&field->ctrl.list, &rule->actionfields);
return 0; return 0;
} }
...@@ -2747,7 +2772,7 @@ static int vcap_rule_mod_key(struct vcap_rule *rule, ...@@ -2747,7 +2772,7 @@ static int vcap_rule_mod_key(struct vcap_rule *rule,
field = vcap_find_keyfield(rule, key); field = vcap_find_keyfield(rule, key);
if (!field) if (!field)
return vcap_rule_add_key(rule, key, ftype, data); return vcap_rule_add_key(rule, key, ftype, data);
vcap_copy_from_client_keyfield(rule, field, data); memcpy(&field->data, data, sizeof(field->data));
return 0; return 0;
} }
...@@ -2773,7 +2798,7 @@ static int vcap_rule_mod_action(struct vcap_rule *rule, ...@@ -2773,7 +2798,7 @@ static int vcap_rule_mod_action(struct vcap_rule *rule,
field = vcap_find_actionfield(rule, action); field = vcap_find_actionfield(rule, action);
if (!field) if (!field)
return vcap_rule_add_action(rule, action, ftype, data); return vcap_rule_add_action(rule, action, ftype, data);
vcap_copy_from_client_actionfield(rule, field, data); memcpy(&field->data, data, sizeof(field->data));
return 0; return 0;
} }
......
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