xfrm: extend add state callback to set failure reason
authorLeon Romanovsky <leonro@nvidia.com>
Tue, 24 Jan 2023 11:54:59 +0000 (13:54 +0200)
committerJakub Kicinski <kuba@kernel.org>
Fri, 27 Jan 2023 00:28:48 +0000 (16:28 -0800)
Almost all validation logic is in the drivers, but they are
missing reliable way to convey failure reason to userspace
applications.

Let's use extack to return this information to users.

Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
12 files changed:
Documentation/networking/xfrm_device.rst
drivers/net/bonding/bond_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/inline_crypto/ch_ipsec/chcr_ipsec.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
drivers/net/ethernet/intel/ixgbevf/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
drivers/net/ethernet/netronome/nfp/crypto/ipsec.c
drivers/net/netdevsim/ipsec.c
include/linux/netdevice.h
net/xfrm/xfrm_device.c
net/xfrm/xfrm_state.c

index b9c53e62698258b1264eb3874e3346a586d39068..83abdfef4ec35674a50ff78b966f8f15628295a2 100644 (file)
@@ -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,
index 0363ce597661422b82a7d33ef001151b275f9ada..686b2a6fd674cfa19a69b3d3a64b93e1a9520bee 100644 (file)
@@ -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;
@@ -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;
                }
index 9cbce1faab26f96f117728f79f5bdaf9a4e94c2d..6c0a41f3ae448ecce8c91aa0e6b72aaef839f0b5 100644 (file)
@@ -6490,7 +6490,8 @@ 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;
@@ -6504,7 +6505,7 @@ static int cxgb4_xfrm_add_state(struct xfrm_state *x)
        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);
index ca21794281d6a6f561db33a45839ed217fb1e997..ac2ea6206af135bc295a8697290570e465cde460 100644 (file)
@@ -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,7 +227,8 @@ out:
  * 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;
index 53a969e348836aedbb76b6e3300bad7301e9e0a4..07c37dc619e81ca5fc69d1b5d25e2171d57e595d 100644 (file)
@@ -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);
@@ -950,7 +952,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;
 
index c1cf540d162a89da68a516ef45defcddd2a884e4..752b9df4fb5192ee4c4d4ddad54fb3f104c33b36 100644 (file)
@@ -257,8 +257,10 @@ static int ixgbevf_ipsec_parse_proto_keys(struct xfrm_state *xs,
 /**
  * ixgbevf_ipsec_add_sa - program device with a security association
  * @xs: pointer to transformer state struct
+ * @extack: extack point to fill failure reason
  **/
-static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs)
+static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs,
+                               struct netlink_ext_ack *extack)
 {
        struct net_device *dev = xs->xso.real_dev;
        struct ixgbevf_adapter *adapter;
index 3236c3b43149fb4c172734f531d33d8b301db89e..a889df77dd2deee64cfc8b4caa09ec101e014f90 100644 (file)
@@ -298,7 +298,8 @@ static void _update_xfrm_state(struct work_struct *work)
        mlx5_accel_esp_modify_xfrm(sa_entry, &modify_work->attrs);
 }
 
-static int mlx5e_xfrm_add_state(struct xfrm_state *x)
+static int mlx5e_xfrm_add_state(struct xfrm_state *x,
+                               struct netlink_ext_ack *extack)
 {
        struct mlx5e_ipsec_sa_entry *sa_entry = NULL;
        struct net_device *netdev = x->xso.real_dev;
index 4632268695cb9558b4f1349e60de3be57702a60c..41b98f2b7402d83cdd65145a81847b500abba2e5 100644 (file)
@@ -260,7 +260,8 @@ static void set_sha2_512hmac(struct nfp_ipsec_cfg_add_sa *cfg, int *trunc_len)
        }
 }
 
-static int nfp_net_xfrm_add_state(struct xfrm_state *x)
+static int nfp_net_xfrm_add_state(struct xfrm_state *x,
+                                 struct netlink_ext_ack *extack)
 {
        struct net_device *netdev = x->xso.dev;
        struct nfp_ipsec_cfg_mssg msg = {};
index b93baf5c8bee09a50a79692f9d0df0b566f80d61..84a02d69abad82e872778b8510c88b429b63014d 100644 (file)
@@ -125,7 +125,8 @@ static int nsim_ipsec_parse_proto_keys(struct xfrm_state *xs,
        return 0;
 }
 
-static int nsim_ipsec_add_sa(struct xfrm_state *xs)
+static int nsim_ipsec_add_sa(struct xfrm_state *xs,
+                            struct netlink_ext_ack *extack)
 {
        struct nsim_ipsec *ipsec;
        struct net_device *dev;
index 7c43b9fb9aaefa2caf84cd4d31219ba6aad5c2a3..63b77cbc947e214dd37c16a1e4cf76cd65681904 100644 (file)
@@ -1035,7 +1035,7 @@ struct netdev_bpf {
 
 #ifdef CONFIG_XFRM_OFFLOAD
 struct xfrmdev_ops {
-       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,
index 2cec637a4a9cd2aca04757fecc4285dafd5482b4..562b9d9515988e0ffe0876431d224f846fb71d57 100644 (file)
@@ -309,7 +309,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
        else
                xso->type = XFRM_DEV_OFFLOAD_CRYPTO;
 
-       err = dev->xfrmdev_ops->xdo_dev_state_add(x);
+       err = dev->xfrmdev_ops->xdo_dev_state_add(x, extack);
        if (err) {
                xso->dev = NULL;
                xso->dir = 0;
@@ -325,10 +325,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
                 * authors to do not return -EOPNOTSUPP in packet offload mode.
                 */
                WARN_ON(err == -EOPNOTSUPP && is_packet_offload);
-               if (err != -EOPNOTSUPP || is_packet_offload) {
-                       NL_SET_ERR_MSG(extack, "Device failed to offload this state");
+               if (err != -EOPNOTSUPP || is_packet_offload)
                        return err;
-               }
        }
 
        return 0;
index 89c731f4f0c7283e28fc7697c8729a5d1064da97..59fffa02d1cc20165ba221cf67be369362f39c18 100644 (file)
@@ -1274,7 +1274,7 @@ found:
                        xso->real_dev = xdo->real_dev;
                        netdev_tracker_alloc(xso->dev, &xso->dev_tracker,
                                             GFP_ATOMIC);
-                       error = xso->dev->xfrmdev_ops->xdo_dev_state_add(x);
+                       error = xso->dev->xfrmdev_ops->xdo_dev_state_add(x, NULL);
                        if (error) {
                                xso->dir = 0;
                                netdev_put(xso->dev, &xso->dev_tracker);