devlink: Expose port function commands to control IPsec crypto offloads
authorDima Chumak <dchumak@nvidia.com>
Fri, 25 Aug 2023 06:28:29 +0000 (23:28 -0700)
committerJakub Kicinski <kuba@kernel.org>
Mon, 28 Aug 2023 00:08:44 +0000 (17:08 -0700)
Expose port function commands to enable / disable IPsec crypto offloads,
this is used to control the port IPsec capabilities.

When IPsec crypto is disabled for a function of the port (default),
function cannot offload any IPsec crypto operations (Encrypt/Decrypt and
XFRM state offloading). When enabled, IPsec crypto operations can be
offloaded by the function of the port.

Example of a PCI VF port which supports IPsec crypto offloads:

$ devlink port show pci/0000:06:00.0/1
    pci/0000:06:00.0/1: type eth netdev enp6s0pf0vf0 flavour pcivf pfnum 0 vfnum 0
        function:
        hw_addr 00:00:00:00:00:00 roce enable ipsec_crypto disable

$ devlink port function set pci/0000:06:00.0/1 ipsec_crypto enable

$ devlink port show pci/0000:06:00.0/1
    pci/0000:06:00.0/1: type eth netdev enp6s0pf0vf0 flavour pcivf pfnum 0 vfnum 0
        function:
        hw_addr 00:00:00:00:00:00 roce enable ipsec_crypto enable

Signed-off-by: Dima Chumak <dchumak@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Link: https://lore.kernel.org/r/20230825062836.103744-2-saeed@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Documentation/networking/devlink/devlink-port.rst
include/net/devlink.h
include/uapi/linux/devlink.h
net/devlink/leftover.c

index 3da5909..6983b11 100644 (file)
@@ -128,6 +128,9 @@ Users may also set the RoCE capability of the function using
 Users may also set the function as migratable using
 'devlink port function set migratable' command.
 
+Users may also set the IPsec crypto capability of the function using
+`devlink port function set ipsec_crypto` command.
+
 Function attributes
 ===================
 
@@ -240,6 +243,30 @@ Attach VF to the VM.
 Start the VM.
 Perform live migration.
 
+IPsec crypto capability setup
+-----------------------------
+When user enables IPsec crypto capability for a VF, user application can offload
+XFRM state crypto operation (Encrypt/Decrypt) to this VF.
+
+When IPsec crypto capability is disabled (default) for a VF, the XFRM state is
+processed in software by the kernel.
+
+- Get IPsec crypto capability of the VF device::
+
+    $ devlink port show pci/0000:06:00.0/2
+    pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1
+        function:
+            hw_addr 00:00:00:00:00:00 ipsec_crypto disabled
+
+- Set IPsec crypto capability of the VF device::
+
+    $ devlink port function set pci/0000:06:00.0/2 ipsec_crypto enable
+
+    $ devlink port show pci/0000:06:00.0/2
+    pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1
+        function:
+            hw_addr 00:00:00:00:00:00 ipsec_crypto enabled
+
 Subfunction
 ============
 
index f7fec07..1cf07a8 100644 (file)
@@ -1583,6 +1583,15 @@ void devlink_free(struct devlink *devlink);
  *                    Should be used by device drivers set
  *                    the admin state of a function managed
  *                    by the devlink port.
+ * @port_fn_ipsec_crypto_get: Callback used to get port function's ipsec_crypto
+ *                           capability. Should be used by device drivers
+ *                           to report the current state of ipsec_crypto
+ *                           capability of a function managed by the devlink
+ *                           port.
+ * @port_fn_ipsec_crypto_set: Callback used to set port function's ipsec_crypto
+ *                           capability. Should be used by device drivers to
+ *                           enable/disable ipsec_crypto capability of a
+ *                           function managed by the devlink port.
  *
  * Note: Driver should return -EOPNOTSUPP if it doesn't support
  * port function (@port_fn_*) handling for a particular port.
