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

#ifndef SVC_EVC_H_
#define SVC_EVC_H_

#include <api_oam_sdk/common/types/inc/mr_api_types.h>
#include <api_oam_sdk/service_bwp/inc/svc_bwp.h>
#include <api_oam_sdk/service_l2cp/inc/svc_l2cp.h>
#include "egl_types.h"

#define MAX_MTU_SIZE	(9600)

typedef uint32_t	evcIndex_t;

typedef enum {

	evcType_pointToPoint			= 1,	// EVC Point-to-Point service, used for EPL and EVPL services
	evcType_multipointToMultipoint	= 2,	// EVC Multipoint-to-Multipoint Service, used for EP-LAN and EVP-LAN services
	evcType_rootedMultipoint		= 3		// EVC Rooted-Multipoint Service, used for EP-Tree and EVP-Tree services
} evcServiceType_t;

typedef enum {
	preserve	= 1,				// The CE-VLAN Id/CoS is preserved. The ingress CE-VLAN Id/CoS is the CE-VLAN CoS at the egress UNI
	noPreserve	= 2					// The CE-VLAN Id/CoS is not preserved. The ingress CE-VLAN Id/CoS may not be the CE-VLAN Id/CoS at the egress UNI
} preserve_t;

typedef enum {
	dt_discard			= 1,
	dt_unconditional	= 2,
	dt_conditional		= 3
} deliveryType_t;

typedef enum {
	state_locked		= 1,
	state_unlocked		= 2
} adminState_t;

typedef enum {
	evcParam_mtuSize		= 1,
	evcParam_l2cpGrpIndex	= 2
} evcWrParam_t;

typedef enum {
	evcUniParam_evcUniType	= 1
} evcUniWrParam_t;

typedef struct evcCfg_s {
	uint32_t				mtuSize;				// Indicates the configured EVC maximum service frame format size. Range = (1522)..16284
	l2cpGrpIndex_t			l2cpGrpIndex;			// The index number of the associated l2cp profile group. A value of 0 indicates that there is no associated l2cpGrp.
	evcServiceType_t		evcServiceType;			// Configures the EVC service type for the ME-NE.
	preserve_t				ceVlanIdPreservation;	// Configures EVC CE-VLAN Id preservation.
	preserve_t				ceVlanCosPreservation;	// Configures EVC CE-VLAN CoS preservation.
	deliveryType_t			unicastDelivery;		// Configures EVC Unicast delivery condition.
	deliveryType_t			multicastDelivery;		// Configures EVC Multicast delivery condition.
	deliveryType_t			broadcastDelivery;		// Configures EVC Broadcast delivery condition.
	adminState_t			adminState;				// Specifies the administrative state of the EVC. Default state is 'unlocked'
} evcCfg_t;

typedef enum {
	evcOpSt_enabled	= 1,			// The EVC is able to ingress and egress service frames and has been set to active.
	evcOpSt_disabled	= 2, 		// The EVC is not able to ingress and egress service frames, has detected an operational failure condition, or has failed an internal test.
	evcOpSt_testing		= 3,		// The EVC has been placed into a test mode, either a troubleshooting mode or a test mode.
	evcOpSt_unknown		= 4			// The EVC is unable to report the operational state.
} evcOpSt_t;

typedef struct evcStatus_s {
	uint32_t	maxMtuSize;			// Indicates the EVC maximum configurable service frame format size. This is fixed at TODO-MAX MTU sise
	uint32_t	maxNumUni;			// Indicates the maximum number of UNIs in an EVC. This is a fixed value of 2 for Eagle.
	evcOpSt_t	operationalState;	// Indicates the operational state (current capability) of the EVC.
} evcStatus_t;

typedef enum {
	eu_root		= 1,				// Valid setting for all service types. A UNI set to this value may send frames to UNIs configured as 'root' or 'leaf'
	eu_leaf		= 2,				// Valid setting for Root-Multipoint EVCs only. A UNI set to this value may send frames to UNIs 'root'
	eu_unknown	= 3					// UNI port is not configured or illegally configured. This value cannot be written, but is only returned when the type is unknown.
} evcUniType_t;

