Commit 2f7ccf1d authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-tja11xx-macsec-support'



Radu Pirea says:

====================
Add MACsec support for TJA11XX C45 PHYs

This is the MACsec support for TJA11XX PHYs. The MACsec block encrypts
the ethernet frames on the fly and has no buffering. This operation will
grow the frames by 32 bytes. If the frames are sent back to back, the
MACsec block will not have enough room to insert the SecTAG and the ICV
and the frames will be dropped.

To mitigate this, the PHY can parse a specific ethertype with some
padding bytes and replace them with the SecTAG and ICV. These padding
bytes might be dummy or might contain information about TX SC that must
be used to encrypt the frame.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c2b2ee36 dc1a0038
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -15444,7 +15444,7 @@ NXP C45 TJA11XX PHY DRIVER
M:	Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
L:	netdev@vger.kernel.org
S:	Maintained
F:	drivers/net/phy/nxp-c45-tja11xx.c
F:	drivers/net/phy/nxp-c45-tja11xx*
NXP FSPI DRIVER
M:	Han Xu <han.xu@nxp.com>
+114 −37
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ struct pcpu_secy_stats {
 * @secys: linked list of SecY's on the underlying device
 * @gro_cells: pointer to the Generic Receive Offload cell
 * @offload: status of offloading on the MACsec device
 * @insert_tx_tag: when offloading, device requires to insert an
 *	additional tag
 */
struct macsec_dev {
	struct macsec_secy secy;
@@ -102,6 +104,7 @@ struct macsec_dev {
	struct list_head secys;
	struct gro_cells gro_cells;
	enum macsec_offload offload;
	bool insert_tx_tag;
};

/**
@@ -604,26 +607,11 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
		return ERR_PTR(-EINVAL);
	}

	if (unlikely(skb_headroom(skb) < MACSEC_NEEDED_HEADROOM ||
		     skb_tailroom(skb) < MACSEC_NEEDED_TAILROOM)) {
		struct sk_buff *nskb = skb_copy_expand(skb,
						       MACSEC_NEEDED_HEADROOM,
						       MACSEC_NEEDED_TAILROOM,
						       GFP_ATOMIC);
		if (likely(nskb)) {
			consume_skb(skb);
			skb = nskb;
		} else {
	ret = skb_ensure_writable_head_tail(skb, dev);
	if (unlikely(ret < 0)) {
		macsec_txsa_put(tx_sa);
		kfree_skb(skb);
			return ERR_PTR(-ENOMEM);
		}
	} else {
		skb = skb_unshare(skb, GFP_ATOMIC);
		if (!skb) {
			macsec_txsa_put(tx_sa);
			return ERR_PTR(-ENOMEM);
		}
		return ERR_PTR(ret);
	}

	unprotected_len = skb->len;
@@ -2583,6 +2571,33 @@ static bool macsec_is_configured(struct macsec_dev *macsec)
	return false;
}

static bool macsec_needs_tx_tag(struct macsec_dev *macsec,
				const struct macsec_ops *ops)
{
	return macsec->offload == MACSEC_OFFLOAD_PHY &&
		ops->mdo_insert_tx_tag;
}

static void macsec_set_head_tail_room(struct net_device *dev)
{
	struct macsec_dev *macsec = macsec_priv(dev);
	struct net_device *real_dev = macsec->real_dev;
	int needed_headroom, needed_tailroom;
	const struct macsec_ops *ops;

	ops = macsec_get_ops(macsec, NULL);
	if (ops) {
		needed_headroom = ops->needed_headroom;
		needed_tailroom = ops->needed_tailroom;
	} else {
		needed_headroom = MACSEC_NEEDED_HEADROOM;
		needed_tailroom = MACSEC_NEEDED_TAILROOM;
	}

	dev->needed_headroom = real_dev->needed_headroom + needed_headroom;
	dev->needed_tailroom = real_dev->needed_tailroom + needed_tailroom;
}

static int macsec_update_offload(struct net_device *dev, enum macsec_offload offload)
{
	enum macsec_offload prev_offload;
@@ -2620,8 +2635,13 @@ static int macsec_update_offload(struct net_device *dev, enum macsec_offload off
	ctx.secy = &macsec->secy;
	ret = offload == MACSEC_OFFLOAD_OFF ? macsec_offload(ops->mdo_del_secy, &ctx)
					    : macsec_offload(ops->mdo_add_secy, &ctx);
	if (ret)
	if (ret) {
		macsec->offload = prev_offload;
		return ret;
	}

	macsec_set_head_tail_room(dev);
	macsec->insert_tx_tag = macsec_needs_tx_tag(macsec, ops);

	return ret;
}
@@ -3379,6 +3399,40 @@ static struct genl_family macsec_fam __ro_after_init = {
	.resv_start_op	= MACSEC_CMD_UPD_OFFLOAD + 1,
};

static struct sk_buff *macsec_insert_tx_tag(struct sk_buff *skb,
					    struct net_device *dev)
{
	struct macsec_dev *macsec = macsec_priv(dev);
	const struct macsec_ops *ops;
	struct phy_device *phydev;
	struct macsec_context ctx;
	int skb_final_len;
	int err;

	ops = macsec_get_ops(macsec, &ctx);
	skb_final_len = skb->len - ETH_HLEN + ops->needed_headroom +
		ops->needed_tailroom;
	if (unlikely(skb_final_len > macsec->real_dev->mtu)) {
		err = -EINVAL;
		goto cleanup;
	}

	phydev = macsec->real_dev->phydev;

	err = skb_ensure_writable_head_tail(skb, dev);
	if (unlikely(err < 0))
		goto cleanup;

	err = ops->mdo_insert_tx_tag(phydev, skb);
	if (unlikely(err))
		goto cleanup;

	return skb;
cleanup:
	kfree_skb(skb);
	return ERR_PTR(err);
}

static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
				     struct net_device *dev)
{
@@ -3393,6 +3447,15 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
		skb_dst_drop(skb);
		dst_hold(&md_dst->dst);
		skb_dst_set(skb, &md_dst->dst);

		if (macsec->insert_tx_tag) {
			skb = macsec_insert_tx_tag(skb, dev);
			if (IS_ERR(skb)) {
				DEV_STATS_INC(dev, tx_dropped);
				return NETDEV_TX_OK;
			}
		}

		skb->dev = macsec->real_dev;
		return dev_queue_xmit(skb);
	}
@@ -3454,10 +3517,7 @@ static int macsec_dev_init(struct net_device *dev)
	dev->features = real_dev->features & MACSEC_FEATURES;
	dev->features |= NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE;

	dev->needed_headroom = real_dev->needed_headroom +
			       MACSEC_NEEDED_HEADROOM;
	dev->needed_tailroom = real_dev->needed_tailroom +
			       MACSEC_NEEDED_TAILROOM;
	macsec_set_head_tail_room(dev);

	if (is_zero_ether_addr(dev->dev_addr))
		eth_hw_addr_inherit(dev, real_dev);
@@ -3604,21 +3664,19 @@ static int macsec_set_mac_address(struct net_device *dev, void *p)
	struct macsec_dev *macsec = macsec_priv(dev);
	struct net_device *real_dev = macsec->real_dev;
	struct sockaddr *addr = p;
	u8  old_addr[ETH_ALEN];
	int err;

	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;

	if (!(dev->flags & IFF_UP))
		goto out;

	if (dev->flags & IFF_UP) {
		err = dev_uc_add(real_dev, addr->sa_data);
		if (err < 0)
			return err;
	}

	dev_uc_del(real_dev, dev->dev_addr);

out:
	ether_addr_copy(old_addr, dev->dev_addr);
	eth_hw_addr_set(dev, addr->sa_data);

	/* If h/w offloading is available, propagate to the device */
@@ -3627,13 +3685,29 @@ static int macsec_set_mac_address(struct net_device *dev, void *p)
		struct macsec_context ctx;

		ops = macsec_get_ops(macsec, &ctx);
		if (ops) {
			ctx.secy = &macsec->secy;
			macsec_offload(ops->mdo_upd_secy, &ctx);
		if (!ops) {
			err = -EOPNOTSUPP;
			goto restore_old_addr;
		}

		ctx.secy = &macsec->secy;
		err = macsec_offload(ops->mdo_upd_secy, &ctx);
		if (err)
			goto restore_old_addr;
	}

	if (dev->flags & IFF_UP)
		dev_uc_del(real_dev, old_addr);

	return 0;

restore_old_addr:
	if (dev->flags & IFF_UP)
		dev_uc_del(real_dev, addr->sa_data);

	eth_hw_addr_set(dev, old_addr);

	return err;
}

static int macsec_change_mtu(struct net_device *dev, int new_mtu)
@@ -4126,6 +4200,9 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
			err = macsec_offload(ops->mdo_add_secy, &ctx);
			if (err)
				goto del_dev;

			macsec->insert_tx_tag =
				macsec_needs_tx_tag(macsec, ops);
		}
	}

