mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-08 09:12:39 -04:00
octeontx2-pf: Tc flower offload support for MPLS
This patch extends flower offload support for MPLS protocol. Due to hardware limitation, currently driver supports lse depth up to 4. Signed-off-by: Hariprasad Kelam <hkelam@marvell.com> Signed-off-by: Sunil Goutham <sgoutham@marvell.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
f77e9f13ba
commit
a63df366d0
@@ -1473,6 +1473,12 @@ struct flow_msg {
|
||||
u8 next_header;
|
||||
};
|
||||
__be16 vlan_itci;
|
||||
#define OTX2_FLOWER_MASK_MPLS_LB GENMASK(31, 12)
|
||||
#define OTX2_FLOWER_MASK_MPLS_TC GENMASK(11, 9)
|
||||
#define OTX2_FLOWER_MASK_MPLS_BOS BIT(8)
|
||||
#define OTX2_FLOWER_MASK_MPLS_TTL GENMASK(7, 0)
|
||||
#define OTX2_FLOWER_MASK_MPLS_NON_TTL GENMASK(31, 8)
|
||||
u32 mpls_lse[4];
|
||||
};
|
||||
|
||||
struct npc_install_flow_req {
|
||||
|
||||
@@ -206,6 +206,14 @@ enum key_fields {
|
||||
NPC_SPORT_SCTP,
|
||||
NPC_DPORT_SCTP,
|
||||
NPC_IPSEC_SPI,
|
||||
NPC_MPLS1_LBTCBOS,
|
||||
NPC_MPLS1_TTL,
|
||||
NPC_MPLS2_LBTCBOS,
|
||||
NPC_MPLS2_TTL,
|
||||
NPC_MPLS3_LBTCBOS,
|
||||
NPC_MPLS3_TTL,
|
||||
NPC_MPLS4_LBTCBOS,
|
||||
NPC_MPLS4_TTL,
|
||||
NPC_HEADER_FIELDS_MAX,
|
||||
NPC_CHAN = NPC_HEADER_FIELDS_MAX, /* Valid when Rx */
|
||||
NPC_PF_FUNC, /* Valid when Tx */
|
||||
|
||||
@@ -2756,6 +2756,27 @@ static int rvu_dbg_npc_rx_miss_stats_display(struct seq_file *filp,
|
||||
|
||||
RVU_DEBUG_SEQ_FOPS(npc_rx_miss_act, npc_rx_miss_stats_display, NULL);
|
||||
|
||||
#define RVU_DBG_PRINT_MPLS_TTL(pkt, mask) \
|
||||
do { \
|
||||
seq_printf(s, "%ld ", FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL, pkt)); \
|
||||
seq_printf(s, "mask 0x%lx\n", \
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL, mask)); \
|
||||
} while (0) \
|
||||
|
||||
#define RVU_DBG_PRINT_MPLS_LBTCBOS(_pkt, _mask) \
|
||||
do { \
|
||||
typeof(_pkt) (pkt) = (_pkt); \
|
||||
typeof(_mask) (mask) = (_mask); \
|
||||
seq_printf(s, "%ld %ld %ld\n", \
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_LB, pkt), \
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TC, pkt), \
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_BOS, pkt)); \
|
||||
seq_printf(s, "\tmask 0x%lx 0x%lx 0x%lx\n", \
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_LB, mask), \
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TC, mask), \
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_BOS, mask)); \
|
||||
} while (0) \
|
||||
|
||||
static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
|
||||
struct rvu_npc_mcam_rule *rule)
|
||||
{
|
||||
@@ -2836,6 +2857,38 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
|
||||
seq_printf(s, "0x%x ", ntohl(rule->packet.spi));
|
||||
seq_printf(s, "mask 0x%x\n", ntohl(rule->mask.spi));
|
||||
break;
|
||||
case NPC_MPLS1_LBTCBOS:
|
||||
RVU_DBG_PRINT_MPLS_LBTCBOS(rule->packet.mpls_lse[0],
|
||||
rule->mask.mpls_lse[0]);
|
||||
break;
|
||||
case NPC_MPLS1_TTL:
|
||||
RVU_DBG_PRINT_MPLS_TTL(rule->packet.mpls_lse[0],
|
||||
rule->mask.mpls_lse[0]);
|
||||
break;
|
||||
case NPC_MPLS2_LBTCBOS:
|
||||
RVU_DBG_PRINT_MPLS_LBTCBOS(rule->packet.mpls_lse[1],
|
||||
rule->mask.mpls_lse[1]);
|
||||
break;
|
||||
case NPC_MPLS2_TTL:
|
||||
RVU_DBG_PRINT_MPLS_TTL(rule->packet.mpls_lse[1],
|
||||
rule->mask.mpls_lse[1]);
|
||||
break;
|
||||
case NPC_MPLS3_LBTCBOS:
|
||||
RVU_DBG_PRINT_MPLS_LBTCBOS(rule->packet.mpls_lse[2],
|
||||
rule->mask.mpls_lse[2]);
|
||||
break;
|
||||
case NPC_MPLS3_TTL:
|
||||
RVU_DBG_PRINT_MPLS_TTL(rule->packet.mpls_lse[2],
|
||||
rule->mask.mpls_lse[2]);
|
||||
break;
|
||||
case NPC_MPLS4_LBTCBOS:
|
||||
RVU_DBG_PRINT_MPLS_LBTCBOS(rule->packet.mpls_lse[3],
|
||||
rule->mask.mpls_lse[3]);
|
||||
break;
|
||||
case NPC_MPLS4_TTL:
|
||||
RVU_DBG_PRINT_MPLS_TTL(rule->packet.mpls_lse[3],
|
||||
rule->mask.mpls_lse[3]);
|
||||
break;
|
||||
default:
|
||||
seq_puts(s, "\n");
|
||||
break;
|
||||
|
||||
@@ -43,6 +43,14 @@ static const char * const npc_flow_names[] = {
|
||||
[NPC_DPORT_SCTP] = "sctp destination port",
|
||||
[NPC_LXMB] = "Mcast/Bcast header ",
|
||||
[NPC_IPSEC_SPI] = "SPI ",
|
||||
[NPC_MPLS1_LBTCBOS] = "lse depth 1 label tc bos",
|
||||
[NPC_MPLS1_TTL] = "lse depth 1 ttl",
|
||||
[NPC_MPLS2_LBTCBOS] = "lse depth 2 label tc bos",
|
||||
[NPC_MPLS2_TTL] = "lse depth 2 ttl",
|
||||
[NPC_MPLS3_LBTCBOS] = "lse depth 3 label tc bos",
|
||||
[NPC_MPLS3_TTL] = "lse depth 3 ttl",
|
||||
[NPC_MPLS4_LBTCBOS] = "lse depth 4 label tc bos",
|
||||
[NPC_MPLS4_TTL] = "lse depth 4",
|
||||
[NPC_UNKNOWN] = "unknown",
|
||||
};
|
||||
|
||||
@@ -528,6 +536,14 @@ do { \
|
||||
|
||||
NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LD, NPC_LT_LD_AH, 4, 4);
|
||||
NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LE, NPC_LT_LE_ESP, 0, 4);
|
||||
NPC_SCAN_HDR(NPC_MPLS1_LBTCBOS, NPC_LID_LC, NPC_LT_LC_MPLS, 0, 3);
|
||||
NPC_SCAN_HDR(NPC_MPLS1_TTL, NPC_LID_LC, NPC_LT_LC_MPLS, 3, 1);
|
||||
NPC_SCAN_HDR(NPC_MPLS2_LBTCBOS, NPC_LID_LC, NPC_LT_LC_MPLS, 4, 3);
|
||||
NPC_SCAN_HDR(NPC_MPLS2_TTL, NPC_LID_LC, NPC_LT_LC_MPLS, 7, 1);
|
||||
NPC_SCAN_HDR(NPC_MPLS3_LBTCBOS, NPC_LID_LC, NPC_LT_LC_MPLS, 8, 3);
|
||||
NPC_SCAN_HDR(NPC_MPLS3_TTL, NPC_LID_LC, NPC_LT_LC_MPLS, 11, 1);
|
||||
NPC_SCAN_HDR(NPC_MPLS4_LBTCBOS, NPC_LID_LC, NPC_LT_LC_MPLS, 12, 3);
|
||||
NPC_SCAN_HDR(NPC_MPLS4_TTL, NPC_LID_LC, NPC_LT_LC_MPLS, 15, 1);
|
||||
|
||||
/* SMAC follows the DMAC(which is 6 bytes) */
|
||||
NPC_SCAN_HDR(NPC_SMAC, NPC_LID_LA, la_ltype, la_start + 6, 6);
|
||||
@@ -593,6 +609,11 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
|
||||
/* for L2M/L2B/L3M/L3B, check if the type is present in the key */
|
||||
if (npc_check_field(rvu, blkaddr, NPC_LXMB, intf))
|
||||
*features |= BIT_ULL(NPC_LXMB);
|
||||
|
||||
for (hdr = NPC_MPLS1_LBTCBOS; hdr <= NPC_MPLS4_TTL; hdr++) {
|
||||
if (npc_check_field(rvu, blkaddr, hdr, intf))
|
||||
*features |= BIT_ULL(hdr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan key extraction profile and record how fields of our interest
|
||||
@@ -959,6 +980,47 @@ do { \
|
||||
NPC_WRITE_FLOW(NPC_INNER_VID, vlan_itci, ntohs(pkt->vlan_itci), 0,
|
||||
ntohs(mask->vlan_itci), 0);
|
||||
|
||||
NPC_WRITE_FLOW(NPC_MPLS1_LBTCBOS, mpls_lse,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_NON_TTL,
|
||||
pkt->mpls_lse[0]), 0,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_NON_TTL,
|
||||
mask->mpls_lse[0]), 0);
|
||||
NPC_WRITE_FLOW(NPC_MPLS1_TTL, mpls_lse,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
pkt->mpls_lse[0]), 0,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
mask->mpls_lse[0]), 0);
|
||||
NPC_WRITE_FLOW(NPC_MPLS2_LBTCBOS, mpls_lse,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_NON_TTL,
|
||||
pkt->mpls_lse[1]), 0,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_NON_TTL,
|
||||
mask->mpls_lse[1]), 0);
|
||||
NPC_WRITE_FLOW(NPC_MPLS2_TTL, mpls_lse,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
pkt->mpls_lse[1]), 0,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
mask->mpls_lse[1]), 0);
|
||||
NPC_WRITE_FLOW(NPC_MPLS3_LBTCBOS, mpls_lse,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_NON_TTL,
|
||||
pkt->mpls_lse[2]), 0,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_NON_TTL,
|
||||
mask->mpls_lse[2]), 0);
|
||||
NPC_WRITE_FLOW(NPC_MPLS3_TTL, mpls_lse,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
pkt->mpls_lse[2]), 0,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
mask->mpls_lse[2]), 0);
|
||||
NPC_WRITE_FLOW(NPC_MPLS4_LBTCBOS, mpls_lse,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_NON_TTL,
|
||||
pkt->mpls_lse[3]), 0,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_NON_TTL,
|
||||
mask->mpls_lse[3]), 0);
|
||||
NPC_WRITE_FLOW(NPC_MPLS4_TTL, mpls_lse,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
pkt->mpls_lse[3]), 0,
|
||||
FIELD_GET(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
mask->mpls_lse[3]), 0);
|
||||
|
||||
NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0,
|
||||
mask->next_header, 0);
|
||||
npc_update_ipv6_flow(rvu, entry, features, pkt, mask, output, intf);
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#define CN10K_TLX_BURST_MANTISSA GENMASK_ULL(43, 29)
|
||||
#define CN10K_TLX_BURST_EXPONENT GENMASK_ULL(47, 44)
|
||||
|
||||
#define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4)
|
||||
|
||||
struct otx2_tc_flow_stats {
|
||||
u64 bytes;
|
||||
u64 pkts;
|
||||
@@ -519,6 +521,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
|
||||
BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
|
||||
BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
|
||||
BIT(FLOW_DISSECTOR_KEY_IPSEC) |
|
||||
BIT_ULL(FLOW_DISSECTOR_KEY_MPLS) |
|
||||
BIT_ULL(FLOW_DISSECTOR_KEY_IP)))) {
|
||||
netdev_info(nic->netdev, "unsupported flow used key 0x%llx",
|
||||
dissector->used_keys);
|
||||
@@ -738,6 +741,61 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
|
||||
}
|
||||
}
|
||||
|
||||
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) {
|
||||
struct flow_match_mpls match;
|
||||
u8 bit;
|
||||
|
||||
flow_rule_match_mpls(rule, &match);
|
||||
|
||||
if (match.mask->used_lses & OTX2_UNSUPP_LSE_DEPTH) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"unsupported LSE depth for MPLS match offload");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
for_each_set_bit(bit, (unsigned long *)&match.mask->used_lses,
|
||||
FLOW_DIS_MPLS_MAX) {
|
||||
/* check if any of the fields LABEL,TC,BOS are set */
|
||||
if (*((u32 *)&match.mask->ls[bit]) &
|
||||
OTX2_FLOWER_MASK_MPLS_NON_TTL) {
|
||||
/* Hardware will capture 4 byte MPLS header into
|
||||
* two fields NPC_MPLSX_LBTCBOS and NPC_MPLSX_TTL.
|
||||
* Derive the associated NPC key based on header
|
||||
* index and offset.
|
||||
*/
|
||||
|
||||
req->features |= BIT_ULL(NPC_MPLS1_LBTCBOS +
|
||||
2 * bit);
|
||||
flow_spec->mpls_lse[bit] =
|
||||
FIELD_PREP(OTX2_FLOWER_MASK_MPLS_LB,
|
||||
match.key->ls[bit].mpls_label) |
|
||||
FIELD_PREP(OTX2_FLOWER_MASK_MPLS_TC,
|
||||
match.key->ls[bit].mpls_tc) |
|
||||
FIELD_PREP(OTX2_FLOWER_MASK_MPLS_BOS,
|
||||
match.key->ls[bit].mpls_bos);
|
||||
|
||||
flow_mask->mpls_lse[bit] =
|
||||
FIELD_PREP(OTX2_FLOWER_MASK_MPLS_LB,
|
||||
match.mask->ls[bit].mpls_label) |
|
||||
FIELD_PREP(OTX2_FLOWER_MASK_MPLS_TC,
|
||||
match.mask->ls[bit].mpls_tc) |
|
||||
FIELD_PREP(OTX2_FLOWER_MASK_MPLS_BOS,
|
||||
match.mask->ls[bit].mpls_bos);
|
||||
}
|
||||
|
||||
if (match.mask->ls[bit].mpls_ttl) {
|
||||
req->features |= BIT_ULL(NPC_MPLS1_TTL +
|
||||
2 * bit);
|
||||
flow_spec->mpls_lse[bit] |=
|
||||
FIELD_PREP(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
match.key->ls[bit].mpls_ttl);
|
||||
flow_mask->mpls_lse[bit] |=
|
||||
FIELD_PREP(OTX2_FLOWER_MASK_MPLS_TTL,
|
||||
match.mask->ls[bit].mpls_ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return otx2_tc_parse_actions(nic, &rule->action, req, f, node);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user