From patchwork Thu Jul 21 21:14:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 12925778 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 491D7C433EF for ; Thu, 21 Jul 2022 21:15:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233713AbiGUVP2 (ORCPT ); Thu, 21 Jul 2022 17:15:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35136 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233692AbiGUVPZ (ORCPT ); Thu, 21 Jul 2022 17:15:25 -0400 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0ECB45727C; Thu, 21 Jul 2022 14:15:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1658438124; x=1689974124; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IK8yIsQs7/XNlGpJ6DBi8pvczdjoYcwqHGzRs/YwapI=; b=Qgn2wq9XK+ZRsyzqOVVcZgAIkUO897dmD35/546AzMc5Vvl7ZCyXNCb0 pG8S+6uAlGtz88T+XxxtlpgdHIUN1PNtuwBCQG9iNNsM98TlrTeLgAHar u3lwD14eUJvfee0Vk7AYZa+kiUYRwZlCPS5sAvfNevOw689i6iJq5lUJE jmeXDHhpFJwmnx+fCeW+rJ5bsCDf7aczkeKrIocjtqqXBKpvPg6Oqed7p WBKUawVNDe7A5gxM3LGSPnTaDE/EGIQZsjvt1qJBHr0EMbrIdDtI+JCp3 M04+nIErhu2q8HwuwNG8ko7AHzUnB3WNAwWqIeTadJv84p3CwwKok5NvX w==; X-IronPort-AV: E=McAfee;i="6400,9594,10415"; a="312892762" X-IronPort-AV: E=Sophos;i="5.93,183,1654585200"; d="scan'208";a="312892762" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2022 14:14:59 -0700 X-IronPort-AV: E=Sophos;i="5.93,183,1654585200"; d="scan'208";a="925816182" Received: from jekeller-desk.amr.corp.intel.com ([10.166.241.7]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2022 14:14:58 -0700 From: Jacob Keller To: netdev@vger.kernel.org Cc: Jacob Keller , Jonathan Corbet , Jiri Pirko , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Tony Nguyen , David Ahern , Stephen Hemminger , linux-doc@vger.kernel.org, intel-wired-lan@lists.osuosl.org Subject: [net-next v2 1/2] devlink: add dry run attribute to flash update Date: Thu, 21 Jul 2022 14:14:46 -0700 Message-Id: <20220721211451.2475600-2-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.35.1.456.ga9c7032d4631 In-Reply-To: <20220721211451.2475600-1-jacob.e.keller@intel.com> References: <20220721211451.2475600-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Users use the devlink flash interface to request a device driver program or update the device flash chip. In some cases, a user (or script) may want to verify that a given flash update command is supported without actually committing to immediately updating the device. For example, a system administrator may want to validate that a particular flash binary image will be accepted by the device, or simply validate a command before finally committing to it. The current flash update interface lacks a method to support such a dry run. Add a new DEVLINK_ATTR_DRY_RUN attribute which shall be used by a devlink command to indicate that a request is a dry run which should not perform device configuration. Instead, the command should report whether the command or configuration request is valid. While we can validate the initial arguments of the devlink command, a proper dry run must be processed by the device driver. This is required because only the driver can perform validation of the flash binary file. Add a new dry_run parameter to the devlink_flash_update_params struct, along with the associated bit to indicate if a driver supports verifying a dry run. We always check the dry run attribute last in order to allow as much verification of other parameters as possible. For example, even if a driver does not support the dry_run option, we can still validate the other optional parameters such as the overwrite_mask and per-component update name. Document that userspace should take care when issuing a dry run to older kernels, as the flash update command is not strictly verified. Thus, unknown attributes will be ignored and this could cause a request for a dry run to perform an actual update. We can't fix old kernels to verify unknown attributes, but userspace can check the maximum attribute and reject the dry run request if it is not supported by the kernel. Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko --- Changes since v1: * Add kernel doc comments to devlink_flash_update_params * Reduce indentation by using nla_get_flag .../networking/devlink/devlink-flash.rst | 23 +++++++++++++++++++ include/net/devlink.h | 4 ++++ include/uapi/linux/devlink.h | 8 +++++++ net/core/devlink.c | 17 +++++++++++++- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/devlink/devlink-flash.rst b/Documentation/networking/devlink/devlink-flash.rst index 603e732f00cc..1dc373229a54 100644 --- a/Documentation/networking/devlink/devlink-flash.rst +++ b/Documentation/networking/devlink/devlink-flash.rst @@ -44,6 +44,29 @@ preserved across the update. A device may not support every combination and the driver for such a device must reject any combination which cannot be faithfully implemented. +Dry run +======= + +Users can request a "dry run" of a flash update by adding the +``DEVLINK_ATTR_DRY_RUN`` attribute to the ``DEVLINK_CMD_FLASH_UPDATE`` +command. If the attribute is present, the kernel will only verify that the +provided command is valid. During a dry run, an update is not performed. + +If supported by the driver, the flash image contents are also validated and +the driver may indicate whether the file is a valid flash image for the +device. + +.. code:: shell + + $ devlink dev flash pci/0000:af:00.0 file image.bin dry-run + Validating flash binary + +Note that user space should take care when adding this attribute. Older +kernels which do not recognize the attribute may accept the command with an +unknown attribute. This could lead to a request for a dry run which performs +an unexpected update. To avoid this, user space should check the policy dump +and verify that the attribute is recognized before adding it to the command. + Firmware Loading ================ diff --git a/include/net/devlink.h b/include/net/devlink.h index 780744b550b8..47b86ccb85b0 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -613,6 +613,8 @@ enum devlink_param_generic_id { * struct devlink_flash_update_params - Flash Update parameters * @fw: pointer to the firmware data to update from * @component: the flash component to update + * @overwrite_mask: what sections of flash can be overwritten + * @dry_run: if true, do not actually update the flash * * With the exception of fw, drivers must opt-in to parameters by * setting the appropriate bit in the supported_flash_update_params field in @@ -622,10 +624,12 @@ struct devlink_flash_update_params { const struct firmware *fw; const char *component; u32 overwrite_mask; + bool dry_run; }; #define DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT BIT(0) #define DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK BIT(1) +#define DEVLINK_SUPPORT_FLASH_UPDATE_DRY_RUN BIT(2) struct devlink_region; struct devlink_info_req; diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index b3d40a5d72ff..e24a5a808a12 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -576,6 +576,14 @@ enum devlink_attr { DEVLINK_ATTR_LINECARD_TYPE, /* string */ DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */ + /* Before adding this attribute to a command, user space should check + * the policy dump and verify the kernel recognizes the attribute. + * Otherwise older kernels which do not recognize the attribute may + * silently accept the unknown attribute while not actually performing + * a dry run. + */ + DEVLINK_ATTR_DRY_RUN, /* flag */ + /* add new attributes above here, update the policy in devlink.c */ __DEVLINK_ATTR_MAX, diff --git a/net/core/devlink.c b/net/core/devlink.c index 98d79feeb3dc..1cff636c9b2b 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4743,7 +4743,8 @@ EXPORT_SYMBOL_GPL(devlink_flash_update_timeout_notify); static int devlink_nl_cmd_flash_update(struct sk_buff *skb, struct genl_info *info) { - struct nlattr *nla_component, *nla_overwrite_mask, *nla_file_name; + struct nlattr *nla_component, *nla_overwrite_mask, *nla_file_name, + *nla_dry_run; struct devlink_flash_update_params params = {}; struct devlink *devlink = info->user_ptr[0]; const char *file_name; @@ -4789,6 +4790,19 @@ static int devlink_nl_cmd_flash_update(struct sk_buff *skb, return ret; } + /* Always check dry run last, in order to allow verification of other + * parameter support even if the particular driver does not yet + * support a full dry-run + */ + params.dry_run = nla_get_flag(info->attrs[DEVLINK_ATTR_DRY_RUN]); + if (params.dry_run && + !(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_DRY_RUN)) { + NL_SET_ERR_MSG_ATTR(info->extack, nla_dry_run, + "flash update is supported, but dry run is not supported for this device"); + release_firmware(params.fw); + return -EOPNOTSUPP; + } + devlink_flash_update_begin_notify(devlink); ret = devlink->ops->flash_update(devlink, ¶ms, info->extack); devlink_flash_update_end_notify(devlink); @@ -9004,6 +9018,7 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_RATE_PARENT_NODE_NAME] = { .type = NLA_NUL_STRING }, [DEVLINK_ATTR_LINECARD_INDEX] = { .type = NLA_U32 }, [DEVLINK_ATTR_LINECARD_TYPE] = { .type = NLA_NUL_STRING }, + [DEVLINK_ATTR_DRY_RUN] = { .type = NLA_FLAG }, }; static const struct genl_small_ops devlink_nl_ops[] = { From patchwork Thu Jul 21 21:14:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 12925779 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93820CCA48A for ; Thu, 21 Jul 2022 21:15:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233718AbiGUVP2 (ORCPT ); Thu, 21 Jul 2022 17:15:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35160 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233702AbiGUVP0 (ORCPT ); Thu, 21 Jul 2022 17:15:26 -0400 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1873258871; Thu, 21 Jul 2022 14:15:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1658438125; x=1689974125; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+b/gLo/Ell1uZ35XWmJYCy+/hdv/bRLcSSge8oMH/lY=; b=eUcdKYkTq73QXd4Rk4SPvNUuRww/oBoZ85a48yEHRnq0ncvwKnQC2+zf 0gN7qACFIT2mucDdGNzrKtWdpdpHhbzLrnOhPDGK01TfUXZLrU5Ds+tGO DzqmIIoO9YcQUAF8ZJvy5xrX56tR8ssKDTAnQyIGI2JmOlRTuaEFanfvN 7NMjtbCA5oPCcksH4h3RMZxGiyIOSCanrR+J6vhHgs/6FdSOTojP1EOWL fm3PqZQROZJvJTMfDN8Ya2YoDAGqsLTqs6bTbmnM+57zqnhy2MVjK4qdl jQ+yyKjcAF5iEyfXswSnhVezqmr6ZXoswtzVokF3LhJ3qXdlqMR3lokZQ g==; X-IronPort-AV: E=McAfee;i="6400,9594,10415"; a="312892768" X-IronPort-AV: E=Sophos;i="5.93,183,1654585200"; d="scan'208";a="312892768" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2022 14:14:59 -0700 X-IronPort-AV: E=Sophos;i="5.93,183,1654585200"; d="scan'208";a="925816194" Received: from jekeller-desk.amr.corp.intel.com ([10.166.241.7]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2022 14:14:59 -0700 From: Jacob Keller To: netdev@vger.kernel.org Cc: Jacob Keller , Jonathan Corbet , Jiri Pirko , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Tony Nguyen , David Ahern , Stephen Hemminger , linux-doc@vger.kernel.org, intel-wired-lan@lists.osuosl.org Subject: [net-next v2 2/2] ice: support dry run of a flash update to validate firmware file Date: Thu, 21 Jul 2022 14:14:47 -0700 Message-Id: <20220721211451.2475600-3-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.35.1.456.ga9c7032d4631 In-Reply-To: <20220721211451.2475600-1-jacob.e.keller@intel.com> References: <20220721211451.2475600-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Now that devlink core flash update can handle dry run requests, update the ice driver to allow validating a PLDM file in dry_run mode. First, add a new dry_run field to the pldmfw context structure. This indicates that the PLDM firmware file library should only validate the file and verify that it has a matching record. Update the pldmfw documentation to indicate this "dry run" mode. In the ice driver, let the stack know that we support the dry run attribute for flash update by setting the appropriate bit in the .supported_flash_update_params field. If the dry run is requested, notify the PLDM firmware library by setting the context bit appropriately. Don't cancel a pending update during a dry run. Signed-off-by: Jacob Keller --- Changes since v1: * Use u8 : 1 instead of bool in structure * Name the PLDMFW parameter validate Documentation/driver-api/pldmfw/index.rst | 10 ++++++++++ drivers/net/ethernet/intel/ice/ice_devlink.c | 3 ++- drivers/net/ethernet/intel/ice/ice_fw_update.c | 14 ++++++++++---- include/linux/pldmfw.h | 5 +++++ lib/pldmfw/pldmfw.c | 12 ++++++++++++ 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Documentation/driver-api/pldmfw/index.rst b/Documentation/driver-api/pldmfw/index.rst index ad2c33ece30f..454b3ed6576a 100644 --- a/Documentation/driver-api/pldmfw/index.rst +++ b/Documentation/driver-api/pldmfw/index.rst @@ -51,6 +51,16 @@ unaligned access of multi-byte fields, and to properly convert from Little Endian to CPU host format. Additionally the records, descriptors, and components are stored in linked lists. +Validating a PLDM firmware file +=============================== + +To simply validate a PLDM firmware file, and verify whether it applies to +the device, set the ``dry_run`` flag in the ``pldmfw`` context structure. +If this flag is set, the library will parse the file, validating its UUID +and checking if any record matches the device. Note that in a dry run, the +library will *not* issue any ops besides ``match_record``. It will not +attempt to send the component table or package data to the device firmware. + Performing a flash update ========================= diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c index 3337314a7b35..18214ea33e2d 100644 --- a/drivers/net/ethernet/intel/ice/ice_devlink.c +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c @@ -467,7 +467,8 @@ ice_devlink_reload_empr_finish(struct devlink *devlink, } static const struct devlink_ops ice_devlink_ops = { - .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK, + .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK | + DEVLINK_SUPPORT_FLASH_UPDATE_DRY_RUN, .reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), /* The ice driver currently does not support driver reinit */ .reload_down = ice_devlink_reload_empr_start, diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c b/drivers/net/ethernet/intel/ice/ice_fw_update.c index 3dc5662d62a6..d79e4536b440 100644 --- a/drivers/net/ethernet/intel/ice/ice_fw_update.c +++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c @@ -1015,15 +1015,21 @@ int ice_devlink_flash_update(struct devlink *devlink, else priv.context.ops = &ice_fwu_ops_e810; priv.context.dev = dev; + priv.context.validate = params->dry_run; priv.extack = extack; priv.pf = pf; priv.activate_flags = preservation; - devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0); + if (params->dry_run) + devlink_flash_update_status_notify(devlink, "Validating flash binary", NULL, 0, 0); + else + devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0); - err = ice_cancel_pending_update(pf, NULL, extack); - if (err) - return err; + if (!params->dry_run) { + err = ice_cancel_pending_update(pf, NULL, extack); + if (err) + return err; + } err = ice_acquire_nvm(hw, ICE_RES_WRITE); if (err) { diff --git a/include/linux/pldmfw.h b/include/linux/pldmfw.h index 0fc831338226..3e221c5e24cb 100644 --- a/include/linux/pldmfw.h +++ b/include/linux/pldmfw.h @@ -124,10 +124,15 @@ struct pldmfw_ops; * should embed this in a private structure and use container_of to obtain * a pointer to their own data, used to implement the device specific * operations. + * + * @ops: function pointers used as callbacks from the PLDMFW library + * @dev: pointer to the device being updated + * @validate: if true, only validate the file, do not perform an update. */ struct pldmfw { const struct pldmfw_ops *ops; struct device *dev; + u8 validate : 1; }; bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record); diff --git a/lib/pldmfw/pldmfw.c b/lib/pldmfw/pldmfw.c index 6e77eb6d8e72..29a132a39876 100644 --- a/lib/pldmfw/pldmfw.c +++ b/lib/pldmfw/pldmfw.c @@ -827,6 +827,10 @@ static int pldm_finalize_update(struct pldmfw_priv *data) * to the device firmware. Extract and write the flash data for each of the * components indicated in the firmware file. * + * If the context->dry_run is set, this is a request for a dry run, i.e. to + * only validate the PLDM firmware file. In this case, stop and exit after we + * find a valid matching record. + * * Returns: zero on success, or a negative error code on failure. */ int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw) @@ -844,14 +848,22 @@ int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw) data->fw = fw; data->context = context; + /* Parse the image and make sure it is a valid PLDM firmware binary */ err = pldm_parse_image(data); if (err) goto out_release_data; + /* Search for a record matching the device */ err = pldm_find_matching_record(data); if (err) goto out_release_data; + /* If this is a dry run, do not perform an update */ + if (context->dry_run) + goto out_release_data; + + /* Perform the device update */ + err = pldm_send_package_data(data); if (err) goto out_release_data; From patchwork Thu Jul 21 21:14:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 12925782 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14AEECCA48A for ; Thu, 21 Jul 2022 21:15:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233777AbiGUVPs (ORCPT ); Thu, 21 Jul 2022 17:15:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35314 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233728AbiGUVP3 (ORCPT ); Thu, 21 Jul 2022 17:15:29 -0400 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FEB15C347; Thu, 21 Jul 2022 14:15:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1658438128; x=1689974128; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=JTYY8pXomkr33uAzR8NUoGnMEQAn0y7xlGD+FEpwqEQ=; b=H6hSg1hf6vfChEBwbDPsmErzkmZp6w2C4ddwS66gibgH8CG0bw0qFRTO MnytE4EhmrZ9rJSu1R7gWTGoGhCMTXANEggYBwUN56e6wd43o7EcEiJ0e w8KpRkqZBFgjh0h2p6awtn5LS36yTjMcwUw+bn93yZZdekT1ACQswmENK lx/56zyIm1+Tnz52DMZ1/we9N5X2XSaDo+UB0eRVP35KQEI9x/sD6mJXF SDN6qXkHHFrLapFTr8E+q1zhVM8rO+BK6ft7Mz+OfTSR4GYoYZWRZezt+ sGzpClujYbXcKfz6L/oGKwmbmtRoQGQhm8nBml1eOIYk//GGDZw2Q1isq g==; X-IronPort-AV: E=McAfee;i="6400,9594,10415"; a="312892815" X-IronPort-AV: E=Sophos;i="5.93,183,1654585200"; d="scan'208";a="312892815" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2022 14:15:01 -0700 X-IronPort-AV: E=Sophos;i="5.93,183,1654585200"; d="scan'208";a="925816231" Received: from jekeller-desk.amr.corp.intel.com ([10.166.241.7]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Jul 2022 14:15:00 -0700 From: Jacob Keller To: netdev@vger.kernel.org Cc: Jacob Keller , Jonathan Corbet , Jiri Pirko , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Tony Nguyen , David Ahern , Stephen Hemminger , linux-doc@vger.kernel.org, intel-wired-lan@lists.osuosl.org Subject: [iproute2-next v2 3/3] devlink: add dry run attribute support to devlink flash Date: Thu, 21 Jul 2022 14:14:51 -0700 Message-Id: <20220721211451.2475600-7-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.35.1.456.ga9c7032d4631 In-Reply-To: <20220721211451.2475600-1-jacob.e.keller@intel.com> References: <20220721211451.2475600-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: dsahern@gmail.com Recent versions of the kernel support the DEVLINK_ATTR_DRY_RUN attribute which allows requesting a dry run of a command. A dry run is simply a request to validate that a command would work, without performing any destructive changes. The attribute is supported by the devlink flash update as a way to validate an update, including potentially the binary image, without modifying the device. Add a "dry_run" option to the command line parsing which will enable this attribute when requested. To avoid potential issues, only allow the attribute to be added to commands when the kernel recognizes it. This is important because some commands do not perform strict validation. If we were to add the attribute without this check, an old kernel may silently accept the command and perform an update even when dry_run was requested. Before adding the attribute, check the maximum attribute from the CTRL_CMD_GETFAMILY and make sure that the kernel recognizes the DEVLINK_ATTR_DRY_RUN attribute. Signed-off-by: Jacob Keller --- Changes since v1 * Make dl_kernel_supports_dry_run more generic by passing attribute devlink/devlink.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/devlink/devlink.c b/devlink/devlink.c index 1e2cfc3d4285..24f1a70a9656 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -296,6 +296,7 @@ static void ifname_map_free(struct ifname_map *ifname_map) #define DL_OPT_PORT_FN_RATE_PARENT BIT(51) #define DL_OPT_LINECARD BIT(52) #define DL_OPT_LINECARD_TYPE BIT(53) +#define DL_OPT_DRY_RUN BIT(54) struct dl_opts { uint64_t present; /* flags of present items */ @@ -372,6 +373,8 @@ struct dl { bool verbose; bool stats; bool hex; + bool max_attr_valid; + uint32_t max_attr; struct { bool present; char *bus_name; @@ -701,6 +704,7 @@ static const enum mnl_attr_data_type devlink_policy[DEVLINK_ATTR_MAX + 1] = { [DEVLINK_ATTR_LINECARD_STATE] = MNL_TYPE_U8, [DEVLINK_ATTR_LINECARD_TYPE] = MNL_TYPE_STRING, [DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES] = MNL_TYPE_NESTED, + [DEVLINK_ATTR_DRY_RUN] = MNL_TYPE_FLAG, }; static const enum mnl_attr_data_type @@ -1522,6 +1526,30 @@ static int dl_args_finding_required_validate(uint64_t o_required, return 0; } +static void dl_get_max_attr(struct dl *dl) +{ + if (!dl->max_attr_valid) { + uint32_t max_attr; + int err; + + err = mnlg_socket_get_max_attr(&dl->nlg, &max_attr); + if (err) { + pr_err("Unable to determine maximum supported devlink attribute\n"); + return; + } + + dl->max_attr = max_attr; + dl->max_attr_valid = true; + } +} + +static bool dl_kernel_supports_attr(struct dl *dl, enum devlink_attr attr) +{ + dl_get_max_attr(dl); + + return (dl->max_attr_valid && dl->max_attr >= attr); +} + static int dl_argv_parse(struct dl *dl, uint64_t o_required, uint64_t o_optional) { @@ -2037,6 +2065,16 @@ static int dl_argv_parse(struct dl *dl, uint64_t o_required, dl_arg_inc(dl); opts->linecard_type = ""; o_found |= DL_OPT_LINECARD_TYPE; + } else if (dl_argv_match(dl, "dry_run") && + (o_all & DL_OPT_DRY_RUN)) { + + if (!dl_kernel_supports_attr(dl, DEVLINK_ATTR_DRY_RUN)) { + pr_err("Kernel does not support dry_run attribute\n"); + return -EOPNOTSUPP; + } + + dl_arg_inc(dl); + o_found |= DL_OPT_DRY_RUN; } else { pr_err("Unknown option \"%s\"\n", dl_argv(dl)); return -EINVAL; @@ -2115,6 +2153,8 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_NODE_NAME, opts->rate_node_name); } + if (opts->present & DL_OPT_DRY_RUN) + mnl_attr_put(nlh, DEVLINK_ATTR_DRY_RUN, 0, NULL); if (opts->present & DL_OPT_PORT_TYPE) mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_TYPE, opts->port_type); @@ -2326,7 +2366,7 @@ static void cmd_dev_help(void) pr_err(" devlink dev reload DEV [ netns { PID | NAME | ID } ]\n"); pr_err(" [ action { driver_reinit | fw_activate } ] [ limit no_reset ]\n"); pr_err(" devlink dev info [ DEV ]\n"); - pr_err(" devlink dev flash DEV file PATH [ component NAME ] [ overwrite SECTION ]\n"); + pr_err(" devlink dev flash DEV file PATH [ component NAME ] [ overwrite SECTION ] [ dry_run ]\n"); } static bool cmp_arr_last_handle(struct dl *dl, const char *bus_name, @@ -3886,7 +3926,8 @@ static int cmd_dev_flash(struct dl *dl) NLM_F_REQUEST | NLM_F_ACK); err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_FLASH_FILE_NAME, - DL_OPT_FLASH_COMPONENT | DL_OPT_FLASH_OVERWRITE); + DL_OPT_FLASH_COMPONENT | DL_OPT_FLASH_OVERWRITE | + DL_OPT_DRY_RUN); if (err) return err;