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 @@ ...@@ -11,6 +11,7 @@
#include "aq_vec.h" #include "aq_vec.h"
#include "aq_ptp.h" #include "aq_ptp.h"
#include "aq_filters.h" #include "aq_filters.h"
#include "aq_macsec.h"
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
...@@ -96,6 +97,62 @@ static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = { ...@@ -96,6 +97,62 @@ static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = {
"Queue[%d] InErrors", "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] = { static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
"DMASystemLoopback", "DMASystemLoopback",
"PKTSystemLoopback", "PKTSystemLoopback",
...@@ -104,18 +161,38 @@ static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = { ...@@ -104,18 +161,38 @@ static const char aq_ethtool_priv_flag_names[][ETH_GSTRING_LEN] = {
"PHYExternalLoopback", "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, static void aq_ethtool_stats(struct net_device *ndev,
struct ethtool_stats *stats, u64 *data) struct ethtool_stats *stats, u64 *data)
{ {
struct aq_nic_s *aq_nic = netdev_priv(ndev); 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) + memset(data, 0, aq_ethtool_n_stats(ndev) * sizeof(u64));
ARRAY_SIZE(aq_ethtool_queue_stat_names) * data = aq_nic_get_stats(aq_nic, data);
cfg->vecs) * sizeof(u64)); #if IS_ENABLED(CONFIG_MACSEC)
aq_nic_get_stats(aq_nic, data); data = aq_macsec_get_stats(aq_nic, data);
#endif
} }
static void aq_ethtool_get_drvinfo(struct net_device *ndev, static void aq_ethtool_get_drvinfo(struct net_device *ndev,
...@@ -123,11 +200,9 @@ 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 pci_dev *pdev = to_pci_dev(ndev->dev.parent);
struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *cfg;
u32 firmware_version; u32 firmware_version;
u32 regs_count; u32 regs_count;
cfg = aq_nic_get_cfg(aq_nic);
firmware_version = aq_nic_get_fw_version(aq_nic); firmware_version = aq_nic_get_fw_version(aq_nic);
regs_count = aq_nic_get_regs_count(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, ...@@ -139,8 +214,7 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "", strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
sizeof(drvinfo->bus_info)); sizeof(drvinfo->bus_info));
drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + drvinfo->n_stats = aq_ethtool_n_stats(ndev);
cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
drvinfo->testinfo_len = 0; drvinfo->testinfo_len = 0;
drvinfo->regdump_len = regs_count; drvinfo->regdump_len = regs_count;
drvinfo->eedump_len = 0; drvinfo->eedump_len = 0;
...@@ -153,6 +227,9 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -153,6 +227,9 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
struct aq_nic_cfg_s *cfg; struct aq_nic_cfg_s *cfg;
u8 *p = data; u8 *p = data;
int i, si; int i, si;
#if IS_ENABLED(CONFIG_MACSEC)
int sa;
#endif
cfg = aq_nic_get_cfg(aq_nic); cfg = aq_nic_get_cfg(aq_nic);
...@@ -170,6 +247,60 @@ static void aq_ethtool_get_strings(struct net_device *ndev, ...@@ -170,6 +247,60 @@ static void aq_ethtool_get_strings(struct net_device *ndev,
p += ETH_GSTRING_LEN; 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; break;
case ETH_SS_PRIV_FLAGS: case ETH_SS_PRIV_FLAGS:
memcpy(p, aq_ethtool_priv_flag_names, memcpy(p, aq_ethtool_priv_flag_names,
...@@ -209,16 +340,11 @@ static int aq_ethtool_set_phys_id(struct net_device *ndev, ...@@ -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) 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; int ret = 0;
cfg = aq_nic_get_cfg(aq_nic);
switch (stringset) { switch (stringset) {
case ETH_SS_STATS: case ETH_SS_STATS:
ret = ARRAY_SIZE(aq_ethtool_stat_names) + ret = aq_ethtool_n_stats(ndev);
cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names);
break; break;
case ETH_SS_PRIV_FLAGS: case ETH_SS_PRIV_FLAGS:
ret = ARRAY_SIZE(aq_ethtool_priv_flag_names); ret = ARRAY_SIZE(aq_ethtool_priv_flag_names);
......
...@@ -23,11 +23,77 @@ enum aq_macsec_sc_sa { ...@@ -23,11 +23,77 @@ enum aq_macsec_sc_sa {
aq_macsec_sa_sc_1sa_32sc, 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 { struct aq_macsec_txsc {
u32 hw_sc_idx; u32 hw_sc_idx;
unsigned long tx_sa_idx_busy; unsigned long tx_sa_idx_busy;
const struct macsec_secy *sw_secy; const struct macsec_secy *sw_secy;
u8 tx_sa_key[MACSEC_NUM_AN][MACSEC_KEYID_LEN]; 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 { struct aq_macsec_rxsc {
...@@ -36,6 +102,7 @@ struct aq_macsec_rxsc { ...@@ -36,6 +102,7 @@ struct aq_macsec_rxsc {
const struct macsec_secy *sw_secy; const struct macsec_secy *sw_secy;
const struct macsec_rx_sc *sw_rxsc; const struct macsec_rx_sc *sw_rxsc;
u8 rx_sa_key[MACSEC_NUM_AN][MACSEC_KEYID_LEN]; 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 { struct aq_macsec_cfg {
...@@ -46,6 +113,8 @@ struct aq_macsec_cfg { ...@@ -46,6 +113,8 @@ struct aq_macsec_cfg {
/* Ingress channel configuration */ /* Ingress channel configuration */
unsigned long rxsc_idx_busy; unsigned long rxsc_idx_busy;
struct aq_macsec_rxsc aq_rxsc[AQ_MACSEC_MAX_SC]; 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; extern const struct macsec_ops aq_macsec_ops;
...@@ -54,6 +123,10 @@ int aq_macsec_init(struct aq_nic_s *nic); ...@@ -54,6 +123,10 @@ int aq_macsec_init(struct aq_nic_s *nic);
void aq_macsec_free(struct aq_nic_s *nic); void aq_macsec_free(struct aq_nic_s *nic);
int aq_macsec_enable(struct aq_nic_s *nic); int aq_macsec_enable(struct aq_nic_s *nic);
void aq_macsec_work(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 #endif
......
...@@ -781,7 +781,7 @@ int aq_nic_get_regs_count(struct aq_nic_s *self) ...@@ -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; 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_vec_s *aq_vec = NULL;
struct aq_stats_s *stats; struct aq_stats_s *stats;
...@@ -831,7 +831,10 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data) ...@@ -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); aq_vec_get_sw_stats(aq_vec, data, &count);
} }
data += count;
err_exit:; err_exit:;
return data;
} }
static void aq_nic_update_ndev_stats(struct aq_nic_s *self) 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, ...@@ -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_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(struct aq_nic_s *self, struct ethtool_regs *regs, void *p);
int aq_nic_get_regs_count(struct aq_nic_s *self); 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); int aq_nic_stop(struct aq_nic_s *self);
void aq_nic_deinit(struct aq_nic_s *self, bool link_down); void aq_nic_deinit(struct aq_nic_s *self, bool link_down);
void aq_nic_set_power(struct aq_nic_s *self); 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