/*
 *  Copyright 2023 NVIDIA Corporation.  All rights reserved.
 *
 * NVIDIA CORPORATION and its licensors retain all intellectual property
 * and proprietary rights in and to this software, related documentation
 * and any modifications thereto.  Any use, reproduction, disclosure or
 * distribution of this software and related documentation without an express
 * license agreement from NVIDIA CORPORATION is strictly prohibited.
 *
 */

#ifndef NV_FM_NVL_TYPES_H
#define NV_FM_NVL_TYPES_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

/***************************************************************************************************/
/** @defgroup FMAPI_Common Common Structures
 *   
 *  This chapter describes the common structures for Fabric Manager API interface library.
 *  @{
 */
/***************************************************************************************************/  

/************************************* Common Data Structures **************************************/

/**
 * @brief Node ID
 * 
 * Unique identifier for each Compute, L1 and L2 Switch Nodes
 */
typedef uint64_t    fmNvlNodeId_t;

/**
 * @brief L1 Domain ID
 * 
 * Unique identifier for connectivity between L1 Switch Nodes and connected Compute Nodes
 * Also, to identify resources belonging to the same L1 domain.
 */
typedef uint16_t    fmNvlL1DomainId_t;

/**
 * @brief Partition ID
 *
 * Unique identifier for each GPU Partition
 */
typedef uint16_t    fmNvlPartitionId_t;

/**
 * Max GPU size partitions
 */
#define FM_MAX_PARTITION_SIZES  256    

/**
 * @brief NVLink Domain Information
 *
 * NVLink Domain information based on its configuration and topology.
 */
typedef struct
{
    char                uuid[FM_UUID_BUFFER_SIZE];                  //!< NVLink Domain UUID

    // Compute Node and GPU Specific Information
    unsigned int        maxComputeNodes;                            //!< Max Compute nodes in the NVLink domain
    unsigned int        maxComputeNodesPerL1Domain;                 //!< Max Compute nodes per L1 Domain
    unsigned int        maxGpusPerComputeNode;                      //!< Max GPUs per Compute Node
    unsigned int        maxGpuNvLinks;                              //!< Max links per GPU
    unsigned int        nvlinkLineRateMBps;                         //!< NVLink Line Rate in MBps

    // Switch Node and Cages Specific Information
    unsigned int        maxCagesPerL1SwitchNode;                    //!< Max Cages per L1 Switch Node
    unsigned int        maxCagesPerL2SwitchNode;                    //!< Max Cages per L1 Switch Node
    unsigned int        maxPortsPerCage;                            //!< Max Ports per Cage
    unsigned int        maxPortSplit;                               //!< Max Splits per Port

    // GPU Partition Specific Information
    unsigned int        maxPartitionsizes;                          //!< Max supported GPU size partitions
    unsigned int        partitionSizeList[FM_MAX_PARTITION_SIZES];  //!< List of supported GPU size Partitions
} fmNvlDomainInfo_t;

/**
 * @brief fmNvlGetDomainInfo()
 *
 * NVLink Domain information 
 */
typedef struct
{
    unsigned int        version;                    //!< [IN]  Version number
    fmNvlDomainInfo_t   domainInfo;                 //!< [OUT] NVLink Domain Information
} fmNvlGetDomainInfo_v1;

/// Typedef for \ref fmNvlGetDomainInfo_v1
typedef fmNvlGetDomainInfo_v1 fmNvlGetDomainInfo_t;

/// Version 1 for \ref fmNvlGetDomainInfo_v1
#define fmNvlGetDomainInfo_version1 MAKE_FM_PARAM_VERSION(fmNvlGetDomainInfo_v1, 1)
/// Latest version for \ref fmGetNvlDomainInfo_v1
#define fmNvlGetDomainInfo_version fmNvlGetDomainInfo_version1

/***************************** Compute Node API specific Data Structures ****************************/

/**
 * @brief Compute Node Health State
 */
typedef enum
{
    COMPUTE_NODE_HEALTH_UNKNOWN = 0,        //!< Unknown health state
    COMPUTE_NODE_HEALTH_HEALTHY,            //!< Fully healthy
    COMPUTE_NODE_HEALTH_DEGRADED,          //!< Some GPUs are degraded to NO_NVLINK
    COMPUTE_NODE_HEALTH_L1_DOMAIN_ONLY,    //!< Unable to participate in multi L1 domain partitions
    COMPUTE_NODE_HEALTH_NO_NVLINK,         //!< Unable to participate in NVLink partition
    COMPUTE_NODE_HEALTH_UNREACHABLE,       //!< Unable to determine the compute node NVLink status since its unreachable
    COMPUTE_NODE_HEALTH_MAX                //!< Max                
} fmNvlComputeNodeHealth_t;

