Messages in this thread Patch in this message | | | From | "Radu Pirea (NXP OSS)" <> | Subject | [RFC net-next v2 4/5] net: phy: nxp-c45-tja11xx: add MACsec statistics | Date | Thu, 24 Aug 2023 12:16:14 +0300 |
| |
Add MACsec statistics callbacks. The statistic registers must be set to 0 if the SC/SA is deleted to read relevant values next time when the SC/SA is used.
Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com> --- drivers/net/phy/nxp-c45-tja11xx-macsec.c | 416 ++++++++++++++++++++++- 1 file changed, 415 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/nxp-c45-tja11xx-macsec.c b/drivers/net/phy/nxp-c45-tja11xx-macsec.c index 1567865b8de4..edfdd2540d39 100644 --- a/drivers/net/phy/nxp-c45-tja11xx-macsec.c +++ b/drivers/net/phy/nxp-c45-tja11xx-macsec.c @@ -140,6 +140,33 @@ #define ADAPTER_EN BIT(6) #define MACSEC_EN BIT(5) +#define MACSEC_INOV1HS 0x0140 +#define MACSEC_INOV2HS 0x0144 +#define MACSEC_INOD1HS 0x0148 +#define MACSEC_INOD2HS 0x014C +#define MACSEC_RXSCIPUS 0x0150 +#define MACSEC_RXSCIPDS 0x0154 +#define MACSEC_RXSCIPLS 0x0158 +#define MACSEC_RXAN0INUSS 0x0160 +#define MACSEC_RXAN0IPUSS 0x0170 +#define MACSEC_RXSAAIPOS 0x0194 +#define MACSEC_RXSAAIPIS 0x01B0 +#define MACSEC_RXSAAIPNVS 0x01B4 +#define MACSEC_RXSABIPOS 0x01D4 +#define MACSEC_RXSABIPIS 0x01F0 +#define MACSEC_RXSABIPNVS 0x01F4 +#define MACSEC_OPUS 0x021C +#define MACSEC_OPTLS 0x022C +#define MACSEC_OOE1HS 0x0248 +#define MACSEC_OOE2HS 0x024C +#define MACSEC_TXSAAOPPS 0x028C +#define MACSEC_TXSAAOPES 0x0290 +#define MACSEC_TXSABOPPS 0x02CC +#define MACSEC_TXSABOPES 0x02D0 +#define MACSEC_INPWTS 0x0630 +#define MACSEC_INPBTS 0x0638 +#define MACSEC_IPSNFS 0x063C + struct nxp_c45_rx_sc { struct macsec_rx_sc *rx_sc; struct macsec_rx_sa *rx_sa_a; @@ -148,6 +175,7 @@ struct nxp_c45_rx_sc { struct nxp_c45_tx_sa { struct macsec_tx_sa *tx_sa; + struct macsec_tx_sa_stats stats; u8 key[MACSEC_MAX_KEY_LEN]; u8 salt[MACSEC_SALT_LEN]; u8 an; @@ -787,6 +815,113 @@ static int nxp_c45_disable_rxsa_key(struct phy_device *phydev, bool key_a) return 0; } +static void nxp_c45_clear_dev_stats(struct phy_device *phydev, + struct nxp_c45_secy *phy_secy) +{ + nxp_c45_macsec_write(phydev, MACSEC_OPUS, 0); + nxp_c45_macsec_write(phydev, MACSEC_OPTLS, 0); + nxp_c45_macsec_write(phydev, MACSEC_OOE1HS, 0); + nxp_c45_macsec_write(phydev, MACSEC_OOE2HS, 0); + nxp_c45_macsec_write(phydev, MACSEC_TXSAAOPES, 0); + nxp_c45_macsec_write(phydev, MACSEC_TXSABOPES, 0); + nxp_c45_macsec_write(phydev, MACSEC_TXSAAOPPS, 0); + nxp_c45_macsec_write(phydev, MACSEC_TXSABOPPS, 0); + + if (phy_secy->rx_sc) { + nxp_c45_macsec_write(phydev, MACSEC_INPBTS, 0); + nxp_c45_macsec_write(phydev, MACSEC_INPWTS, 0); + nxp_c45_macsec_write(phydev, MACSEC_IPSNFS, 0); + } +} + +static void nxp_c45_clear_rx_sc_stats(struct phy_device *phydev) +{ + int i; + + nxp_c45_macsec_write(phydev, MACSEC_RXSAAIPIS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSAAIPNVS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSAAIPOS, 0); + + nxp_c45_macsec_write(phydev, MACSEC_RXSABIPIS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSABIPNVS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSABIPOS, 0); + + nxp_c45_macsec_write(phydev, MACSEC_INOD1HS, 0); + nxp_c45_macsec_write(phydev, MACSEC_INOD2HS, 0); + + nxp_c45_macsec_write(phydev, MACSEC_INOV1HS, 0); + nxp_c45_macsec_write(phydev, MACSEC_INOV2HS, 0); + + nxp_c45_macsec_write(phydev, MACSEC_RXSCIPDS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSCIPLS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSCIPUS, 0); + + for (i = 0; i < MACSEC_NUM_AN; i++) + nxp_c45_macsec_write(phydev, MACSEC_RXAN0INUSS + i * 4, 0); + + for (i = 0; i < MACSEC_NUM_AN; i++) + nxp_c45_macsec_write(phydev, MACSEC_RXAN0IPUSS + i * 4, 0); +} + +static void nxp_c45_tx_sa_stats_read(struct phy_device *phydev, + struct nxp_c45_tx_sa *tx_sa, + struct macsec_tx_sa_stats *stats) +{ + u32 reg = 0; + + if (tx_sa->is_key_a) { + nxp_c45_macsec_read(phydev, MACSEC_TXSAAOPES, ®); + stats->OutPktsEncrypted = reg; + nxp_c45_macsec_read(phydev, MACSEC_TXSAAOPPS, ®); + stats->OutPktsProtected = reg; + } else { + nxp_c45_macsec_read(phydev, MACSEC_TXSABOPES, ®); + stats->OutPktsEncrypted = reg; + nxp_c45_macsec_read(phydev, MACSEC_TXSABOPPS, ®); + stats->OutPktsProtected = reg; + } +} + +static void nxp_c45_tx_sa_stats_clear(struct phy_device *phydev, + struct nxp_c45_tx_sa *tx_sa) +{ + if (tx_sa->is_key_a) { + nxp_c45_macsec_write(phydev, MACSEC_TXSAAOPES, 0); + nxp_c45_macsec_write(phydev, MACSEC_TXSAAOPPS, 0); + } else { + nxp_c45_macsec_write(phydev, MACSEC_TXSABOPES, 0); + nxp_c45_macsec_write(phydev, MACSEC_TXSABOPPS, 0); + } +} + +static void nxp_c45_tx_sa_stats_backup(struct phy_device *phydev, + struct nxp_c45_tx_sa *tx_sa) +{ + struct macsec_tx_sa_stats stats; + + nxp_c45_tx_sa_stats_read(phydev, tx_sa, &stats); + tx_sa->stats.OutPktsEncrypted += stats.OutPktsEncrypted; + tx_sa->stats.OutPktsProtected += stats.OutPktsProtected; + nxp_c45_tx_sa_stats_clear(phydev, tx_sa); +} + +static void nxp_c45_clear_rx_sa_stats(struct phy_device *phydev, + u8 an, bool is_key_a) +{ + if (is_key_a) { + nxp_c45_macsec_write(phydev, MACSEC_RXSAAIPIS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSAAIPNVS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSAAIPOS, 0); + } else { + nxp_c45_macsec_write(phydev, MACSEC_RXSABIPIS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSABIPNVS, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXSABIPOS, 0); + } + + nxp_c45_macsec_write(phydev, MACSEC_RXAN0INUSS + an * 4, 0); + nxp_c45_macsec_write(phydev, MACSEC_RXAN0IPUSS + an * 4, 0); +} + static int nxp_c45_rx_sc_del(struct phy_device *phydev, struct nxp_c45_rx_sc *rx_sc) { @@ -801,6 +936,8 @@ static int nxp_c45_rx_sc_del(struct phy_device *phydev, if (rx_sc->rx_sa_b) nxp_c45_disable_rxsa_key(phydev, false); + nxp_c45_clear_rx_sc_stats(phydev); + return 0; } @@ -961,6 +1098,7 @@ static int nxp_c45_mdo_upd_secy(struct macsec_context *ctx) if (old_tx_sa) { old_tx_sa->is_enabled = false; nxp_c45_txsa_get_pn(phydev, old_tx_sa); + nxp_c45_tx_sa_stats_backup(phydev, old_tx_sa); } } @@ -979,6 +1117,7 @@ static int nxp_c45_mdo_del_secy(struct macsec_context *ctx) struct nxp_c45_phy *priv = phydev->priv; struct nxp_c45_secy *phy_secy; u32 reg; + int i; phydev_dbg(phydev, "delete secy SCI %llu\n", ctx->secy->sci); @@ -990,11 +1129,16 @@ static int nxp_c45_mdo_del_secy(struct macsec_context *ctx) nxp_c45_mdo_dev_stop(ctx); nxp_c45_tx_sa_disable(phydev, phy_secy); nxp_c45_tx_sc_clear(phy_secy); + nxp_c45_clear_dev_stats(phydev, phy_secy); if (phy_secy->rx_sc) { nxp_c45_rx_sc_del(phydev, phy_secy->rx_sc); kfree(phy_secy->rx_sc); } + for (i = 0; i < ARRAY_SIZE(phy_secy->tx_sa); i++) + if (phy_secy->tx_sa[i] && phy_secy->tx_sa[i]->is_enabled) + nxp_c45_tx_sa_stats_clear(phydev, phy_secy->tx_sa[i]); + if (phy_interrupt_is_valid(phydev)) { nxp_c45_macsec_read(phydev, MACSEC_EVER, ®); reg &= ~TX_SC_BIT(phy_secy->secy_id); @@ -1188,6 +1332,7 @@ static int nxp_c45_mdo_del_rxsa(struct macsec_context *ctx) phydev_dbg(phydev, "delete RX SA A %u %s\n", an, rx_sa->active ? "enabled" : "disabled"); nxp_c45_disable_rxsa_key(phydev, true); + nxp_c45_clear_rx_sa_stats(phydev, an, true); rx_sc->rx_sa_a = NULL; return 0; } @@ -1196,6 +1341,7 @@ static int nxp_c45_mdo_del_rxsa(struct macsec_context *ctx) phydev_dbg(phydev, "delete RX SA B %u %s\n", an, rx_sa->active ? "enabled" : "disabled"); nxp_c45_disable_rxsa_key(phydev, false); + nxp_c45_clear_rx_sa_stats(phydev, an, false); rx_sc->rx_sa_b = NULL; return 0; } @@ -1323,8 +1469,10 @@ static int nxp_c45_mdo_del_txsa(struct macsec_context *ctx) nxp_c45_select_secy(phydev, phy_secy->secy_id); - if (tx_sa->is_enabled) + if (tx_sa->is_enabled) { nxp_c45_update_key_status(phydev, tx_sa); + nxp_c45_tx_sa_stats_clear(phydev, tx_sa); + } phy_secy->tx_sa[sa] = NULL; kfree(tx_sa); @@ -1332,6 +1480,267 @@ static int nxp_c45_mdo_del_txsa(struct macsec_context *ctx) return 0; } +static int nxp_c45_mdo_get_dev_stats(struct macsec_context *ctx) +{ + struct phy_device *phydev = ctx->phydev; + struct nxp_c45_phy *priv = phydev->priv; + struct macsec_dev_stats *dev_stats; + struct nxp_c45_secy *phy_secy; + u32 reg = 0; + + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); + if (IS_ERR(phy_secy)) + return PTR_ERR(phy_secy); + + dev_stats = ctx->stats.dev_stats; + nxp_c45_select_secy(phydev, phy_secy->secy_id); + + nxp_c45_macsec_read(phydev, MACSEC_OPUS, ®); + dev_stats->OutPktsUntagged = reg; + nxp_c45_macsec_read(phydev, MACSEC_OPTLS, ®); + dev_stats->OutPktsTooLong = reg; + + dev_stats->InPktsUntagged = 0; + dev_stats->InPktsNoTag = 0; + dev_stats->InPktsBadTag = 0; + dev_stats->InPktsUnknownSCI = 0; + dev_stats->InPktsNoSCI = 0; + + if (phy_secy->rx_sc) { + nxp_c45_macsec_read(phydev, MACSEC_INPBTS, ®); + dev_stats->InPktsBadTag = reg; + + nxp_c45_macsec_read(phydev, MACSEC_INPWTS, ®); + if (phy_secy->secy->validate_frames == MACSEC_VALIDATE_STRICT) + dev_stats->InPktsNoTag += reg; + else + dev_stats->InPktsUntagged += reg; + + nxp_c45_macsec_read(phydev, MACSEC_IPSNFS, ®); + if (phy_secy->secy->validate_frames == MACSEC_VALIDATE_STRICT) + dev_stats->InPktsNoSCI += reg; + else + dev_stats->InPktsUnknownSCI += reg; + } + + /* Always 0. */ + dev_stats->InPktsOverrun = 0; + + return 0; +} + +static int nxp_c45_mdo_get_tx_sc_stats(struct macsec_context *ctx) +{ + struct phy_device *phydev = ctx->phydev; + struct nxp_c45_phy *priv = phydev->priv; + struct macsec_tx_sc_stats *tx_sc_stats; + struct macsec_tx_sa_stats tx_sa_stats; + struct nxp_c45_secy *phy_secy; + struct nxp_c45_tx_sa *tx_sa; + u32 reg = 0; + u64 stat; + int i; + + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); + if (IS_ERR(phy_secy)) + return PTR_ERR(phy_secy); + + tx_sc_stats = ctx->stats.tx_sc_stats; + nxp_c45_select_secy(phydev, phy_secy->secy_id); + + nxp_c45_macsec_read(phydev, MACSEC_OOE1HS, ®); + stat = (u64)reg << 32; + nxp_c45_macsec_read(phydev, MACSEC_OOE2HS, ®); + stat |= reg; + if (ctx->secy->tx_sc.encrypt) + tx_sc_stats->OutOctetsEncrypted = stat; + else + tx_sc_stats->OutOctetsEncrypted = 0; + + if (ctx->secy->protect_frames) + tx_sc_stats->OutOctetsProtected = stat; + else + tx_sc_stats->OutOctetsProtected = 0; + + tx_sc_stats->OutPktsEncrypted = 0; + tx_sc_stats->OutPktsProtected = 0; + + for (i = 0; i < ARRAY_SIZE(phy_secy->tx_sa); i++) { + tx_sa = phy_secy->tx_sa[i]; + if (!tx_sa) + continue; + + if (tx_sa->is_enabled) { + nxp_c45_tx_sa_stats_read(phydev, tx_sa, &tx_sa_stats); + tx_sc_stats->OutPktsEncrypted += + tx_sa_stats.OutPktsEncrypted; + tx_sc_stats->OutPktsProtected += + tx_sa_stats.OutPktsProtected; + continue; + } + + tx_sc_stats->OutPktsEncrypted += tx_sa->stats.OutPktsEncrypted; + tx_sc_stats->OutPktsProtected += tx_sa->stats.OutPktsProtected; + } + + return 0; +} + +static int nxp_c45_mdo_get_tx_sa_stats(struct macsec_context *ctx) +{ + struct phy_device *phydev = ctx->phydev; + struct nxp_c45_phy *priv = phydev->priv; + struct macsec_tx_sa_stats *tx_sa_stats; + struct nxp_c45_secy *phy_secy; + struct nxp_c45_tx_sa *tx_sa; + + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); + if (IS_ERR(phy_secy)) + return PTR_ERR(phy_secy); + + tx_sa = phy_secy->tx_sa[ctx->sa.assoc_num]; + if (!tx_sa) + return -EINVAL; + + tx_sa_stats = ctx->stats.tx_sa_stats; + + if (!tx_sa->is_enabled) { + tx_sa_stats->OutPktsEncrypted = tx_sa->stats.OutPktsEncrypted; + tx_sa_stats->OutPktsProtected = tx_sa->stats.OutPktsProtected; + return 0; + } + + nxp_c45_select_secy(phydev, phy_secy->secy_id); + nxp_c45_tx_sa_stats_read(phydev, tx_sa, tx_sa_stats); + + return 0; +} + +static int nxp_c45_mdo_get_rx_sc_stats(struct macsec_context *ctx) +{ + struct phy_device *phydev = ctx->phydev; + struct nxp_c45_phy *priv = phydev->priv; + struct macsec_rx_sc_stats *rx_sc_stats; + struct nxp_c45_secy *phy_secy; + struct nxp_c45_rx_sc *rx_sc; + u32 reg = 0; + int i; + + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); + if (IS_ERR(phy_secy)) + return PTR_ERR(phy_secy); + + rx_sc = phy_secy->rx_sc; + if (rx_sc->rx_sc != ctx->rx_sc) + return -EINVAL; + + rx_sc_stats = ctx->stats.rx_sc_stats; + nxp_c45_select_secy(phydev, phy_secy->secy_id); + + rx_sc_stats->InPktsInvalid = 0; + rx_sc_stats->InPktsNotValid = 0; + rx_sc_stats->InPktsOK = 0; + + if (rx_sc->rx_sa_a) { + nxp_c45_macsec_read(phydev, MACSEC_RXSAAIPIS, ®); + rx_sc_stats->InPktsInvalid += reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSAAIPNVS, ®); + rx_sc_stats->InPktsNotValid += reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSAAIPOS, ®); + rx_sc_stats->InPktsOK += reg; + } + + if (rx_sc->rx_sa_b) { + nxp_c45_macsec_read(phydev, MACSEC_RXSABIPIS, ®); + rx_sc_stats->InPktsInvalid += reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSABIPNVS, ®); + rx_sc_stats->InPktsNotValid += reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSABIPOS, ®); + rx_sc_stats->InPktsOK += reg; + } + + ctx->stats.rx_sa_stats->InPktsNotUsingSA = 0; + for (i = 0; i < MACSEC_NUM_AN; i++) { + nxp_c45_macsec_read(phydev, MACSEC_RXAN0INUSS + i * 4, ®); + rx_sc_stats->InPktsNotUsingSA += reg; + } + + ctx->stats.rx_sa_stats->InPktsUnusedSA = 0; + for (i = 0; i < MACSEC_NUM_AN; i++) { + nxp_c45_macsec_read(phydev, MACSEC_RXAN0IPUSS + i * 4, ®); + rx_sc_stats->InPktsUnusedSA += reg; + } + + nxp_c45_macsec_read(phydev, MACSEC_INOD1HS, ®); + rx_sc_stats->InOctetsDecrypted = (u64)reg << 32; + nxp_c45_macsec_read(phydev, MACSEC_INOD2HS, ®); + rx_sc_stats->InOctetsDecrypted |= reg; + + nxp_c45_macsec_read(phydev, MACSEC_INOV1HS, ®); + rx_sc_stats->InOctetsValidated = (u64)reg << 32; + nxp_c45_macsec_read(phydev, MACSEC_INOV2HS, ®); + rx_sc_stats->InOctetsValidated |= reg; + + nxp_c45_macsec_read(phydev, MACSEC_RXSCIPDS, ®); + rx_sc_stats->InPktsDelayed = reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSCIPLS, ®); + rx_sc_stats->InPktsLate = reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSCIPUS, ®); + rx_sc_stats->InPktsUnchecked = reg; + + return 0; +} + +static int nxp_c45_mdo_get_rx_sa_stats(struct macsec_context *ctx) +{ + struct phy_device *phydev = ctx->phydev; + struct nxp_c45_phy *priv = phydev->priv; + struct macsec_rx_sa_stats *rx_sa_stats; + struct nxp_c45_secy *phy_secy; + struct nxp_c45_rx_sc *rx_sc; + u8 an = ctx->sa.assoc_num; + u32 reg = 0; + + phy_secy = nxp_c45_find_secy(&priv->macsec->secy_list, ctx->secy->sci); + if (IS_ERR(phy_secy)) + return PTR_ERR(phy_secy); + + rx_sc = phy_secy->rx_sc; + if (rx_sc->rx_sc != ctx->sa.rx_sa->sc) + return -EINVAL; + + if (!rx_sc->rx_sa_a && !rx_sc->rx_sa_b) + return -EINVAL; + + rx_sa_stats = ctx->stats.rx_sa_stats; + nxp_c45_select_secy(phydev, phy_secy->secy_id); + + if (rx_sc->rx_sa_a == ctx->sa.rx_sa) { + nxp_c45_macsec_read(phydev, MACSEC_RXSAAIPIS, ®); + rx_sa_stats->InPktsInvalid = reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSAAIPNVS, ®); + rx_sa_stats->InPktsNotValid = reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSAAIPOS, ®); + rx_sa_stats->InPktsOK = reg; + } + + if (rx_sc->rx_sa_b == ctx->sa.rx_sa) { + nxp_c45_macsec_read(phydev, MACSEC_RXSABIPIS, ®); + rx_sa_stats->InPktsInvalid = reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSABIPNVS, ®); + rx_sa_stats->InPktsNotValid = reg; + nxp_c45_macsec_read(phydev, MACSEC_RXSABIPOS, ®); + rx_sa_stats->InPktsOK = reg; + } + + nxp_c45_macsec_read(phydev, MACSEC_RXAN0INUSS + an * 4, ®); + rx_sa_stats->InPktsNotUsingSA = reg; + nxp_c45_macsec_read(phydev, MACSEC_RXAN0IPUSS + an * 4, ®); + rx_sa_stats->InPktsUnusedSA = reg; + + return 0; +} + static const struct macsec_ops nxp_c45_macsec_ops = { .mdo_dev_open = nxp_c45_mdo_dev_open, .mdo_dev_stop = nxp_c45_mdo_dev_stop, @@ -1347,6 +1756,11 @@ static const struct macsec_ops nxp_c45_macsec_ops = { .mdo_add_txsa = nxp_c45_mdo_add_txsa, .mdo_upd_txsa = nxp_c45_mdo_upd_txsa, .mdo_del_txsa = nxp_c45_mdo_del_txsa, + .mdo_get_dev_stats = nxp_c45_mdo_get_dev_stats, + .mdo_get_tx_sc_stats = nxp_c45_mdo_get_tx_sc_stats, + .mdo_get_tx_sa_stats = nxp_c45_mdo_get_tx_sa_stats, + .mdo_get_rx_sc_stats = nxp_c45_mdo_get_rx_sc_stats, + .mdo_get_rx_sa_stats = nxp_c45_mdo_get_rx_sa_stats, }; int nxp_c45_macsec_probe(struct phy_device *phydev) -- 2.34.1
| |