octeontx2-pf: TC flower offload support for ICMP type and code
authorGeetha sowjanya <gakula@marvell.com>
Wed, 22 Nov 2023 11:41:42 +0000 (17:11 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 24 Nov 2023 12:10:17 +0000 (12:10 +0000)
Adds tc offload support for matching on ICMP type and code.

Example usage:
To enable adding tc ingress rules
        tc qdisc add dev eth0 ingress

TC rule drop the ICMP echo reply:
        tc filter add dev eth0 protocol ip parent ffff: \
        flower ip_proto icmp type 8 code 0 skip_sw action drop

TC rule to drop ICMPv6 echo reply:
        tc filter add dev eth0 protocol ipv6 parent ffff: flower \
        indev eth0 ip_proto icmpv6 type 128 code 0 action drop

Signed-off-by: Geetha sowjanya <gakula@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/npc.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c

index 6845556581c3fa3f01c74e8a138d1c6a7a945723..b4ced739ae44eccbf7c948ca6f23d96a5320f7d1 100644 (file)
@@ -1479,6 +1479,8 @@ struct flow_msg {
 #define OTX2_FLOWER_MASK_MPLS_TTL              GENMASK(7, 0)
 #define OTX2_FLOWER_MASK_MPLS_NON_TTL          GENMASK(31, 8)
        u32 mpls_lse[4];
+       u8 icmp_type;
+       u8 icmp_code;
 };
 
 struct npc_install_flow_req {
index ab3e39eef2eb4197ed9c7b3ea701a3b6fc4fe859..ffc0aa0a7b473f9d6a403910e7be9c254e2bbfd0 100644 (file)
@@ -214,6 +214,8 @@ enum key_fields {
        NPC_MPLS3_TTL,
        NPC_MPLS4_LBTCBOS,
        NPC_MPLS4_TTL,
+       NPC_TYPE_ICMP,
+       NPC_CODE_ICMP,
        NPC_HEADER_FIELDS_MAX,
        NPC_CHAN = NPC_HEADER_FIELDS_MAX, /* Valid when Rx */
        NPC_PF_FUNC, /* Valid when Tx */
index bd817ee88735b732166cfd7da27d443a8cad5f31..468b6561ed3fb11636f771cfa8003f982a38a895 100644 (file)
@@ -2889,6 +2889,14 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
                        RVU_DBG_PRINT_MPLS_TTL(rule->packet.mpls_lse[3],
                                               rule->mask.mpls_lse[3]);
                        break;
+               case NPC_TYPE_ICMP:
+                       seq_printf(s, "%d ", rule->packet.icmp_type);
+                       seq_printf(s, "mask 0x%x\n", rule->mask.icmp_type);
+                       break;
+               case NPC_CODE_ICMP:
+                       seq_printf(s, "%d ", rule->packet.icmp_code);
+                       seq_printf(s, "mask 0x%x\n", rule->mask.icmp_code);
+                       break;
                default:
                        seq_puts(s, "\n");
                        break;
index 114e4ec218023b80b7a2aa150e82827107261727..db8f151636af5bc2d0e5357ba112e9e0aa4f7f69 100644 (file)
@@ -51,6 +51,8 @@ static const char * const npc_flow_names[] = {
        [NPC_MPLS3_TTL]     = "lse depth 3 ttl",
        [NPC_MPLS4_LBTCBOS] = "lse depth 4 label tc bos",
        [NPC_MPLS4_TTL]     = "lse depth 4",
+       [NPC_TYPE_ICMP] = "icmp type",
+       [NPC_CODE_ICMP] = "icmp code",
        [NPC_UNKNOWN]   = "unknown",
 };
 
@@ -526,6 +528,8 @@ do {                                                                               \
        NPC_SCAN_HDR(NPC_DPORT_TCP, NPC_LID_LD, NPC_LT_LD_TCP, 2, 2);
        NPC_SCAN_HDR(NPC_SPORT_SCTP, NPC_LID_LD, NPC_LT_LD_SCTP, 0, 2);
        NPC_SCAN_HDR(NPC_DPORT_SCTP, NPC_LID_LD, NPC_LT_LD_SCTP, 2, 2);
+       NPC_SCAN_HDR(NPC_TYPE_ICMP, NPC_LID_LD, NPC_LT_LD_ICMP, 0, 1);
+       NPC_SCAN_HDR(NPC_CODE_ICMP, NPC_LID_LD, NPC_LT_LD_ICMP, 1, 1);
        NPC_SCAN_HDR(NPC_ETYPE_ETHER, NPC_LID_LA, NPC_LT_LA_ETHER, 12, 2);
        NPC_SCAN_HDR(NPC_ETYPE_TAG1, NPC_LID_LB, NPC_LT_LB_CTAG, 4, 2);
        NPC_SCAN_HDR(NPC_ETYPE_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8, 2);
@@ -555,7 +559,7 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
 {
        struct npc_mcam *mcam = &rvu->hw->mcam;
        u64 *features = &mcam->rx_features;
-       u64 tcp_udp_sctp;
+       u64 proto_flags;
        int hdr;
 
        if (is_npc_intf_tx(intf))
@@ -566,18 +570,21 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
                        *features |= BIT_ULL(hdr);
        }
 
-       tcp_udp_sctp = BIT_ULL(NPC_SPORT_TCP) | BIT_ULL(NPC_SPORT_UDP) |
+       proto_flags = BIT_ULL(NPC_SPORT_TCP) | BIT_ULL(NPC_SPORT_UDP) |
                       BIT_ULL(NPC_DPORT_TCP) | BIT_ULL(NPC_DPORT_UDP) |
-                      BIT_ULL(NPC_SPORT_SCTP) | BIT_ULL(NPC_DPORT_SCTP);
+                      BIT_ULL(NPC_SPORT_SCTP) | BIT_ULL(NPC_DPORT_SCTP) |
+                      BIT_ULL(NPC_SPORT_SCTP) | BIT_ULL(NPC_DPORT_SCTP) |
+                      BIT_ULL(NPC_TYPE_ICMP) | BIT_ULL(NPC_CODE_ICMP);
 
        /* for tcp/udp/sctp corresponding layer type should be in the key */
-       if (*features & tcp_udp_sctp) {
+       if (*features & proto_flags) {
                if (!npc_check_field(rvu, blkaddr, NPC_LD, intf))
-                       *features &= ~tcp_udp_sctp;
+                       *features &= ~proto_flags;
                else
                        *features |= BIT_ULL(NPC_IPPROTO_TCP) |
                                     BIT_ULL(NPC_IPPROTO_UDP) |
-                                    BIT_ULL(NPC_IPPROTO_SCTP);
+                                    BIT_ULL(NPC_IPPROTO_SCTP) |
+                                    BIT_ULL(NPC_IPPROTO_ICMP);
        }
 
        /* for AH/ICMP/ICMPv6/, check if corresponding layer type is present in the key */
@@ -971,6 +978,10 @@ do {                                                                             \
                       ntohs(mask->sport), 0);
        NPC_WRITE_FLOW(NPC_DPORT_SCTP, dport, ntohs(pkt->dport), 0,
                       ntohs(mask->dport), 0);
+       NPC_WRITE_FLOW(NPC_TYPE_ICMP, icmp_type, pkt->icmp_type, 0,
+                      mask->icmp_type, 0);
+       NPC_WRITE_FLOW(NPC_CODE_ICMP, icmp_code, pkt->icmp_code, 0,
+                      mask->icmp_code, 0);
 
        NPC_WRITE_FLOW(NPC_IPSEC_SPI, spi, ntohl(pkt->spi), 0,
                       ntohl(mask->spi), 0);
index 8a5e3987a482c2986b1780d7cb5ce87b6a16c3b9..10657a7559d7871c680cf9c51106cd62b21caacf 100644 (file)
@@ -522,6 +522,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
              BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
              BIT(FLOW_DISSECTOR_KEY_IPSEC) |
              BIT_ULL(FLOW_DISSECTOR_KEY_MPLS) |
+             BIT_ULL(FLOW_DISSECTOR_KEY_ICMP) |
              BIT_ULL(FLOW_DISSECTOR_KEY_IP))))  {
                netdev_info(nic->netdev, "unsupported flow used key 0x%llx",
                            dissector->used_keys);
@@ -796,6 +797,19 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
                }
        }
 
+       if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) {
+               struct flow_match_icmp match;
+
+               flow_rule_match_icmp(rule, &match);
+
+               flow_spec->icmp_type = match.key->type;
+               flow_mask->icmp_type = match.mask->type;
+               req->features |= BIT_ULL(NPC_TYPE_ICMP);
+
+               flow_spec->icmp_code = match.key->code;
+               flow_mask->icmp_code = match.mask->code;
+               req->features |= BIT_ULL(NPC_CODE_ICMP);
+       }
        return otx2_tc_parse_actions(nic, &rule->action, req, f, node);
 }