/**
 * @brief Compute Node Information
 * 
 * Describes details of Compute Node.
 */
typedef struct
{
    fmNvlNodeId_t               nodeId;                      //!< Compute Node ID
    char                        hostname[FM_MAX_STR_LENGTH]; //!< Compute Node hostname 
    unsigned int                numGpus;                     //!< Number of GPUs (maxGpusPerComputeNode)
    fmNvlL1DomainId_t           l1DomainId;                  //!< L1 Domain ID
    fmNvlComputeNodeHealth_t    nodeHealth;                  //!< Compute Node Health
    fmNvlPartitionId_t          *partitionIdList;            //!< List of Partition IDs (maxGpusPerComputeNode)
} fmNvlComputeNodeInfo_t;

/**
 * @brief Compute Node Attributes
 * 
 * Compute Node Attributes that can be used to fetch the required set of Compute Nodes.
 */
typedef enum
{
    COMPUTE_NODE_ATTR_ALL = 1,              //!< All Compute nodes
    COMPUTE_NODE_ATTR_FREE,                 //!< Compute nodes with all GPUs available for partition creation
    COMPUTE_NODE_ATTR_FULLY_ALLOCATED,      //!< Compute nodes with all GPUs allocated to partitions
    COMPUTE_NODE_ATTR_PARTIALLY_ALLOCATED,  //!< Compute nodes with some GPUs allocated to partitions
    COMPUTE_NODE_ATTR_MAX                   //!< Max
} fmNvlComputeNodeAttr_t;

/**
 * @brief fmNvlGetComputeNodeCount()
 * 
 * Structure to return the number of Compute nodes in a given NVLink Domain based on given attribute
 * and node health (optional).
 */
typedef struct
{
    unsigned int                 version;   //!< [IN] Version number
    fmNvlComputeNodeAttr_t       attr;      //!< [IN] Compute Node Attributes
    fmNvlComputeNodeHealth_t     nodeHealth;//!< [IN] Compute Node Health (Optional)
    unsigned int                 numNodes;  //!< [OUT] Number of Compute nodes found of requested attr type
} fmNvlGetComputeNodeCount_v1;

/// Typedef for \ref fmNvlGetComputeNodeCount_v1
typedef fmNvlGetComputeNodeCount_v1 fmNvlGetComputeNodeCount_t;
/// Version 1 for \ref fmNvlComputeNodeCount_v1
#define fmNvlGetComputeNodeCount_version1 MAKE_FM_PARAM_VERSION(fmNvlGetComputeNodeCount_v1, 1)
/// Latest version for \ref fmNvlComputeNodeCount_v1
#define fmNvlGetComputeNodeCount_version fmNvlGetComputeNodeCount_version1

/**
 * @brief fmNvlGetComputeNodeIdList()
 * 
 * Structure to return the list of Compute node IDs in a given NVLink Domain based on given attribute
 * and node health (optional).
 */
typedef struct
{
    unsigned int                version;       //!< [IN] Version number
    fmNvlComputeNodeAttr_t      attr;          //!< [IN] Compute Node Attributes
    fmNvlComputeNodeHealth_t    nodeHealth;    //!< [IN] Compute Node Health (Optional)
    unsigned int                numNodes;      //!< [IN| [OUT] Number of Compute nodes
    fmNvlNodeId_t               *nodeIdList;   //!< [IN| [OUT] List of Compute node IDs
} fmNvlGetComputeNodeIdList_v1;

/// @brief Typedef for \ref fmNvlGetComputeNodeIdList_v1
typedef fmNvlGetComputeNodeIdList_v1 fmNvlGetComputeNodeIdList_t;
/// @brief Version 1 for \ref fmNvlGetComputeNodeIdList_v1
#define fmNvlGetComputeNodeIdList_version1 MAKE_FM_PARAM_VERSION(fmNvlGetComputeNodeIdList_v1, 1)
///Latest version for \ref fmNvlGetComputeNodeIdList_v1
#define fmNvlGetComputeNodeIdList_version fmNvlGetComputeNodeIdList_version1