typedef struct evcUniCfg_s {
	evcUniType_t	evcUniType;		// This object configures UNI type on an EVC.
}evcUniCfg_t;

typedef enum {
	st_epl		= 1,	// Ethernet Private Line Service (EPL) Point-to-Point EVC, all to one bundling
	st_evpl		= 2,	// Ethernet Virtual Private Line (EVPL) Point-to-Point EVC, bundling and/or multiplexing
	st_eplan	= 3,	// Ethernet Private LAN Service (EP-LAN) Multipoint-to-Multipoint EVC, all to one bundling
	st_evplan	= 4,	// Ethernet Virtual Private LAN Service (EVP-LAN) Multipoint-to-Multipoint EVC, bundling and/or multiplexing
	st_eptree	= 5,	// Ethernet Private Tree Service (EP-Tree) Rooted-Multipoint EVC, all to one bundling
	st_evptree	= 6		// Ethernet Virtual Private Tree Service (EVP-Tree) Rooted-Multipoint EVC, bundling and/or multiplexing
} serviceType_t;

typedef enum {
	evcPerUniParam_serviceType			= 1,	// The write parameter value to select the service Type.
	evcPerUniParam_ceVlanMap			= 2,	// The write parameter value to select the ceVlanMap.
	evcPerUniParam_ingressBwpGrpIndex	= 3,	// The write parameter value to select the ingressBwpGrpIndex.
	//evcPerUniParam_egressBwpGrpIndex	= 4		// ** NOT SUPPORTED ** The write parameter value to select the egressBwpGrpIndex.
	evcPerUniParam_outerTagVLan			= 5,	// The write parameter value to select the outerTagVLan value
	evcPerUniParam_tagAction			= 6,	// The write parameter value to select the tag Action value
	evcPerUniParam_tagType				= 7		// The write parameter value to select the tag type
} evcPerUniWrParam_t;

typedef struct svcEvcPerUniCfg_s {
	char			ceVlanMap[256];			// indicates the CE-VLANs associated with the specific EVC on a UNI.
	bwpGrpIndex_t	ingressBwpGrpIndex;		// The index number of the associated ingress bandwidth profile group. A value of 0 indicates that there is no associated bwpGrp.
	bwpGrpIndex_t	egressBwpGrpIndex;		// The index number of the associated egress bandwidth profile group. A value of 0 indicates that there is no associated bwpGrp.
	serviceType_t	serviceType;			// indicates the specific Ethernet service type. The value is derived from the EVC object 'mefServiceEvcCfgType' and the UNI object 'mefServiceUniCfgBundlingMultiplex'.
} evcPerUniCfg_t;


typedef struct evcPerUniEglCfg_s {
	uint16_t		outerTagVLan;			// Specify the VLan value to use as the outer tags vlan
	tagAction_t		tagAction;				// Specify what action to take with tags on ingress packets before forwarding them to the egress port
	pushTag_t		tagType;				// Specify what tag type should be used is if tagAction is 'push'
} evcPerUniEglCfg_t;

/**
 * @brief Returns the next available EVC index
 *
 * @return The next available EVC index.
 */
evcIndex_t	svcEvcGetNextIndex(void);

/**
 * @brief Read the next entry in the list of configured EVCs.
 *
 * Read the next entry in the list of configured EVCs. If evcIndex is 0 it
 * returns the evcIndex of the first EVC entry or 0 if there are
 * no EVC entries. If a valid evcIndex is provided it returns
 * the mdIndex of the next MD in the list.
 *
 * @param[in] nextEvcIdx The EVC Index from a previous call to this function or 0.
 * @return	evcIndex of the next entry or 0 if no more entries.
 *
 */
evcIndex_t svcEvcReadList(evcIndex_t nextEvcIdx);

