Commit 21e74835 authored by Suman Ghosh's avatar Suman Ghosh Committed by Jakub Kicinski

octeontx2-af: TC flower offload support for inner VLAN

Extend the current TC flower offload support to enable filters matching
inner VLAN, and support offload of those filters to hardware.
Signed-off-by: default avatarSuman Ghosh <sumang@marvell.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20230804045935.3010554-3-sumang@marvell.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent aa07a0f4
...@@ -1465,6 +1465,7 @@ struct flow_msg { ...@@ -1465,6 +1465,7 @@ struct flow_msg {
u8 ip_flag; u8 ip_flag;
u8 next_header; u8 next_header;
}; };
__be16 vlan_itci;
}; };
struct npc_install_flow_req { struct npc_install_flow_req {
......
...@@ -184,6 +184,7 @@ enum key_fields { ...@@ -184,6 +184,7 @@ enum key_fields {
NPC_VLAN_ETYPE_CTAG, /* 0x8100 */ NPC_VLAN_ETYPE_CTAG, /* 0x8100 */
NPC_VLAN_ETYPE_STAG, /* 0x88A8 */ NPC_VLAN_ETYPE_STAG, /* 0x88A8 */
NPC_OUTER_VID, NPC_OUTER_VID,
NPC_INNER_VID,
NPC_TOS, NPC_TOS,
NPC_IPFRAG_IPV4, NPC_IPFRAG_IPV4,
NPC_SIP_IPV4, NPC_SIP_IPV4,
...@@ -230,6 +231,8 @@ enum key_fields { ...@@ -230,6 +231,8 @@ enum key_fields {
NPC_VLAN_TAG1, NPC_VLAN_TAG1,
/* outer vlan tci for double tagged frame */ /* outer vlan tci for double tagged frame */
NPC_VLAN_TAG2, NPC_VLAN_TAG2,
/* inner vlan tci for double tagged frame */
NPC_VLAN_TAG3,
/* other header fields programmed to extract but not of our interest */ /* other header fields programmed to extract but not of our interest */
NPC_UNKNOWN, NPC_UNKNOWN,
NPC_KEY_FIELDS_MAX, NPC_KEY_FIELDS_MAX,
......
...@@ -2787,6 +2787,11 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s, ...@@ -2787,6 +2787,11 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
seq_printf(s, "mask 0x%x\n", seq_printf(s, "mask 0x%x\n",
ntohs(rule->mask.vlan_tci)); ntohs(rule->mask.vlan_tci));
break; break;
case NPC_INNER_VID:
seq_printf(s, "0x%x ", ntohs(rule->packet.vlan_itci));
seq_printf(s, "mask 0x%x\n",
ntohs(rule->mask.vlan_itci));
break;
case NPC_TOS: case NPC_TOS:
seq_printf(s, "%d ", rule->packet.tos); seq_printf(s, "%d ", rule->packet.tos);
seq_printf(s, "mask 0x%x\n", rule->mask.tos); seq_printf(s, "mask 0x%x\n", rule->mask.tos);
......
...@@ -20,6 +20,7 @@ static const char * const npc_flow_names[] = { ...@@ -20,6 +20,7 @@ static const char * const npc_flow_names[] = {
[NPC_VLAN_ETYPE_CTAG] = "vlan ether type ctag", [NPC_VLAN_ETYPE_CTAG] = "vlan ether type ctag",
[NPC_VLAN_ETYPE_STAG] = "vlan ether type stag", [NPC_VLAN_ETYPE_STAG] = "vlan ether type stag",
[NPC_OUTER_VID] = "outer vlan id", [NPC_OUTER_VID] = "outer vlan id",
[NPC_INNER_VID] = "inner vlan id",
[NPC_TOS] = "tos", [NPC_TOS] = "tos",
[NPC_IPFRAG_IPV4] = "fragmented IPv4 header ", [NPC_IPFRAG_IPV4] = "fragmented IPv4 header ",
[NPC_SIP_IPV4] = "ipv4 source ip", [NPC_SIP_IPV4] = "ipv4 source ip",
...@@ -328,6 +329,8 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf) ...@@ -328,6 +329,8 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf)
*/ */
struct npc_key_field *vlan_tag1; struct npc_key_field *vlan_tag1;
struct npc_key_field *vlan_tag2; struct npc_key_field *vlan_tag2;
/* Inner VLAN TCI for double tagged frames */
struct npc_key_field *vlan_tag3;
u64 *features; u64 *features;
u8 start_lid; u8 start_lid;
int i; int i;
...@@ -350,6 +353,7 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf) ...@@ -350,6 +353,7 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf)
etype_tag2 = &key_fields[NPC_ETYPE_TAG2]; etype_tag2 = &key_fields[NPC_ETYPE_TAG2];
vlan_tag1 = &key_fields[NPC_VLAN_TAG1]; vlan_tag1 = &key_fields[NPC_VLAN_TAG1];
vlan_tag2 = &key_fields[NPC_VLAN_TAG2]; vlan_tag2 = &key_fields[NPC_VLAN_TAG2];
vlan_tag3 = &key_fields[NPC_VLAN_TAG3];
/* if key profile programmed does not extract Ethertype at all */ /* if key profile programmed does not extract Ethertype at all */
if (!etype_ether->nr_kws && !etype_tag1->nr_kws && !etype_tag2->nr_kws) { if (!etype_ether->nr_kws && !etype_tag1->nr_kws && !etype_tag2->nr_kws) {
...@@ -431,6 +435,12 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf) ...@@ -431,6 +435,12 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf)
goto done; goto done;
} }
*features |= BIT_ULL(NPC_OUTER_VID); *features |= BIT_ULL(NPC_OUTER_VID);
/* If key profile extracts inner vlan tci */
if (vlan_tag3->nr_kws) {
key_fields[NPC_INNER_VID] = *vlan_tag3;
*features |= BIT_ULL(NPC_INNER_VID);
}
done: done:
return; return;
} }
...@@ -513,6 +523,7 @@ do { \ ...@@ -513,6 +523,7 @@ do { \
NPC_SCAN_HDR(NPC_ETYPE_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8, 2); NPC_SCAN_HDR(NPC_ETYPE_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8, 2);
NPC_SCAN_HDR(NPC_VLAN_TAG1, NPC_LID_LB, NPC_LT_LB_CTAG, 2, 2); NPC_SCAN_HDR(NPC_VLAN_TAG1, NPC_LID_LB, NPC_LT_LB_CTAG, 2, 2);
NPC_SCAN_HDR(NPC_VLAN_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 2, 2); NPC_SCAN_HDR(NPC_VLAN_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 2, 2);
NPC_SCAN_HDR(NPC_VLAN_TAG3, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6, 2);
NPC_SCAN_HDR(NPC_DMAC, NPC_LID_LA, la_ltype, la_start, 6); NPC_SCAN_HDR(NPC_DMAC, NPC_LID_LA, la_ltype, la_start, 6);
NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LD, NPC_LT_LD_AH, 4, 4); NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LD, NPC_LT_LD_AH, 4, 4);
...@@ -943,6 +954,8 @@ do { \ ...@@ -943,6 +954,8 @@ do { \
NPC_WRITE_FLOW(NPC_OUTER_VID, vlan_tci, ntohs(pkt->vlan_tci), 0, NPC_WRITE_FLOW(NPC_OUTER_VID, vlan_tci, ntohs(pkt->vlan_tci), 0,
ntohs(mask->vlan_tci), 0); ntohs(mask->vlan_tci), 0);
NPC_WRITE_FLOW(NPC_INNER_VID, vlan_itci, ntohs(pkt->vlan_itci), 0,
ntohs(mask->vlan_itci), 0);
NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0, NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0,
mask->next_header, 0); mask->next_header, 0);
......
...@@ -447,10 +447,11 @@ static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec ...@@ -447,10 +447,11 @@ static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec
u16 vlan_tci, vlan_tci_mask; u16 vlan_tci, vlan_tci_mask;
if (is_inner) if (is_inner)
return -EOPNOTSUPP; flow_rule_match_cvlan(rule, &match);
else
flow_rule_match_vlan(rule, &match); flow_rule_match_vlan(rule, &match);
if (ntohs(match.key->vlan_tpid) != ETH_P_8021Q) {
if (!eth_type_vlan(match.key->vlan_tpid)) {
netdev_err(nic->netdev, "vlan tpid 0x%x not supported\n", netdev_err(nic->netdev, "vlan tpid 0x%x not supported\n",
ntohs(match.key->vlan_tpid)); ntohs(match.key->vlan_tpid));
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -480,10 +481,16 @@ static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec ...@@ -480,10 +481,16 @@ static int otx2_tc_process_vlan(struct otx2_nic *nic, struct flow_msg *flow_spec
vlan_tci_mask = match.mask->vlan_id | vlan_tci_mask = match.mask->vlan_id |
match.mask->vlan_dei << 12 | match.mask->vlan_dei << 12 |
match.mask->vlan_priority << 13; match.mask->vlan_priority << 13;
if (is_inner) {
flow_spec->vlan_itci = htons(vlan_tci);
flow_mask->vlan_itci = htons(vlan_tci_mask);
req->features |= BIT_ULL(NPC_INNER_VID);
} else {
flow_spec->vlan_tci = htons(vlan_tci); flow_spec->vlan_tci = htons(vlan_tci);
flow_mask->vlan_tci = htons(vlan_tci_mask); flow_mask->vlan_tci = htons(vlan_tci_mask);
req->features |= BIT_ULL(NPC_OUTER_VID); req->features |= BIT_ULL(NPC_OUTER_VID);
} }
}
return 0; return 0;
} }
...@@ -507,6 +514,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, ...@@ -507,6 +514,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) | BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
BIT(FLOW_DISSECTOR_KEY_CVLAN) |
BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
...@@ -647,6 +655,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, ...@@ -647,6 +655,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
return ret; return ret;
} }
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
int ret;
ret = otx2_tc_process_vlan(nic, flow_spec, flow_mask, rule, req, true);
if (ret)
return ret;
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
struct flow_match_ipv4_addrs match; struct flow_match_ipv4_addrs match;
......
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