Commit f6615590 authored by Ratheesh Kannoth's avatar Ratheesh Kannoth Committed by David S. Miller

octeontx2-af: Fix issues with NPC field hash extract

1. Allow field hash configuration for both source and destination IPv6.
2. Configure hardware parser based on hash extract feature enable flag
   for IPv6.
3. Fix IPv6 endianness issue while updating the source/destination IP
   address via ntuple rule.

Fixes: 56d9f5fd ("octeontx2-af: Use hashed field in MCAM key")
Signed-off-by: default avatarRatheesh Kannoth <rkannoth@marvell.com>
Signed-off-by: default avatarSunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarSai Krishna <saikrishnag@marvell.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 406bed11
...@@ -13,11 +13,6 @@ ...@@ -13,11 +13,6 @@
#include "rvu_npc_fs.h" #include "rvu_npc_fs.h"
#include "rvu_npc_hash.h" #include "rvu_npc_hash.h"
#define NPC_BYTESM GENMASK_ULL(19, 16)
#define NPC_HDR_OFFSET GENMASK_ULL(15, 8)
#define NPC_KEY_OFFSET GENMASK_ULL(5, 0)
#define NPC_LDATA_EN BIT_ULL(7)
static const char * const npc_flow_names[] = { static const char * const npc_flow_names[] = {
[NPC_DMAC] = "dmac", [NPC_DMAC] = "dmac",
[NPC_SMAC] = "smac", [NPC_SMAC] = "smac",
...@@ -442,6 +437,7 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf) ...@@ -442,6 +437,7 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf)
static void npc_scan_ldata(struct rvu *rvu, int blkaddr, u8 lid, static void npc_scan_ldata(struct rvu *rvu, int blkaddr, u8 lid,
u8 lt, u64 cfg, u8 intf) u8 lt, u64 cfg, u8 intf)
{ {
struct npc_mcam_kex_hash *mkex_hash = rvu->kpu.mkex_hash;
struct npc_mcam *mcam = &rvu->hw->mcam; struct npc_mcam *mcam = &rvu->hw->mcam;
u8 hdr, key, nr_bytes, bit_offset; u8 hdr, key, nr_bytes, bit_offset;
u8 la_ltype, la_start; u8 la_ltype, la_start;
...@@ -490,8 +486,21 @@ do { \ ...@@ -490,8 +486,21 @@ do { \
NPC_SCAN_HDR(NPC_SIP_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 12, 4); NPC_SCAN_HDR(NPC_SIP_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 12, 4);
NPC_SCAN_HDR(NPC_DIP_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 16, 4); NPC_SCAN_HDR(NPC_DIP_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 16, 4);
NPC_SCAN_HDR(NPC_IPFRAG_IPV6, NPC_LID_LC, NPC_LT_LC_IP6_EXT, 6, 1); NPC_SCAN_HDR(NPC_IPFRAG_IPV6, NPC_LID_LC, NPC_LT_LC_IP6_EXT, 6, 1);
NPC_SCAN_HDR(NPC_SIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 8, 16); if (rvu->hw->cap.npc_hash_extract) {
NPC_SCAN_HDR(NPC_DIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 24, 16); if (mkex_hash->lid_lt_ld_hash_en[intf][lid][lt][0])
NPC_SCAN_HDR(NPC_SIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 8, 4);
else
NPC_SCAN_HDR(NPC_SIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 8, 16);
if (mkex_hash->lid_lt_ld_hash_en[intf][lid][lt][1])
NPC_SCAN_HDR(NPC_DIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 24, 4);
else
NPC_SCAN_HDR(NPC_DIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 24, 16);
} else {
NPC_SCAN_HDR(NPC_SIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 8, 16);
NPC_SCAN_HDR(NPC_DIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 24, 16);
}
NPC_SCAN_HDR(NPC_SPORT_UDP, NPC_LID_LD, NPC_LT_LD_UDP, 0, 2); NPC_SCAN_HDR(NPC_SPORT_UDP, NPC_LID_LD, NPC_LT_LD_UDP, 0, 2);
NPC_SCAN_HDR(NPC_DPORT_UDP, NPC_LID_LD, NPC_LT_LD_UDP, 2, 2); NPC_SCAN_HDR(NPC_DPORT_UDP, NPC_LID_LD, NPC_LT_LD_UDP, 2, 2);
NPC_SCAN_HDR(NPC_SPORT_TCP, NPC_LID_LD, NPC_LT_LD_TCP, 0, 2); NPC_SCAN_HDR(NPC_SPORT_TCP, NPC_LID_LD, NPC_LT_LD_TCP, 0, 2);
......
...@@ -9,6 +9,10 @@ ...@@ -9,6 +9,10 @@
#define __RVU_NPC_FS_H #define __RVU_NPC_FS_H
#define IPV6_WORDS 4 #define IPV6_WORDS 4
#define NPC_BYTESM GENMASK_ULL(19, 16)
#define NPC_HDR_OFFSET GENMASK_ULL(15, 8)
#define NPC_KEY_OFFSET GENMASK_ULL(5, 0)
#define NPC_LDATA_EN BIT_ULL(7)
void npc_update_entry(struct rvu *rvu, enum key_fields type, void npc_update_entry(struct rvu *rvu, enum key_fields type,
struct mcam_entry *entry, u64 val_lo, struct mcam_entry *entry, u64 val_lo,
......
...@@ -78,42 +78,43 @@ static u32 rvu_npc_toeplitz_hash(const u64 *data, u64 *key, size_t data_bit_len, ...@@ -78,42 +78,43 @@ static u32 rvu_npc_toeplitz_hash(const u64 *data, u64 *key, size_t data_bit_len,
return hash_out; return hash_out;
} }
u32 npc_field_hash_calc(u64 *ldata, struct npc_mcam_kex_hash *mkex_hash, u32 npc_field_hash_calc(u64 *ldata, struct npc_get_field_hash_info_rsp rsp,
u64 *secret_key, u8 intf, u8 hash_idx) u8 intf, u8 hash_idx)
{ {
u64 hash_key[3]; u64 hash_key[3];
u64 data_padded[2]; u64 data_padded[2];
u32 field_hash; u32 field_hash;
hash_key[0] = secret_key[1] << 31; hash_key[0] = rsp.secret_key[1] << 31;
hash_key[0] |= secret_key[2]; hash_key[0] |= rsp.secret_key[2];
hash_key[1] = secret_key[1] >> 33; hash_key[1] = rsp.secret_key[1] >> 33;
hash_key[1] |= secret_key[0] << 31; hash_key[1] |= rsp.secret_key[0] << 31;
hash_key[2] = secret_key[0] >> 33; hash_key[2] = rsp.secret_key[0] >> 33;
data_padded[0] = mkex_hash->hash_mask[intf][hash_idx][0] & ldata[0]; data_padded[0] = rsp.hash_mask[intf][hash_idx][0] & ldata[0];
data_padded[1] = mkex_hash->hash_mask[intf][hash_idx][1] & ldata[1]; data_padded[1] = rsp.hash_mask[intf][hash_idx][1] & ldata[1];
field_hash = rvu_npc_toeplitz_hash(data_padded, hash_key, 128, 159); field_hash = rvu_npc_toeplitz_hash(data_padded, hash_key, 128, 159);
field_hash &= mkex_hash->hash_ctrl[intf][hash_idx] >> 32; field_hash &= FIELD_GET(GENMASK(63, 32), rsp.hash_ctrl[intf][hash_idx]);
field_hash |= mkex_hash->hash_ctrl[intf][hash_idx]; field_hash += FIELD_GET(GENMASK(31, 0), rsp.hash_ctrl[intf][hash_idx]);
return field_hash; return field_hash;
} }
static u64 npc_update_use_hash(int lt, int ld) static u64 npc_update_use_hash(struct rvu *rvu, int blkaddr,
u8 intf, int lid, int lt, int ld)
{ {
u64 cfg = 0; u8 hdr, key;
u64 cfg;
switch (lt) {
case NPC_LT_LC_IP6: cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf, lid, lt, ld));
/* Update use_hash(bit-20) and bytesm1 (bit-16:19) hdr = FIELD_GET(NPC_HDR_OFFSET, cfg);
* in KEX_LD_CFG key = FIELD_GET(NPC_KEY_OFFSET, cfg);
*/
cfg = KEX_LD_CFG_USE_HASH(0x1, 0x03, /* Update use_hash(bit-20) to 'true' and
ld ? 0x18 : 0x8, * bytesm1(bit-16:19) to '0x3' in KEX_LD_CFG
0x1, 0x0, ld ? 0x14 : 0x10); */
break; cfg = KEX_LD_CFG_USE_HASH(0x1, 0x03,
} hdr, 0x1, 0x0, key);
return cfg; return cfg;
} }
...@@ -132,11 +133,13 @@ static void npc_program_mkex_hash_rx(struct rvu *rvu, int blkaddr, ...@@ -132,11 +133,13 @@ static void npc_program_mkex_hash_rx(struct rvu *rvu, int blkaddr,
for (lt = 0; lt < NPC_MAX_LT; lt++) { for (lt = 0; lt < NPC_MAX_LT; lt++) {
for (ld = 0; ld < NPC_MAX_LD; ld++) { for (ld = 0; ld < NPC_MAX_LD; ld++) {
if (mkex_hash->lid_lt_ld_hash_en[intf][lid][lt][ld]) { if (mkex_hash->lid_lt_ld_hash_en[intf][lid][lt][ld]) {
u64 cfg = npc_update_use_hash(lt, ld); u64 cfg;
if (hash_cnt == NPC_MAX_HASH) if (hash_cnt == NPC_MAX_HASH)
return; return;
cfg = npc_update_use_hash(rvu, blkaddr,
intf, lid, lt, ld);
/* Set updated KEX configuration */ /* Set updated KEX configuration */
SET_KEX_LD(intf, lid, lt, ld, cfg); SET_KEX_LD(intf, lid, lt, ld, cfg);
/* Set HASH configuration */ /* Set HASH configuration */
...@@ -170,11 +173,13 @@ static void npc_program_mkex_hash_tx(struct rvu *rvu, int blkaddr, ...@@ -170,11 +173,13 @@ static void npc_program_mkex_hash_tx(struct rvu *rvu, int blkaddr,
for (lt = 0; lt < NPC_MAX_LT; lt++) { for (lt = 0; lt < NPC_MAX_LT; lt++) {
for (ld = 0; ld < NPC_MAX_LD; ld++) for (ld = 0; ld < NPC_MAX_LD; ld++)
if (mkex_hash->lid_lt_ld_hash_en[intf][lid][lt][ld]) { if (mkex_hash->lid_lt_ld_hash_en[intf][lid][lt][ld]) {
u64 cfg = npc_update_use_hash(lt, ld); u64 cfg;
if (hash_cnt == NPC_MAX_HASH) if (hash_cnt == NPC_MAX_HASH)
return; return;
cfg = npc_update_use_hash(rvu, blkaddr,
intf, lid, lt, ld);
/* Set updated KEX configuration */ /* Set updated KEX configuration */
SET_KEX_LD(intf, lid, lt, ld, cfg); SET_KEX_LD(intf, lid, lt, ld, cfg);
/* Set HASH configuration */ /* Set HASH configuration */
...@@ -264,44 +269,45 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf, ...@@ -264,44 +269,45 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf,
* is hashed to 32 bit value. * is hashed to 32 bit value.
*/ */
case NPC_LT_LC_IP6: case NPC_LT_LC_IP6:
if (features & BIT_ULL(NPC_SIP_IPV6)) { /* ld[0] == hash_idx[0] == Source IPv6
* ld[1] == hash_idx[1] == Destination IPv6
*/
if ((features & BIT_ULL(NPC_SIP_IPV6)) && !hash_idx) {
u32 src_ip[IPV6_WORDS]; u32 src_ip[IPV6_WORDS];
be32_to_cpu_array(src_ip, pkt->ip6src, IPV6_WORDS); be32_to_cpu_array(src_ip, pkt->ip6src, IPV6_WORDS);
ldata[0] = (u64)src_ip[0] << 32 | src_ip[1]; ldata[1] = (u64)src_ip[0] << 32 | src_ip[1];
ldata[1] = (u64)src_ip[2] << 32 | src_ip[3]; ldata[0] = (u64)src_ip[2] << 32 | src_ip[3];
field_hash = npc_field_hash_calc(ldata, field_hash = npc_field_hash_calc(ldata,
mkex_hash, rsp,
rsp.secret_key,
intf, intf,
hash_idx); hash_idx);
npc_update_entry(rvu, NPC_SIP_IPV6, entry, npc_update_entry(rvu, NPC_SIP_IPV6, entry,
field_hash, 0, 32, 0, intf); field_hash, 0,
GENMASK(31, 0), 0, intf);
memcpy(&opkt->ip6src, &pkt->ip6src, memcpy(&opkt->ip6src, &pkt->ip6src,
sizeof(pkt->ip6src)); sizeof(pkt->ip6src));
memcpy(&omask->ip6src, &mask->ip6src, memcpy(&omask->ip6src, &mask->ip6src,
sizeof(mask->ip6src)); sizeof(mask->ip6src));
break; } else if ((features & BIT_ULL(NPC_DIP_IPV6)) && hash_idx) {
}
if (features & BIT_ULL(NPC_DIP_IPV6)) {
u32 dst_ip[IPV6_WORDS]; u32 dst_ip[IPV6_WORDS];
be32_to_cpu_array(dst_ip, pkt->ip6dst, IPV6_WORDS); be32_to_cpu_array(dst_ip, pkt->ip6dst, IPV6_WORDS);
ldata[0] = (u64)dst_ip[0] << 32 | dst_ip[1]; ldata[1] = (u64)dst_ip[0] << 32 | dst_ip[1];
ldata[1] = (u64)dst_ip[2] << 32 | dst_ip[3]; ldata[0] = (u64)dst_ip[2] << 32 | dst_ip[3];
field_hash = npc_field_hash_calc(ldata, field_hash = npc_field_hash_calc(ldata,
mkex_hash, rsp,
rsp.secret_key,
intf, intf,
hash_idx); hash_idx);
npc_update_entry(rvu, NPC_DIP_IPV6, entry, npc_update_entry(rvu, NPC_DIP_IPV6, entry,
field_hash, 0, 32, 0, intf); field_hash, 0,
GENMASK(31, 0), 0, intf);
memcpy(&opkt->ip6dst, &pkt->ip6dst, memcpy(&opkt->ip6dst, &pkt->ip6dst,
sizeof(pkt->ip6dst)); sizeof(pkt->ip6dst));
memcpy(&omask->ip6dst, &mask->ip6dst, memcpy(&omask->ip6dst, &mask->ip6dst,
sizeof(mask->ip6dst)); sizeof(mask->ip6dst));
} }
break; break;
} }
} }
......
...@@ -62,8 +62,8 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf, ...@@ -62,8 +62,8 @@ void npc_update_field_hash(struct rvu *rvu, u8 intf,
struct flow_msg *omask); struct flow_msg *omask);
void npc_config_secret_key(struct rvu *rvu, int blkaddr); void npc_config_secret_key(struct rvu *rvu, int blkaddr);
void npc_program_mkex_hash(struct rvu *rvu, int blkaddr); void npc_program_mkex_hash(struct rvu *rvu, int blkaddr);
u32 npc_field_hash_calc(u64 *ldata, struct npc_mcam_kex_hash *mkex_hash, u32 npc_field_hash_calc(u64 *ldata, struct npc_get_field_hash_info_rsp rsp,
u64 *secret_key, u8 intf, u8 hash_idx); u8 intf, u8 hash_idx);
static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = { static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
.lid_lt_ld_hash_en = { .lid_lt_ld_hash_en = {
......
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