+0 −5
Original line number Diff line number Diff line
@@ -3,11 +3,6 @@
#include <net/macsec.h>
#include "netdevsim.h"

static inline u64 sci_to_cpu(sci_t sci)
{
	return be64_to_cpu((__force __be64)sci);
}

static int nsim_macsec_find_secy(struct netdevsim *ns, sci_t sci)
{
	int i;
+2 −1
Original line number Diff line number Diff line
@@ -317,9 +317,10 @@ config NXP_CBTX_PHY
config NXP_C45_TJA11XX_PHY
	tristate "NXP C45 TJA11XX PHYs"
	depends on PTP_1588_CLOCK_OPTIONAL
	depends on MACSEC || !MACSEC
	help
	  Enable support for NXP C45 TJA11XX PHYs.
	  Currently supports the TJA1103 and TJA1120 PHYs.
	  Currently supports the TJA1103, TJA1104 and TJA1120 PHYs.

config NXP_TJA11XX_PHY
	tristate "NXP TJA11xx PHYs support"
+5 −1
Original line number Diff line number Diff line
@@ -84,7 +84,11 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc/
obj-$(CONFIG_MOTORCOMM_PHY)	+= motorcomm.o
obj-$(CONFIG_NATIONAL_PHY)	+= national.o
obj-$(CONFIG_NCN26000_PHY)	+= ncn26000.o
obj-$(CONFIG_NXP_C45_TJA11XX_PHY)	+= nxp-c45-tja11xx.o
nxp-c45-tja-objs		+= nxp-c45-tja11xx.o
ifdef CONFIG_MACSEC
nxp-c45-tja-objs		+= nxp-c45-tja11xx-macsec.o
endif
obj-$(CONFIG_NXP_C45_TJA11XX_PHY)	+= nxp-c45-tja.o
obj-$(CONFIG_NXP_CBTX_PHY)	+= nxp-cbtx.o
obj-$(CONFIG_NXP_TJA11XX_PHY)	+= nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY)		+= qsemi.o
Loading