/**
 * @brief fmNvlGetComputeNodeInfoList()
 *
 * Structure to return the list of Compute node information based on Node ID list
 */
typedef struct
{
    unsigned int                version;        //!< [IN] Version number
    unsigned int                numNodes;       //!< [IN] Number of Compute nodes
    fmNvlNodeId_t               *nodeIdList;    //!< [IN] List of Compute node IDs
    fmNvlComputeNodeInfo_t      *nodeInfoList;  //!< [IN| [OUT] List of Compute Nodes Information for given nodeID list
} fmNvlGetComputeNodeInfoList_v1;

/// Typedef for \ref fmNvlGetComputeNodeInfoList_v1
typedef fmNvlGetComputeNodeInfoList_v1 fmNvlGetComputeNodeInfoList_t;
/// Version 1 for \ref fmNvlGetComputeNodeInfoList_v1
#define fmNvlGetComputeNodeInfoList_version1 MAKE_FM_PARAM_VERSION(fmNvlGetComputeNodeInfoList_v1, 1)
/// Latest version for \ref fmNvlGetComputeNodeInfoList_v1
#define fmNvlGetComputeNodeInfoList_version fmNvlGetComputeNodeInfoList_version1

/**
 * @brief GPU Health State
 */
typedef enum
{
    GPU_HEALTH_UNKNOWN = 0,     //!< Unknown health state
    GPU_HEALTH_HEALTHY,         //!< Fully healthy
    GPU_HEALTH_L1_DOMAIN_ONLY,  //!< Unable to participate in multi L1 domain partitions
    GPU_HEALTH_DEGRADED,        //!< One or more links are down
    GPU_HEALTH_NO_NVLINK,       //!< Unable to participate in NVLink partition
    GPU_HEALTH_UNREACHABLE,     //!< Unable to determine the GPU NVLink status since its unreachable 
    GPU_HEALTH_MAX              //!< Max
} fmNvlGpuHealth_t;

/**
 * @brief GPU Information
 * 
 * Describes details of GPU.
 */
typedef struct
{
    fmNvlNodeId_t               nodeId;        //!< Compute Node ID
    unsigned int                gpuId;         //!< GPU Module ID        
    fmNvlGpuHealth_t            gpuHealth;     //!< GPU Health
    fmNvlPartitionId_t          partitionId;   //!< Partition ID
} fmNvlGpuInfo_t;

/**
 * @brief GPU Attributes
 * 
 * GPU Attributes that can be used to fetch the required set of GPUs.
 */
typedef enum
{
    GPU_ATTR_ALL = 1,           //!< All GPUs in the NVLink Domain
    GPU_ATTR_COMPUTE_NODE_ID,   //!< All GPUs that are associated with a given Compute node ID
    GPU_ATTR_PARTITION_ID,      //!< All GPUs that are associated with a given Partition ID
    GPU_ATTR_MAX                //!< Max
} fmNvlGpuAttr_t;

/**
 * @brief fmNvlGetGpuInfoList()
 * 
 * Structure to return the list of GPU device information based on attributes and other
 * information.
 */
typedef struct
{
    unsigned int          version;          //!< [IN] Version number
    fmNvlGpuAttr_t        attr;             //!< [IN] GPU Attributes
    unsigned int          numGpus;          //!< [IN] Number of GPUs requested
    fmNvlNodeId_t         nodeId;           //!< [IN] Compute node ID (required when GPU_ATTR_COMPUTE_NODE_ID is specified)
    fmNvlPartitionId_t    partitionId;      //!< [IN] Partition ID (required when GPU_ATTR_PARTITION_ID is specified)
    fmNvlGpuInfo_t        *gpuInfoList;     //!< [IN| [OUT] Information for list of GPUs
} fmNvlGetGpuInfoList_v1;

/// Typedef for \ref fmNvlGetGpuInfoList_v1
typedef fmNvlGetGpuInfoList_v1 fmNvlGetGpuInfoList_t;
/// Version 1 for \ref fmNvlGetGpuInfoList_v1
#define fmNvlGetGpuInfoList_version1 MAKE_FM_PARAM_VERSION(fmNvlGetGpuInfoList_v1, 1)
/// Latest version for \ref fmNvlGetGpuInfoList_v1
#define fmNvlGetGpuInfoList_version fmNvlGetGpuInfoList_version1

/***************************** Switch Node API specific Data Structures *****************************/

/**
 * @brief Switch Node Type
 */
