]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xfrm: Add explicit dev to .xdo_dev_state_{add,delete,free}
authorCosmin Ratiu <cratiu@nvidia.com>
Fri, 11 Apr 2025 07:49:56 +0000 (10:49 +0300)
committerSteffen Klassert <steffen.klassert@secunet.com>
Wed, 16 Apr 2025 09:01:41 +0000 (11:01 +0200)
Previously, device driver IPSec offload implementations would fall into
two categories:
1. Those that used xso.dev to determine the offload device.
2. Those that used xso.real_dev to determine the offload device.

The first category didn't work with bonding while the second did.
In a non-bonding setup the two pointers are the same.

This commit adds explicit pointers for the offload netdevice to
.xdo_dev_state_add() / .xdo_dev_state_delete() / .xdo_dev_state_free()
which eliminates the confusion and allows drivers from the first
category to work with bonding.

xso.real_dev now becomes a private pointer managed by the bonding
driver.

Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
14 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/marvell/octeontx2/nic/cn10k_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
include/net/xfrm.h
net/xfrm/xfrm_device.c
net/xfrm/xfrm_state.c

index 7f24c09f269431f4871b961fa75ec1d73b965fe5..122204da0fff690e53448fc00b0f4e0e6b78af23 100644 (file)
@@ -65,9 +65,13 @@ 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, struct netlink_ext_ack *extack);
-       void    (*xdo_dev_state_delete) (struct xfrm_state *x);
-       void    (*xdo_dev_state_free) (struct xfrm_state *x);
+       int     (*xdo_dev_state_add)(struct net_device *dev,
+                                     struct xfrm_state *x,
+                                     struct netlink_ext_ack *extack);
+       void    (*xdo_dev_state_delete)(struct net_device *dev,
+                                        struct xfrm_state *x);
+       void    (*xdo_dev_state_free)(struct net_device *dev,
+                                      struct xfrm_state *x);
        bool    (*xdo_dev_offload_ok) (struct sk_buff *skb,
                                       struct xfrm_state *x);
        void    (*xdo_dev_state_advance_esn) (struct xfrm_state *x);
index 950d8e4d86f8b4e9f7a620f315be675f44080f27..4ba525a564c53fc55ea605c2c90aa97c70671b8a 100644 (file)
@@ -453,13 +453,14 @@ static struct net_device *bond_ipsec_dev(struct xfrm_state *xs)
 
 /**
  * bond_ipsec_add_sa - program device with a security association
+ * @bond_dev: pointer to the bond net device
  * @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 net_device *bond_dev,
+                            struct xfrm_state *xs,
                             struct netlink_ext_ack *extack)
 {
-       struct net_device *bond_dev = xs->xso.dev;
        struct net_device *real_dev;
        netdevice_tracker tracker;
        struct bond_ipsec *ipsec;
@@ -496,7 +497,7 @@ static int bond_ipsec_add_sa(struct xfrm_state *xs,
        }
 
        xs->xso.real_dev = real_dev;
-       err = real_dev->xfrmdev_ops->xdo_dev_state_add(xs, extack);
+       err = real_dev->xfrmdev_ops->xdo_dev_state_add(real_dev, xs, extack);
        if (!err) {
                ipsec->xs = xs;
                INIT_LIST_HEAD(&ipsec->list);
@@ -540,7 +541,8 @@ static void bond_ipsec_add_sa_all(struct bonding *bond)
                        continue;
 
                ipsec->xs->xso.real_dev = real_dev;
-               if (real_dev->xfrmdev_ops->xdo_dev_state_add(ipsec->xs, NULL)) {
+               if (real_dev->xfrmdev_ops->xdo_dev_state_add(real_dev,
+                                                            ipsec->xs, NULL)) {
                        slave_warn(bond_dev, real_dev, "%s: failed to add SA\n", __func__);
                        ipsec->xs->xso.real_dev = NULL;
                }
@@ -551,11 +553,12 @@ out:
 
 /**
  * bond_ipsec_del_sa - clear out this specific SA
+ * @bond_dev: pointer to the bond net device
  * @xs: pointer to transformer state struct
  **/
-static void bond_ipsec_del_sa(struct xfrm_state *xs)
+static void bond_ipsec_del_sa(struct net_device *bond_dev,
+                             struct xfrm_state *xs)
 {
-       struct net_device *bond_dev = xs->xso.dev;
        struct net_device *real_dev;
        netdevice_tracker tracker;
        struct bond_ipsec *ipsec;
@@ -587,7 +590,7 @@ static void bond_ipsec_del_sa(struct xfrm_state *xs)
                goto out;
        }
 
