Commit f95a392e authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'macsec-inherit-lower-device-s-features-and-tso-limits-when-offloading'

Sabrina Dubroca says:

====================
macsec: inherit lower device's features and TSO limits when offloading

When macsec is offloaded to a NIC, we can take advantage of some of
its features, mainly TSO and checksumming. This increases performance
significantly. Some features cannot be inherited, because they require
additional ops that aren't provided by the macsec netdevice.

We also need to inherit TSO limits from the lower device, like
VLAN/macvlan devices do.

This series also moves the existing macsec offload selftest to the
netdevsim selftests before adding tests for the new features. To allow
this new selftest to work, netdevsim's hw_features are expanded.
====================

Link: https://patch.msgid.link/cover.1730929545.git.sd@queasysnail.net


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 4d1d3b52 0f8800eb
Loading
Loading
Loading
Loading
+44 −20
Original line number Diff line number Diff line
@@ -2621,6 +2621,17 @@ static void macsec_set_head_tail_room(struct net_device *dev)
	dev->needed_tailroom = real_dev->needed_tailroom + needed_tailroom;
}

static void macsec_inherit_tso_max(struct net_device *dev)
{
	struct macsec_dev *macsec = macsec_priv(dev);

	/* if macsec is offloaded, we need to follow the lower
	 * device's capabilities. otherwise, we can ignore them.
	 */
	if (macsec_is_offloaded(macsec))
		netif_inherit_tso_max(dev, macsec->real_dev);
}

static int macsec_update_offload(struct net_device *dev, enum macsec_offload offload)
{
	enum macsec_offload prev_offload;
@@ -2666,6 +2677,10 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload off
	macsec_set_head_tail_room(dev);
	macsec->insert_tx_tag = macsec_needs_tx_tag(macsec, ops);

	macsec_inherit_tso_max(dev);

	netdev_update_features(dev);

	return ret;
}

@@ -3521,6 +3536,10 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
#define MACSEC_FEATURES \
	(NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)

#define MACSEC_OFFLOAD_FEATURES \
	(MACSEC_FEATURES | NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES | \
	 NETIF_F_LRO | NETIF_F_RXHASH | NETIF_F_CSUM_MASK | NETIF_F_RXCSUM)