/**
 * @brief Create a new EVC service.
 *
 * Create a new EVC service using the configuration
 * parameters provided.
 *
 * @param[in] evcIndex the index value of EVC to create.
 * @param[in] evcCfg A pointer to a evcCfg_t data type  containing configuration values.
 * @return
 * \li  1: Operation rejected due to invalid Service Type
 * \li  2: Operation rejected due to invalid mtuSize
 * \li  3: Operation rejected due to invalid l2cpGrpIndex
 * \li  4: Operation rejected due to invalid adminState
 * \li  5: Operation accepted
 * \li -1: Operation rejected due to invalid Evc Index
 * \li -2: Operation rejected due to evcCfg = NULL
 * \li -3: Operation rejected due to insufficient resources
 */
int svcEvcCreate(evcIndex_t evcIndex, evcCfg_t *evcCfg);

/**
 * @brief	Delete the EVC with the supplied evcIndex.
 *
 * This will delete the selected EVC and any associations with UNIs.
 *
 * @param[in] evcIndex the index value of EVC to delete.
 * @returns
 * \li 1: Operation rejected due to invalid or nonexistent EVC
 * \li 2: Operation accepted
 *
 */
int svcEvcDelete(evcIndex_t evcIndex);

/**
 * @brief Read the service EVC configuration.
 *
 * Read information related to this service EVC. If a NULL pointer is supplied for
 * evcCfg then no information is returned for that parameter.
 * Information is only valid if the return value is 2.
 *
 * @param[in] evcIndex the index value of EVC to read from.
 * @param[out] evcCfg A pointer to a evcCfg_t data type or NULL. If not NULL its values will be updated.
 * @param[out] evcStatus A pointer to a evcStatus_t data type or NULL. If not NULL its values will be updated.
 * @return
 * \li 1: Operation rejected due to invalid or nonexistent EVC index.
 * \li 2: Operation accepted.
 */
int svcEvcRead(evcIndex_t evcIndex, evcCfg_t *evcCfg, evcStatus_t *evcStatus);

/**
 * @brief	Write a new value to the selected service EVC parameter.
 *
 * The writable parameters for an service EVC and the associated data type are:
 *	evcParam_mtuSize		uint32_t
 *	evcParam_l2cpGrpIndex	l2cpGrpIndex_t  !!NOT SUPPORTED - a value of 0 is the only valid value
 *
 * Write a new value to a writable parameter of the service EVC. The wrParam 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.
 *
 * @param[in] evcIndex the index value of EVC to write to.
 * @param[in] wrParam is an enum value that identifies the service UNI 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 EVC index
 * \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
 */
int svcEvcWrite(evcIndex_t evcIndex, evcWrParam_t wrParam, void *paramValue);
#if 0 // Not needed - simply write a valid type to 'create'
/*
 * ======================================================================================
 */

/**
 * @brief Assign the specified interface with an EVC service.
 *
 * Assign a UNI to an EVC service and apply the configuration
 * parameters provided.
 *
 * @param[in] iFace the index value of the UNI to assign to an EVC.
 * @param[in] evcIndex the index value of EVC to which the UNI is assigned.
 * @param[in] evcUniCfg A pointer to a evcUniCfg_t data type containing configuration values for the UNI_EVC assoociation.
 * @return
 * \li 1: Operation rejected due to invalid or nonexistent UNI(iFace) or EVC index.
 * \li 2: Operation accepted.
 */
int svcEvcUniCreate(iFace_t iFace, evcIndex_t evcIndex, evcUniCfg_t *evcUniCfg);

/**
 * @brief	Delete the EVC with the supplied iFace and evcIndex.
 *
 * This will delete the association between the selected UNI and EVC.
 *
 * @param[in] iFace the index value of the UNI to be removed from the EVC.
 * @param[in] evcIndex the index value of EVC.
 * @returns
 * \li 1: Operation rejected due to invalid or nonexistent UNI(iFace) or EVC index.
 * \li 2: Operation accepted
 *
 */
int svcEvcUniDelete(iFace_t iFace, evcIndex_t evcIndex);
#endif