@@ -1620,6 +1629,12 @@ struct devlink_port_ops {
        int (*port_fn_state_set)(struct devlink_port *port,
                                 enum devlink_port_fn_state state,
                                 struct netlink_ext_ack *extack);
+       int (*port_fn_ipsec_crypto_get)(struct devlink_port *devlink_port,
+                                       bool *is_enable,
+                                       struct netlink_ext_ack *extack);
+       int (*port_fn_ipsec_crypto_set)(struct devlink_port *devlink_port,
+                                       bool enable,
+                                       struct netlink_ext_ack *extack);
 };
 
 void devlink_port_init(struct devlink *devlink,
index 3782d42..f9ae9a0 100644 (file)
@@ -661,6 +661,7 @@ enum devlink_resource_unit {
 enum devlink_port_fn_attr_cap {
        DEVLINK_PORT_FN_ATTR_CAP_ROCE_BIT,
        DEVLINK_PORT_FN_ATTR_CAP_MIGRATABLE_BIT,
+       DEVLINK_PORT_FN_ATTR_CAP_IPSEC_CRYPTO_BIT,
 
        /* Add new caps above */
        __DEVLINK_PORT_FN_ATTR_CAPS_MAX,
@@ -669,6 +670,7 @@ enum devlink_port_fn_attr_cap {
 #define DEVLINK_PORT_FN_CAP_ROCE _BITUL(DEVLINK_PORT_FN_ATTR_CAP_ROCE_BIT)
 #define DEVLINK_PORT_FN_CAP_MIGRATABLE \
        _BITUL(DEVLINK_PORT_FN_ATTR_CAP_MIGRATABLE_BIT)
+#define DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO _BITUL(DEVLINK_PORT_FN_ATTR_CAP_IPSEC_CRYPTO_BIT)
 
 enum devlink_port_function_attr {
        DEVLINK_PORT_FUNCTION_ATTR_UNSPEC,
index e2cd139..fcc1a06 100644 (file)
@@ -492,6 +492,28 @@ static int devlink_port_fn_migratable_fill(struct devlink_port *devlink_port,
        return 0;
 }
 
+static int devlink_port_fn_ipsec_crypto_fill(struct devlink_port *devlink_port,
+                                            struct nla_bitfield32 *caps,
+                                            struct netlink_ext_ack *extack)
+{
+       bool is_enable;
+       int err;
+
+       if (!devlink_port->ops->port_fn_ipsec_crypto_get ||
+           devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF)
+               return 0;
+
+       err = devlink_port->ops->port_fn_ipsec_crypto_get(devlink_port, &is_enable, extack);
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       return 0;
+               return err;
+       }
+
+       devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO, is_enable);
+       return 0;
+}
+
 static int devlink_port_fn_caps_fill(struct devlink_port *devlink_port,
                                     struct sk_buff *msg,
                                     struct netlink_ext_ack *extack,
@@ -508,6 +530,10 @@ static int devlink_port_fn_caps_fill(struct devlink_port *devlink_port,
        if (err)
                return err;
 
+       err = devlink_port_fn_ipsec_crypto_fill(devlink_port, &caps, extack);
+       if (err)
+               return err;
+
        if (!caps.selector)
                return 0;
        err = nla_put_bitfield32(msg, DEVLINK_PORT_FN_ATTR_CAPS, caps.value,
@@ -838,6 +864,13 @@ devlink_port_fn_roce_set(struct devlink_port *devlink_port, bool enable,
                                                   extack);
 }
 
+static int
+devlink_port_fn_ipsec_crypto_set(struct devlink_port *devlink_port, bool enable,
+                                struct netlink_ext_ack *extack)
+{
+       return devlink_port->ops->port_fn_ipsec_crypto_set(devlink_port, enable, extack);
+}
+
 static int devlink_port_fn_caps_set(struct devlink_port *devlink_port,
                                    const struct nlattr *attr,
                                    struct netlink_ext_ack *extack)
@@ -862,6 +895,13 @@ static int devlink_port_fn_caps_set(struct devlink_port *devlink_port,
                if (err)
                        return err;
        }
+       if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO) {
+               err = devlink_port_fn_ipsec_crypto_set(devlink_port, caps_value &
+                                                      DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO,
+                                                      extack);
+               if (err)
+                       return err;
+       }
        return 0;
 }
 
@@ -1226,6 +1266,18 @@ static int devlink_port_function_validate(struct devlink_port *devlink_port,
                                return -EOPNOTSUPP;
                        }
                }
+               if (caps.selector & DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO) {
+                       if (!ops->port_fn_ipsec_crypto_set) {
+                               NL_SET_ERR_MSG_ATTR(extack, attr,
+                                                   "Port doesn't support ipsec_crypto function attribute");
+                               return -EOPNOTSUPP;
+                       }
+                       if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) {
+                               NL_SET_ERR_MSG_ATTR(extack, attr,
+                                                   "ipsec_crypto function attribute supported for VFs only");
+                               return -EOPNOTSUPP;
+                       }
+               }
        }
        return 0;
 }