static int macsec_dev_init(struct net_device *dev)
{
	struct macsec_dev *macsec = macsec_priv(dev);
@@ -3531,7 +3550,12 @@ static int macsec_dev_init(struct net_device *dev)
	if (err)
		return err;

	dev->features = real_dev->features & MACSEC_FEATURES;
	macsec_inherit_tso_max(dev);

	dev->hw_features = real_dev->hw_features & MACSEC_OFFLOAD_FEATURES;
	dev->hw_features |= NETIF_F_GSO_SOFTWARE;

	dev->features = real_dev->features & MACSEC_OFFLOAD_FEATURES;
	dev->features |= NETIF_F_GSO_SOFTWARE;
	dev->lltx = true;
	dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
@@ -3561,8 +3585,12 @@ static netdev_features_t macsec_fix_features(struct net_device *dev,
{
	struct macsec_dev *macsec = macsec_priv(dev);
	struct net_device *real_dev = macsec->real_dev;
	netdev_features_t mask;

	mask = macsec_is_offloaded(macsec) ? MACSEC_OFFLOAD_FEATURES
					   : MACSEC_FEATURES;

	features &= (real_dev->features & MACSEC_FEATURES) |
	features &= (real_dev->features & mask) |
		    NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES;

	return features;
@@ -4428,31 +4456,26 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
			 void *ptr)
{
	struct net_device *real_dev = netdev_notifier_info_to_dev(ptr);
	struct macsec_rxh_data *rxd;
	struct macsec_dev *m, *n;
	LIST_HEAD(head);

	if (!is_macsec_master(real_dev))
		return NOTIFY_DONE;

	rxd = macsec_data_rtnl(real_dev);

	switch (event) {
	case NETDEV_DOWN:
	case NETDEV_UP:
	case NETDEV_CHANGE: {
		struct macsec_dev *m, *n;
		struct macsec_rxh_data *rxd;

		rxd = macsec_data_rtnl(real_dev);
	case NETDEV_CHANGE:
		list_for_each_entry_safe(m, n, &rxd->secys, secys) {
			struct net_device *dev = m->secy.netdev;

			netif_stacked_transfer_operstate(real_dev, dev);
		}
		break;
	}
	case NETDEV_UNREGISTER: {
		struct macsec_dev *m, *n;
		struct macsec_rxh_data *rxd;

		rxd = macsec_data_rtnl(real_dev);
	case NETDEV_UNREGISTER:
		list_for_each_entry_safe(m, n, &rxd->secys, secys) {
			macsec_common_dellink(m->secy.netdev, &head);
		}
@@ -4462,12 +4485,7 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,

		unregister_netdevice_many(&head);
		break;
	}
	case NETDEV_CHANGEMTU: {
		struct macsec_dev *m;
		struct macsec_rxh_data *rxd;

		rxd = macsec_data_rtnl(real_dev);
	case NETDEV_CHANGEMTU:
		list_for_each_entry(m, &rxd->secys, secys) {
			struct net_device *dev = m->secy.netdev;
			unsigned int mtu = real_dev->mtu - (m->secy.icv_len +
@@ -4476,7 +4494,13 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
			if (dev->mtu > mtu)
				dev_set_mtu(dev, mtu);
		}
		break;
	case NETDEV_FEAT_CHANGE:
		list_for_each_entry(m, &rxd->secys, secys) {
			macsec_inherit_tso_max(m->secy.netdev);
			netdev_update_features(m->secy.netdev);
		}
		break;
	}

	return NOTIFY_OK;
+5 −1
Original line number Diff line number Diff line
@@ -663,7 +663,11 @@ static void nsim_setup(struct net_device *dev)
			 NETIF_F_FRAGLIST |
			 NETIF_F_HW_CSUM |
			 NETIF_F_TSO;
	dev->hw_features |= NETIF_F_HW_TC;
	dev->hw_features |= NETIF_F_HW_TC |
			    NETIF_F_SG |
			    NETIF_F_FRAGLIST |
			    NETIF_F_HW_CSUM |
			    NETIF_F_TSO;
	dev->max_mtu = ETH_MAX_MTU;
	dev->xdp_features = NETDEV_XDP_ACT_HW_OFFLOAD;
}
+2 −0
Original line number Diff line number Diff line
@@ -4,12 +4,14 @@ TEST_PROGS = devlink.sh \
	devlink_in_netns.sh \
	devlink_trap.sh \
	ethtool-coalesce.sh \
	ethtool-features.sh \
	ethtool-fec.sh \
	ethtool-pause.sh \
	ethtool-ring.sh \
	fib.sh \
	fib_notifications.sh \
	hw_stats_l3.sh \
	macsec-offload.sh \
	nexthop.sh \
	peer.sh \
	psample.sh \
+1 −0
Original line number Diff line number Diff line
CONFIG_DUMMY=y
CONFIG_GENEVE=m
CONFIG_IPV6=y
CONFIG_MACSEC=m
CONFIG_NETDEVSIM=m
CONFIG_NET_SCH_MQPRIO=y
CONFIG_NET_SCH_MULTIQ=y
+31 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only

source ethtool-common.sh

NSIM_NETDEV=$(make_netdev)

set -o pipefail

FEATS="
  tx-checksum-ip-generic
  tx-scatter-gather
  tx-tcp-segmentation
  generic-segmentation-offload
  generic-receive-offload"

for feat in $FEATS ; do
    s=$(ethtool --json -k $NSIM_NETDEV | jq ".[].\"$feat\".active" 2>/dev/null)
    check $? "$s" true

    s=$(ethtool --json -k $NSIM_NETDEV | jq ".[].\"$feat\".fixed" 2>/dev/null)
    check $? "$s" false
done

if [ $num_errors -eq 0 ]; then
    echo "PASSED all $((num_passes)) checks"
    exit 0
else
    echo "FAILED $num_errors/$((num_errors+num_passes)) checks"
    exit 1
fi
Loading