/*******************************************************************************
 * (c) Copyright 2015 Microsemi Corporation.  All rights reserved.
 *
 *
 *
 * SVN $Revision: $
 * SVN $Date: $
 */

#ifndef MA_H_
#define MA_H_

/**
 * @file
 * @brief The Maintenance Association API.
 *
 * ma.h defines the structs, data types and functions used to interact with
 * Maintenance Association (MA) objects.
 */

#include <api_oam_sdk/common/types/inc/mr_api_types.h>
#include <api_oam_sdk/maintenance_domain/inc/md.h>
#include "egl_types.h"

/**
 * @brief Defines indices for 'Writable' parameters in an MA.
 *
 * This data type defines the indices for valid writable
 * parameters that can be selected when writing to an MA object.
 */
typedef enum
{
	maParam_maMhfCreation = 1,				//!< Mep Half Function creation option
	maParam_maMhfIdPermission,				//!< What, if anything, is to be included in the Sender ID TLV
	maParam_maCcmInterval,					//!< The CCM interval
	maParam_maFaultAlarmNetAddress,			//!< The network address to which Fault Alarms (12.14.7.7) are to be transmitted
	maParam_maMepIdListAdd,					//!< Add a mepID to the list of MEP IDs on this MA
	maParam_maMepIdListRemove,				//!< Remove a mepID from the list of MEP IDs on this MA
	maParam_maMEFPortStatusTlvEnable,		//!< Enable or disable the sending of port Status TLV on CCM
	maParam_maMEFInterfaceStatusTlvEnable	//!< Enable or disable the sending of interface Status TLV on CCM
} maWrParam_t;

/**
 * @brief Defines the valid Intervals that can be chosen CCMs in an MA.
 *
 * This data type defines the valid CCM Intervals that
 * can be selected for a MA object.
 */
typedef enum
{
	ccmIntervalInvalid	= 0,
	ccmInterval300Hz 	= 1,
	ccmInterval10ms 	= 2,
	ccmInterval100ms 	= 3,
	ccmInterval1s 		= 4,
	ccmInterval10s 		= 5,
	ccmInterval1min 	= 6,
	ccmInterval10min 	= 7
} ccmInterval_t;

/**
 * @brief Defines the valid MA name types.
 *
 * This data type defines the valid MA name types that can
 * be used when creating a MA object.
 */
typedef enum {
	ma_primaryVid 		= 1,
	ma_characterString 	= 2,
	ma_unsignedInt16 	= 3,
	ma_rfc2685VpnId 	= 4,
	ma_ituY1731_32		= 32
} maNameType_t;

/**
 * @brief Defines the valid MEP Half Function creation actions
 */
typedef enum {
	ma_defMHFnone 		= 1,
	ma_defMHFdefault 	= 2,
	ma_defMHFexplicit	= 3,
	ma_defMHFdefer		= 4
} maMhfCreation_t;

/**
 * @brief The set of Sender ID TLV options
 *
 * Each value indicates what, if anything, is to be included in the Sender ID TLV
 */
typedef enum
{
	ma_sendIdNone			= 1,
	ma_sendIdChassis		= 2,
	ma_sendIdManage			= 3,
	ma_sendIdChassisManage 	= 4,
	ma_sendIdDefer			= 5
} maMhfIdPermission_t;

/**
 * @brief The set of valid Service Selector types
 *
 */
typedef enum
{
	ss_vlanId	= 1,
	ss_isid		= 2,
	ss_tesid	= 3,
	ss_segid	= 4
} serviceSelector_t;

typedef char		maName_t[45+1];				//!< Character array to hold the MD name. The last character must always be 0.
typedef uint32_t	maIndex_t;					//!< Defines the type for a MD MIB Index. A value of 0 is an invalid Index.
typedef uint32_t	serviceSelectorId_t;		//!< Defines the type for a Service Selector ID. A value of 0 is an invalid ID.

/**
 * @brief This is used when reading Component information about the MA.
 */
typedef struct
{
	serviceSelectorId_t	primarySelectorIdOrNone;//!< Primary service selector Id or None (0)
	uint16_t			numVids;				//!< Indicates the number of VLan IDs associated with this MA
	serviceSelector_t	primarySelectorType;	//!< Primary service selector type
	tagType_t			tagType;				//!< Indicates the tag type if any to be used on this MA
	maMhfCreation_t		mhfCreation;			//!< Mep Half Function creation
	maMhfIdPermission_t	mhfIdPermission;		//!< What if anything to put in sender ID TLV
} maCompInfo_t;

