octeontx2-pf: TC flower offload support for SPI field
authorRatheesh Kannoth <rkannoth@marvell.com>
Tue, 1 Aug 2023 01:41:01 +0000 (07:11 +0530)
committerDavid S. Miller <davem@davemloft.net>
Wed, 2 Aug 2023 09:09:32 +0000 (10:09 +0100)
Driver support to offload TC flower rules which matches
against SPI field of IPSEC packets (AH/ESP).

Signed-off-by: Ratheesh Kannoth <rkannoth@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 ed66c59..a8f3c8f 100644 (file)
@@ -1451,6 +1451,10 @@ struct flow_msg {
                __be32 ip4dst;
                __be32 ip6dst[4];
        };
+       union {
+               __be32 spi;
+       };
+
        u8 tos;
        u8 ip_ver;
        u8 ip_proto;
index 9beeead..534f20c 100644 (file)
@@ -204,6 +204,7 @@ enum key_fields {
        NPC_DPORT_UDP,
        NPC_SPORT_SCTP,
        NPC_DPORT_SCTP,
+       NPC_IPSEC_SPI,
        NPC_HEADER_FIELDS_MAX,
        NPC_CHAN = NPC_HEADER_FIELDS_MAX, /* Valid when Rx */
        NPC_PF_FUNC, /* Valid when Tx */
index 3b26893..7cd33ed 100644 (file)
@@ -2827,6 +2827,10 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
                        seq_printf(s, "%d ", ntohs(rule->packet.dport));
                        seq_printf(s, "mask 0x%x\n", ntohs(rule->mask.dport));
                        break;
+               case NPC_IPSEC_SPI:
+                       seq_printf(s, "0x%x ", ntohl(rule->packet.spi));
+                       seq_printf(s, "mask 0x%x\n", ntohl(rule->mask.spi));
+                       break;
                default:
                        seq_puts(s, "\n");
                        break;
index 9c365cc..bb715e6 100644 (file)
@@ -41,6 +41,7 @@ static const char * const npc_flow_names[] = {
        [NPC_SPORT_SCTP] = "sctp source port",
        [NPC_DPORT_SCTP] = "sctp destination port",
        [NPC_LXMB]      = "Mcast/Bcast header ",
+       [NPC_IPSEC_SPI] = "SPI ",
        [NPC_UNKNOWN]   = "unknown",
 };
 
@@ -513,6 +514,10 @@ do {                                                                              \
        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_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_LE, NPC_LT_LE_ESP, 0, 4);
+
        /* SMAC follows the DMAC(which is 6 bytes) */
        NPC_SCAN_HDR(NPC_SMAC, NPC_LID_LA, la_ltype, la_start + 6, 6);
        /* PF_FUNC is 2 bytes at 0th byte of NPC_LT_LA_IH_NIX_ETHER */
@@ -564,6 +569,9 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
                if (!npc_check_field(rvu, blkaddr, NPC_LB, intf))
                        *features &= ~BIT_ULL(NPC_OUTER_VID);
 
+       if (*features & (BIT_ULL(NPC_IPPROTO_AH) | BIT_ULL(NPC_IPPROTO_ESP)))
+               *features |= BIT_ULL(NPC_IPSEC_SPI);
+
        /* for vlan ethertypes corresponding layer type should be in the key */
        if (npc_check_field(rvu, blkaddr, NPC_LB, intf))
                *features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG) |
@@ -930,6 +938,9 @@ do {                                                                              \
        NPC_WRITE_FLOW(NPC_DPORT_SCTP, dport, ntohs(pkt->dport), 0,
                       ntohs(mask->dport), 0);
 
+       NPC_WRITE_FLOW(NPC_IPSEC_SPI, spi, ntohl(pkt->spi), 0,
+                      ntohl(mask->spi), 0);
+
        NPC_WRITE_FLOW(NPC_OUTER_VID, vlan_tci, ntohs(pkt->vlan_tci), 0,
                       ntohs(mask->vlan_tci), 0);
 
index 5a44e9b..4bb511e 100644 (file)
@@ -461,6 +461,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
              BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
              BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
              BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
+             BIT(FLOW_DISSECTOR_KEY_IPSEC) |
              BIT_ULL(FLOW_DISSECTOR_KEY_IP))))  {
                netdev_info(nic->netdev, "unsupported flow used key 0x%llx",
                            dissector->used_keys);
@@ -482,6 +483,8 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
                     match.key->ip_proto != IPPROTO_UDP &&
                     match.key->ip_proto != IPPROTO_SCTP &&
                     match.key->ip_proto != IPPROTO_ICMP &&
+                    match.key->ip_proto != IPPROTO_ESP &&
+                    match.key->ip_proto != IPPROTO_AH &&
                     match.key->ip_proto != IPPROTO_ICMPV6)) {
                        netdev_info(nic->netdev,
                                    "ip_proto=0x%x not supported\n",
@@ -501,6 +504,10 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
                        req->features |= BIT_ULL(NPC_IPPROTO_ICMP);
                else if (ip_proto == IPPROTO_ICMPV6)
                        req->features |= BIT_ULL(NPC_IPPROTO_ICMP6);
+               else if (ip_proto == IPPROTO_ESP)
+                       req->features |= BIT_ULL(NPC_IPPROTO_ESP);
+               else if (ip_proto == IPPROTO_AH)
+                       req->features |= BIT_ULL(NPC_IPPROTO_AH);
        }
 
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
@@ -545,6 +552,26 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
                }
        }
 
+       if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPSEC)) {
+               struct flow_match_ipsec match;
+
+               flow_rule_match_ipsec(rule, &match);
+               if (!match.mask->spi) {
+                       NL_SET_ERR_MSG_MOD(extack, "spi index not specified");
+                       return -EOPNOTSUPP;
+               }
+               if (ip_proto != IPPROTO_ESP &&
+                   ip_proto != IPPROTO_AH) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "SPI index is valid only for ESP/AH proto");
+                       return -EOPNOTSUPP;
+               }
+
+               flow_spec->spi = match.key->spi;
+               flow_mask->spi = match.mask->spi;
+               req->features |= BIT_ULL(NPC_IPSEC_SPI);
+       }
+
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
                struct flow_match_ip match;