typedef enum
{
    SWITCH_NODE_TYPE_L1 = 1,                //!< L1 Switch
    SWITCH_NODE_TYPE_L2,                    //!< L2 Switch
    SWITCH_NODE_TYPE_MAX                    //!< Max
} fmNvlSwitchNodeType_t;

/**
 * @brief Switch Node Health State
 */
typedef enum
{
    SWITCH_NODE_HEALTH_UNKNOWN = 0,         //!< Unknown health state
    SWITCH_NODE_HEALTH_HEALTHY,             //!< Fully healthy
    SWITCH_NODE_HEALTH_DEGRADED,            //!< one or more devices within the node is unhealthy
    SWITCH_NODE_HEALTH_L1_DOMAIN_ONLY,      //!< Unable to participate in NVLink fabric
    SWITCH_NODE_HEALTH_NO_NVLINK,           //!< Unable to participate in NVLink fabric
    SWITCH_NODE_HEALTH_UNREACHABLE,         //!< Unable to participate in NVLink fabric since it is unresponsive or down
    SWITCH_NODE_HEALTH_NO_IP,               //!< Unable to participate in NVLink fabric since IP address is missing
    SWITCH_NODE_HEALTH_L2_ISOLATED,         //!< L2 Node Isolated
    SWITCH_NODE_HEALTH_UNHEALTHY,           //!< Fully unhealthy
    SWITCH_NODE_HEALTH_NEEDS_LFM_REBOOT,    //!< The Local FM needs to be rebooted in order to participate in NVLink fabric
    SWITCH_NODE_HEALTH_MAX                  //!< Max
} fmNvlSwitchNodeHealth_t;

/**
 * @brief Switch Node Information
 * 
 * Describes Switch node.
 */
typedef struct
{
    fmNvlNodeId_t             nodeId;                          //!< Switch Node ID
    char                      hostname[FM_MAX_STR_LENGTH];     //!< Switch Node hostname 
    char                      addressInfo[FM_MAX_STR_LENGTH];  //!< Switch Node IPv4/IPv6 address
    fmNvlSwitchNodeType_t     nodeType;                        //!< L1:L2
    unsigned int              numSwitches;                     //!< Number of Switches
    unsigned int              numCages;                        //!< Number of Cages
    fmNvlL1DomainId_t         l1DomainId;                      //!< L1 Domain ID
    fmNvlSwitchNodeHealth_t   nodeHealth;                      //!< Node health
} fmNvlSwitchNodeInfo_t;

/**
 * @brief Swicth Node Attributes
 * 
 * Switch Node Attributes that can be used to fetch the required set of Switch Nodes.
 */
typedef enum
{
    SWITCH_NODE_ATTR_ALL = 1,   //!< All Switch nodes
    SWITCH_NODE_ATTR_L1,        //!< L1 Switch nodes
    SWITCH_NODE_ATTR_L2,        //!< L2 Switch nodes
    SWITCH_NODE_ATTR_MAX        //!< Max
} fmNvlSwitchNodeAttr_t;

/**
 * @brief fmNvlGetSwitchNodeCount()
 * 
 * Structure to return the number of Switch nodes in a given NVLink Domain based on given attribute
 * and node health (optional).
 */
typedef struct
{
    unsigned int                version;   //!< [IN] Version number 
    fmNvlSwitchNodeAttr_t       attr;      //!< [IN] Switch Node Attributes
    fmNvlSwitchNodeHealth_t     nodeHealth;//!< [IN] Switch Node Health (Optional)
    unsigned int                numNodes;  //!< [IN| [OUT] Number of Switch Nodes
} fmNvlGetSwitchNodeCount_v1;

/// Typedef for \ref fmNvlGetSwitchNodeCount_v1
typedef fmNvlGetSwitchNodeCount_v1 fmNvlGetSwitchNodeCount_t;
/// Version 1 for \ref fmNvlGetSwitchNodeCount_v1
#define fmNvlGetSwitchNodeCount_version1 MAKE_FM_PARAM_VERSION(fmNvlGetSwitchNodeCount_v1, 1)
/// Latest version for \ref fmNvlGetSwitchNodeCount_v1
#define fmNvlGetSwitchNodeCount_version fmNvlGetSwitchNodeCount_version1

/**
 * @brief fmNvlGetSwitchNodeIdList()
 * 
 * Structure to return the list of Switch node IDs in a given NVLink Domain based on given attribute
 * and node health (optional).
 */
