octeontx2-af: Add support for dynamic flow cfg to RSS field generation
Introduce state-based algorithm to convert the flow_key value to RSS algo field used by NIX_AF_RX_FLOW_KEY_ALGX_FIELDX register. The outer `for loop` goes over _all_ protocol field and the following variables depict the state machine forward progress logic. a) keyoff_marker - Enabled when hash byte length needs to be accounted in field->key_offset update. b) field_marker - Enabled when a new field needs to be selected. c) group_member - Enabled when a protocol is part of a group. This would remove the existing hard coding and enable to add new protocol support seamlessly. Signed-off-by: Jerin Jacob <jerinj@marvell.com> Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
bd522d6870
commit
b648366c2c
@ -414,6 +414,7 @@ enum nix_af_status {
|
||||
NIX_AF_INVAL_TXSCHQ_CFG = -412,
|
||||
NIX_AF_SMQ_FLUSH_FAILED = -413,
|
||||
NIX_AF_ERR_LF_RESET = -414,
|
||||
NIX_AF_ERR_RSS_NOSPC_FIELD = -415,
|
||||
NIX_AF_INVAL_NPA_PF_FUNC = -419,
|
||||
NIX_AF_INVAL_SSO_PF_FUNC = -420,
|
||||
};
|
||||
|
@ -1650,80 +1650,139 @@ int rvu_mbox_handler_nix_rss_flowkey_cfg(struct rvu *rvu,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
|
||||
static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg)
|
||||
{
|
||||
struct nix_rx_flowkey_alg *field = NULL;
|
||||
int idx, key_type;
|
||||
int idx, nr_field, key_off, field_marker, keyoff_marker;
|
||||
int max_key_off, max_bit_pos, group_member;
|
||||
struct nix_rx_flowkey_alg *field;
|
||||
struct nix_rx_flowkey_alg tmp;
|
||||
u32 key_type, valid_key;
|
||||
|
||||
if (!alg)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
/* FIELD0: IPv4
|
||||
* FIELD1: IPv6
|
||||
* FIELD2: TCP/UDP/SCTP/ALL
|
||||
* FIELD3: Unused
|
||||
* FIELD4: Unused
|
||||
*
|
||||
* Each of the 32 possible flow key algorithm definitions should
|
||||
#define FIELDS_PER_ALG 5
|
||||
#define MAX_KEY_OFF 40
|
||||
/* Clear all fields */
|
||||
memset(alg, 0, sizeof(uint64_t) * FIELDS_PER_ALG);
|
||||
|
||||
/* Each of the 32 possible flow key algorithm definitions should
|
||||
* fall into above incremental config (except ALG0). Otherwise a
|
||||
* single NPC MCAM entry is not sufficient for supporting RSS.
|
||||
*
|
||||
* If a different definition or combination needed then NPC MCAM
|
||||
* has to be programmed to filter such pkts and it's action should
|
||||
* point to this definition to calculate flowtag or hash.
|
||||
*
|
||||
* The `for loop` goes over _all_ protocol field and the following
|
||||
* variables depicts the state machine forward progress logic.
|
||||
*
|
||||
* keyoff_marker - Enabled when hash byte length needs to be accounted
|
||||
* in field->key_offset update.
|
||||
* field_marker - Enabled when a new field needs to be selected.
|
||||
* group_member - Enabled when protocol is part of a group.
|
||||
*/
|
||||
for (idx = 0; idx < 32; idx++) {
|
||||
key_type = flow_cfg & BIT_ULL(idx);
|
||||
if (!key_type)
|
||||
continue;
|
||||
|
||||
keyoff_marker = 0; max_key_off = 0; group_member = 0;
|
||||
nr_field = 0; key_off = 0; field_marker = 1;
|
||||
field = &tmp; max_bit_pos = fls(flow_cfg);
|
||||
for (idx = 0;
|
||||
idx < max_bit_pos && nr_field < FIELDS_PER_ALG &&
|
||||
key_off < MAX_KEY_OFF; idx++) {
|
||||
key_type = BIT(idx);
|
||||
valid_key = flow_cfg & key_type;
|
||||
/* Found a field marker, reset the field values */
|
||||
if (field_marker)
|
||||
memset(&tmp, 0, sizeof(tmp));
|
||||
|
||||
switch (key_type) {
|
||||
case NIX_FLOW_KEY_TYPE_PORT:
|
||||
field = &alg[0];
|
||||
field->sel_chan = true;
|
||||
/* This should be set to 1, when SEL_CHAN is set */
|
||||
field->bytesm1 = 1;
|
||||
field_marker = true;
|
||||
keyoff_marker = true;
|
||||
break;
|
||||
case NIX_FLOW_KEY_TYPE_IPV4:
|
||||
field = &alg[0];
|
||||
field->lid = NPC_LID_LC;
|
||||
field->ltype_match = NPC_LT_LC_IP;
|
||||
field->hdr_offset = 12; /* SIP offset */
|
||||
field->bytesm1 = 7; /* SIP + DIP, 8 bytes */
|
||||
field->ltype_mask = 0xF; /* Match only IPv4 */
|
||||
field_marker = true;
|
||||
keyoff_marker = false;
|
||||
break;
|
||||
case NIX_FLOW_KEY_TYPE_IPV6:
|
||||
field = &alg[1];
|
||||
field->lid = NPC_LID_LC;
|
||||
field->ltype_match = NPC_LT_LC_IP6;
|
||||
field->hdr_offset = 8; /* SIP offset */
|
||||
field->bytesm1 = 31; /* SIP + DIP, 32 bytes */
|
||||
field->ltype_mask = 0xF; /* Match only IPv6 */
|
||||
field_marker = true;
|
||||
keyoff_marker = true;
|
||||
break;
|
||||
case NIX_FLOW_KEY_TYPE_TCP:
|
||||
case NIX_FLOW_KEY_TYPE_UDP:
|
||||
case NIX_FLOW_KEY_TYPE_SCTP:
|
||||
field = &alg[2];
|
||||
field->lid = NPC_LID_LD;
|
||||
field->bytesm1 = 3; /* Sport + Dport, 4 bytes */
|
||||
if (key_type == NIX_FLOW_KEY_TYPE_TCP)
|
||||
if (key_type == NIX_FLOW_KEY_TYPE_TCP && valid_key) {
|
||||
field->ltype_match |= NPC_LT_LD_TCP;
|
||||
else if (key_type == NIX_FLOW_KEY_TYPE_UDP)
|
||||
group_member = true;
|
||||
} else if (key_type == NIX_FLOW_KEY_TYPE_UDP &&
|
||||
valid_key) {
|
||||
field->ltype_match |= NPC_LT_LD_UDP;
|
||||
else if (key_type == NIX_FLOW_KEY_TYPE_SCTP)
|
||||
group_member = true;
|
||||
} else if (key_type == NIX_FLOW_KEY_TYPE_SCTP &&
|
||||
valid_key) {
|
||||
field->ltype_match |= NPC_LT_LD_SCTP;
|
||||
field->key_offset = 32; /* After IPv4/v6 SIP, DIP */
|
||||
group_member = true;
|
||||
}
|
||||
field->ltype_mask = ~field->ltype_match;
|
||||
if (key_type == NIX_FLOW_KEY_TYPE_SCTP) {
|
||||
/* Handle the case where any of the group item
|
||||
* is enabled in the group but not the final one
|
||||
*/
|
||||
if (group_member) {
|
||||
valid_key = true;
|
||||
group_member = false;
|
||||
}
|
||||
field_marker = true;
|
||||
keyoff_marker = true;
|
||||
} else {
|
||||
field_marker = false;
|
||||
keyoff_marker = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (field)
|
||||
field->ena = 1;
|
||||
field = NULL;
|
||||
field->ena = 1;
|
||||
|
||||
/* Found a valid flow key type */
|
||||
if (valid_key) {
|
||||
field->key_offset = key_off;
|
||||
memcpy(&alg[nr_field], field, sizeof(*field));
|
||||
max_key_off = max(max_key_off, field->bytesm1 + 1);
|
||||
|
||||
/* Found a field marker, get the next field */
|
||||
if (field_marker)
|
||||
nr_field++;
|
||||
}
|
||||
|
||||
/* Found a keyoff marker, update the new key_off */
|
||||
if (keyoff_marker) {
|
||||
key_off += max_key_off;
|
||||
max_key_off = 0;
|
||||
}
|
||||
}
|
||||
/* Processed all the flow key types */
|
||||
if (idx == max_bit_pos && key_off <= MAX_KEY_OFF)
|
||||
return 0;
|
||||
else
|
||||
return NIX_AF_ERR_RSS_NOSPC_FIELD;
|
||||
}
|
||||
|
||||
static void nix_rx_flowkey_alg_cfg(struct rvu *rvu, int blkaddr)
|
||||
{
|
||||
#define FIELDS_PER_ALG 5
|
||||
u64 field[NIX_FLOW_KEY_ALG_MAX][FIELDS_PER_ALG];
|
||||
u32 flowkey_cfg, minkey_cfg;
|
||||
int alg, fid;
|
||||
|
Loading…
Reference in New Issue
Block a user