Commit 2b9cef66 authored by Naveen Mamindlapalli's avatar Naveen Mamindlapalli Committed by David S. Miller

octeontx2-pf: Add ip tos and ip proto icmp/icmpv6 flow offload support

Add support for programming the HW MCAM match key with IP tos, IP(v6)
proto icmp/icmpv6, allowing flow offload rules to be installed using
those fields. The NPC HW extracts layer type, which will be used as a
matching criteria for different IP protocols.

The ethtool n-tuple filter logic has been updated to parse the IP tos
and l4proto for HW offloading. l4proto tcp/udp/sctp/ah/esp/icmp are
supported. See example usage below.

Ex: Redirect l4proto icmp to vf 0 queue 0
ethtool -U eth0 flow-type ip4 l4proto 1 action vf 0 queue 0

Ex: Redirect flow with ip tos 8 to vf 0 queue 0
ethtool -U eth0 flow-type ip4 tos 8 vf 0 queue 0
Signed-off-by: default avatarNaveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a04be4b6
...@@ -167,6 +167,8 @@ enum key_fields { ...@@ -167,6 +167,8 @@ enum key_fields {
NPC_IPPROTO_SCTP, NPC_IPPROTO_SCTP,
NPC_IPPROTO_AH, NPC_IPPROTO_AH,
NPC_IPPROTO_ESP, NPC_IPPROTO_ESP,
NPC_IPPROTO_ICMP,
NPC_IPPROTO_ICMP6,
NPC_SPORT_TCP, NPC_SPORT_TCP,
NPC_DPORT_TCP, NPC_DPORT_TCP,
NPC_SPORT_UDP, NPC_SPORT_UDP,
......
...@@ -29,6 +29,8 @@ static const char * const npc_flow_names[] = { ...@@ -29,6 +29,8 @@ static const char * const npc_flow_names[] = {
[NPC_IPPROTO_TCP] = "ip proto tcp", [NPC_IPPROTO_TCP] = "ip proto tcp",
[NPC_IPPROTO_UDP] = "ip proto udp", [NPC_IPPROTO_UDP] = "ip proto udp",
[NPC_IPPROTO_SCTP] = "ip proto sctp", [NPC_IPPROTO_SCTP] = "ip proto sctp",
[NPC_IPPROTO_ICMP] = "ip proto icmp",
[NPC_IPPROTO_ICMP6] = "ip proto icmp6",
[NPC_IPPROTO_AH] = "ip proto AH", [NPC_IPPROTO_AH] = "ip proto AH",
[NPC_IPPROTO_ESP] = "ip proto ESP", [NPC_IPPROTO_ESP] = "ip proto ESP",
[NPC_SPORT_TCP] = "tcp source port", [NPC_SPORT_TCP] = "tcp source port",
...@@ -427,6 +429,7 @@ do { \ ...@@ -427,6 +429,7 @@ do { \
* packet header fields below. * packet header fields below.
* Example: Source IP is 4 bytes and starts at 12th byte of IP header * Example: Source IP is 4 bytes and starts at 12th byte of IP header
*/ */
NPC_SCAN_HDR(NPC_TOS, NPC_LID_LC, NPC_LT_LC_IP, 1, 1);
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_SIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 8, 16); NPC_SCAN_HDR(NPC_SIP_IPV6, NPC_LID_LC, NPC_LT_LC_IP6, 8, 16);
...@@ -477,9 +480,12 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf) ...@@ -477,9 +480,12 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
BIT_ULL(NPC_IPPROTO_SCTP); BIT_ULL(NPC_IPPROTO_SCTP);
} }
/* for AH, check if corresponding layer type is present in the key */ /* for AH/ICMP/ICMPv6/, check if corresponding layer type is present in the key */
if (npc_check_field(rvu, blkaddr, NPC_LD, intf)) if (npc_check_field(rvu, blkaddr, NPC_LD, intf)) {
*features |= BIT_ULL(NPC_IPPROTO_AH); *features |= BIT_ULL(NPC_IPPROTO_AH);
*features |= BIT_ULL(NPC_IPPROTO_ICMP);
*features |= BIT_ULL(NPC_IPPROTO_ICMP6);
}
/* for ESP, check if corresponding layer type is present in the key */ /* for ESP, check if corresponding layer type is present in the key */
if (npc_check_field(rvu, blkaddr, NPC_LE, intf)) if (npc_check_field(rvu, blkaddr, NPC_LE, intf))
...@@ -769,6 +775,12 @@ static void npc_update_flow(struct rvu *rvu, struct mcam_entry *entry, ...@@ -769,6 +775,12 @@ static void npc_update_flow(struct rvu *rvu, struct mcam_entry *entry,
if (features & BIT_ULL(NPC_IPPROTO_SCTP)) if (features & BIT_ULL(NPC_IPPROTO_SCTP))
npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_SCTP, npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_SCTP,
0, ~0ULL, 0, intf); 0, ~0ULL, 0, intf);
if (features & BIT_ULL(NPC_IPPROTO_ICMP))
npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP,
0, ~0ULL, 0, intf);
if (features & BIT_ULL(NPC_IPPROTO_ICMP6))
npc_update_entry(rvu, NPC_LD, entry, NPC_LT_LD_ICMP6,
0, ~0ULL, 0, intf);
if (features & BIT_ULL(NPC_OUTER_VID)) if (features & BIT_ULL(NPC_OUTER_VID))
npc_update_entry(rvu, NPC_LB, entry, npc_update_entry(rvu, NPC_LB, entry,
...@@ -798,6 +810,7 @@ do { \ ...@@ -798,6 +810,7 @@ do { \
NPC_WRITE_FLOW(NPC_SMAC, smac, smac_val, 0, smac_mask, 0); NPC_WRITE_FLOW(NPC_SMAC, smac, smac_val, 0, smac_mask, 0);
NPC_WRITE_FLOW(NPC_ETYPE, etype, ntohs(pkt->etype), 0, NPC_WRITE_FLOW(NPC_ETYPE, etype, ntohs(pkt->etype), 0,
ntohs(mask->etype), 0); ntohs(mask->etype), 0);
NPC_WRITE_FLOW(NPC_TOS, tos, pkt->tos, 0, mask->tos, 0);
NPC_WRITE_FLOW(NPC_SIP_IPV4, ip4src, ntohl(pkt->ip4src), 0, NPC_WRITE_FLOW(NPC_SIP_IPV4, ip4src, ntohl(pkt->ip4src), 0,
ntohl(mask->ip4src), 0); ntohl(mask->ip4src), 0);
NPC_WRITE_FLOW(NPC_DIP_IPV4, ip4dst, ntohl(pkt->ip4dst), 0, NPC_WRITE_FLOW(NPC_DIP_IPV4, ip4dst, ntohl(pkt->ip4dst), 0,
......
...@@ -301,6 +301,35 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp, ...@@ -301,6 +301,35 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
sizeof(pmask->ip4dst)); sizeof(pmask->ip4dst));
req->features |= BIT_ULL(NPC_DIP_IPV4); req->features |= BIT_ULL(NPC_DIP_IPV4);
} }
if (ipv4_usr_mask->tos) {
pkt->tos = ipv4_usr_hdr->tos;
pmask->tos = ipv4_usr_mask->tos;
req->features |= BIT_ULL(NPC_TOS);
}
if (ipv4_usr_mask->proto) {
switch (ipv4_usr_hdr->proto) {
case IPPROTO_ICMP:
req->features |= BIT_ULL(NPC_IPPROTO_ICMP);
break;
case IPPROTO_TCP:
req->features |= BIT_ULL(NPC_IPPROTO_TCP);
break;
case IPPROTO_UDP:
req->features |= BIT_ULL(NPC_IPPROTO_UDP);
break;
case IPPROTO_SCTP:
req->features |= BIT_ULL(NPC_IPPROTO_SCTP);
break;
case IPPROTO_AH:
req->features |= BIT_ULL(NPC_IPPROTO_AH);
break;
case IPPROTO_ESP:
req->features |= BIT_ULL(NPC_IPPROTO_ESP);
break;
default:
return -EOPNOTSUPP;
}
}
pkt->etype = cpu_to_be16(ETH_P_IP); pkt->etype = cpu_to_be16(ETH_P_IP);
pmask->etype = cpu_to_be16(0xFFFF); pmask->etype = cpu_to_be16(0xFFFF);
req->features |= BIT_ULL(NPC_ETYPE); req->features |= BIT_ULL(NPC_ETYPE);
...@@ -325,6 +354,11 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp, ...@@ -325,6 +354,11 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
sizeof(pmask->ip4dst)); sizeof(pmask->ip4dst));
req->features |= BIT_ULL(NPC_DIP_IPV4); req->features |= BIT_ULL(NPC_DIP_IPV4);
} }
if (ipv4_l4_mask->tos) {
pkt->tos = ipv4_l4_hdr->tos;
pmask->tos = ipv4_l4_mask->tos;
req->features |= BIT_ULL(NPC_TOS);
}
if (ipv4_l4_mask->psrc) { if (ipv4_l4_mask->psrc) {
memcpy(&pkt->sport, &ipv4_l4_hdr->psrc, memcpy(&pkt->sport, &ipv4_l4_hdr->psrc,
sizeof(pkt->sport)); sizeof(pkt->sport));
...@@ -375,10 +409,14 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp, ...@@ -375,10 +409,14 @@ static int otx2_prepare_ipv4_flow(struct ethtool_rx_flow_spec *fsp,
sizeof(pmask->ip4dst)); sizeof(pmask->ip4dst));
req->features |= BIT_ULL(NPC_DIP_IPV4); req->features |= BIT_ULL(NPC_DIP_IPV4);
} }
if (ah_esp_mask->tos) {
pkt->tos = ah_esp_hdr->tos;
pmask->tos = ah_esp_mask->tos;
req->features |= BIT_ULL(NPC_TOS);
}
/* NPC profile doesn't extract AH/ESP header fields */ /* NPC profile doesn't extract AH/ESP header fields */
if ((ah_esp_mask->spi & ah_esp_hdr->spi) || if (ah_esp_mask->spi & ah_esp_hdr->spi)
(ah_esp_mask->tos & ah_esp_mask->tos))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (flow_type == AH_V4_FLOW) if (flow_type == AH_V4_FLOW)
......
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