-       real_dev->xfrmdev_ops->xdo_dev_state_delete(xs);
+       real_dev->xfrmdev_ops->xdo_dev_state_delete(real_dev, xs);
 out:
        netdev_put(real_dev, &tracker);
        mutex_lock(&bond->ipsec_lock);
@@ -624,18 +627,20 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
                        slave_warn(bond_dev, real_dev,
                                   "%s: no slave xdo_dev_state_delete\n",
                                   __func__);
-               } else {
-                       real_dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
-                       if (real_dev->xfrmdev_ops->xdo_dev_state_free)
-                               real_dev->xfrmdev_ops->xdo_dev_state_free(ipsec->xs);
+                       continue;
                }
+               real_dev->xfrmdev_ops->xdo_dev_state_delete(real_dev,
+                                                           ipsec->xs);
+               if (real_dev->xfrmdev_ops->xdo_dev_state_free)
+                       real_dev->xfrmdev_ops->xdo_dev_state_free(real_dev,
+                                                                 ipsec->xs);
        }
        mutex_unlock(&bond->ipsec_lock);
 }
 
-static void bond_ipsec_free_sa(struct xfrm_state *xs)
+static void bond_ipsec_free_sa(struct net_device *bond_dev,
+                              struct xfrm_state *xs)
 {
-       struct net_device *bond_dev = xs->xso.dev;
        struct net_device *real_dev;
        netdevice_tracker tracker;
        struct bonding *bond;
@@ -661,7 +666,7 @@ static void bond_ipsec_free_sa(struct xfrm_state *xs)
 
        if (real_dev && real_dev->xfrmdev_ops &&
            real_dev->xfrmdev_ops->xdo_dev_state_free)
-               real_dev->xfrmdev_ops->xdo_dev_state_free(xs);
+               real_dev->xfrmdev_ops->xdo_dev_state_free(real_dev, xs);
 out:
        netdev_put(real_dev, &tracker);
 }
index 551c279dc14bed76f0bd0dac640a52247fc6af94..51395c96b2e9948a6369e6abed87fab6d0a3bd8c 100644 (file)
@@ -6480,10 +6480,11 @@ 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 net_device *dev,
+                               struct xfrm_state *x,
                                struct netlink_ext_ack *extack)
 {
-       struct adapter *adap = netdev2adap(x->xso.dev);
+       struct adapter *adap = netdev2adap(dev);
        int ret;
 
        if (!mutex_trylock(&uld_mutex)) {
@@ -6494,7 +6495,8 @@ 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, extack);
+       ret = adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_add(dev, x,
+                                                                       extack);
 
 out_unlock:
        mutex_unlock(&uld_mutex);
@@ -6502,9 +6504,9 @@ out_unlock:
        return ret;
 }
 