/**
 * @brief Read the service EVC-UNI configuration for the specified interface and EVC.
 *
 * Read information related to this service EVC-UNI. If a NULL pointer is supplied
 * for evcUniCfg then no information is returned for that parameter.
 * Information is only valid if the return value is 2.
 *
 * @param[in] iFace the UNI index of the EVC-UNI to read from.
 * @param[in] evcIndex the EVC index of EVC-UNI to read from.
 * @param[out] evcUniCfg A pointer to a evcUniCfg_t data type or NULL. If not NULL its values will be updated.
 * @param[out] svcEvcPerUniCfg A pointer to a evcPerUniCfg_t data type or NULL. If not NULL its values will be updated.
 * @return
 * \li 1: Operation rejected due to invalid or nonexistent UNI(iFace) or EVC index.
 * \li 2: Operation accepted.
 */
int svcEvcUniRead(iFace_t iFace, evcIndex_t evcIndex, evcUniCfg_t *evcUniCfg);

/**
 * @brief	Write a new value to the selected service EVC-UNI parameter.
 *
 * The writable parameters for an service EVC-UNI and the associated data type are:
	evcUniParam_evcUniType		evcUniType_t
 *
 * Write a new value to a writable parameter of the service EVC-UNI. The wrParam 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.
 *
 * @param[in] iFace selects the UNI index of the EVC-UNI to write the parameter to.
 * @param[in] evcIndex is EVC index of EVC-UNI to write the parameter to.
 * @param[in] wrParam is an enum value that identifies the service UNI 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 UNI(iFace) or EVC index.
 * \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
 */
int svcEvcUniWrite(iFace_t iFace, evcIndex_t evcIndex, evcUniWrParam_t wrParam, void *paramValue);

/**
 * @brief Read the service Evc Per UNI configuration for the specified interface and UNI.
 *
 * Read information related to the specified service UNI and EVC. If a NULL pointer is supplied for
 * svcEvcPerUniCfg then no information is returned for that parameter.
 * Information is only valid if the return value is 2.
 *
 * @param[in] iFace is the index value of the interface to read from.
 * @param[in] evc is the index value of the evc to read from.
 * @param[out] svcIfaceCfg A pointer to a svcIfaceCfg_t data type or NULL. If not NULL its values will be updated.
 * @return
 * \li 1: Operation rejected due to invalid or nonexistent interface.
 * \li 2: Operation accepted.
 */
int svcEvcPerUniRead(iFace_t iFace, evcIndex_t evcIndex, evcPerUniCfg_t *evcPerUniCfg, evcPerUniEglCfg_t *evcPerUniEglCfg);

/**
 * @brief	Write a new value to the selected EVC per UNI parameter.
 *
 * The writable parameters for a service EVC Per UNI and the associated data type are:
	evcPerUniParam_serviceType			serviceType_t
	evcPerUniParam_ceVlanMap			char[256]
	evcPerUniParam_ingressBwpGrpIndex	bwpGrpIndex_t
	evcPerUniParam_outerTagVLan			uint16_t
	evcPerUniParam_tagAction			tagAction_t
	evcPerUniParam_tagType				pushTag_t
 *
 * Write a new value to a writable parameter of the service EVC per UNI. The wrParam 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.
 *
 * @param[in] iFace selects the interface to write the parameter to.
 * @param[in] evc is the index value of the evc to write to.
 * @param[in] wrParam is an enum value that identifies the service EVC per UNI 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 ceVlanMap contains the Management Vlan
 * \li 1: Operation rejected due to invalid or nonexistent iFace or EVC
 * \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 5: Operation rejected due to ceVlanMap contains a vlan that is already in use.
 *
 */
int svcEvcPerUniWrite(iFace_t iFace, evcIndex_t evcIndex, evcPerUniWrParam_t wrParam, void *paramValue);

#if 0
/*
 * TODO: add comment
 */
int svcEvcImplement(evcIndex_t evcIndex);
#endif
#endif /* SVC_EVC_H_ */
