Commit 868c82f3 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'convert-drivers-to-return-xfrm-configuration-errors-through-extack'

Leon Romanovsky says:

====================
Convert drivers to return XFRM configuration errors through extack

This series continues effort started by Sabrina to return XFRM configuration
errors through extack. It allows for user space software stack easily present
driver failure reasons to users.

As a note, Intel drivers have a path where extack is equal to NULL, and error
prints won't be available in current patchset. If it is needed, it can be
changed by adding special to Intel macro to print to dmesg in case of
extack == NULL.
====================

Link: https://lore.kernel.org/r/cover.1674560845.git.leon@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 9179f5fe 8c284ea4
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ Callbacks to implement
  /* from include/linux/netdevice.h */
  struct xfrmdev_ops {
        /* Crypto and Packet offload callbacks */
	int	(*xdo_dev_state_add) (struct xfrm_state *x);
	int	(*xdo_dev_state_add) (struct xfrm_state *x, struct netlink_ext_ack *extack);
	void	(*xdo_dev_state_delete) (struct xfrm_state *x);
	void	(*xdo_dev_state_free) (struct xfrm_state *x);
	bool	(*xdo_dev_offload_ok) (struct sk_buff *skb,
@@ -73,7 +73,7 @@ Callbacks to implement

        /* Solely packet offload callbacks */
	void    (*xdo_dev_state_update_curlft) (struct xfrm_state *x);
	int	(*xdo_dev_policy_add) (struct xfrm_policy *x);
	int	(*xdo_dev_policy_add) (struct xfrm_policy *x, struct netlink_ext_ack *extack);
	void	(*xdo_dev_policy_delete) (struct xfrm_policy *x);
	void	(*xdo_dev_policy_free) (struct xfrm_policy *x);
  };
+6 −4
Original line number Diff line number Diff line
@@ -419,8 +419,10 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
/**
 * bond_ipsec_add_sa - program device with a security association
 * @xs: pointer to transformer state struct
 * @extack: extack point to fill failure reason
 **/
static int bond_ipsec_add_sa(struct xfrm_state *xs)
static int bond_ipsec_add_sa(struct xfrm_state *xs,
			     struct netlink_ext_ack *extack)
{
	struct net_device *bond_dev = xs->xso.dev;
	struct bond_ipsec *ipsec;
@@ -442,7 +444,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs)
	if (!slave->dev->xfrmdev_ops ||
	    !slave->dev->xfrmdev_ops->xdo_dev_state_add ||
	    netif_is_bond_master(slave->dev)) {
		slave_warn(bond_dev, slave->dev, "Slave does not support ipsec offload\n");
		NL_SET_ERR_MSG_MOD(extack, "Slave does not support ipsec offload");
		rcu_read_unlock();
		return -EINVAL;
	}
@@ -454,7 +456,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs)
	}
	xs->xso.real_dev = slave->dev;

	err = slave->dev->xfrmdev_ops->xdo_dev_state_add(xs);
	err = slave->dev->xfrmdev_ops->xdo_dev_state_add(xs, extack);
	if (!err) {
		ipsec->xs = xs;
		INIT_LIST_HEAD(&ipsec->list);
@@ -494,7 +496,7 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
	spin_lock_bh(&bond->ipsec_lock);
	list_for_each_entry(ipsec, &bond->ipsec_list, list) {
		ipsec->xs->xso.real_dev = slave->dev;
		if (slave->dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs)) {
		if (slave->dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
			slave_warn(bond_dev, slave->dev, "%s: failed to add SA\n", __func__);
			ipsec->xs->xso.real_dev = NULL;
		}
+4 −4
Original line number Diff line number Diff line
@@ -6490,21 +6490,21 @@ static const struct tlsdev_ops cxgb4_ktls_ops = {

#if IS_ENABLED(CONFIG_CHELSIO_IPSEC_INLINE)

static int cxgb4_xfrm_add_state(struct xfrm_state *x)
static int cxgb4_xfrm_add_state(struct xfrm_state *x,
				struct netlink_ext_ack *extack)
{
	struct adapter *adap = netdev2adap(x->xso.dev);
	int ret;

	if (!mutex_trylock(&uld_mutex)) {
		dev_dbg(adap->pdev_dev,
			"crypto uld critical resource is under use\n");
		NL_SET_ERR_MSG_MOD(extack, "crypto uld critical resource is under use");
		return -EBUSY;
	}
	ret = chcr_offload_state(adap, CXGB4_XFRMDEV_OPS);
	if (ret)
		goto out_unlock;

	ret = adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_add(x);
	ret = adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_add(x, extack);

out_unlock:
	mutex_unlock(&uld_mutex);
+18 −16
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ static void *ch_ipsec_uld_add(const struct cxgb4_lld_info *infop);
static void ch_ipsec_advance_esn_state(struct xfrm_state *x);
static void ch_ipsec_xfrm_free_state(struct xfrm_state *x);
static void ch_ipsec_xfrm_del_state(struct xfrm_state *x);
static int ch_ipsec_xfrm_add_state(struct xfrm_state *x);
static int ch_ipsec_xfrm_add_state(struct xfrm_state *x,
				   struct netlink_ext_ack *extack);

static const struct xfrmdev_ops ch_ipsec_xfrmdev_ops = {
	.xdo_dev_state_add      = ch_ipsec_xfrm_add_state,
@@ -226,65 +227,66 @@ static int ch_ipsec_setkey(struct xfrm_state *x,
 * returns 0 on success, negative error if failed to send message to FPGA
 * positive error if FPGA returned a bad response
 */
static int ch_ipsec_xfrm_add_state(struct xfrm_state *x)
static int ch_ipsec_xfrm_add_state(struct xfrm_state *x,
				   struct netlink_ext_ack *extack)
{
	struct ipsec_sa_entry *sa_entry;
	int res = 0;

	if (x->props.aalgo != SADB_AALG_NONE) {
		pr_debug("Cannot offload authenticated xfrm states\n");
		NL_SET_ERR_MSG_MOD(extack, "Cannot offload authenticated xfrm states");
		return -EINVAL;
	}
	if (x->props.calgo != SADB_X_CALG_NONE) {
		pr_debug("Cannot offload compressed xfrm states\n");
		NL_SET_ERR_MSG_MOD(extack, "Cannot offload compressed xfrm states");
		return -EINVAL;
	}
	if (x->props.family != AF_INET &&
	    x->props.family != AF_INET6) {
		pr_debug("Only IPv4/6 xfrm state offloaded\n");
		NL_SET_ERR_MSG_MOD(extack, "Only IPv4/6 xfrm state offloaded");
		return -EINVAL;
	}
	if (x->props.mode != XFRM_MODE_TRANSPORT &&
	    x->props.mode != XFRM_MODE_TUNNEL) {
		pr_debug("Only transport and tunnel xfrm offload\n");
		NL_SET_ERR_MSG_MOD(extack, "Only transport and tunnel xfrm offload");
		return -EINVAL;
	}
	if (x->id.proto != IPPROTO_ESP) {
		pr_debug("Only ESP xfrm state offloaded\n");
		NL_SET_ERR_MSG_MOD(extack, "Only ESP xfrm state offloaded");
		return -EINVAL;
	}
	if (x->encap) {
		pr_debug("Encapsulated xfrm state not offloaded\n");
		NL_SET_ERR_MSG_MOD(extack, "Encapsulated xfrm state not offloaded");
		return -EINVAL;
	}
	if (!x->aead) {
		pr_debug("Cannot offload xfrm states without aead\n");
		NL_SET_ERR_MSG_MOD(extack, "Cannot offload xfrm states without aead");
		return -EINVAL;
	}
	if (x->aead->alg_icv_len != 128 &&
	    x->aead->alg_icv_len != 96) {
		pr_debug("Cannot offload xfrm states with AEAD ICV length other than 96b & 128b\n");
		NL_SET_ERR_MSG_MOD(extack, "Cannot offload xfrm states with AEAD ICV length other than 96b & 128b");
		return -EINVAL;
	}
	if ((x->aead->alg_key_len != 128 + 32) &&
	    (x->aead->alg_key_len != 256 + 32)) {
		pr_debug("cannot offload xfrm states with AEAD key length other than 128/256 bit\n");
		NL_SET_ERR_MSG_MOD(extack, "cannot offload xfrm states with AEAD key length other than 128/256 bit");
		return -EINVAL;
	}
	if (x->tfcpad) {
		pr_debug("Cannot offload xfrm states with tfc padding\n");
		NL_SET_ERR_MSG_MOD(extack, "Cannot offload xfrm states with tfc padding");
		return -EINVAL;
	}
	if (!x->geniv) {
		pr_debug("Cannot offload xfrm states without geniv\n");
		NL_SET_ERR_MSG_MOD(extack, "Cannot offload xfrm states without geniv");
		return -EINVAL;
	}
	if (strcmp(x->geniv, "seqiv")) {
		pr_debug("Cannot offload xfrm states with geniv other than seqiv\n");
		NL_SET_ERR_MSG_MOD(extack, "Cannot offload xfrm states with geniv other than seqiv");
		return -EINVAL;
	}
	if (x->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
		pr_debug("Unsupported xfrm offload\n");
		NL_SET_ERR_MSG_MOD(extack, "Unsupported xfrm offload");
		return -EINVAL;
	}

+14 −13
Original line number Diff line number Diff line
@@ -557,8 +557,10 @@ static int ixgbe_ipsec_check_mgmt_ip(struct xfrm_state *xs)
/**
 * ixgbe_ipsec_add_sa - program device with a security association
 * @xs: pointer to transformer state struct
 * @extack: extack point to fill failure reason
 **/
static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
static int ixgbe_ipsec_add_sa(struct xfrm_state *xs,
			      struct netlink_ext_ack *extack)
{
	struct net_device *dev = xs->xso.real_dev;
	struct ixgbe_adapter *adapter = netdev_priv(dev);
@@ -570,23 +572,22 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
	int i;

	if (xs->id.proto != IPPROTO_ESP && xs->id.proto != IPPROTO_AH) {
		netdev_err(dev, "Unsupported protocol 0x%04x for ipsec offload\n",
			   xs->id.proto);
		NL_SET_ERR_MSG_MOD(extack, "Unsupported protocol for ipsec offload");
		return -EINVAL;
	}

	if (xs->props.mode != XFRM_MODE_TRANSPORT) {
		netdev_err(dev, "Unsupported mode for ipsec offload\n");
		NL_SET_ERR_MSG_MOD(extack, "Unsupported mode for ipsec offload");
		return -EINVAL;
	}

	if (ixgbe_ipsec_check_mgmt_ip(xs)) {
		netdev_err(dev, "IPsec IP addr clash with mgmt filters\n");
		NL_SET_ERR_MSG_MOD(extack, "IPsec IP addr clash with mgmt filters");
		return -EINVAL;
	}

	if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
		netdev_err(dev, "Unsupported ipsec offload type\n");
		NL_SET_ERR_MSG_MOD(extack, "Unsupported ipsec offload type");
		return -EINVAL;
	}

@@ -594,14 +595,14 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
		struct rx_sa rsa;

		if (xs->calg) {
			netdev_err(dev, "Compression offload not supported\n");
			NL_SET_ERR_MSG_MOD(extack, "Compression offload not supported");
			return -EINVAL;
		}

		/* find the first unused index */
		ret = ixgbe_ipsec_find_empty_idx(ipsec, true);
		if (ret < 0) {
			netdev_err(dev, "No space for SA in Rx table!\n");
			NL_SET_ERR_MSG_MOD(extack, "No space for SA in Rx table!");
			return ret;
		}
		sa_idx = (u16)ret;
@@ -616,7 +617,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
		/* get the key and salt */
		ret = ixgbe_ipsec_parse_proto_keys(xs, rsa.key, &rsa.salt);
		if (ret) {
			netdev_err(dev, "Failed to get key data for Rx SA table\n");
			NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Rx SA table");
			return ret;
		}

@@ -676,7 +677,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)

		} else {
			/* no match and no empty slot */
			netdev_err(dev, "No space for SA in Rx IP SA table\n");
			NL_SET_ERR_MSG_MOD(extack, "No space for SA in Rx IP SA table");
			memset(&rsa, 0, sizeof(rsa));
			return -ENOSPC;
		}
@@ -711,7 +712,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)
		/* find the first unused index */
		ret = ixgbe_ipsec_find_empty_idx(ipsec, false);
		if (ret < 0) {
			netdev_err(dev, "No space for SA in Tx table\n");
			NL_SET_ERR_MSG_MOD(extack, "No space for SA in Tx table");
			return ret;
		}
		sa_idx = (u16)ret;
@@ -725,7 +726,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs)

		ret = ixgbe_ipsec_parse_proto_keys(xs, tsa.key, &tsa.salt);
		if (ret) {
			netdev_err(dev, "Failed to get key data for Tx SA table\n");
			NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Tx SA table");
			memset(&tsa, 0, sizeof(tsa));
			return ret;
		}
@@ -950,7 +951,7 @@ int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
	memcpy(xs->aead->alg_name, aes_gcm_name, sizeof(aes_gcm_name));

	/* set up the HW offload */
	err = ixgbe_ipsec_add_sa(xs);
	err = ixgbe_ipsec_add_sa(xs, NULL);
	if (err)
		goto err_aead;

Loading