-static void cxgb4_xfrm_del_state(struct xfrm_state *x)
+static void cxgb4_xfrm_del_state(struct net_device *dev, struct xfrm_state *x)
 {
-       struct adapter *adap = netdev2adap(x->xso.dev);
+       struct adapter *adap = netdev2adap(dev);
 
        if (!mutex_trylock(&uld_mutex)) {
                dev_dbg(adap->pdev_dev,
@@ -6514,15 +6516,15 @@ static void cxgb4_xfrm_del_state(struct xfrm_state *x)
        if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
                goto out_unlock;
 
-       adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_delete(x);
+       adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_delete(dev, x);
 
 out_unlock:
        mutex_unlock(&uld_mutex);
 }
 
-static void cxgb4_xfrm_free_state(struct xfrm_state *x)
+static void cxgb4_xfrm_free_state(struct net_device *dev, struct xfrm_state *x)
 {
-       struct adapter *adap = netdev2adap(x->xso.dev);
+       struct adapter *adap = netdev2adap(dev);
 
        if (!mutex_trylock(&uld_mutex)) {
                dev_dbg(adap->pdev_dev,
@@ -6532,7 +6534,7 @@ static void cxgb4_xfrm_free_state(struct xfrm_state *x)
        if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
                goto out_unlock;
 
-       adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_free(x);
+       adap->uld[CXGB4_ULD_IPSEC].xfrmdev_ops->xdo_dev_state_free(dev, x);
 
 out_unlock:
        mutex_unlock(&uld_mutex);
index baba96883f48b57ad52379dae7295338ad56650b..ecd9a0bd5e18222a153c231cf6f886d1fcb72cfd 100644 (file)
@@ -75,9 +75,12 @@ static int ch_ipsec_uld_state_change(void *handle, enum cxgb4_state new_state);
 static int ch_ipsec_xmit(struct sk_buff *skb, struct net_device *dev);
 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 void ch_ipsec_xfrm_free_state(struct net_device *dev,
+                                    struct xfrm_state *x);
+static void ch_ipsec_xfrm_del_state(struct net_device *dev,
+                                   struct xfrm_state *x);
+static int ch_ipsec_xfrm_add_state(struct net_device *dev,
+                                  struct xfrm_state *x,
                                   struct netlink_ext_ack *extack);
 
 static const struct xfrmdev_ops ch_ipsec_xfrmdev_ops = {
@@ -223,7 +226,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 net_device *dev,
+                                  struct xfrm_state *x,
                                   struct netlink_ext_ack *extack)
 {
        struct ipsec_sa_entry *sa_entry;
@@ -302,14 +306,16 @@ out:
        return res;
 }
 
-static void ch_ipsec_xfrm_del_state(struct xfrm_state *x)
+static void ch_ipsec_xfrm_del_state(struct net_device *dev,
+                                   struct xfrm_state *x)
 {
        /* do nothing */
        if (!x->xso.offload_handle)
                return;
 }
 
-static void ch_ipsec_xfrm_free_state(struct xfrm_state *x)
+static void ch_ipsec_xfrm_free_state(struct net_device *dev,
+                                    struct xfrm_state *x)
 {
        struct ipsec_sa_entry *sa_entry;
 
index 07ea1954a276ed96837a0283ec5f8eb0dc125fa8..796e90d741f022e60ab16e66662434bac904a4c4 100644 (file)
@@ -9,7 +9,7 @@
 #define IXGBE_IPSEC_KEY_BITS  160
 static const char aes_gcm_name[] = "rfc4106(gcm(aes))";
 
-static void ixgbe_ipsec_del_sa(struct xfrm_state *xs);
+static void ixgbe_ipsec_del_sa(struct net_device *dev, struct xfrm_state *xs);
 
 /**
  * ixgbe_ipsec_set_tx_sa - set the Tx SA registers
@@ -321,7 +321,7 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
 
                if (r->used) {
                        if (r->mode & IXGBE_RXTXMOD_VF)
-                               ixgbe_ipsec_del_sa(r->xs);
+                               ixgbe_ipsec_del_sa(adapter->netdev, r->xs);
                        else
                                ixgbe_ipsec_set_rx_sa(hw, i, r->xs->id.spi,
                                                      r->key, r->salt,
@@ -330,7 +330,7 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
 
                if (t->used) {
                        if (t->mode & IXGBE_RXTXMOD_VF)
-                               ixgbe_ipsec_del_sa(t->xs);
+                               ixgbe_ipsec_del_sa(adapter->netdev, t->xs);
                        else
                                ixgbe_ipsec_set_tx_sa(hw, i, t->key, t->salt);
                }
@@ -417,6 +417,7 @@ static struct xfrm_state *ixgbe_ipsec_find_rx_state(struct ixgbe_ipsec *ipsec,
 
 /**
  * ixgbe_ipsec_parse_proto_keys - find the key and salt based on the protocol
+ * @dev: pointer to net device
  * @xs: pointer to xfrm_state struct
  * @mykey: pointer to key array to populate
  * @mysalt: pointer to salt value to populate
@@ -424,10 +425,10 @@ static struct xfrm_state *ixgbe_ipsec_find_rx_state(struct ixgbe_ipsec *ipsec,
  * This copies the protocol keys and salt to our own data tables.  The
  * 82599 family only supports the one algorithm.
  **/
-static int ixgbe_ipsec_parse_proto_keys(struct xfrm_state *xs,
+static int ixgbe_ipsec_parse_proto_keys(struct net_device *dev,
+                                       struct xfrm_state *xs,
                                        u32 *mykey, u32 *mysalt)
 {
-       struct net_device *dev = xs->xso.real_dev;
        unsigned char *key_data;
        char *alg_name = NULL;
        int key_len;
@@ -473,11 +474,12 @@ static int ixgbe_ipsec_parse_proto_keys(struct xfrm_state *xs,
 
 /**
  * ixgbe_ipsec_check_mgmt_ip - make sure there is no clash with mgmt IP filters
+ * @dev: pointer to net device
  * @xs: pointer to transformer state struct
  **/
-static int ixgbe_ipsec_check_mgmt_ip(struct xfrm_state *xs)
+static int ixgbe_ipsec_check_mgmt_ip(struct net_device *dev,
+                                    struct xfrm_state *xs)
 {
-       struct net_device *dev = xs->xso.real_dev;
        struct ixgbe_adapter *adapter = netdev_priv(dev);
        struct ixgbe_hw *hw = &adapter->hw;
        u32 mfval, manc, reg;
@@ -556,13 +558,14 @@ static int ixgbe_ipsec_check_mgmt_ip(struct xfrm_state *xs)
 
 /**
  * ixgbe_ipsec_add_sa - program device with a security association
+ * @dev: pointer to device to program
  * @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 net_device *dev,
+                             struct xfrm_state *xs,
                              struct netlink_ext_ack *extack)
 {
-       struct net_device *dev = xs->xso.real_dev;
        struct ixgbe_adapter *adapter = netdev_priv(dev);
        struct ixgbe_ipsec *ipsec = adapter->ipsec;
        struct ixgbe_hw *hw = &adapter->hw;
@@ -581,7 +584,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs,
                return -EINVAL;
        }
 
-       if (ixgbe_ipsec_check_mgmt_ip(xs)) {
+       if (ixgbe_ipsec_check_mgmt_ip(dev, xs)) {
                NL_SET_ERR_MSG_MOD(extack, "IPsec IP addr clash with mgmt filters");
                return -EINVAL;
        }
@@ -615,7 +618,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs,
                        rsa.decrypt = xs->ealg || xs->aead;
 
                /* get the key and salt */
-               ret = ixgbe_ipsec_parse_proto_keys(xs, rsa.key, &rsa.salt);
+               ret = ixgbe_ipsec_parse_proto_keys(dev, xs, rsa.key, &rsa.salt);
                if (ret) {
                        NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Rx SA table");
                        return ret;
@@ -724,7 +727,7 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs,
                if (xs->id.proto & IPPROTO_ESP)
                        tsa.encrypt = xs->ealg || xs->aead;
 
-               ret = ixgbe_ipsec_parse_proto_keys(xs, tsa.key, &tsa.salt);
+               ret = ixgbe_ipsec_parse_proto_keys(dev, xs, tsa.key, &tsa.salt);
                if (ret) {
                        NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Tx SA table");
                        memset(&tsa, 0, sizeof(tsa));
@@ -752,11 +755,11 @@ static int ixgbe_ipsec_add_sa(struct xfrm_state *xs,
 
 /**
  * ixgbe_ipsec_del_sa - clear out this specific SA
+ * @dev: pointer to device to program
  * @xs: pointer to transformer state struct
  **/
-static void ixgbe_ipsec_del_sa(struct xfrm_state *xs)
+static void ixgbe_ipsec_del_sa(struct net_device *dev, struct xfrm_state *xs)
 {
-       struct net_device *dev = xs->xso.real_dev;
        struct ixgbe_adapter *adapter = netdev_priv(dev);
        struct ixgbe_ipsec *ipsec = adapter->ipsec;
        struct ixgbe_hw *hw = &adapter->hw;
@@ -841,7 +844,8 @@ void ixgbe_ipsec_vf_clear(struct ixgbe_adapter *adapter, u32 vf)
                        continue;
                if (ipsec->rx_tbl[i].mode & IXGBE_RXTXMOD_VF &&
                    ipsec->rx_tbl[i].vf == vf)
-                       ixgbe_ipsec_del_sa(ipsec->rx_tbl[i].xs);
+                       ixgbe_ipsec_del_sa(adapter->netdev,
+                                          ipsec->rx_tbl[i].xs);
        }
 
        /* search tx sa table */
@@ -850,7 +854,8 @@ void ixgbe_ipsec_vf_clear(struct ixgbe_adapter *adapter, u32 vf)
                        continue;
                if (ipsec->tx_tbl[i].mode & IXGBE_RXTXMOD_VF &&
                    ipsec->tx_tbl[i].vf == vf)
-                       ixgbe_ipsec_del_sa(ipsec->tx_tbl[i].xs);
+                       ixgbe_ipsec_del_sa(adapter->netdev,
+                                          ipsec->tx_tbl[i].xs);
        }
 }
 
@@ -930,7 +935,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, NULL);
+       err = ixgbe_ipsec_add_sa(adapter->netdev, xs, NULL);
        if (err)
                goto err_aead;
 
@@ -1034,7 +1039,7 @@ int ixgbe_ipsec_vf_del_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
                xs = ipsec->tx_tbl[sa_idx].xs;
        }
 
-       ixgbe_ipsec_del_sa(xs);
+       ixgbe_ipsec_del_sa(adapter->netdev, xs);
 
        /* remove the xs that was made-up in the add request */
        kfree_sensitive(xs);
index 8ba037e3d9c270d3ab6fe19f6fe50003973e249b..65580b9cb06f217f6dd7adffc6f409baa655d164 100644 (file)
@@ -201,6 +201,7 @@ struct xfrm_state *ixgbevf_ipsec_find_rx_state(struct ixgbevf_ipsec *ipsec,
 
 /**
  * ixgbevf_ipsec_parse_proto_keys - find the key and salt based on the protocol
+ * @dev: pointer to net device to program
  * @xs: pointer to xfrm_state struct
  * @mykey: pointer to key array to populate
  * @mysalt: pointer to salt value to populate
@@ -208,10 +209,10 @@ struct xfrm_state *ixgbevf_ipsec_find_rx_state(struct ixgbevf_ipsec *ipsec,
  * This copies the protocol keys and salt to our own data tables.  The
  * 82599 family only supports the one algorithm.
  **/
-static int ixgbevf_ipsec_parse_proto_keys(struct xfrm_state *xs,
+static int ixgbevf_ipsec_parse_proto_keys(struct net_device *dev,
+                                         struct xfrm_state *xs,
                                          u32 *mykey, u32 *mysalt)
 {
-       struct net_device *dev = xs->xso.real_dev;
        unsigned char *key_data;
        char *alg_name = NULL;
        int key_len;
@@ -256,13 +257,14 @@ static int ixgbevf_ipsec_parse_proto_keys(struct xfrm_state *xs,
 
 /**
  * ixgbevf_ipsec_add_sa - program device with a security association
+ * @dev: pointer to net device to program
  * @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 net_device *dev,
+                               struct xfrm_state *xs,
                                struct netlink_ext_ack *extack)
 {
-       struct net_device *dev = xs->xso.real_dev;
        struct ixgbevf_adapter *adapter;
        struct ixgbevf_ipsec *ipsec;
        u16 sa_idx;
@@ -310,7 +312,8 @@ static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs,
                        rsa.decrypt = xs->ealg || xs->aead;
 
                /* get the key and salt */
-               ret = ixgbevf_ipsec_parse_proto_keys(xs, rsa.key, &rsa.salt);
+               ret = ixgbevf_ipsec_parse_proto_keys(dev, xs, rsa.key,
+                                                    &rsa.salt);
                if (ret) {
                        NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Rx SA table");
                        return ret;
@@ -363,7 +366,8 @@ static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs,
                if (xs->id.proto & IPPROTO_ESP)
                        tsa.encrypt = xs->ealg || xs->aead;
 
-               ret = ixgbevf_ipsec_parse_proto_keys(xs, tsa.key, &tsa.salt);
+               ret = ixgbevf_ipsec_parse_proto_keys(dev, xs, tsa.key,
+                                                    &tsa.salt);
                if (ret) {
                        NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Tx SA table");
                        memset(&tsa, 0, sizeof(tsa));
@@ -388,11 +392,12 @@ static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs,
 
 /**
  * ixgbevf_ipsec_del_sa - clear out this specific SA
+ * @dev: pointer to net device to program
  * @xs: pointer to transformer state struct
  **/
-static void ixgbevf_ipsec_del_sa(struct xfrm_state *xs)
+static void ixgbevf_ipsec_del_sa(struct net_device *dev,
+                                struct xfrm_state *xs)
 {
-       struct net_device *dev = xs->xso.real_dev;
        struct ixgbevf_adapter *adapter;
        struct ixgbevf_ipsec *ipsec;
        u16 sa_idx;
index fc59e50bafce668b50040f0fbefefe54bed11210..a6500e3673f248f6f75d6e81d5915d7d9cade789 100644 (file)
@@ -663,10 +663,10 @@ static int cn10k_ipsec_inb_add_state(struct xfrm_state *x,
        return -EOPNOTSUPP;
 }
 
-static int cn10k_ipsec_outb_add_state(struct xfrm_state *x,
+static int cn10k_ipsec_outb_add_state(struct net_device *dev,
+                                     struct xfrm_state *x,
                                      struct netlink_ext_ack *extack)
 {
-       struct net_device *netdev = x->xso.dev;
        struct cn10k_tx_sa_s *sa_entry;
        struct qmem *sa_info;
        struct otx2_nic *pf;
@@ -676,7 +676,7 @@ static int cn10k_ipsec_outb_add_state(struct xfrm_state *x,
        if (err)
                return err;
 
-       pf = netdev_priv(netdev);
+       pf = netdev_priv(dev);
 
        err = qmem_alloc(pf->dev, &sa_info, pf->ipsec.sa_size, OTX2_ALIGN);
        if (err)
@@ -700,18 +700,18 @@ static int cn10k_ipsec_outb_add_state(struct xfrm_state *x,
        return 0;
 }
 
-static int cn10k_ipsec_add_state(struct xfrm_state *x,
+static int cn10k_ipsec_add_state(struct net_device *dev,
+                                struct xfrm_state *x,
                                 struct netlink_ext_ack *extack)
 {
        if (x->xso.dir == XFRM_DEV_OFFLOAD_IN)
                return cn10k_ipsec_inb_add_state(x, extack);
        else
-               return cn10k_ipsec_outb_add_state(x, extack);
+               return cn10k_ipsec_outb_add_state(dev, x, extack);
 }
 
-static void cn10k_ipsec_del_state(struct xfrm_state *x)
+static void cn10k_ipsec_del_state(struct net_device *dev, struct xfrm_state *x)
 {
-       struct net_device *netdev = x->xso.dev;
        struct cn10k_tx_sa_s *sa_entry;
        struct qmem *sa_info;
        struct otx2_nic *pf;
@@ -720,7 +720,7 @@ static void cn10k_ipsec_del_state(struct xfrm_state *x)
        if (x->xso.dir == XFRM_DEV_OFFLOAD_IN)
                return;
 
-       pf = netdev_priv(netdev);
+       pf = netdev_priv(dev);
 
        sa_info = (struct qmem *)x->xso.offload_handle;
        sa_entry = (struct cn10k_tx_sa_s *)sa_info->base;
@@ -732,7 +732,7 @@ static void cn10k_ipsec_del_state(struct xfrm_state *x)
 
        err = cn10k_outb_write_sa(pf, sa_info);
        if (err)
-               netdev_err(netdev, "Error (%d) deleting SA\n", err);
+               netdev_err(dev, "Error (%d) deleting SA\n", err);
 
        x->xso.offload_handle = 0;
        qmem_free(pf->dev, sa_info);
index 0dfbbe21936f31057a961122fa0730e7e4ce8561..77f61cd28a7993feb9d9ef4e46dbbcf3536cc597 100644 (file)
@@ -689,17 +689,17 @@ static int mlx5e_ipsec_create_dwork(struct mlx5e_ipsec_sa_entry *sa_entry)
        return 0;
 }
 
-static int mlx5e_xfrm_add_state(struct xfrm_state *x,
+static int mlx5e_xfrm_add_state(struct net_device *dev,
+                               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;
        struct mlx5e_ipsec *ipsec;
        struct mlx5e_priv *priv;
        gfp_t gfp;
        int err;
 
-       priv = netdev_priv(netdev);
+       priv = netdev_priv(dev);
        if (!priv->ipsec)
                return -EOPNOTSUPP;
 
@@ -710,7 +710,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
                return -ENOMEM;
 
        sa_entry->x = x;
-       sa_entry->dev = netdev;
+       sa_entry->dev = dev;
        sa_entry->ipsec = ipsec;
        /* Check if this SA is originated from acquire flow temporary SA */
        if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ)
@@ -807,7 +807,7 @@ err_xfrm:
        return err;
 }
 
-static void mlx5e_xfrm_del_state(struct xfrm_state *x)
+static void mlx5e_xfrm_del_state(struct net_device *dev, struct xfrm_state *x)
 {
        struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
        struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
@@ -820,7 +820,7 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
        WARN_ON(old != sa_entry);
 }
 
-static void mlx5e_xfrm_free_state(struct xfrm_state *x)
+static void mlx5e_xfrm_free_state(struct net_device *dev, struct xfrm_state *x)
 {
        struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
        struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
index 671af5d4c5d25c1385cfb6ceb968acb9f1fe1b9e..9e7c285eaa6bca554eaa84c0b988d45f56fd8c7a 100644 (file)
@@ -266,17 +266,17 @@ 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 net_device *dev,
+                                 struct xfrm_state *x,
                                  struct netlink_ext_ack *extack)
 {
-       struct net_device *netdev = x->xso.real_dev;
        struct nfp_ipsec_cfg_mssg msg = {};
        int i, key_len, trunc_len, err = 0;
        struct nfp_ipsec_cfg_add_sa *cfg;
        struct nfp_net *nn;
        unsigned int saidx;
 
-       nn = netdev_priv(netdev);
+       nn = netdev_priv(dev);
        cfg = &msg.cfg_add_sa;
 
        /* General */
@@ -546,17 +546,16 @@ static int nfp_net_xfrm_add_state(struct xfrm_state *x,
        return 0;
 }
 
-static void nfp_net_xfrm_del_state(struct xfrm_state *x)
+static void nfp_net_xfrm_del_state(struct net_device *dev, struct xfrm_state *x)
 {
        struct nfp_ipsec_cfg_mssg msg = {
                .cmd = NFP_IPSEC_CFG_MSSG_INV_SA,
                .sa_idx = x->xso.offload_handle - 1,
        };
-       struct net_device *netdev = x->xso.real_dev;
        struct nfp_net *nn;
        int err;
 
-       nn = netdev_priv(netdev);
+       nn = netdev_priv(dev);
        err = nfp_net_sched_mbox_amsg_work(nn, NFP_NET_CFG_MBOX_CMD_IPSEC, &msg,
                                           sizeof(msg), nfp_net_ipsec_cfg);
        if (err)
index d88bdb9a17176a3af556e357ce41aade0991e743..47cdee5577d461008c884e2428e914be81569a95 100644 (file)
@@ -85,11 +85,11 @@ static int nsim_ipsec_find_empty_idx(struct nsim_ipsec *ipsec)
        return -ENOSPC;
 }
 
-static int nsim_ipsec_parse_proto_keys(struct xfrm_state *xs,
+static int nsim_ipsec_parse_proto_keys(struct net_device *dev,
+                                      struct xfrm_state *xs,
                                       u32 *mykey, u32 *mysalt)
 {
        const char aes_gcm_name[] = "rfc4106(gcm(aes))";
-       struct net_device *dev = xs->xso.real_dev;
        unsigned char *key_data;
        char *alg_name = NULL;
        int key_len;
@@ -129,17 +129,16 @@ 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 net_device *dev,
+                            struct xfrm_state *xs,
                             struct netlink_ext_ack *extack)
 {
        struct nsim_ipsec *ipsec;
-       struct net_device *dev;
        struct netdevsim *ns;
        struct nsim_sa sa;
        u16 sa_idx;
        int ret;
 
-       dev = xs->xso.real_dev;
        ns = netdev_priv(dev);
        ipsec = &ns->ipsec;
 
@@ -174,7 +173,7 @@ static int nsim_ipsec_add_sa(struct xfrm_state *xs,
                sa.crypt = xs->ealg || xs->aead;
 
        /* get the key and salt */
-       ret = nsim_ipsec_parse_proto_keys(xs, sa.key, &sa.salt);
+       ret = nsim_ipsec_parse_proto_keys(dev, xs, sa.key, &sa.salt);
        if (ret) {
                NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for SA table");
                return ret;
@@ -200,9 +199,9 @@ static int nsim_ipsec_add_sa(struct xfrm_state *xs,
        return 0;
 }
 
-static void nsim_ipsec_del_sa(struct xfrm_state *xs)
+static void nsim_ipsec_del_sa(struct net_device *dev, struct xfrm_state *xs)
 {
-       struct netdevsim *ns = netdev_priv(xs->xso.real_dev);
+       struct netdevsim *ns = netdev_priv(dev);
        struct nsim_ipsec *ipsec = &ns->ipsec;
        u16 sa_idx;
 
index d8544f6a680cd5e5bd6c64265813a7d4a09fe37a..88dfb8aeed3c8add4a071c0003dfe109f62e8803 100644 (file)
@@ -1013,9 +1013,13 @@ struct netdev_bpf {
 
 #ifdef CONFIG_XFRM_OFFLOAD
 struct xfrmdev_ops {
-       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);
+       int     (*xdo_dev_state_add)(struct net_device *dev,
+                                    struct xfrm_state *x,
+                                    struct netlink_ext_ack *extack);
+       void    (*xdo_dev_state_delete)(struct net_device *dev,
+                                       struct xfrm_state *x);
+       void    (*xdo_dev_state_free)(struct net_device *dev,
+                                     struct xfrm_state *x);
        bool    (*xdo_dev_offload_ok) (struct sk_buff *skb,
                                       struct xfrm_state *x);
        void    (*xdo_dev_state_advance_esn) (struct xfrm_state *x);
index 39365fd2ea175ca307ad71a71d1b1ce8952b4d90..3d2f6c8793114fa8ae85c83f79e64b1fc9daf782 100644 (file)
@@ -147,8 +147,16 @@ enum {
 };
 
 struct xfrm_dev_offload {
+       /* The device for this offload.
+        * Device drivers should not use this directly, as that will prevent
+        * them from working with bonding device. Instead, the device passed
+        * to the add/delete callbacks should be used.
+        */
        struct net_device       *dev;
        netdevice_tracker       dev_tracker;
+       /* This is a private pointer used by the bonding driver.
+        * Device drivers should not use it.
+        */
        struct net_device       *real_dev;
        unsigned long           offload_handle;
        u8                      dir : 2;
index 0be5f7ffd019588ec2d71026f6bd19ace7ea0bac..3be0139373f75b947e39207331ba2a91d26156d4 100644 (file)
@@ -309,7 +309,6 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
 
        xso->dev = dev;
        netdev_tracker_alloc(dev, &xso->dev_tracker, GFP_ATOMIC);
-       xso->real_dev = dev;
 
        if (xuo->flags & XFRM_OFFLOAD_INBOUND)
                xso->dir = XFRM_DEV_OFFLOAD_IN;
@@ -321,11 +320,10 @@ 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, extack);
+       err = dev->xfrmdev_ops->xdo_dev_state_add(dev, x, extack);
        if (err) {
                xso->dev = NULL;
                xso->dir = 0;
-               xso->real_dev = NULL;
                netdev_put(dev, &xso->dev_tracker);
                xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
 
index d67420e7638911e3098ddc828eeb250a76afc4e8..3c2e27e5a1e3863329ff8ff54c1477d686a04cd5 100644 (file)
@@ -767,7 +767,7 @@ void xfrm_dev_state_delete(struct xfrm_state *x)
        struct net_device *dev = READ_ONCE(xso->dev);
 
        if (dev) {
-               dev->xfrmdev_ops->xdo_dev_state_delete(x);
+               dev->xfrmdev_ops->xdo_dev_state_delete(dev, x);
                spin_lock_bh(&xfrm_state_dev_gc_lock);
                hlist_add_head(&x->dev_gclist, &xfrm_state_dev_gc_list);
                spin_unlock_bh(&xfrm_state_dev_gc_lock);
@@ -789,7 +789,7 @@ void xfrm_dev_state_free(struct xfrm_state *x)
                spin_unlock_bh(&xfrm_state_dev_gc_lock);
 
                if (dev->xfrmdev_ops->xdo_dev_state_free)
-                       dev->xfrmdev_ops->xdo_dev_state_free(x);
+                       dev->xfrmdev_ops->xdo_dev_state_free(dev, x);
                WRITE_ONCE(xso->dev, NULL);
                xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
                netdev_put(dev, &xso->dev_tracker);
@@ -1551,16 +1551,18 @@ found:
                if (pol->xdo.type == XFRM_DEV_OFFLOAD_PACKET) {
                        struct xfrm_dev_offload *xdo = &pol->xdo;
                        struct xfrm_dev_offload *xso = &x->xso;
+                       struct net_device *dev = xdo->dev;
 
                        xso->type = XFRM_DEV_OFFLOAD_PACKET;
                        xso->dir = xdo->dir;
-                       xso->dev = xdo->dev;
+                       xso->dev = dev;
                        xso->flags = XFRM_DEV_OFFLOAD_FLAG_ACQ;
-                       netdev_hold(xso->dev, &xso->dev_tracker, GFP_ATOMIC);
-                       error = xso->dev->xfrmdev_ops->xdo_dev_state_add(x, NULL);
+                       netdev_hold(dev, &xso->dev_tracker, GFP_ATOMIC);
+                       error = dev->xfrmdev_ops->xdo_dev_state_add(dev, x,
+                                                                   NULL);
                        if (error) {
                                xso->dir = 0;
-                               netdev_put(xso->dev, &xso->dev_tracker);
+                               netdev_put(dev, &xso->dev_tracker);
                                xso->dev = NULL;
                                xso->type = XFRM_DEV_OFFLOAD_UNSPECIFIED;
                                x->km.state = XFRM_STATE_DEAD;