typedef struct
{
    unsigned int              version;      //!< [IN] Version number
    fmNvlSwitchNodeAttr_t     attr;         //!< [IN] Switch Node Attributes
    fmNvlSwitchNodeHealth_t   nodeHealth;   //!< [IN] Switch Node Health (Optional)
    unsigned int              numNodes;     //!< [IN| [OUT] Number of Switch Nodes
    fmNvlNodeId_t             *nodeIdList;  //!< [IN| [OUT] List of Switch Node IDs
} fmNvlGetSwitchNodeIdList_v1;

/// Typedef for \ref fmNvlGetSwitchNodeIdList_v1
typedef fmNvlGetSwitchNodeIdList_v1 fmNvlGetSwitchNodeIdList_t;
/// Version 1 for \ref fmNvlGetSwitchNodeIdList_v1
#define fmNvlGetSwitchNodeIdList_version1 MAKE_FM_PARAM_VERSION(fmNvlGetSwitchNodeIdList_v1, 1)
/// Latest version for \ref fmNvlGetSwitchNodeIdList_v1
#define fmNvlGetSwitchNodeIdList_version fmNvlGetSwitchNodeIdList_version1

/**
 * @brief fmNvlGetSwitchNodeInfoList()
 * 
 * Structure to return the list of Switch node information based on Node ID list
 */
typedef struct
{
    unsigned int              version;        //!< [IN] Version number
    unsigned int              numNodes;       //!< [IN] Number of switch nodes
    fmNvlNodeId_t             *nodeIdList;    //!< [IN] List of switch Node IDs
    fmNvlSwitchNodeInfo_t     *nodeInfoList;  //!< [IN|OUT] Switch Nodes information for given list of nodeID.
} fmNvlGetSwitchNodeInfoList_v1;

/// Typedef for \ref fmNvlGetSwitchNodeInfoList_v1
typedef fmNvlGetSwitchNodeInfoList_v1 fmNvlGetSwitchNodeInfoList_t;
/// Version 1 for \ref fmNvlGetSwitchNodeInfoList_v1
#define fmNvlGetSwitchNodeInfoList_version1 MAKE_FM_PARAM_VERSION(fmNvlGetSwitchNodeInfoList_v1, 1)
/// Latest version for \ref fmNvlGetSwitchNodeInfoList_v1
#define fmNvlGetSwitchNodeInfoList_version fmNvlGetSwitchNodeInfoList_version1

/**
 * @brief Switch Health State
 */
typedef enum
{
    SWITCH_HEALTH_UNKNOWN = 0,              //!< Unknown health state
    SWITCH_HEALTH_HEALTHY ,                 //!< Fully healthy
    SWITCH_HEALTH_DEGRADED,                 //!< one or more links are unhealthy
    SWITCH_HEALTH_NO_NVLINK,                //!< Missing Switch
    SWITCH_HEALTH_UNHEALTHY,                //!< Fully unhealthy
    SWITCH_HEALTH_MAX                       //!< Max
} fmNvlSwitchHealth_t;

/**
 * @brief NVLink Switch Information
 * 
 * Describes details of NVLink Switch.
 */
typedef struct
{
    unsigned int        switchId;                       //!< Switch Physical ID (1-based)
    fmPciDevice_t       pciDevId;                       //!< PCI device Id
    char                uuid[FM_UUID_BUFFER_SIZE];      //!< Device UUID
    unsigned int        numCages;                       //!< Number of Cages
    fmNvlSwitchHealth_t health;                         //!< Switch Health
} fmNvlSwitchInfo_t;

/**
 * @brief fmNvlGetSwitchInfoList()
 * 
 * Structure to return the list of switch device information for a given Switch node
 */
typedef struct
{
    unsigned int          version;            //!< [IN] Version number
    fmNvlNodeId_t         nodeId;             //!< [IN] Switch node ID
    unsigned int          numSwitches;        //!< [IN] Number of Switches requested
    fmNvlSwitchInfo_t     *switchInfoList;    //!< [IN| [OUT] Information for list of Switches
} fmNvlGetSwitchInfoList_v1;

/// Typedef for \ref fmNvlGetSwitchInfoList_v1
typedef fmNvlGetSwitchInfoList_v1 fmNvlGetSwitchInfoList_t;
/// Version 1 for \ref fmNvlGetSwitchInfoList_v1
#define fmNvlGetSwitchInfoList_version1 MAKE_FM_PARAM_VERSION(fmNvlGetSwitchInfoList_v1, 1)
/// Latest version for \ref fmNvlGetSwitchInfoList_v1
#define fmNvlGetSwitchInfoList_version fmNvlGetSwitchInfoList_version1

