Commit 05cc6c5b authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-atlantic-MACSec-support-for-AQC-devices'

Igor Russkikh says:

====================
net: atlantic: MACSec support for AQC devices

This patchset introduces MACSec HW offloading support in
Marvell(Aquantia) AQC atlantic driver.

This implementation is a joint effort of Marvell developers on top of
the work started by Antoine Tenart.

v2:
 * clean up the generated code (removed useless bit operations);
 * use WARN_ONCE to avoid log spam;
 * use put_unaligned_be64;
 * removed trailing \0 and length limit for format strings;

v1: https://patchwork.ozlabs.org/cover/1259998/

RFC v2: https://patchwork.ozlabs.org/cover/1252204/

RFC v1: https://patchwork.ozlabs.org/cover/1238082/



Several patches introduce backward-incompatible changes and are
subject for discussion/drop:

1) patch 0007:
  multicast/broadcast when offloading is needed to handle ARP requests,
  because they have broadcast destination address;
  With this patch we also match and encrypt/decrypt packets between macsec
  hw and realdev based on device's mac address.
  This can potentially be used to support multiple macsec offloaded
  interfaces on top of one realdev.
  However in some environments this could lead to problems, e.g. the
  'bridge over macsec' configuration will expect the packets with unknown
  src MAC should come through macsec.
  The patch is questionable, we've used it because our current hw setup
  and requirements both assume that the decryption is done based on mac
  address match only.
  This could be changed by encrypting/decripting all the traffic (except
  control).

2) patch 0009:
  real_dev features are now propagated to macsec device (when HW
  offloading is enabled), otherwise feature set might lead to HW
  reconfiguration during MACSec configuration.
  Also, HW offloaded macsec should be able to keep LRO LSO features,
  since they are transparent for macsec engine (at least in our hardware).
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 673040c3 e8e9e13c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ config AQTION
	tristate "aQuantia AQtion(tm) Support"
	depends on PCI
	depends on X86_64 || ARM64 || COMPILE_TEST
	depends on MACSEC || MACSEC=n
	---help---
	  This enables the support for the aQuantia AQtion(tm) Ethernet card.

+6 −1
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@

obj-$(CONFIG_AQTION) += atlantic.o

ccflags-y += -I$(src)

atlantic-objs := aq_main.o \
	aq_nic.o \
	aq_pci_func.o \
@@ -22,6 +24,9 @@ atlantic-objs := aq_main.o \
	hw_atl/hw_atl_b0.o \
	hw_atl/hw_atl_utils.o \
	hw_atl/hw_atl_utils_fw2x.o \
	hw_atl/hw_atl_llh.o
	hw_atl/hw_atl_llh.o \
	macsec/macsec_api.o

atlantic-$(CONFIG_MACSEC) += aq_macsec.o

atlantic-$(CONFIG_PTP_1588_CLOCK) += aq_ptp.o
 No newline at end of file
+143 −17
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -343,6 +343,12 @@ struct aq_fw_ops {

	int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate,
			    u32 *supported_rates);

	u32 (*get_link_capabilities)(struct aq_hw_s *self);

	int (*send_macsec_req)(struct aq_hw_s *self,
			       struct macsec_msg_fw_request *msg,
			       struct macsec_msg_fw_response *resp);
};

#endif /* AQ_HW_H */
+1777 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading