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

#ifndef LB_H_
#define LB_H_

#include <api_oam_sdk/common/types/inc/mr_api_types.h>
#include <api_oam_sdk/maintenance_association/inc/ma.h>

typedef struct
{
	uint32_t		nextLbmTransId;		// (x)Next sequence number/transaction identifier to be sent in a Loopback message
	uint32_t		_lbrIn;				// (y)Total number of valid, in-order Loopback Replies received
	uint32_t		_lbrInOutOfOrder;	// (z)The total number of valid, out-of-order Loopback Replies received
	uint32_t		__lbrInBadMsdu;		// (aa)The total number of LBRs received whose mac_service_data_unit did not match (except for the OpCode)that of the corresponding LBM (20.2.3).
	uint32_t		_lbrOut;			// (ad)Total number of Loopback Replies transmitted
	uint32_t		txLbmSeqNumber;		// The Transaction Id (nextLbmTransId) of the first LBM (to be) sent. The value returned is undefined if txLbmResultOK is false
	macAddress_t	txLbmDestMacAddr;
	mepId_t			txLbmDestMepId;
	uint16_t		txLbmNumMessages;	// The number of Loopback messages to be transmitted
	uint16_t		_txLbmDataTlvLength;// TODO: ** proprietary parameter - size of the data tlv to add
	uint8_t			_txLbmDataTlv[32];	// The data tlv payload TODO: ** may not be supported so limited in size for now
	prio_t			txLbmVlanPriority;	// Priority. 3 bit value to be used in the VLAN tag (default = CCM prio)
	bool			txLbmVlanDropEnable;// Drop Enable bit value to be used in the VLAN tag
	bool			txLbmResultOk;		// Indicates the result of the operation: -true: The Loopback Message(s) will be (or has been) sent. -false: The Loopback Message(s) will not be sent.
	bool			txLbmStatus;		// Set True to indicate another LBM is being transmitted
	bool			txLbmDestIsMepId;	// true indicates use txLbmDestMepId as the target mepId, false means use txLbmDestMacAddr
} mepLbInfo_t;

typedef struct
{
	bool			txLbmStatus;		// Set True to indicate another LBM is being transmitted or should be transmitted
	bool			txLbmDestIsMepId;	// true indicates use txLbmDestMepId as the target mepId, false means use txLbmDestMacAddr
	prio_t			txLbmVlanPriority;	// Priority. 3 bit value to be used in the VLAN tag (default = CCM prio)
	bool			txLbmVlanDropEnable;// Drop Enable bit value to be used in the VLAN tag
	macAddress_t	txLbmDestMacAddr;
	mepId_t			txLbmDestMepId;
	uint16_t		txLbmNumMessages;	// The number of Loopback messages to be transmitted
	uint8_t			_txLbmDataTlv[32];	// The data tlv payload TODO: ** may not be supported so limited in size for now
	uint16_t		_txLbmDataTlvLength;// size of the data tlv to add
} mepLbTxInfo_t;

typedef struct
{
	uint32_t			_numLbrInCrcError;	// contains the count of the total number of LBR messages received with CRC errors
	uint16_t			interval;			// specifies the period between LBM transmissions in an LB Session (granularity of 100ms required - range 0 to 60sec)
	uint16_t			frameSize;			// specifies the LBM frame size - only relevant if _txLbmDataTlvLength = 0
	uint16_t			timeout;			// units of 1ms - specifies the maximum amount of time to receive an LBR in response to a LBM. If a LBR is not received within the timeout value it is considered lost
	bool				multicastEnable;	// specifies whether a MEP uses unicast or multicast to send the ETH-LB messages
	dataPattern_t		_dataPattern;		// specifies the LBM data pattern included in a Data TLV - only relevant if _txLbmDataTlvLength = 0
	bool				_testTlvIncluded;	// Indicates whether a Test TLV or Data TLV is included - only relevant if _txLbmDataTlvLength = 0
	testTlvPattern_t	_testTlvPattern;	// specifies the type of test pattern to be sent in the LBM frame - only relevant if _txLbmDataTlvLength = 0
} mepLbMefInfo_t;

typedef struct
{
	bool				multicastEnable;	// specifies whether a MEP uses unicast or multicast to send the ETH-LB messages
	dataPattern_t		_dataPattern;		// specifies the LBM data pattern included in a Data TLV
	bool				_testTlvIncluded;	// Indicates whether a Test TLV or Data TLV is included
	testTlvPattern_t	_testTlvPattern;	// specifies the type of test pattern to be sent in the LBM frame
	uint16_t			interval;			// specifies the period between LBM transmissions in an LB Session (granularity of 100ms required - range 0 to 60sec)
	uint16_t			frameSize;			// specifies the LBM frame size - only relevant if _txLbmDataTlvLength = 0
	uint16_t			timeout;			// units of 1ms - specifies the maximum amount of time to receive an LBR in response to a LBM. If a LBR is not received within the timeout value it is considered lost
} mepLbMefTxInfo_t;

typedef enum
{
	lb_continuousMode	= 0,
	lb_burstMode		= 1
} lbMode_t;