/**
 * @brief Cage and Port Maintenance State
 *
 * The maintenance states are applicable to the Cages and Ports
 */
typedef enum
{
    MAINTENANCE_UNKNOWN = 0,                //!< Unknown maintenance state
    MAINTENANCE_OFF,                        //!< Not in the Maintenance State
    MAINTENANCE_ON,                         //!< In maintenance state and set by User
    MAINTENANCE_ON_AUTO                     //!< In maintenance state and set by GFM
} fmNvlMaintenanceState_t;

/*
 *  @brief NVLink Link or Connection state
 */
typedef enum
{
    NVLINK_CONN_STATE_UNKNOWN = 0,     //!< Unknown connection state
    NVLINK_CONN_STATE_ACTIVE,          //!< Active link or connection state
    NVLINK_CONN_STATE_INACTIVE         //!< Inactive link or connection state
} fmNvlConnState_t;

/**
 * @brief Describes an Split Port Information
 */
typedef struct {
    unsigned int        portNum;       //!< NVLink Port Number
    fmNvlConnState_t    portState;     //!< NVLink port state
} fmNvlSplitPortInfo_t;

/**
 * @brief Port Health State
 */
typedef enum
{
    PORT_HEALTH_UNKNOWN = 0,           //!< Unknown health state
    PORT_HEALTH_HEALTHY,               //!< Fully healthy
    PORT_HEALTH_DEGRADED,              //!< one or more links are unhealthy
    PORT_HEALTH_UNHEALTHY,             //!< Fully unhealthy
    PORT_HEALTH_MAX                    //!< Max
} fmNvlPortHealth_t;

/**
 * @brief Describes an Port Information
 */
typedef struct {
    unsigned int                portNum;                //!< Port Number
    fmNvlPortHealth_t           portHealth;             //!< Port Health
    fmNvlMaintenanceState_t     portMaintenanceState;   //!< Port maintenance state
    unsigned int                numSplit;               //!< Number of Port Splits (maxPortSplit)
    fmNvlSplitPortInfo_t        *splitPortInfoList;     //<! List of Split Port Information (maxPortSplit)
} fmNvlPortInfo_t;

/**
 * @brief Cage Health State
 */
typedef enum
{
    CAGE_HEALTH_UNKNOWN = 0,           //!< Unknown health state
    CAGE_HEALTH_HEALTHY,               //!< Fully healthy
    CAGE_HEALTH_DEGRADED,              //!< one or more ports are unhealthy
    CAGE_HEALTH_UNHEALTHY,             //!< Fully unhealthy
    CAGE_HEALTH_MAX                    //!< Max
} fmNvlCageHealth_t;

/**
 * @brief Describes an Cage Information
 */
typedef struct {
    unsigned int            cageNum;                //!< Cage Number
    fmNvlCageHealth_t       cageHealth;             //!< Cage Health
    fmNvlMaintenanceState_t cageMaintenanceState;   //!< Cage maintenance state
    unsigned int            numPorts;               //!< Number of Ports (maxPortsPerCage)
    fmNvlPortInfo_t         *portInfoList;          //!< List of Port information (maxPortsPerCage)
} fmNvlCageInfo_t;

/**
 * @brief fmNvlGetCageInfoList()
 * 
 * Structure to return the list of cage information for a given Switch node
 */
typedef struct
{
    unsigned int            version;                //!< [IN] Version number
    fmNvlNodeId_t           nodeId;                 //!< [IN] Switch node ID
    fmNvlMaintenanceState_t portMaintenanceState;   //!< [IN] Filter based  on Port Maintenance state
    unsigned int            numCages;               //!< [IN] Number of Cages requested (maxCagesPerL1SwitchNode or maxCagesPerL2SwitchNode)
    fmNvlCageInfo_t         *cageInfoList;          //!< [IN| [OUT] Information for list of Cages
} fmNvlGetCageInfoList_v1;

