diff --git a/doc/ot_api_doc.h b/doc/ot_api_doc.h index 3d58b682b..2e0a1bb05 100644 --- a/doc/ot_api_doc.h +++ b/doc/ot_api_doc.h @@ -109,6 +109,7 @@ * @brief This module includes functions for all Thread roles. * @defgroup api-joiner Joiner * @defgroup api-operational-dataset Operational Dataset + * @brief Includes functions for the Operational Dataset API. * @defgroup api-thread-router Router/Leader * @brief This module includes functions for Thread Routers and Leaders. * @defgroup api-server Server diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h index 63e1e26ad..3edf952ba 100644 --- a/include/openthread/dataset.h +++ b/include/openthread/dataset.h @@ -49,6 +49,8 @@ extern "C" { * * @{ * + * For FTD and MTD builds, the Operational Dataset API includes functions to manage Active and Pending datasets + * and dataset TLVs. */ #define OT_NETWORK_KEY_SIZE 16 ///< Size of the Thread Network Key (bytes) @@ -339,7 +341,7 @@ typedef void (*otDatasetMgmtSetCallback)(otError aResult, void *aContext); bool otDatasetIsCommissioned(otInstance *aInstance); /** - * This function gets the Active Operational Dataset. + * Gets the Active Operational Dataset. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[out] aDataset A pointer to where the Active Operational Dataset will be placed. @@ -363,7 +365,7 @@ otError otDatasetGetActive(otInstance *aInstance, otOperationalDataset *aDataset otError otDatasetGetActiveTlvs(otInstance *aInstance, otOperationalDatasetTlvs *aDataset); /** - * This function sets the Active Operational Dataset. + * Sets the Active Operational Dataset. * * If the dataset does not include an Active Timestamp, the dataset is only partially complete. * @@ -439,7 +441,7 @@ otError otDatasetGetPending(otInstance *aInstance, otOperationalDataset *aDatase otError otDatasetGetPendingTlvs(otInstance *aInstance, otOperationalDatasetTlvs *aDataset); /** - * This function sets the Pending Operational Dataset. + * Sets the Pending Operational Dataset. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aDataset A pointer to the Pending Operational Dataset. @@ -465,7 +467,7 @@ otError otDatasetSetPending(otInstance *aInstance, const otOperationalDataset *a otError otDatasetSetPendingTlvs(otInstance *aInstance, const otOperationalDatasetTlvs *aDataset); /** - * This function sends MGMT_ACTIVE_GET. + * Sends MGMT_ACTIVE_GET. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aDatasetComponents A pointer to a Dataset Components structure specifying which components to request. @@ -484,7 +486,7 @@ otError otDatasetSendMgmtActiveGet(otInstance * aInstan const otIp6Address * aAddress); /** - * This function sends MGMT_ACTIVE_SET. + * Sends MGMT_ACTIVE_SET. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aDataset A pointer to operational dataset. @@ -506,7 +508,7 @@ otError otDatasetSendMgmtActiveSet(otInstance * aInstance, void * aContext); /** - * This function sends MGMT_PENDING_GET. + * Sends MGMT_PENDING_GET. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aDatasetComponents A pointer to a Dataset Components structure specifying which components to request. @@ -525,7 +527,7 @@ otError otDatasetSendMgmtPendingGet(otInstance * aInsta const otIp6Address * aAddress); /** - * This function sends MGMT_PENDING_SET. + * Sends MGMT_PENDING_SET. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aDataset A pointer to operational dataset. @@ -566,9 +568,9 @@ otError otDatasetGeneratePskc(const char * aPassPhrase, otPskc * aPskc); /** - * This function sets an `otNetworkName` instance from a given null terminated C string. + * Sets an `otNetworkName` instance from a given null terminated C string. * - * This function also validates that the given @p aNameString follows UTF-8 encoding and its length is not longer than + * @p aNameString must follow UTF-8 encoding and the Network Name length must not be longer than * `OT_NETWORK_NAME_MAX_SIZE`. * * @param[out] aNetworkName A pointer to the `otNetworkName` to set. diff --git a/include/openthread/dataset_ftd.h b/include/openthread/dataset_ftd.h index f1ae621ef..05e37a1b2 100644 --- a/include/openthread/dataset_ftd.h +++ b/include/openthread/dataset_ftd.h @@ -50,7 +50,7 @@ extern "C" { */ /** - * This method creates a new Operational Dataset to use when forming a new network. + * For FTD only, creates a new Operational Dataset to use when forming a new network. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[out] aDataset The Operational Dataset. @@ -62,7 +62,7 @@ extern "C" { otError otDatasetCreateNewNetwork(otInstance *aInstance, otOperationalDataset *aDataset); /** - * Get minimal delay timer. + * For FTD only, gets a minimal delay timer. * * @param[in] aInstance A pointer to an OpenThread instance. * @@ -72,7 +72,7 @@ otError otDatasetCreateNewNetwork(otInstance *aInstance, otOperationalDataset *a uint32_t otDatasetGetDelayTimerMinimal(otInstance *aInstance); /** - * Set minimal delay timer. + * For FTD only, sets a minimal delay timer. * * @note This API is reserved for testing and demo purposes only. Changing settings with * this API will render a production application non-compliant with the Thread Specification. diff --git a/include/openthread/dataset_updater.h b/include/openthread/dataset_updater.h index 627ddb390..9760286a6 100644 --- a/include/openthread/dataset_updater.h +++ b/include/openthread/dataset_updater.h @@ -45,20 +45,18 @@ extern "C" { /** * @addtogroup api-operational-dataset * - * @brief - * This module includes functions for Dataset Updater. - * - * The functions in this module are available when Dataset Updater feature is enabled (i.e. - * `OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE` is set to 1). Further this feature is available only on an FTD build. - * * @{ * + * For FTD builds only, Dataset Updater includes functions to manage dataset updates. + * */ /** * This callback function pointer is called when a Dataset update request finishes, reporting success or failure status * of the Dataset update request. * + * Available when `OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE` is enabled. + * * @param[in] aError The error status. * OT_ERROR_NONE indicates successful Dataset update. * OT_ERROR_INVALID_STATE indicates failure due invalid state (MLE being disabled). @@ -73,6 +71,8 @@ typedef void (*otDatasetUpdaterCallback)(otError aError, void *aContext); /** * This function requests an update to Operational Dataset. * + * Available when `OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE` is enabled. + * * @p aDataset should contain the fields to be updated and their new value. It must not contain Active or Pending * Timestamp fields. The Delay field is optional, if not provided a default value (1000 ms) would be used. * @@ -96,6 +96,8 @@ otError otDatasetUpdaterRequestUpdate(otInstance * aInstance, /** * This function cancels an ongoing (if any) Operational Dataset update request. * + * Available when `OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE` is enabled. + * * @param[in] aInstance A pointer to an OpenThread instance. * */ @@ -104,6 +106,8 @@ void otDatasetUpdaterCancelUpdate(otInstance *aInstance); /** * This function indicates whether there is an ongoing Operation Dataset update request. * + * Available when `OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE` is enabled. + * * @param[in] aInstance A pointer to an OpenThread instance. * * @retval TRUE There is an ongoing update. diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 5eee72d99..75477199d 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (238) +#define OPENTHREAD_API_VERSION (239) /** * @addtogroup api-instance diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index 573436aea..9d4caf3b6 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -118,6 +118,21 @@ otError Dataset::Print(otOperationalDataset &aDataset) return OT_ERROR_NONE; } +/** + * @cli dataset init (active,new,pending,tlvs) + * @code + * dataset init new + * Done + * @endcode + * @cparam dataset init {@ca{active}|@ca{new}|@ca{pending}|@ca{tlvs}} [@ca{hex-encoded-tlvs}] + * Use `new` to initialize a new dataset, then enter the command `dataset commit active`. + * Use `tlvs` for hex-encoded TLVs. + * @par + * OT CLI checks for `active`, `pending`, or `tlvs` and returns the corresponding values. Otherwise, + * OT CLI creates a new, random network and returns a new dataset. + * @csa{dataset commit active} + * @csa{dataset active} + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_INVALID_ARGS; @@ -151,6 +166,34 @@ exit: return error; } +/** + * @cli dataset active + * @code + * dataset active + * Active Timestamp: 1 + * Channel: 13 + * Channel Mask: 0x07fff800 + * Ext PAN ID: d63e8e3e495ebbc3 + * Mesh Local Prefix: fd3d:b50b:f96d:722d::/64 + * Network Key: dfd34f0f05cad978ec4e32b0413038ff + * Network Name: OpenThread-8f28 + * PAN ID: 0x8f28 + * PSKc: c23a76e98f1a6483639b1ac1271e2e27 + * Security Policy: 0, onrcb + * Done + * @endcode + * @code + * dataset active -x + * 0e08000000000001000000030000103506000...3023d82c841eff0e68db86f35740c030000ff + * Done + * @endcode + * @cparam dataset active [-x] + * The optional `-x` argument prints the Active Operational %Dataset values as hex-encoded TLVs. + * @par api_copy + * #otDatasetGetActive + * @par + * OT CLI uses #otOperationalDataset members to return dataset values to the console. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_INVALID_ARGS; @@ -197,6 +240,22 @@ exit: return error; } +/** + * @cli dataset activetimestamp (get, set) + * @code + * dataset activetimestamp + * 123456789 + * Done + * @endcode + * @code + * dataset activetimestamp 123456789 + * Done + * @endcode + * @cparam dataset activetimestamp [@ca{timestamp}] + * Pass the optional `timestamp` argument to set the active timestamp. + * @par + * Gets or sets #otOperationalDataset::mActiveTimestamp. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -220,6 +279,22 @@ exit: return error; } +/** + * @cli dataset channel (get,set) + * @code + * dataset channel + * 12 + * Done + * @endcode + * @code + * dataset channel 12 + * Done + * @endcode + * @cparam dataset channel [@ca{channel-num}] + * Use the optional `channel-num` argument to set the channel. + * @par + * Gets or sets #otOperationalDataset::mChannel. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -241,6 +316,22 @@ exit: return error; } +/** + * @cli dataset channelmask (get,set) + * @code + * dataset channelmask + * 0x07fff800 + * Done + * @endcode + * @code + * dataset channelmask 0x07fff800 + * Done + * @endcode + * @cparam dataset channelmask [@ca{channel-mask}] + * Use the optional `channel-mask` argument to set the channel mask. + * @par + * Gets or sets #otOperationalDataset::mChannelMask + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -262,6 +353,15 @@ exit: return error; } +/** + * @cli dataset clear + * @code + * dataset clear + * Done + * @endcode + * @par + * Reset the Operational %Dataset buffer. + */ template <> otError Dataset::Process(Arg aArgs[]) { OT_UNUSED_VARIABLE(aArgs); @@ -274,10 +374,32 @@ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_INVALID_ARGS; + /** + * @cli dataset commit active + * @code + * dataset commit active + * Done + * @endcode + * @par + * Commit the Operational %Dataset buffer to Active Operational %Dataset. + * @csa{dataset commit pending} + * @sa #otDatasetSetPending + */ if (aArgs[0] == "active") { error = otDatasetSetActive(GetInstancePtr(), &sDataset); } + /** + * @cli dataset commit pending + * @code + * dataset commit pending + * Done + * @endcode + * @par + * Commit the Operational %Dataset buffer to Pending Operational %Dataset. + * @csa{dataset commit active} + * @sa #otDatasetSetActive + */ else if (aArgs[0] == "pending") { error = otDatasetSetPending(GetInstancePtr(), &sDataset); @@ -286,6 +408,23 @@ template <> otError Dataset::Process(Arg aArgs[]) return error; } +/** + * @cli dataset delay (get,set) + * @code + * dataset delay + * 1000 + * Done + * @endcode + * @code + * dataset delay 1000 + * Done + * @endcode + * @cparam dataset delay [@ca{delay}] + * Use the optional `delay` argument to set the delay timer value. + * @par + * Gets or sets #otOperationalDataset::mDelay. + * @sa otDatasetSetDelayTimerMinimal + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -307,6 +446,25 @@ exit: return error; } +/** + * @cli dataset extpanid (get,set) + * @code + * dataset extpanid + * 000db80123456789 + * Done + * @endcode + * @code + * dataset extpanid 000db80123456789 + * Done + * @endcode + * @cparam dataset extpanid [@ca{extpanid}] + * Use the optional `extpanid` argument to set the Extended Personal Area Network ID. + * @par + * Gets or sets #otOperationalDataset::mExtendedPanId. + * @note The commissioning credential in the dataset buffer becomes stale after changing + * this value. Use `dataset pskc` to reset. + * @csa{dataset pskc (get,set)} + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -328,6 +486,22 @@ exit: return error; } +/** + * @cli dataset meshlocalprefix (get,set) + * @code + * dataset meshlocalprefix + * fd00:db8:0:0::/64 + * Done + * @endcode + * @code + * dataset meshlocalprefix fd00:db8:0:0::/64 + * Done + * @endcode + * @cparam dataset meshlocalprefix [@ca{meshlocalprefix}] + * Use the optional `meshlocalprefix` argument to set the Mesh-Local Prefix. + * @par + * Gets or sets #otOperationalDataset::mMeshLocalPrefix. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -354,6 +528,22 @@ exit: return error; } +/** + * @cli dataset networkkey (get,set) + * @code + * dataset networkkey + * 00112233445566778899aabbccddeeff + * Done + * @endcode + * @code + * dataset networkkey 00112233445566778899aabbccddeeff + * Done + * @endcode + * @cparam dataset networkkey [@ca{key}] + * Use the optional `key` argument to set the Network Key. + * @par + * Gets or sets #otOperationalDataset::mNetworkKey. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -375,6 +565,25 @@ exit: return error; } +/** + * @cli dataset networkname (get,set) + * @code + * dataset networkname + * OpenThread + * Done + * @endcode + * @code + * dataset networkname OpenThread + * Done + * @endcode + * @cparam dataset networkname [@ca{name}] + * Use the optional `name` argument to set the Network Name. + * @par + * Gets or sets #otOperationalDataset::mNetworkName. + * @note The Commissioning Credential in the dataset buffer becomes stale after changing this value. + * Use `dataset pskc` to reset. + * @csa{dataset pskc (get,set)} + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -396,6 +605,22 @@ exit: return error; } +/** + * @cli dataset panid (get,set) + * @code + * dataset panid + * 0x1234 + * Done + * @endcode + * @code + * dataset panid 0x1234 + * Done + * @endcode + * @cparam dataset panid [@ca{panid}] + * Use the optional `panid` argument to set the PAN ID. + * @par + * Gets or sets #otOperationalDataset::mPanId. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -417,6 +642,22 @@ exit: return error; } +/** + * @cli dataset pendingtimestamp (get,set) + * @code + * dataset pendingtimestamp + * 123456789 + * Done + * @endcode + * @code + * dataset pendingtimestamp 123456789 + * Done + * @endcode + * @cparam dataset pendingtimestamp [@ca{timestamp}] + * Use the optional `timestamp` argument to set the pending timestamp seconds. + * @par + * Gets or sets #otOperationalDataset::mPendingTimestamp. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -540,11 +781,43 @@ template <> otError Dataset::Process(Arg aArgs[]) } } + /** + * @cli dataset mgmtsetcommand active + * @code + * dataset mgmtsetcommand active activetimestamp 123 securitypolicy 1 onrcb + * Done + * @endcode + * @cparam dataset mgmtsetcommand active [@ca{dataset-components}] [-x @ca{tlv-list}] + * To learn more about these parameters and argument mappings, refer to @dataset. + * @par + * @note This command is primarily used for testing only. + * @par api_copy + * #otDatasetSendMgmtActiveSet + * @csa{dataset mgmtgetcommand active} + * @csa{dataset mgmtgetcommand pending} + * @csa{dataset mgmtsetcommand pending} + */ if (aArgs[0] == "active") { error = otDatasetSendMgmtActiveSet(GetInstancePtr(), &dataset, tlvs, tlvsLength, /* aCallback */ nullptr, /* aContext */ nullptr); } + /** + * @cli dataset mgmtsetcommand pending + * @code + * dataset mgmtsetcommand pending activetimestamp 123 securitypolicy 1 onrcb + * Done + * @endcode + * @cparam dataset mgmtsetcommand pending [@ca{dataset-components}] [-x @ca{tlv-list}] + * To learn more about these parameters and argument mappings, refer to @dataset. + * @par + * @note This command is primarily used for testing only. + * @par api_copy + * #otDatasetSendMgmtPendingSet + * @csa{dataset mgmtgetcommand active} + * @csa{dataset mgmtgetcommand pending} + * @csa{dataset mgmtsetcommand active} + */ else if (aArgs[0] == "pending") { error = otDatasetSendMgmtPendingSet(GetInstancePtr(), &dataset, tlvs, tlvsLength, /* aCallback */ nullptr, @@ -633,11 +906,56 @@ template <> otError Dataset::Process(Arg aArgs[]) } } + /** + * @cli dataset mgmtgetcommand active + * @code + * dataset mgmtgetcommand active address fdde:ad00:beef:0:558:f56b:d688:799 activetimestamp securitypolicy + * Done + * @endcode + * @code + * dataset mgmtgetcommand active networkname + * Done + * @endcode + * @cparam dataset mgmtgetcommand active [address @ca{leader-address}] [@ca{dataset-components}] [-x @ca{tlv-list}] + * * Use `address` to specify the IPv6 destination; otherwise, the Leader ALOC is used as default. + * * For `dataset-components`, you can pass any combination of #otOperationalDatasetComponents, for + * example `activetimestamp`, `pendingtimestamp`, or `networkkey`. + * * The optional `-x` argument specifies raw TLVs to be requested. + * @par + * OT CLI sends a MGMT_ACTIVE_GET with the relevant arguments. + * To learn more about these parameters and argument mappings, refer to @dataset. + * @note This command is primarily used for testing only. + * @par api_copy + * #otDatasetSendMgmtActiveGet + * @csa{dataset mgmtgetcommand pending} + * @csa{dataset mgmtsetcommand active} + * @csa{dataset mgmtsetcommand pending} + */ if (aArgs[0] == "active") { error = otDatasetSendMgmtActiveGet(GetInstancePtr(), &datasetComponents, tlvs, tlvsLength, destAddrSpecified ? &address : nullptr); } + /** + * @cli dataset mgmtgetcommand pending + * @code + * dataset mgmtgetcommand pending address fdde:ad00:beef:0:558:f56b:d688:799 activetimestamp securitypolicy + * Done + * @endcode + * @code + * dataset mgmtgetcommand pending networkname + * Done + * @endcode + * @cparam dataset mgmtgetcommand pending [address @ca{leader-address}] [@ca{dataset-components}] [-x @ca{tlv-list}] + * To learn more about these parameters and argument mappings, refer to @dataset. + * @par + * @note This command is primarily used for testing only. + * @par api_copy + * #otDatasetSendMgmtPendingGet + * @csa{dataset mgmtgetcommand active} + * @csa{dataset mgmtsetcommand active} + * @csa{dataset mgmtsetcommand pending} + */ else if (aArgs[0] == "pending") { error = otDatasetSendMgmtPendingGet(GetInstancePtr(), &datasetComponents, tlvs, tlvsLength, @@ -652,6 +970,30 @@ exit: return error; } +/** + * @cli dataset pskc (get,set) + * @code + * dataset pskc + * 67c0c203aa0b042bfb5381c47aef4d9e + * Done + * @endcode + * @code + * dataset pskc -p 123456 + * Done + * @endcode + * @code + * dataset pskc 67c0c203aa0b042bfb5381c47aef4d9e + * Done + * @endcode + * @cparam dataset pskc [@ca{-p} @ca{passphrase}] | [@ca{key}] + * For FTD only, use `-p` with the `passphrase` argument. `-p` generates a pskc from + * the UTF-8 encoded `passphrase` that you provide, together with + * the network name and extended PAN ID. If set, `-p` uses the dataset buffer; + * otherwise, it uses the current stack. + * Alternatively, you can set pskc as `key` (hex format). + * @par + * Gets or sets #otOperationalDataset::mPskc. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -806,6 +1148,26 @@ exit: return error; } +/** + * @cli dataset securitypolicy (get,set) + * @code + * dataset securitypolicy + * 672 onrc + * Done + * @endcode + * @code + * dataset securitypolicy 672 onrc + * Done + * @endcode + * @cparam dataset securitypolicy [@ca{rotationtime} [@ca{onrcCepR}]] + * * Use `rotationtime` for `thrKeyRotation`, in units of hours. + * * Security Policy commands use the `onrcCepR` argument mappings to get and set + * #otSecurityPolicy members, for example `o` represents + * #otSecurityPolicy::mObtainNetworkKeyEnabled. + * @moreinfo{@dataset}. + * @par + * Gets or sets the %Dataset security policy. + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -829,6 +1191,22 @@ exit: return error; } +/** + * @cli dataset set (active,pending) + * @code + * dataset set active 0e08000000000001000000030000103506000...3023d82c841eff0e68db86f35740c030000ff + * Done + * @endcode + * @code + * dataset set pending 0e08000000000001000000030000103506000...3023d82c841eff0e68db86f35740c030000ff + * Done + * @endcode + * @cparam dataset set {active|pending} @ca{tlvs} + * @par + * The CLI `dataset set` command sets the Active Operational %Dataset using hex-encoded TLVs. + * @par api_copy + * #otDatasetSetActive + */ template <> otError Dataset::Process(Arg aArgs[]) { otError error = OT_ERROR_NONE; @@ -955,6 +1333,35 @@ otError Dataset::Process(Arg aArgs[]) ExitNow(error = Print(sDataset)); } + /** + * @cli dataset help + * @code + * dataset help + * help + * active + * activetimestamp + * channel + * channelmask + * clear + * commit + * delay + * extpanid + * init + * meshlocalprefix + * mgmtgetcommand + * mgmtsetcommand + * networkkey + * networkname + * panid + * pending + * pendingtimestamp + * pskc + * securitypolicy + * Done + * @endcode + * @par + * Gets a list of `dataset` CLI commands. @moreinfo{@dataset}. + */ if (aArgs[0] == "help") { OutputCommandTable(kCommands);