]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
octeontx2-af: npc: cn20k: Reject missing default-rule MCAM indices
authorRatheesh Kannoth <rkannoth@marvell.com>
Wed, 29 Apr 2026 02:27:22 +0000 (07:57 +0530)
committerJakub Kicinski <kuba@kernel.org>
Fri, 1 May 2026 01:50:17 +0000 (18:50 -0700)
When cn20k default L2 rules are not installed,
npc_cn20k_dft_rules_idx_get() leaves broadcast, multicast, promiscuous, and
unicast slots at USHRT_MAX. npc_get_nixlf_mcam_index() previously returned
that sentinel as a valid MCAM index, so callers could program hardware with
an invalid index.

Return -EINVAL from the cn20k branches of npc_get_nixlf_mcam_index() when
the requested slot is still USHRT_MAX. Harden cn20k NPC MCAM entry helpers
to reject out-of-range indices before touching hardware.

Drop the early bounds check in npc_enable_mcam_entry() for cn20k so invalid
indices are validated inside npc_cn20k_enable_mcam_entry() instead of being
silently ignored.

In rvu_npc_update_flowkey_alg_idx(), treat negative MCAM indices like
out-of-range values, and only update RSS actions for promiscuous and
all-multi paths when the resolved index is non-negative.

Cc: Suman Ghosh <sumang@marvell.com>
Fixes: 6d1e70282f76 ("octeontx2-af: npc: cn20k: Use common APIs")
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260429022722.1110289-11-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c

index 1129565a01bdf46108a9c5697c4f66d8dcaaaf84..6b3f453fd5004e66345bfc2e0e594c80c56cec18 100644 (file)
@@ -808,6 +808,9 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
        u64 cfg, hw_prio;
        u8 kw_type;
 
+       if (index < 0 || index >= mcam->total_entries)
+               return -EINVAL;
+
        if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
                return -EINVAL;
 
@@ -1056,6 +1059,9 @@ int npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
        int kw = 0;
        u8 kw_type;
 
+       if (index < 0 || index >= mcam->total_entries)
+               return -EINVAL;
+
        if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
                return -EINVAL;
 
@@ -1148,6 +1154,9 @@ int npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
        int bank, i, sb, db;
        int dbank, sbank;
 
+       if (src >= mcam->total_entries || dest >= mcam->total_entries)
+               return -EINVAL;
+
        dbank = npc_get_bank(mcam, dest);
        sbank = npc_get_bank(mcam, src);
 
@@ -1213,6 +1222,9 @@ int npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
        int kw = 0, bank;
        u8 kw_type;
 
+       if (index >= mcam->total_entries)
+               return -EINVAL;
+
        if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
                return -EINVAL;
 
@@ -4170,7 +4182,7 @@ int rvu_mbox_handler_npc_get_dft_rl_idxs(struct rvu *rvu, struct msg_req *req,
        return 0;
 }
 
-static bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc)
+bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc)
 {
        return is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc)) ||
                is_lbk_vf(rvu, pcifunc);
index 2f761b97f91b11de8e01a768bbea4db0e9be36ae..3d5eb952cc07364a9e4ac4825a97922a361c54cc 100644 (file)
@@ -335,5 +335,6 @@ int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type);
 u16 npc_cn20k_vidx2idx(u16 index);
 u16 npc_cn20k_idx2vidx(u16 idx);
 int npc_cn20k_defrag(struct rvu *rvu);
+bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc);
 
 #endif /* NPC_CN20K_H */
