Commit c672e372 authored by Suman Ghosh's avatar Suman Ghosh Committed by David S. Miller

octeontx2-pf: Add support to filter packet based on IP fragment

1. Added support to filter packets based on IP fragment.
For IPv4 packets check for ip_flag == 0x20 (more fragment bit set).
For IPv6 packets check for next_header == 0x2c (next_header set to
'fragment header for IPv6')
2. Added configuration support from both "ethtool ntuple" and "tc flower".
Signed-off-by: default avatarSuman Ghosh <sumang@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a66d79ee
...@@ -1440,6 +1440,10 @@ struct flow_msg { ...@@ -1440,6 +1440,10 @@ struct flow_msg {
u8 tc; u8 tc;
__be16 sport; __be16 sport;
__be16 dport; __be16 dport;
union {
u8 ip_flag;
u8 next_header;
};
}; };
struct npc_install_flow_req { struct npc_install_flow_req {
......
...@@ -185,8 +185,10 @@ enum key_fields { ...@@ -185,8 +185,10 @@ enum key_fields {
NPC_VLAN_ETYPE_STAG, /* 0x88A8 */ NPC_VLAN_ETYPE_STAG, /* 0x88A8 */
NPC_OUTER_VID, NPC_OUTER_VID,
NPC_TOS, NPC_TOS,
NPC_IPFRAG_IPV4,
NPC_SIP_IPV4, NPC_SIP_IPV4,
NPC_DIP_IPV4, NPC_DIP_IPV4,
NPC_IPFRAG_IPV6,
NPC_SIP_IPV6, NPC_SIP_IPV6,
NPC_DIP_IPV6, NPC_DIP_IPV6,
NPC_IPPROTO_TCP, NPC_IPPROTO_TCP,
......
...@@ -2799,6 +2799,14 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s, ...@@ -2799,6 +2799,14 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
seq_printf(s, "%pI6 ", rule->packet.ip6dst); seq_printf(s, "%pI6 ", rule->packet.ip6dst);
seq_printf(s, "mask %pI6\n", rule->mask.ip6dst); seq_printf(s, "mask %pI6\n", rule->mask.ip6dst);
break; break;
case NPC_IPFRAG_IPV6:
seq_printf(s, "0x%x ", rule->packet.next_header);
seq_printf(s, "mask 0x%x\n", rule->mask.next_header);
break;
case NPC_IPFRAG_IPV4:
seq_printf(s, "0x%x ", rule->packet.ip_flag);
seq_printf(s, "mask 0x%x\n", rule->mask.ip_flag);
break;
case NPC_SPORT_TCP: case NPC_SPORT_TCP:
case NPC_SPORT_UDP: case NPC_SPORT_UDP:
case NPC_SPORT_SCTP: case NPC_SPORT_SCTP:
......
...@@ -26,8 +26,10 @@ static const char * const npc_flow_names[] = { ...@@ -26,8 +26,10 @@ static const char * const npc_flow_names[] = {
[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_TOS] = "tos", [NPC_TOS] = "tos",
[NPC_IPFRAG_IPV4] = "fragmented IPv4 header ",
[NPC_SIP_IPV4] = "ipv4 source ip", [NPC_SIP_IPV4] = "ipv4 source ip",
[NPC_DIP_IPV4] = "ipv4 destination ip", [NPC_DIP_IPV4] = "ipv4 destination ip",
[NPC_IPFRAG_IPV6] = "fragmented IPv6 header ",
[NPC_SIP_IPV6] = "ipv6 source ip", [NPC_SIP_IPV6] = "ipv6 source ip",
[NPC_DIP_IPV6] = "ipv6 destination ip", [NPC_DIP_IPV6] = "ipv6 destination ip",
[NPC_IPPROTO_TCP] = "ip proto tcp", [NPC_IPPROTO_TCP] = "ip proto tcp",
...@@ -484,8 +486,10 @@ do { \ ...@@ -484,8 +486,10 @@ do { \
* 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_TOS, NPC_LID_LC, NPC_LT_LC_IP, 1, 1);
NPC_SCAN_HDR(NPC_IPFRAG_IPV4, NPC_LID_LC, NPC_LT_LC_IP, 6, 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_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); 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_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);
...@@ -899,6 +903,8 @@ do { \ ...@@ -899,6 +903,8 @@ do { \
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_TOS, tos, pkt->tos, 0, mask->tos, 0);
NPC_WRITE_FLOW(NPC_IPFRAG_IPV4, ip_flag, pkt->ip_flag, 0,
mask->ip_flag, 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,
...@@ -919,6 +925,8 @@ do { \ ...@@ -919,6 +925,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_IPFRAG_IPV6, next_header, pkt->next_header, 0,
mask->next_header, 0);
npc_update_ipv6_flow(rvu, entry, features, pkt, mask, output, intf); npc_update_ipv6_flow(rvu, entry, features, pkt, mask, output, intf);
npc_update_vlan_features(rvu, entry, features, intf); npc_update_vlan_features(rvu, entry, features, intf);
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#include "otx2_devlink.h" #include "otx2_devlink.h"
#include <rvu_trace.h> #include <rvu_trace.h>
/* IPv4 flag more fragment bit */
#define IPV4_FLAG_MORE 0x20
/* PCI device IDs */ /* PCI device IDs */
#define PCI_DEVID_OCTEONTX2_RVU_PF 0xA063 #define PCI_DEVID_OCTEONTX2_RVU_PF 0xA063
#define PCI_DEVID_OCTEONTX2_RVU_VF 0xA064 #define PCI_DEVID_OCTEONTX2_RVU_VF 0xA064
......
...@@ -711,6 +711,11 @@ static int otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec *fsp, ...@@ -711,6 +711,11 @@ static int otx2_prepare_ipv6_flow(struct ethtool_rx_flow_spec *fsp,
sizeof(pmask->ip6dst)); sizeof(pmask->ip6dst));
req->features |= BIT_ULL(NPC_DIP_IPV6); req->features |= BIT_ULL(NPC_DIP_IPV6);
} }
if (ipv6_usr_hdr->l4_proto == IPPROTO_FRAGMENT) {
pkt->next_header = ipv6_usr_hdr->l4_proto;
pmask->next_header = ipv6_usr_mask->l4_proto;
req->features |= BIT_ULL(NPC_IPFRAG_IPV6);
}
pkt->etype = cpu_to_be16(ETH_P_IPV6); pkt->etype = cpu_to_be16(ETH_P_IPV6);
pmask->etype = cpu_to_be16(0xFFFF); pmask->etype = cpu_to_be16(0xFFFF);
req->features |= BIT_ULL(NPC_ETYPE); req->features |= BIT_ULL(NPC_ETYPE);
...@@ -891,10 +896,22 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp, ...@@ -891,10 +896,22 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
req->features |= BIT_ULL(NPC_OUTER_VID); req->features |= BIT_ULL(NPC_OUTER_VID);
} }
/* Not Drop/Direct to queue but use action in default entry */ if (fsp->m_ext.data[1]) {
if (fsp->m_ext.data[1] && if (flow_type == IP_USER_FLOW) {
fsp->h_ext.data[1] == cpu_to_be32(OTX2_DEFAULT_ACTION)) if (be32_to_cpu(fsp->h_ext.data[1]) != IPV4_FLAG_MORE)
req->op = NIX_RX_ACTION_DEFAULT; return -EINVAL;
pkt->ip_flag = be32_to_cpu(fsp->h_ext.data[1]);
pmask->ip_flag = be32_to_cpu(fsp->m_ext.data[1]);
req->features |= BIT_ULL(NPC_IPFRAG_IPV4);
} else if (fsp->h_ext.data[1] ==
cpu_to_be32(OTX2_DEFAULT_ACTION)) {
/* Not Drop/Direct to queue but use action
* in default entry
*/
req->op = NIX_RX_ACTION_DEFAULT;
}
}
} }
if (fsp->flow_type & FLOW_MAC_EXT && if (fsp->flow_type & FLOW_MAC_EXT &&
......
...@@ -532,6 +532,31 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, ...@@ -532,6 +532,31 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
req->features |= BIT_ULL(NPC_IPPROTO_ICMP6); req->features |= BIT_ULL(NPC_IPPROTO_ICMP6);
} }
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
struct flow_match_control match;
flow_rule_match_control(rule, &match);
if (match.mask->flags & FLOW_DIS_FIRST_FRAG) {
NL_SET_ERR_MSG_MOD(extack, "HW doesn't support frag first/later");
return -EOPNOTSUPP;
}
if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
if (ntohs(flow_spec->etype) == ETH_P_IP) {
flow_spec->ip_flag = IPV4_FLAG_MORE;
flow_mask->ip_flag = 0xff;
req->features |= BIT_ULL(NPC_IPFRAG_IPV4);
} else if (ntohs(flow_spec->etype) == ETH_P_IPV6) {
flow_spec->next_header = IPPROTO_FRAGMENT;
flow_mask->next_header = 0xff;
req->features |= BIT_ULL(NPC_IPFRAG_IPV6);
} else {
NL_SET_ERR_MSG_MOD(extack, "flow-type should be either IPv4 and IPv6");
return -EOPNOTSUPP;
}
}
}
if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
struct flow_match_eth_addrs match; struct flow_match_eth_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