/**
 * @brief This is used when reading Network information about the MA.
 */
typedef struct
{
	maName_t			name;					//!< The MA name value.
	maNameType_t		type;					//!< The MA name type.
	ccmInterval_t		ccmInterval;			//!< The ccm Interval.
} maNetInfo_t;

/**
 * @brief This is used when reading MEF (Y1731) Network information about the MA.
 */
typedef struct
{
	bool			y1731Compliant;				//!< A boolean flag to indicate whether the MEG ID/MAID for this MEG operates in conformance with 802.1ag (if FALSE) or Y.1731 (if TRUE).
	maNameType_t	megIdFormat;				//!< This indicates the MEG name format. This is read only. Use type field in maCreate() to set name format.
	mdLevel_t		megLevel;					//!< This indicates the MEG Level. This is read only. Use the level field in mdCreate() to set the MEG level.
} maMEFNetInfo_t;

/**
 * @brief This is used when reading MEF (Y1731) Component information about the MA.
 */
typedef struct
{
	uint32_t	connectivityStatusInterval;		//!< A configurable time interval (in ms) to detect a change in Connectivity Status.
	uint32_t	peerMepInfoAgingTime;			//!< The period of time (in ms) after which an instance in the dot1agCfmMepDbTable is removed if a valid CCM has not been received by the local MEP
	bool		portStatusTlvIncluded;			//!< Indicates whether a Port Status TLV is included in CCM frame transmission.
	bool		interfaceStatusTlvIncluded;		//!< Indicates whether a Interface Status TLV is included in CCM frame transmission.
} maMEFCompInfo_t;

/**
 * @brief This is used when reading MEF (Y1731) Network/Component information about the MA.
 */
typedef struct
{
	maMEFNetInfo_t	maMEFNetInfo;				//!< MEF Network Specific information
	maMEFCompInfo_t maMEFCompInfo;				//!< MEF Component Specific information
} maMEFInfo_t;

/**
 * @brief	Create a new Maintenance Association (MA)
 *
 * Create a new Maintenance Association (MA) on the MD identified by mdIndex. The MA Index to
 * use for this new MA should be maIndex.
 * The maName and type must be provided to uniquely identify the MA.
 * vLanList is a pointer to an array of vLan IDs (or Service IDs). The end of the list is
 * identified with a zero value. The vLanList array length is limited to MAX_NUM_MEPS for the device.
 * tagType value is used to identify what tag type if any to use on CFM services in this MA.
 * If y1731Compliant is true then the 'type' value for the MA must be 'ma_ituY1731_32' and the
 * name type for the parent MD (identified by mdIndex) must be 'md_none'. This will then
 * create a Y1731 MEG group. The MEG level is set by the MD level set in the MD when it was
 * created.
 *
 * @param[in]	mdIndex The MIB Index of the MD this MA is to be added to
 * @param[in]	maIndex The MA MIB index to use for this MA.
 * @param[in]	maName A pointer to the MA name.
 * @param[in]	type The MA name type.
 * @param[in]	vLanList A pointer to a list of vLans associated with this MA, list must be terminated with a '0' entry.
 * @param[in]	tagType Identifies the tag type to use for the vlan, if any.
 * @param[in]	y1731Compliant Ahis should be set to true to create a y1731 compliant MA (MEG).
 *
 * @returns
 * \li  1: Operation rejected due to invalid MD Index
 * \li  2: Operation rejected due to invalid Maintenance Association Name
 * \li  3: Operation rejected due to duplicate Maintenance Association Name
 * \li  4: (NA) Operation rejected because creation of this MA would exceed the number of MD Levels supported by this device
 * \li  5: Operation rejected due to invalid VLANs
 * \li  9: Operation accepted
 * \li -1: Operation rejected due to invalid MA Index
 * \li -2: Operation rejected due to invalid tag Type
 * \li -3: Operation rejected due to incorrect MD Name Type (%d). For y1731 it must be md_none (1)
 * \li -4: Operation rejected due to incorrect MA Name Type (%d). For y1731 it must be ma_ituY1731_32 (32)
 * \li -5: Operation rejected due to insufficient resources
 */
int maCreate(mdIndex_t mdIndex, maIndex_t maIndex, char* maName, maNameType_t type, uint16_t *vLanList, tagType_t tagType, bool y1731Compliant);

/**
 * @brief Read the next entry in the MA List
 *
 * Read the next entry in the MA List. If prevMaIndex is 0 it
 * returns the maIndex of the first MA entry or 0 if there are
 * no MA entries. If a valid prevMaIndex is provided it returns
 * the maIndex of the next MA in the list.
 *
 * @param[in] mdIndex The MD index of the parent MD.
 * @param[in] prevMaIndex This is the previous return value from the function or 0
 * @return	maIndex of the next entry or 0 if no more entries
 */