/// Typedef for \ref fmNvlGetCageInfoList_v1
typedef fmNvlGetCageInfoList_v1 fmNvlGetCageInfoList_t;
/// Version 1 for \ref fmNvlGetCageInfoList_v1
#define fmNvlGetCageInfoList_version1 MAKE_FM_PARAM_VERSION(fmNvlGetCageInfoList_v1, 1)
/// Latest version for \ref fmNvlGetCageInfoList_v1
#define fmNvlGetCageInfoList_version fmNvlGetCageInfoList_version1

/*********************************** Connection API specific Data Structures ************************************/

/*
 *  @brief NVLink COnnection Types
 *
 *  NVLink Connection Type that can be used to fetch the list of NVLink connections for a given NVLink Domain.
 */
typedef enum
{
    NVLINK_CONN_TYPE_ALL = 1,                //!< Dump the inter and intra node connections
    NVLINK_CONN_TYPE_GPU,                    //!< Dump the GPU connections
    NVLINK_CONN_TYPE_SWITCH,                 //!< Dump the Switch connections
    NVLINK_CONN_TYPE_MAX                     //!< Max
} fmNvlConnType_t;

/*
 *  @brief NVLink Connection Attributes
 *
 *  NVLink Connection Attributes that can be used to fetch the list of NVLink connections for a given NVLink Domain.
 */
typedef enum
{
    NVLINK_CONN_ATTR_EXPECTED = 1,             //!< All expected connections as per FM Topology
    NVLINK_CONN_ATTR_DISCOVERED,               //!< All discovered connections based on the connections type attribute(All/GPU/Switch)
    NVLINK_CONN_ATTR_EXPECTED_ACTIVE,          //!< All expected active connections based on the connection type attribute (All/Gpu/Switch)
    NVLINK_CONN_ATTR_EXPECTED_MISSING,         //!< All expected connections which are missing valid only for Switch connections
    NVLINK_CONN_ATTR_EXPECTED_INACTIVE,        //!< All expected discovered and inactive connections valid for All/Gpu/Switch connection type attributes
    NVLINK_CONN_ATTR_UNEXPECTED,               //!< All unexpected connections which are discovered valid only for Switch connections
    NVLINK_CONN_ATTR_MAX                       //!< Max
} fmNvlConnAttr_t;

/**
 * @brief NVLink Endpoint
 * 
 * Describes details of one end of a cable link.
 */
typedef struct
{
    fmNvlNodeId_t       nodeId;                             //!< Switch | Compute nodeId on one end of link
    char                hostname[FM_MAX_STR_LENGTH];        //!< Switch | Compute node hostname 
    unsigned int        switchOrGpuId;                      //!< Switch Physical | GPU Module ID (1-based)
    unsigned int        cageNum;                            //!< Cage number printed on chassis
    unsigned int        portNum;                            //!< Port number
    unsigned int        splitNum;                           //!< Port split number
    unsigned int        nvlPortNum;                         //!< NVSwitch NVLink port number
} fmNvlLinkEndPoint_t;

/**
 * @brief Describes a NVLink Connection Information
 */
typedef struct
{
    fmNvlLinkEndPoint_t endPointA;                          //!< One end of the link
    fmNvlLinkEndPoint_t endPointB;                          //!< Other end of the link
    unsigned int        connType;                           //!< Connection Type
    fmNvlConnState_t    connState;                          //!< Connection State
} fmNvlConnInfo_t;

/**
 * @brief fmNvlGetConnCount()
 * 
 * Structure to return the NVLink Connection Count. 
 */
typedef struct
{
    unsigned int       version;	                            //!< [IN] Version number
    fmNvlConnType_t    connType;                            //!< [IN] Connection Type
    fmNvlConnAttr_t    connAttr;                            //!< [IN] NVLink connection attribute
    fmNvlNodeId_t      nodeId;                              //!< [IN] Switch | Compute node ID (Optional) - Use 0 for all node connections associatd with NVLink Domain
    unsigned int       numConns;                            //!< [OUT] Number of matching connections
    char               timeStamp[FM_MAX_STR_LENGTH];        //!< [OUT] Timestamp (UTC format - yyyy-mm-dd hh.mm.ss ) of last GFM connection update
} fmNvlGetConnCount_v1;

/// Typedef for \ref fmNvlGetConnCount_v1
typedef fmNvlGetConnCount_v1 fmNvlGetConnCount_t;
/// Version 1 for \ref fmNvlGetConnCount_v1
#define fmNvlGetConnCount_version1 MAKE_FM_PARAM_VERSION(fmNvlGetConnCount_v1, 1)
/// Latest version for \ref fmNvlGetConnCount_v1
#define fmNvlGetConnCount_version fmNvlGetConnCount_version1