index ef5b081162ebfb17be03d017258db9564b7f6444..f977734ae712c603e77547613b4735e12941bc1c 100644 (file)
@@ -3577,6 +3577,9 @@ static int nix_update_mce_rule(struct rvu *rvu, u16 pcifunc,
        mcam_index = npc_get_nixlf_mcam_index(mcam,
                                              pcifunc & ~RVU_PFVF_FUNC_MASK,
                                              nixlf, type);
+       if (mcam_index < 0)
+               return -EINVAL;
+
        err = nix_update_mce_list(rvu, pcifunc, mce_list,
                                  mce_idx, mcam_index, add);
        return err;
index 5d349d131fdb63a4ed44d84d455be7eb4e8d320b..3c814d157ab9883acde05c8fa53ac1f3207393a5 100644 (file)
@@ -163,14 +163,35 @@ int npc_get_nixlf_mcam_index(struct npc_mcam *mcam,
                if (rc)
                        return -EFAULT;
 
+               if (is_lbk_vf(rvu, pcifunc)) {
+                       if (promisc == USHRT_MAX)
+                               return -EINVAL;
+                       return promisc;
+               }
+
+               if (is_cgx_vf(rvu, pcifunc)) {
+                       if (ucast == USHRT_MAX)
+                               return -EINVAL;
+
+                       return ucast;
+               }
+
                switch (type) {
                case NIXLF_BCAST_ENTRY:
+                       if (bcast == USHRT_MAX)
+                               return -EINVAL;
                        return bcast;
                case NIXLF_ALLMULTI_ENTRY:
+                       if (mcast == USHRT_MAX)
+                               return -EINVAL;
                        return mcast;
                case NIXLF_PROMISC_ENTRY:
+                       if (promisc == USHRT_MAX)
+                               return -EINVAL;
                        return promisc;
                case NIXLF_UCAST_ENTRY:
+                       if (ucast == USHRT_MAX)
+                               return -EINVAL;
                        return ucast;
                default:
                        return -EINVAL;
@@ -238,9 +259,6 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
        int actbank = bank;
 
        if (is_cn20k(rvu->pdev)) {
-               if (index < 0 || index >= mcam->banksize * mcam->banks)
-                       return;
-
                if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable))
                        dev_err(rvu->dev, "Error to %s mcam %u entry\n",
                                enable ? "enable" : "disable", index);
@@ -434,6 +452,15 @@ static u64 npc_get_default_entry_action(struct rvu *rvu, struct npc_mcam *mcam,
 
        index = npc_get_nixlf_mcam_index(mcam, pf_func, nixlf,
                                         NIXLF_UCAST_ENTRY);
+
+       if (index < 0) {
+               dev_err(rvu->dev,
+                       "%s: failed to get ucast entry pcifunc:0x%x\n",
+                       __func__, pf_func);
+               /* Action 0 is drop */
+               return 0;
+       }
+
        bank = npc_get_bank(mcam, index);
        index &= (mcam->banksize - 1);
 
@@ -700,6 +727,12 @@ void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc,
 
        index = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                         nixlf, NIXLF_UCAST_ENTRY);
+       if (index < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get ucast entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
 
        /* Don't change the action if entry is already enabled
         * Otherwise RSS action may get overwritten.
@@ -755,11 +788,21 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
        index = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                         nixlf, NIXLF_PROMISC_ENTRY);
 
+       /* In cn20k, default indexes are installed only for CGX mapped
+        * and lbk interfaces
+        */
        if (is_cgx_vf(rvu, pcifunc))
                index = npc_get_nixlf_mcam_index(mcam,
                                                 pcifunc & ~RVU_PFVF_FUNC_MASK,
                                                 nixlf, NIXLF_PROMISC_ENTRY);
 
+       if (index < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get promisc entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
+
        /* If the corresponding PF's ucast action is RSS,
         * use the same action for promisc also
         * Please note that for lbk(s) "index" and "ucast_idx"
@@ -770,6 +813,12 @@ void rvu_npc_install_promisc_entry(struct rvu *rvu, u16 pcifunc,
        else
                ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                                     nixlf, NIXLF_UCAST_ENTRY);
+       if (ucast_idx < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get ucast/promisc entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
 
        if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
                *(u64 *)&action = npc_get_mcam_action(rvu, mcam,
@@ -844,6 +893,14 @@ void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc,
 
        index = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                         nixlf, NIXLF_PROMISC_ENTRY);
+
+       if (index < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get promisc entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
+
        npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
 }
 
@@ -884,6 +941,12 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
 
        index = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                         nixlf, NIXLF_BCAST_ENTRY);
+       if (index < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get bcast entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
 
        if (!hw->cap.nix_rx_multicast) {
                /* Early silicon doesn't support pkt replication,
@@ -948,12 +1011,25 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
 
        index = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                         nixlf, NIXLF_ALLMULTI_ENTRY);
+       if (index < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get mcast entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
 
        /* If the corresponding PF's ucast action is RSS,
         * use the same action for multicast entry also
         */
        ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                             nixlf, NIXLF_UCAST_ENTRY);
+       if (ucast_idx < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get ucast entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
+
        if (is_mcam_entry_enabled(rvu, mcam, blkaddr, ucast_idx))
                *(u64 *)&action = npc_get_mcam_action(rvu, mcam,
                                                        blkaddr, ucast_idx);
@@ -1018,6 +1094,13 @@ void rvu_npc_enable_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
 
        index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
                                         NIXLF_ALLMULTI_ENTRY);
+       if (index < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get mcast entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
+
        npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
 }
 
@@ -1130,8 +1213,12 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
                index = mcam_index;
        }
 
-       if (index >= mcam->total_entries)
+       if (index < 0 || index >= mcam->total_entries) {
+               dev_err(rvu->dev,
+                       "%s: Invalid mcam index, pcifunc=%#x\n",
+                       __func__, pcifunc);
                return;
+       }
 
        bank = npc_get_bank(mcam, index);
        index &= (mcam->banksize - 1);
@@ -1175,16 +1262,18 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
                /* If PF's promiscuous  entry is enabled,
                 * Set RSS action for that entry as well
                 */
-               npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index,
-                                                 blkaddr, alg_idx);
+               if (index >= 0)
+                       npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index,
+                                                         blkaddr, alg_idx);
 
                index = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                                 nixlf, NIXLF_ALLMULTI_ENTRY);
                /* If PF's allmulti  entry is enabled,
                 * Set RSS action for that entry as well
                 */
