Commit aec0f1aa authored by Dmitry Bogdanov's avatar Dmitry Bogdanov Committed by David S. Miller

net: atlantic: MACSec offload statistics implementation

This patch adds support for MACSec statistics on Atlantic network cards.
Signed-off-by: default avatarDmitry Bogdanov <dbogdanov@marvell.com>
Signed-off-by: default avatarMark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent aaa36515
......@@ -11,6 +11,7 @@
#include "aq_vec.h"
#include "aq_ptp.h"
#include "aq_filters.h"
#include "aq_macsec.h"
#include <linux/ptp_clock_kernel.h>
......@@ -96,6 +97,62 @@ static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
"Queue[%d] InErrors",
};
#if IS_ENABLED(CONFIG_MACSEC)
static const char aq_macsec_stat_names[][ETH_GSTRING_LEN] = {
"MACSec InCtlPackets",
"MACSec InTaggedMissPackets",
"MACSec InUntaggedMissPackets",
"MACSec InNotagPackets",
"MACSec InUntaggedPackets",
"MACSec InBadTagPackets",
"MACSec InNoSciPackets",
"MACSec InUnknownSciPackets",
"MACSec InCtrlPortPassPackets",
"MACSec InUnctrlPortPassPackets",
"MACSec InCtrlPortFailPackets",
"MACSec InUnctrlPortFailPackets",
"MACSec InTooLongPackets",
"MACSec InIgpocCtlPackets",
"MACSec InEccErrorPackets",
"MACSec InUnctrlHitDropRedir",
"MACSec OutCtlPackets",
"MACSec OutUnknownSaPackets",
"MACSec OutUntaggedPackets",
"MACSec OutTooLong",
"MACSec OutEccErrorPackets",
"MACSec OutUnctrlHitDropRedir",
};
static const char *aq_macsec_txsc_stat_names[] = {
"MACSecTXSC%d ProtectedPkts",
"MACSecTXSC%d EncryptedPkts",
"MACSecTXSC%d ProtectedOctets",
"MACSecTXSC%d EncryptedOctets",
};
static const char *aq_macsec_txsa_stat_names[] = {
"MACSecTXSC%dSA%d HitDropRedirect",
"MACSecTXSC%dSA%d Protected2Pkts",
"MACSecTXSC%dSA%d ProtectedPkts",
"MACSecTXSC%dSA%d EncryptedPkts",
};
static const char *aq_macsec_rxsa_stat_names[] = {
"MACSecRXSC%dSA%d UntaggedHitPkts",
"MACSecRXSC%dSA%d CtrlHitDrpRedir",
"MACSecRXSC%dSA%d NotUsingSa",
"MACSecRXSC%dSA%d UnusedSa",
"MACSecRXSC%dSA%d NotValidPkts",
"MACSecRXSC%dSA%d InvalidPkts",
"MACSecRXSC%dSA%d OkPkts",
"MACSecRXSC%dSA%d LatePkts",
"MACSecRXSC%dSA%d DelayedPkts",
"MACSecRXSC%dSA%d UncheckedPkts",
"MACSecRXSC%dSA%d ValidatedOctets",
"MACSecRXSC%dSA%d DecryptedOctets",
};
#endif
static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
"DMASystemLoopback",
"PKTSystemLoopback",
......@@ -104,18 +161,38 @@ static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
"PHYExternalLoopback",
};
static u32 aq_ethtool_n_stats(struct net_device *ndev)
{
struct aq_nic_s *nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(nic);
u32 n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
ARRAY_SIZE(aq_ethtool_queue_stat_names) * cfg->vecs;
#if IS_ENABLED(CONFIG_MACSEC)
if (nic->macsec_cfg) {
n_stats += ARRAY_SIZE(aq_macsec_stat_names) +
ARRAY_SIZE(aq_macsec_txsc_stat_names) *
aq_macsec_tx_sc_cnt(nic) +
ARRAY_SIZE(aq_macsec_txsa_stat_names) *
aq_macsec_tx_sa_cnt(nic) +
ARRAY_SIZE(aq_macsec_rxsa_stat_names) *
aq_macsec_rx_sa_cnt(nic);
}
#endif
return n_stats;
}
static void aq_ethtool_stats(struct net_device *ndev,
struct ethtool_stats *stats, u64 *data)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg;
cfg = aq_nic_get_cfg(aq_nic);
memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) +
ARRAY_SIZE(aq_ethtool_queue_stat_names) *
cfg->vecs) * sizeof(u64));
aq_nic_get_stats(aq_nic, data);
memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
data = aq_nic_get_stats(aq_nic, data);
#if IS_ENABLED(CONFIG_MACSEC)
data = aq_macsec_get_stats(aq_nic, data);
#endif
}
static void aq_ethtool_get_drvinfo(struct net_device *ndev,
......@@ -123,11 +200,9 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
{
struct pci_dev *pdev = to_pci_dev(ndev->dev.parent);
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg;
u32 firmware_version;
u32 regs_count;
cfg = aq_nic_get_cfg(aq_nic);
firmware_version = aq_nic_get_fw_version(aq_nic);
regs_count = aq_nic_get_regs_count(aq_nic);
......@@ -139,8 +214,7 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
sizeof(drvinfo->bus_info));
drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) +
cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
drvinfo->n_stats = aq_ethtool_n_stats(ndev);
drvinfo->testinfo_len = 0;
drvinfo->regdump_len = regs_count;
drvinfo->eedump_len = 0;
......@@ -153,6 +227,9 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
struct aq_nic_cfg_s *cfg;
u8 *p = data;
int i, si;
#if IS_ENABLED(CONFIG_MACSEC)
int sa;
#endif
cfg = aq_nic_get_cfg(aq_nic);
......@@ -170,6 +247,60 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
p += ETH_GSTRING_LEN;
}
}
#if IS_ENABLED(CONFIG_MACSEC)
if (!aq_nic->macsec_cfg)
break;
memcpy(p, aq_macsec_stat_names, sizeof(aq_macsec_stat_names));
p = p + sizeof(aq_macsec_stat_names);
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
struct aq_macsec_txsc *aq_txsc;
if (!(test_bit(i, &aq_nic->macsec_cfg->txsc_idx_busy)))
continue;
for (si = 0;
si < ARRAY_SIZE(aq_macsec_txsc_stat_names);
si++) {
snprintf(p, ETH_GSTRING_LEN,
aq_macsec_txsc_stat_names[si], i);
p += ETH_GSTRING_LEN;
}
aq_txsc = &aq_nic->macsec_cfg->aq_txsc[i];
for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
if (!(test_bit(sa, &aq_txsc->tx_sa_idx_busy)))
continue;
for (si = 0;
si < ARRAY_SIZE(aq_macsec_txsa_stat_names);
si++) {
snprintf(p, ETH_GSTRING_LEN,
aq_macsec_txsa_stat_names[si],
i, sa);
p += ETH_GSTRING_LEN;
}
}
}
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
struct aq_macsec_rxsc *aq_rxsc;
if (!(test_bit(i, &aq_nic->macsec_cfg->rxsc_idx_busy)))
continue;
aq_rxsc = &aq_nic->macsec_cfg->aq_rxsc[i];
for (sa = 0; sa < MACSEC_NUM_AN; sa++) {
if (!(test_bit(sa, &aq_rxsc->rx_sa_idx_busy)))
continue;
for (si = 0;
si < ARRAY_SIZE(aq_macsec_rxsa_stat_names);
si++) {
snprintf(p, ETH_GSTRING_LEN,
aq_macsec_rxsa_stat_names[si],
i, sa);
p += ETH_GSTRING_LEN;
}
}
}
#endif
break;
case ETH_SS_PRIV_FLAGS:
memcpy(p, aq_ethtool_priv_flag_names,
......@@ -209,16 +340,11 @@ static int aq_ethtool_set_phys_id(struct net_device *ndev,
static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg;
int ret = 0;
cfg = aq_nic_get_cfg(aq_nic);
switch (stringset) {
case ETH_SS_STATS:
ret = ARRAY_SIZE(aq_ethtool_stat_names) +
cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
ret = aq_ethtool_n_stats(ndev);
break;
case ETH_SS_PRIV_FLAGS:
ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
......
......@@ -127,6 +127,166 @@ static void aq_rotate_keys(u32 (*key)[8], const int key_len)
}
}
#define STATS_2x32_TO_64(stat_field) \
(((u64)stat_field[1] << 32) | stat_field[0])
static int aq_get_macsec_common_stats(struct aq_hw_s *hw,
struct aq_macsec_common_stats *stats)
{
struct aq_mss_ingress_common_counters ingress_counters;
struct aq_mss_egress_common_counters egress_counters;
int ret;
/* MACSEC counters */
ret = aq_mss_get_ingress_common_counters(hw, &ingress_counters);
if (unlikely(ret))
return ret;
stats->in.ctl_pkts = STATS_2x32_TO_64(ingress_counters.ctl_pkts);
stats->in.tagged_miss_pkts =
STATS_2x32_TO_64(ingress_counters.tagged_miss_pkts);
stats->in.untagged_miss_pkts =
STATS_2x32_TO_64(ingress_counters.untagged_miss_pkts);
stats->in.notag_pkts = STATS_2x32_TO_64(ingress_counters.notag_pkts);
stats->in.untagged_pkts =
STATS_2x32_TO_64(ingress_counters.untagged_pkts);
stats->in.bad_tag_pkts =
STATS_2x32_TO_64(ingress_counters.bad_tag_pkts);
stats->in.no_sci_pkts = STATS_2x32_TO_64(ingress_counters.no_sci_pkts);
stats->in.unknown_sci_pkts =
STATS_2x32_TO_64(ingress_counters.unknown_sci_pkts);
stats->in.ctrl_prt_pass_pkts =
STATS_2x32_TO_64(ingress_counters.ctrl_prt_pass_pkts);
stats->in.unctrl_prt_pass_pkts =
STATS_2x32_TO_64(ingress_counters.unctrl_prt_pass_pkts);
stats->in.ctrl_prt_fail_pkts =
STATS_2x32_TO_64(ingress_counters.ctrl_prt_fail_pkts);
stats->in.unctrl_prt_fail_pkts =
STATS_2x32_TO_64(ingress_counters.unctrl_prt_fail_pkts);
stats->in.too_long_pkts =
STATS_2x32_TO_64(ingress_counters.too_long_pkts);
stats->in.igpoc_ctl_pkts =
STATS_2x32_TO_64(ingress_counters.igpoc_ctl_pkts);
stats->in.ecc_error_pkts =
STATS_2x32_TO_64(ingress_counters.ecc_error_pkts);
stats->in.unctrl_hit_drop_redir =
STATS_2x32_TO_64(ingress_counters.unctrl_hit_drop_redir);
ret = aq_mss_get_egress_common_counters(hw, &egress_counters);
if (unlikely(ret))
return ret;
stats->out.ctl_pkts = STATS_2x32_TO_64(egress_counters.ctl_pkt);
stats->out.unknown_sa_pkts =
STATS_2x32_TO_64(egress_counters.unknown_sa_pkts);
stats->out.untagged_pkts =
STATS_2x32_TO_64(egress_counters.untagged_pkts);
stats->out.too_long = STATS_2x32_TO_64(egress_counters.too_long);
stats->out.ecc_error_pkts =
STATS_2x32_TO_64(egress_counters.ecc_error_pkts);
stats->out.unctrl_hit_drop_redir =
STATS_2x32_TO_64(egress_counters.unctrl_hit_drop_redir);
return 0;
}
static int aq_get_rxsa_stats(struct aq_hw_s *hw, const int sa_idx,
struct aq_macsec_rx_sa_stats *stats)
{
struct aq_mss_ingress_sa_counters i_sa_counters;
int ret;
ret = aq_mss_get_ingress_sa_counters(hw, &i_sa_counters, sa_idx);
if (unlikely(ret))
return ret;
stats->untagged_hit_pkts =
STATS_2x32_TO_64(i_sa_counters.untagged_hit_pkts);
stats->ctrl_hit_drop_redir_pkts =
STATS_2x32_TO_64(i_sa_counters.ctrl_hit_drop_redir_pkts);
stats->not_using_sa = STATS_2x32_TO_64(i_sa_counters.not_using_sa);
stats->unused_sa = STATS_2x32_TO_64(i_sa_counters.unused_sa);
stats->not_valid_pkts = STATS_2x32_TO_64(i_sa_counters.not_valid_pkts);
stats->invalid_pkts = STATS_2x32_TO_64(i_sa_counters.invalid_pkts);
stats->ok_pkts = STATS_2x32_TO_64(i_sa_counters.ok_pkts);
stats->late_pkts = STATS_2x32_TO_64(i_sa_counters.late_pkts);
stats->delayed_pkts = STATS_2x32_TO_64(i_sa_counters.delayed_pkts);
stats->unchecked_pkts = STATS_2x32_TO_64(i_sa_counters.unchecked_pkts);
stats->validated_octets =
STATS_2x32_TO_64(i_sa_counters.validated_octets);
stats->decrypted_octets =
STATS_2x32_TO_64(i_sa_counters.decrypted_octets);
return 0;
}
static int aq_get_txsa_stats(struct aq_hw_s *hw, const int sa_idx,
struct aq_macsec_tx_sa_stats *stats)
{
struct aq_mss_egress_sa_counters e_sa_counters;
int ret;
ret = aq_mss_get_egress_sa_counters(hw, &e_sa_counters, sa_idx);
if (unlikely(ret))
return ret;
stats->sa_hit_drop_redirect =
STATS_2x32_TO_64(e_sa_counters.sa_hit_drop_redirect);
stats->sa_protected2_pkts =
STATS_2x32_TO_64(e_sa_counters.sa_protected2_pkts);
stats->sa_protected_pkts =
STATS_2x32_TO_64(e_sa_counters.sa_protected_pkts);
stats->sa_encrypted_pkts =
STATS_2x32_TO_64(e_sa_counters.sa_encrypted_pkts);
return 0;
}
static int aq_get_txsa_next_pn(struct aq_hw_s *hw, const int sa_idx, u32 *pn)
{
struct aq_mss_egress_sa_record sa_rec;
int ret;
ret = aq_mss_get_egress_sa_record(hw, &sa_rec, sa_idx);
if (likely(!ret))
*pn = sa_rec.next_pn;
return ret;
}
static int aq_get_rxsa_next_pn(struct aq_hw_s *hw, const int sa_idx, u32 *pn)
{
struct aq_mss_ingress_sa_record sa_rec;
int ret;
ret = aq_mss_get_ingress_sa_record(hw, &sa_rec, sa_idx);
if (likely(!ret))
*pn = (!sa_rec.sat_nextpn) ? sa_rec.next_pn : 0;
return ret;
}
static int aq_get_txsc_stats(struct aq_hw_s *hw, const int sc_idx,
struct aq_macsec_tx_sc_stats *stats)
{
struct aq_mss_egress_sc_counters e_sc_counters;
int ret;
ret = aq_mss_get_egress_sc_counters(hw, &e_sc_counters, sc_idx);
if (unlikely(ret))
return ret;
stats->sc_protected_pkts =
STATS_2x32_TO_64(e_sc_counters.sc_protected_pkts);
stats->sc_encrypted_pkts =
STATS_2x32_TO_64(e_sc_counters.sc_encrypted_pkts);
stats->sc_protected_octets =
STATS_2x32_TO_64(e_sc_counters.sc_protected_octets);
stats->sc_encrypted_octets =
STATS_2x32_TO_64(e_sc_counters.sc_encrypted_octets);
return 0;
}
static int aq_mdo_dev_open(struct macsec_context *ctx)
{
struct aq_nic_s *nic = netdev_priv(ctx->netdev);
......@@ -873,6 +1033,191 @@ static int aq_mdo_del_rxsa(struct macsec_context *ctx)
return ret;
}
static int aq_mdo_get_dev_stats(struct macsec_context *ctx)
{
struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_common_stats *stats = &nic->macsec_cfg->stats;
struct aq_hw_s *hw = nic->aq_hw;
if (ctx->prepare)
return 0;
aq_get_macsec_common_stats(hw, stats);
ctx->stats.dev_stats->OutPktsUntagged = stats->out.untagged_pkts;
ctx->stats.dev_stats->InPktsUntagged = stats->in.untagged_pkts;
ctx->stats.dev_stats->OutPktsTooLong = stats->out.too_long;
ctx->stats.dev_stats->InPktsNoTag = stats->in.notag_pkts;
ctx->stats.dev_stats->InPktsBadTag = stats->in.bad_tag_pkts;
ctx->stats.dev_stats->InPktsUnknownSCI = stats->in.unknown_sci_pkts;
ctx->stats.dev_stats->InPktsNoSCI = stats->in.no_sci_pkts;
ctx->stats.dev_stats->InPktsOverrun = 0;
return 0;
}
static int aq_mdo_get_tx_sc_stats(struct macsec_context *ctx)
{
struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_tx_sc_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
struct aq_macsec_txsc *aq_txsc;
int txsc_idx;
txsc_idx = aq_get_txsc_idx_from_secy(nic->macsec_cfg, ctx->secy);
if (txsc_idx < 0)
return -ENOENT;
if (ctx->prepare)
return 0;
aq_txsc = &nic->macsec_cfg->aq_txsc[txsc_idx];
stats = &aq_txsc->stats;
aq_get_txsc_stats(hw, aq_txsc->hw_sc_idx, stats);
ctx->stats.tx_sc_stats->OutPktsProtected = stats->sc_protected_pkts;
ctx->stats.tx_sc_stats->OutPktsEncrypted = stats->sc_encrypted_pkts;
ctx->stats.tx_sc_stats->OutOctetsProtected = stats->sc_protected_octets;
ctx->stats.tx_sc_stats->OutOctetsEncrypted = stats->sc_encrypted_octets;
return 0;
}
static int aq_mdo_get_tx_sa_stats(struct macsec_context *ctx)
{
struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_tx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
const struct macsec_secy *secy;
struct aq_macsec_txsc *aq_txsc;
struct macsec_tx_sa *tx_sa;
unsigned int sa_idx;
int txsc_idx;
u32 next_pn;
int ret;
txsc_idx = aq_get_txsc_idx_from_secy(cfg, ctx->secy);
if (txsc_idx < 0)
return -EINVAL;
if (ctx->prepare)
return 0;
aq_txsc = &cfg->aq_txsc[txsc_idx];
sa_idx = aq_txsc->hw_sc_idx | ctx->sa.assoc_num;
stats = &aq_txsc->tx_sa_stats[ctx->sa.assoc_num];
ret = aq_get_txsa_stats(hw, sa_idx, stats);
if (ret)
return ret;
ctx->stats.tx_sa_stats->OutPktsProtected = stats->sa_protected_pkts;
ctx->stats.tx_sa_stats->OutPktsEncrypted = stats->sa_encrypted_pkts;
secy = aq_txsc->sw_secy;
tx_sa = rcu_dereference_bh(secy->tx_sc.sa[ctx->sa.assoc_num]);
ret = aq_get_txsa_next_pn(hw, sa_idx, &next_pn);
if (ret == 0) {
spin_lock_bh(&tx_sa->lock);
tx_sa->next_pn = next_pn;
spin_unlock_bh(&tx_sa->lock);
}
return ret;
}
static int aq_mdo_get_rx_sc_stats(struct macsec_context *ctx)
{
struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_rx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
struct aq_macsec_rxsc *aq_rxsc;
unsigned int sa_idx;
int rxsc_idx;
int ret = 0;
int i;
rxsc_idx = aq_get_rxsc_idx_from_rxsc(cfg, ctx->rx_sc);
if (rxsc_idx < 0)
return -ENOENT;
if (ctx->prepare)
return 0;
aq_rxsc = &cfg->aq_rxsc[rxsc_idx];
for (i = 0; i < MACSEC_NUM_AN; i++) {
if (!test_bit(i, &aq_rxsc->rx_sa_idx_busy))
continue;
stats = &aq_rxsc->rx_sa_stats[i];
sa_idx = aq_rxsc->hw_sc_idx | i;
ret = aq_get_rxsa_stats(hw, sa_idx, stats);
if (ret)
break;
ctx->stats.rx_sc_stats->InOctetsValidated +=
stats->validated_octets;
ctx->stats.rx_sc_stats->InOctetsDecrypted +=
stats->decrypted_octets;
ctx->stats.rx_sc_stats->InPktsUnchecked +=
stats->unchecked_pkts;
ctx->stats.rx_sc_stats->InPktsDelayed += stats->delayed_pkts;
ctx->stats.rx_sc_stats->InPktsOK += stats->ok_pkts;
ctx->stats.rx_sc_stats->InPktsInvalid += stats->invalid_pkts;
ctx->stats.rx_sc_stats->InPktsLate += stats->late_pkts;
ctx->stats.rx_sc_stats->InPktsNotValid += stats->not_valid_pkts;
ctx->stats.rx_sc_stats->InPktsNotUsingSA += stats->not_using_sa;
ctx->stats.rx_sc_stats->InPktsUnusedSA += stats->unused_sa;
}
return ret;
}
static int aq_mdo_get_rx_sa_stats(struct macsec_context *ctx)
{
struct aq_nic_s *nic = netdev_priv(ctx->netdev);
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_rx_sa_stats *stats;
struct aq_hw_s *hw = nic->aq_hw;
struct aq_macsec_rxsc *aq_rxsc;
struct macsec_rx_sa *rx_sa;
unsigned int sa_idx;
int rxsc_idx;
u32 next_pn;
int ret;
rxsc_idx = aq_get_rxsc_idx_from_rxsc(cfg, ctx->rx_sc);
if (rxsc_idx < 0)
return -EINVAL;
if (ctx->prepare)
return 0;
aq_rxsc = &cfg->aq_rxsc[rxsc_idx];
stats = &aq_rxsc->rx_sa_stats[ctx->sa.assoc_num];
sa_idx = aq_rxsc->hw_sc_idx | ctx->sa.assoc_num;
ret = aq_get_rxsa_stats(hw, sa_idx, stats);
if (ret)
return ret;
ctx->stats.rx_sa_stats->InPktsOK = stats->ok_pkts;
ctx->stats.rx_sa_stats->InPktsInvalid = stats->invalid_pkts;
ctx->stats.rx_sa_stats->InPktsNotValid = stats->not_valid_pkts;
ctx->stats.rx_sa_stats->InPktsNotUsingSA = stats->not_using_sa;
ctx->stats.rx_sa_stats->InPktsUnusedSA = stats->unused_sa;
rx_sa = rcu_dereference_bh(aq_rxsc->sw_rxsc->sa[ctx->sa.assoc_num]);
ret = aq_get_rxsa_next_pn(hw, sa_idx, &next_pn);
if (ret == 0) {
spin_lock_bh(&rx_sa->lock);
rx_sa->next_pn = next_pn;
spin_unlock_bh(&rx_sa->lock);
}
return ret;
}
static int apply_txsc_cfg(struct aq_nic_s *nic, const int txsc_idx)
{
struct aq_macsec_txsc *aq_txsc = &nic->macsec_cfg->aq_txsc[txsc_idx];
......@@ -1116,6 +1461,11 @@ const struct macsec_ops aq_macsec_ops = {
.mdo_add_txsa = aq_mdo_add_txsa,
.mdo_upd_txsa = aq_mdo_upd_txsa,
.mdo_del_txsa = aq_mdo_del_txsa,
.mdo_get_dev_stats = aq_mdo_get_dev_stats,
.mdo_get_tx_sc_stats = aq_mdo_get_tx_sc_stats,
.mdo_get_tx_sa_stats = aq_mdo_get_tx_sa_stats,
.mdo_get_rx_sc_stats = aq_mdo_get_rx_sc_stats,
.mdo_get_rx_sa_stats = aq_mdo_get_rx_sa_stats,
};
int aq_macsec_init(struct aq_nic_s *nic)
......@@ -1225,3 +1575,198 @@ void aq_macsec_work(struct aq_nic_s *nic)
aq_check_txsa_expiration(nic);
rtnl_unlock();
}
int aq_macsec_rx_sa_cnt(struct aq_nic_s *nic)
{
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
int i, cnt = 0;
if (!cfg)
return 0;
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
if (!test_bit(i, &cfg->rxsc_idx_busy))
continue;
cnt += hweight_long(cfg->aq_rxsc[i].rx_sa_idx_busy);
}
return cnt;
}
int aq_macsec_tx_sc_cnt(struct aq_nic_s *nic)
{
if (!nic->macsec_cfg)
return 0;
return hweight_long(nic->macsec_cfg->txsc_idx_busy);
}
int aq_macsec_tx_sa_cnt(struct aq_nic_s *nic)
{
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
int i, cnt = 0;
if (!cfg)
return 0;
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
if (!test_bit(i, &cfg->txsc_idx_busy))
continue;
cnt += hweight_long(cfg->aq_txsc[i].tx_sa_idx_busy);
}
return cnt;
}
static int aq_macsec_update_stats(struct aq_nic_s *nic)
{
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_hw_s *hw = nic->aq_hw;
struct aq_macsec_txsc *aq_txsc;
struct aq_macsec_rxsc *aq_rxsc;
int i, sa_idx, assoc_num;
int ret = 0;
aq_get_macsec_common_stats(hw, &cfg->stats);
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
if (!(cfg->txsc_idx_busy & BIT(i)))
continue;
aq_txsc = &cfg->aq_txsc[i];
ret = aq_get_txsc_stats(hw, aq_txsc->hw_sc_idx,
&aq_txsc->stats);
if (ret)
return ret;
for (assoc_num = 0; assoc_num < MACSEC_NUM_AN; assoc_num++) {
if (!test_bit(assoc_num, &aq_txsc->tx_sa_idx_busy))
continue;
sa_idx = aq_txsc->hw_sc_idx | assoc_num;
ret = aq_get_txsa_stats(hw, sa_idx,
&aq_txsc->tx_sa_stats[assoc_num]);
if (ret)
return ret;
}
}
for (i = 0; i < AQ_MACSEC_MAX_SC; i++) {
if (!(test_bit(i, &cfg->rxsc_idx_busy)))
continue;
aq_rxsc = &cfg->aq_rxsc[i];
for (assoc_num = 0; assoc_num < MACSEC_NUM_AN; assoc_num++) {
if (!test_bit(assoc_num, &aq_rxsc->rx_sa_idx_busy))
continue;
sa_idx = aq_rxsc->hw_sc_idx | assoc_num;
ret = aq_get_rxsa_stats(hw, sa_idx,
&aq_rxsc->rx_sa_stats[assoc_num]);
if (ret)
return ret;
}
}
return ret;
}
u64 *aq_macsec_get_stats(struct aq_nic_s *nic, u64 *data)
{
struct aq_macsec_cfg *cfg = nic->macsec_cfg;
struct aq_macsec_common_stats *common_stats;
struct aq_macsec_tx_sc_stats *txsc_stats;
struct aq_macsec_tx_sa_stats *txsa_stats;
struct aq_macsec_rx_sa_stats *rxsa_stats;
struct aq_macsec_txsc *aq_txsc;
struct aq_macsec_rxsc *aq_rxsc;
unsigned int assoc_num;
unsigned int sc_num;
unsigned int i = 0U;
if (!cfg)
return data;
aq_macsec_update_stats(nic);
common_stats = &cfg->stats;
data[i] = common_stats->in.ctl_pkts;
data[++i] = common_stats->in.tagged_miss_pkts;
data[++i] = common_stats->in.untagged_miss_pkts;
data[++i] = common_stats->in.notag_pkts;
data[++i] = common_stats->in.untagged_pkts;
data[++i] = common_stats->in.bad_tag_pkts;
data[++i] = common_stats->in.no_sci_pkts;
data[++i] = common_stats->in.unknown_sci_pkts;
data[++i] = common_stats->in.ctrl_prt_pass_pkts;
data[++i] = common_stats->in.unctrl_prt_pass_pkts;
data[++i] = common_stats->in.ctrl_prt_fail_pkts;
data[++i] = common_stats->in.unctrl_prt_fail_pkts;
data[++i] = common_stats->in.too_long_pkts;
data[++i] = common_stats->in.igpoc_ctl_pkts;
data[++i] = common_stats->in.ecc_error_pkts;
data[++i] = common_stats->in.unctrl_hit_drop_redir;
data[++i] = common_stats->out.ctl_pkts;
data[++i] = common_stats->out.unknown_sa_pkts;
data[++i] = common_stats->out.untagged_pkts;
data[++i] = common_stats->out.too_long;
data[++i] = common_stats->out.ecc_error_pkts;
data[++i] = common_stats->out.unctrl_hit_drop_redir;
for (sc_num = 0; sc_num < AQ_MACSEC_MAX_SC; sc_num++) {
if (!(test_bit(sc_num, &cfg->txsc_idx_busy)))
continue;
aq_txsc = &cfg->aq_txsc[sc_num];
txsc_stats = &aq_txsc->stats;
data[++i] = txsc_stats->sc_protected_pkts;
data[++i] = txsc_stats->sc_encrypted_pkts;
data[++i] = txsc_stats->sc_protected_octets;
data[++i] = txsc_stats->sc_encrypted_octets;
for (assoc_num = 0; assoc_num < MACSEC_NUM_AN; assoc_num++) {
if (!test_bit(assoc_num, &aq_txsc->tx_sa_idx_busy))
continue;
txsa_stats = &aq_txsc->tx_sa_stats[assoc_num];
data[++i] = txsa_stats->sa_hit_drop_redirect;
data[++i] = txsa_stats->sa_protected2_pkts;
data[++i] = txsa_stats->sa_protected_pkts;
data[++i] = txsa_stats->sa_encrypted_pkts;
}
}
for (sc_num = 0; sc_num < AQ_MACSEC_MAX_SC; sc_num++) {
if (!(test_bit(sc_num, &cfg->rxsc_idx_busy)))
continue;
aq_rxsc = &cfg->aq_rxsc[sc_num];
for (assoc_num = 0; assoc_num < MACSEC_NUM_AN; assoc_num++) {
if (!test_bit(assoc_num, &aq_rxsc->rx_sa_idx_busy))
continue;
rxsa_stats = &aq_rxsc->rx_sa_stats[assoc_num];
data[++i] = rxsa_stats->untagged_hit_pkts;
data[++i] = rxsa_stats->ctrl_hit_drop_redir_pkts;
data[++i] = rxsa_stats->not_using_sa;
data[++i] = rxsa_stats->unused_sa;
data[++i] = rxsa_stats->not_valid_pkts;
data[++i] = rxsa_stats->invalid_pkts;
data[++i] = rxsa_stats->ok_pkts;
data[++i] = rxsa_stats->late_pkts;
data[++i] = rxsa_stats->delayed_pkts;
data[++i] = rxsa_stats->unchecked_pkts;
data[++i] = rxsa_stats->validated_octets;
data[++i] = rxsa_stats->decrypted_octets;
}
}
i++;
data += i;
return data;
}
......@@ -23,11 +23,77 @@ enum aq_macsec_sc_sa {
aq_macsec_sa_sc_1sa_32sc,
};
struct aq_macsec_common_stats {
/* Ingress Common Counters */
struct {
u64 ctl_pkts;
u64 tagged_miss_pkts;
u64 untagged_miss_pkts;
u64 notag_pkts;
u64 untagged_pkts;
u64 bad_tag_pkts;
u64 no_sci_pkts;
u64 unknown_sci_pkts;
u64 ctrl_prt_pass_pkts;
u64 unctrl_prt_pass_pkts;
u64 ctrl_prt_fail_pkts;
u64 unctrl_prt_fail_pkts;
u64 too_long_pkts;
u64 igpoc_ctl_pkts;
u64 ecc_error_pkts;
u64 unctrl_hit_drop_redir;
} in;
/* Egress Common Counters */
struct {
u64 ctl_pkts;
u64 unknown_sa_pkts;
u64 untagged_pkts;
u64 too_long;
u64 ecc_error_pkts;
u64 unctrl_hit_drop_redir;
} out;
};
/* Ingress SA Counters */
struct aq_macsec_rx_sa_stats {
u64 untagged_hit_pkts;
u64 ctrl_hit_drop_redir_pkts;
u64 not_using_sa;
u64 unused_sa;
u64 not_valid_pkts;
u64 invalid_pkts;
u64 ok_pkts;
u64 late_pkts;
u64 delayed_pkts;
u64 unchecked_pkts;
u64 validated_octets;
u64 decrypted_octets;
};
/* Egress SA Counters */
struct aq_macsec_tx_sa_stats {
u64 sa_hit_drop_redirect;
u64 sa_protected2_pkts;
u64 sa_protected_pkts;
u64 sa_encrypted_pkts;
};
/* Egress SC Counters */
struct aq_macsec_tx_sc_stats {
u64 sc_protected_pkts;
u64 sc_encrypted_pkts;
u64 sc_protected_octets;
u64 sc_encrypted_octets;
};
struct aq_macsec_txsc {
u32 hw_sc_idx;
unsigned long tx_sa_idx_busy;
const struct macsec_secy *sw_secy;
u8 tx_sa_key[MACSEC_NUM_AN][MACSEC_KEYID_LEN];
struct aq_macsec_tx_sc_stats stats;
struct aq_macsec_tx_sa_stats tx_sa_stats[MACSEC_NUM_AN];
};
struct aq_macsec_rxsc {
......@@ -36,6 +102,7 @@ struct aq_macsec_rxsc {
const struct macsec_secy *sw_secy;
const struct macsec_rx_sc *sw_rxsc;
u8 rx_sa_key[MACSEC_NUM_AN][MACSEC_KEYID_LEN];
struct aq_macsec_rx_sa_stats rx_sa_stats[MACSEC_NUM_AN];
};
struct aq_macsec_cfg {
......@@ -46,6 +113,8 @@ struct aq_macsec_cfg {
/* Ingress channel configuration */
unsigned long rxsc_idx_busy;
struct aq_macsec_rxsc aq_rxsc[AQ_MACSEC_MAX_SC];
/* Statistics / counters */
struct aq_macsec_common_stats stats;
};
extern const struct macsec_ops aq_macsec_ops;
......@@ -54,6 +123,10 @@ int aq_macsec_init(struct aq_nic_s *nic);
void aq_macsec_free(struct aq_nic_s *nic);
int aq_macsec_enable(struct aq_nic_s *nic);
void aq_macsec_work(struct aq_nic_s *nic);
u64 *aq_macsec_get_stats(struct aq_nic_s *nic, u64 *data);
int aq_macsec_rx_sa_cnt(struct aq_nic_s *nic);
int aq_macsec_tx_sc_cnt(struct aq_nic_s *nic);
int aq_macsec_tx_sa_cnt(struct aq_nic_s *nic);
#endif
......
......@@ -781,7 +781,7 @@ int aq_nic_get_regs_count(struct aq_nic_s *self)
return self->aq_nic_cfg.aq_hw_caps->mac_regs_count;
}
void aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
{
struct aq_vec_s *aq_vec = NULL;
struct aq_stats_s *stats;
......@@ -831,7 +831,10 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
aq_vec_get_sw_stats(aq_vec, data, &count);
}
data += count;
err_exit:;
return data;
}
static void aq_nic_update_ndev_stats(struct aq_nic_s *self)
......
......@@ -158,7 +158,7 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb);
int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p);
int aq_nic_get_regs_count(struct aq_nic_s *self);
void aq_nic_get_stats(struct aq_nic_s *self, u64 *data);
u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data);
int aq_nic_stop(struct aq_nic_s *self);
void aq_nic_deinit(struct aq_nic_s *self, bool link_down);
void aq_nic_set_power(struct aq_nic_s *self);
......
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