/**
 * @brief fmNvlGetConnInfoList()
 * 
 * Structure to return NVLink connection information based on connType and connAttr 
 */
typedef struct
{
    unsigned int       version;	                            //!< [IN] Version number
    unsigned int       connType;                            //!< [IN] Connection type
    unsigned int       connAttr;                            //!< [IN] NVLink connection attribute
    unsigned int       numConns;                            //!< [IN|OUT] Number of NVLink connections
    fmNvlNodeId_t      nodeId;                              //!< [IN] Switch | Compute node ID (Optional) - Use 0 for all node connections associatd with NVLink Domain
    fmNvlConnInfo_t    *connInfoList;                       //!< [IN|OUT] Information of NVLink connections
    char               timeStamp[FM_MAX_STR_LENGTH];        //!< [OUT] Timestamp (UTC format - yyyy-mm-dd hh.mm.ss ) of last GFM connection dump
} fmNvlGetConnInfoList_v1;

/// Typedef for \ref fmNvlGetConnInfoList_v1
typedef fmNvlGetConnInfoList_v1 fmNvlGetConnInfoList_t;
/// Version 1 for \ref fmNvlGetConnInfoList_v1
#define fmNvlGetConnInfoList_version1 MAKE_FM_PARAM_VERSION(fmNvlGetConnInfoList_v1, 1)
/// Latest version for \ref fmNvlGetConnInfoList_v1
#define fmNvlGetConnInfoList_version fmNvlGetConnInfoList_version1

/*********************************** Maintence API specific Data Structures ************************************/

/**
 * @brief Describes a port associated with a Switch node
 */
typedef struct {
    fmNvlNodeId_t       nodeId;         //!< Switch node ID
    unsigned int        cageNum;        //!< Cage Number (1-based); Use 0 to refer to all cages associated with nodeId
    unsigned int        portNum;        //!< Port Number (1-based); Use 0 to refer to all ports associated with cageNum
} fmNvlPort_t;

/**
 * @brief fmNvlSetMaintenanceOnPortList() and fmNvlClearMaintenanceOnPortList()
 *
 * Structure to set or clear maintenance on a list of Ports associated with Switch nodes 
 */
typedef struct
{
    unsigned int        version;        //!< [IN] Version number
    unsigned int        numPorts;       //!< [IN] Number of Ports
    fmNvlPort_t         *portList;      //!< [IN] List of Ports
} fmNvlPortList_v1;

typedef fmNvlPortList_v1    fmNvlPortList_t;
/// Version 1 for \ref fmNvlPortList_v1
#define fmNvlPortList_version1 MAKE_FM_PARAM_VERSION(fmNvlPortList_v1, 1)
/// Latest version for \ref fmNvlPortList_v1
#define fmNvlPortList_version fmNvlPortList_version1

/**
 * fmNvlSwitchNode_t
 *
 * Structure to add|remove switch node to|from the running NVLink domain.
 */
typedef struct
{
    fmNvlNodeId_t       nodeId;                           //!< [IN] L1|L2 Switch Node
    char                addressInfo[FM_MAX_STR_LENGTH];   //!< Switch Node IPv4/IPv6 address
    char                hostname[FM_MAX_STR_LENGTH];      //!< Switch Node hostname
} fmNvlSwitchNode_t;

/**
 * fmNvlAddSwitchNodeList() and fmNvlRemoveSwitchNodeList()
 *
 * Structure to add|remove switch node to|from the running NVLink domain.
 */
typedef struct
{
    unsigned int            version;        //!< [IN] Version number
    unsigned int            numNodes;       //!< [IN] Number of Switch Nodes
    fmNvlSwitchNode_t       *nodeList;      //!< [IN] List of Switch Nodes
} fmNvlSwitchNodeList_v1;

typedef fmNvlSwitchNodeList_v1    fmNvlSwitchNodeList_t;

/// Version 1 for \ref fmNvlSwitchNodeList_v1
#define fmNvlSwitchNodeList_version1 MAKE_FM_PARAM_VERSION(fmNvlSwitchNodeList_v1, 1)
/// Latest version for \ref fmNvlSwitchNodeList_v1
#define fmNvlSwitchNodeList_version fmNvlSwitchNodeList_version1

#ifdef __cplusplus
}
#endif

#endif /* NV_FM_NVL_TYPES_H */