-               npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index,
-                                                 blkaddr, alg_idx);
+               if (index >= 0)
+                       npc_update_rx_action_with_alg_idx(rvu, action, pfvf, index,
+                                                         blkaddr, alg_idx);
        }
 }
 
@@ -1197,12 +1286,22 @@ void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
        int index, blkaddr, mce_idx;
        struct rvu_pfvf *pfvf;
 
+       /* multicast pkt replication is not enabled for AF's VFs & SDP links */
+       if (is_lbk_vf(rvu, pcifunc) || is_sdp_pfvf(rvu, pcifunc))
+               return;
+
        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
        if (blkaddr < 0)
                return;
 
        index = npc_get_nixlf_mcam_index(mcam, pcifunc & ~RVU_PFVF_FUNC_MASK,
                                         nixlf, type);
+       if (index < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get entry for pcifunc=%#x, type=%u\n",
+                       __func__, pcifunc, type);
+               return;
+       }
 
        /* disable MCAM entry when packet replication is not supported by hw */
        if (!hw->cap.nix_rx_multicast && !is_vf(pcifunc)) {
@@ -1231,6 +1330,10 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
        struct npc_mcam *mcam = &rvu->hw->mcam;
        int index, blkaddr;
 
+       /* only CGX or LBK interfaces have default entries */
+       if (is_cn20k(rvu->pdev) && !npc_is_cgx_or_lbk(rvu, pcifunc))
+               return;
+
        blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
        if (blkaddr < 0)
                return;
@@ -1240,6 +1343,12 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
                                     pfvf->nix_rx_intf)) {
                index = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                                 nixlf, NIXLF_UCAST_ENTRY);
+               if (index < 0) {
+                       dev_err(rvu->dev,
+                               "%s: Error to get ucast entry for pcifunc=%#x\n",
+                               __func__, pcifunc);
+                       return;
+               }
                npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
        }
 
@@ -3897,6 +4006,12 @@ int rvu_mbox_handler_npc_read_base_steer_rule(struct rvu *rvu,
        /* Read the default ucast entry if there is no pkt steering rule */
        index = npc_get_nixlf_mcam_index(mcam, pcifunc, nixlf,
                                         NIXLF_UCAST_ENTRY);
+       if (index < 0) {
+               mutex_unlock(&mcam->lock);
+               rc = NIX_AF_ERR_AF_LF_INVALID;
+               goto out;
+       }
+
 read_entry:
        /* Read the mcam entry */
        npc_read_mcam_entry(rvu, mcam, blkaddr, index, &rsp->entry, &intf,
@@ -3970,6 +4085,12 @@ void rvu_npc_clear_ucast_entry(struct rvu *rvu, int pcifunc, int nixlf)
 
        ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
                                             nixlf, NIXLF_UCAST_ENTRY);
+       if (ucast_idx < 0) {
+               dev_err(rvu->dev,
+                       "%s: Error to get ucast entry for pcifunc=%#x\n",
+                       __func__, pcifunc);
+               return;
+       }
 
        npc_enable_mcam_entry(rvu, mcam, blkaddr, ucast_idx, false);
 
index fe10554b1f0e2419774fca67e9724df7b6549c43..6ae9cdcb608b0c8db0da9b4846168560720db049 100644 (file)
@@ -1444,7 +1444,7 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
        struct msg_rsp write_rsp;
        struct mcam_entry *entry;
        bool new = false;
-       u16 entry_index;
+       int entry_index;
        int err;
 
        installed_features = req->features;
@@ -1477,6 +1477,14 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
        if (req->default_rule) {
                entry_index = npc_get_nixlf_mcam_index(mcam, target, nixlf,
                                                       NIXLF_UCAST_ENTRY);
+
+               if (entry_index < 0) {
+                       dev_err(rvu->dev,
+                               "%s: Error to get ucast entry for target=%#x\n",
+                               __func__, target);
+                       return -EINVAL;
+               }
+
                enable = is_mcam_entry_enabled(rvu, mcam, blkaddr, entry_index);
        }