maIndex_t maReadList(mdIndex_t mdIndex, maIndex_t prevMaIndex);

/**
 * @brief	Delete the MA with the supplied MD and MA MIB index
 *
 * This will delete the selected MA and all its child objects.
 *
 * @param[in] mdIndex The MD index of the parent MD.
 * @param[in] maIndex The MA index of the MA to delete.
 *
 * @returns
 * \li 1: Operation rejected due to invalid or nonexistent Maintenance Association.
 * \li 2: Operation accepted.
 */
int maDelete(mdIndex_t mdIndex, maIndex_t maIndex);

/**
 * @brief	Read the information for the MA	selected by mdIndex and maIndex
 *
 * Read information related to this MA. It is possible to request information in specific groupings.
 * If information for a specific group is desired then a pointer to a data structure to hold that information
 * must be provided. If a NULL pointer is supplied for a group then that information is not read and returned.
 * Information is only valid if the return value is 2.
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the MA to read from
 * @param[out] maNetInfo A pointer to a maNetInfo data type or NULL. If not NULL its values will be updated
 * @param[out] maCompInfo A pointer to a maCompInfo data type or NULL. If not NULL its values will be updated
 * @param[out] maMEFInfo A pointer to a maMEFInfo data type or NULL. If not NULL its values will be updated
 * @param[out] vLanList A pointer to a array of uint16_t or NULL. If not NULL (AND maCompInfo is not NULL) its values will be updated with the list of vLans associated with this MA; max array length = MAX_NUM_MEPS+1 and the end of the list is indicated by a value of 0
 * @param[out] mepIdList A pointer to a array of mepIds or NULL. If not NULL its values will be updated with the list of mepIds associated with this MA; max array length = MAX_NUM_MEPS+1 and the end of the list is indicated by a value of 0
 * @param[out] alarmNetAddress If the value of alarmNetAddress is not NULL its values will be updated with the IPV4 fault alarm address associated with this MA
 *
 * @returns
 * \li 1: Operation rejected due to invalid or nonexistent Maintenance Association
 * \li 2: Operation accepted
 */
int maRead(mdIndex_t mdIndex, maIndex_t maIndex, maNetInfo_t *maNetInfo, maCompInfo_t *maCompInfo, maMEFInfo_t *maMEFInfo, uint16_t *vLanList, mepId_t *mepIdList, networkAddress_t *alarmNetAddress);

/**
 * @brief	Write a new value to the selected MA parameter
 *
 * Write a new value to a writable parameter of the MA. The maParm value is used to
 * select one of the valid writable parameters (listed above) and the paramValue is
 * a pointer to the new value. The data type of the parameter (also listed above)
 * must be valid for the parameter or errors/misconfigurations may occur.
 *
 * The writable parameters for an MA and the associated data type are:
 * maParam_maMhfCreation					type = serviceSelector_t
 * maParam_maMhfIdPermission 				serviceSelectorId_t
 * maParam_maCcmInterval 					ccmInterval_t
 * maParam_maFaultAlarmNetAddress 			networkAddress_t
 * maParam_maMepIdListAdd,					mepId_t
 * maParam_maMepIdListRemove				mepId_t
 * maParam_maMEFPortStatusTlvEnable			bool
 * maParam_maMEFInterfaceStatusTlvEnable	bool
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the selected MA to read from
 * @param[in] maParam is an enum value that identifies the MA parameter to write to
 * @param[in] paramValue is a pointer to the new value for the selected parameter
 * @returns
 * \li  1: Operation rejected due to invalid or nonexistent Maintenance Association
 * \li  2: Operation rejected due to the selected managed object being Read-Only
 * \li  3: Operation rejected due to invalid value for parameter
 * \li  4: Operation accepted
 * \li -1: Operation rejected because MEPID is ID of a local MEP
 *

 */
int maWrite(mdIndex_t mdIndex, maIndex_t maIndex, maWrParam_t maParam, void *paramValue);

/**
 * @brief	Test if the MA (and associated MD) index selects a valid MA
 *
 * Test if the MA (and associated MD) index selects a valid MA on this device
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex is the MA index to verify selects a valid MA on this device
 * @return true if the index selects a valid MA on device, otherwise false.
 */
bool maIsMaMibIdxValid(mdIndex_t mdIndex, maIndex_t maIndex);

#endif /* MA_H_ */