typedef struct
{
	uint32_t		pktsPerBurst;	// The Number of packets in each burst. Applies only in burst mode.
	uint32_t		numberOfBursts;	// The number of bursts to send in burst mode. Applies only in burst mode.
	uint32_t		interBurstTime;	// The time, in Micro-seconds, between bursts. Applies only in burst mode.
	uint16_t		transmitRate;	// The transmit packet rate, in MBits, to use when transmitting.
	bool			enableAdvMode;	// This is used to place the LB in advanced mode. The other settings have no meaning if enableAdvMode is false
	bool			txActive;		// Set to true to enable Transmit of LBMs. Set False to disable transmit of LBMs
	//uint16_t		frameSize;		// The packet size in bytes (including CRC)
	lbMode_t		lbMode;			// Set the loopack operating mode (continuous or burst)
} mepLbTxAdvanceCfg_t;

typedef lbStats_t mepLbAdvanceStats_t;


/**
 * @brief Configure loopback on a local MEP to transmit one or more LBM packets
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the MEPID of the local MEP this Loopback service is on
 * @param[out] mepLbTxInfo This holds the parameters used to configure basic CFM loopback
 * @param[in] mepLbMefTxInfo This holds the parameters used to configure additional loopback options defined by MEF
 * @return values:
 *  1: Operation rejected due to nonexistent MEP
 *  2: Operation rejected due to invalid number of LBMs to be transmitted (1 < must be > MAX_LB_NUM_BURSTS)
 *  3: Operation rejected due to too much data to be transmitted (data TLV too long)
 *  4: Operation rejected due to invalid priority
 *  6: Operation accepted. The LBMs will be (or have been) sent
 *  7: Operation rejected due to insufficient LB resources
 * -1: Operation rejected due to inter packet time too large (MAX=0x1FFFFF)
 * -2: Operation rejected due to invalid mepLbTxInfo. It cannot be NULL.
 * -3: Operation rejected due to invalid mep state. (link is down to the selected remote MEP)
 *
 * Use the information provided in mepLbTxInfo to configure and begin transmitting LBM packets on the selected local MEP
 */
int lbTransmit(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, mepLbTxInfo_t *mepLbTxInfo, mepLbMefTxInfo_t *mepLbMefTxInfo);

/**
 * @brief Stop/Disable a loopback on a local MEP.
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the MEPID of the local MEP this Loopback service is on
 * @return values:
 *  1: Operation rejected due to nonexistent MEP
 *  2: Operation accepted.
 *
 */
int lbAbort(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId);

/**
 * @brief Read the MAC address's of peer MEPs that replied to a Multicast LBM
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the MEPID of the local MEP this Loopback service is on
 * @param[in] lbmSeqNum Is the sequence number used in the Multicast LMR. This value is ignored in this version.
 * @param[in] receiveOrder Is an index value used to read the MAC value in their received order.
 * @param[out] macAddress is a pointer to a macAddress_t struct that will be updated with the selected MAC
 * @return values:
 *  -1: The Index supplied is invalid or no Multicast LB session was run on the indexed MEP
 *  0: The receiveOrder value is outside the valid bounds
 *  1: A MAC address has been returned in the macAddress struct.
 *
 * Repeated Calls to this function can be used to retrieve all the MAC addresses of any peer MEPs that
 * responded to the multicast LBM.
 */
int lbReadNextMcMAC(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, uint32_t lbmSeqNum, uint8_t receiveOrder, macAddress_t macAddress);

/**
 * @brief Configure Advanced Mode loopback options for a MEP
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the MEPID of the local MEP this Loopback service is on
 * @param[out] mepLbTxAdvanceCfg This provides parameters to configure Advanced loopback features specific to this device
 * @return values:
 *  1: Operation rejected due to nonexistent MEP
 *  2: Operation rejected due to invalid number of LBMs to be transmitted
 *  3: Operation rejected due to invalid Transmit Rate
 *  4: Operation accepted. The LBMs will be (or have been) sent
 *  5: Operation rejected due to insufficient LB resources
 *
 * The information provided in mepLbTxAdvanceCfg is used to configure Loopback to operate in an advanced mode. This function
 * should be called prior to calling lbTransmit(). The advanced setting must be configured and enableAdvMode must be set to
 * true for them to take effect. If enableAdvMode is true when lbTransmit() is called then the advanced mode setting will
 * be used to configure loopback. If lbMode is set to lb_continuousMode then a call to lbTransmitAdvanced(), with txActive
 * set to false or enableAdvMode set to false, is required to stop continuous LBM.
 */
int lbTransmitAdvanced(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, mepLbTxAdvanceCfg_t *mepLbTxAdvanceCfg);

/**
 * @brief Configure Advanced Mode loopback options for a MEP
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the MEPID of the local MEP this Loopback service is on
 * @param[out] mepLbAdvanceStats A pointer to a mepLbAdvanceStats_t which will be updated with the advanced stats information
 * @return values:
 *  1: Operation rejected due to nonexistent MEP
 *  2: Operation accepted.
 *
 * This function is used to read back the advanced loopback stats. These stats are available even if loopback
 * is operated in normal mode.
 */
int lbReadAdvancedStats(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, mepLbAdvanceStats_t *mepLbAdvanceStats);

#endif /* LB_H_ */
