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

#ifndef RFC2544_H_
#define RFC2544_H_

#include <api_oam_sdk/common/types/inc/mr_api_types.h>
#include <api_oam_sdk/maintenance_association/inc/ma.h>				// needed for mdLevel_t, mdIndex_t, etc.
#include <api_oam_sdk/performance_monitoring/inc/pm.h>				// needed for dateAndTime_t
#include <api_oam_sdk/service_activation/inc/service_activation.h>

#define MAX_FRAME_RATE_STEPS	(8)		// Sets the number of steps that can be recorded in the Frame Loss test

typedef enum {
	thruPutTest		= 1,
	delayTest		= 2,
	frameLossTest	= 3,
	backToBackTest	= 4
} rfc2544TestType_t;

typedef struct {
	uint32_t			stepSize;			// units are kbps (default = 1000 i.e. 1Mbps)
	uint32_t			maxRate;			// units are kbps (default = 1000000 i.e. 1000Mbps)
	uint32_t			minRate;			// units are kbps (default = 1000 i.e. 1Mbps)
	uint32_t			acceptedFrameLoss;	// units are 0.001% (default = 0)
	uint16_t			frameSizeList[MAX_NUM_FRAME_SIZES];	// Array of frame sizes to use (default = "512") values of 0 mean 'not-used'
	uint32_t			trialDuration;		// units are seconds (default = 60)
} throughPutCfg_t;

typedef throughPutCfg_t delayCfg_t;			// Delay configuration uses the exact same settings as throughput

typedef throughPutCfg_t frameLossCfg_t;		// Frame Loss configuration uses the exact same settings as throughput but acceptedFrameLoss is ignored

typedef struct {
	uint32_t			trialDuration;		// units are milli seconds (default = 2000)
	uint32_t			stepSize;			// The number of frames to increase/decrease the burst size by
	uint16_t			frameSizeList[MAX_NUM_FRAME_SIZES];	// Array of frame sizes to use (default = "512") values of 0 mean 'not-used'
	uint16_t			repeat;				// number of times to repeat the test (default = 50)
} backToBackCfg_t;

typedef struct {
	saFrameType_t		frameType;			// default = y1731_lbm_frames
	uint8_t				binaryDuration;		// The time in seconds for each step in the Throughput binary search. Range 1 to 10, default 2.
	mepIndices_t		targetMep;			// only valid if targetIsMep is true
	frameCfg_t			frameCfg;				// only valid if targetIsMep is false
	bool				targetIsMep;		// (default = true)
	bool				continueAfterErr;	// If true all tests are run even if one fails - if false stop if any test fails (default = false)
	bool				enThroughput;		// (default = false)
	bool				enDelay;			// (default = false)
	bool				enFrameLoss;		// (default = false)
	bool				enBackToBack;		// (default = false)
	throughPutCfg_t		throughPutCfg;
	delayCfg_t			delayCfg;
	frameLossCfg_t		frameLossCfg;
	backToBackCfg_t		backToBackCfg;
} rfc2544Cfg_t;

// --------------------- Throughput results -----------------
typedef struct {
	uint16_t			elapsedTime;		// Units are seconds - The number of number of seconds the test has been running
	uint16_t			frameSize;			// The frame size for which these results apply
	uint32_t			frameRate;			// units are kbps - the throughput rate achieved for this packet size
	testStatus_t		status;				// status of the throughput test for a specific packet size
} throughPutData_t;

typedef struct {
	throughPutData_t	data[MAX_NUM_FRAME_SIZES];	// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	dateAndTime_t		startTime;			// Time and date that the test was started - only valid if test is enabled
	dateAndTime_t		endTime;			// Time and date that the test completed - only valid if test runs
	testStatus_t		status;				// overall status of the throughput test
} throughPutResults_t;

// --------------------- Delay results -----------------
typedef struct {
	uint32_t			elapsedTime;		// Units are seconds - The number of number of seconds the test has been running
	uint32_t			frameRate;			// units are kbps - the throughput rate achieved for this packet size
	uint32_t			frameDelayMax;		// units are 1us - the Maximum Frame Delay measured at the throughput rate
	uint32_t			frameDelayMin;		// units are 1us - the Minimum Frame Delay measured at the throughput rate
	uint32_t			frameDelayAvg;		// units are 1us - the Average Frame Delay measured at the throughput rate
	uint32_t			frameDelayVarMax;	// units are 1us - the Maximum Frame Delay Variation measured at the throughput rate
	uint32_t			frameDelayVarMin;	// units are 1us - the Minimum Frame Delay Variation measured at the throughput rate
	uint32_t			frameDelayVarAvg;	// units are 1us - the Average Frame Delay Variation measured at the throughput rate
	uint16_t			frameSize;			// The frame size for which these results apply
	testStatus_t		status;				// status of the throughput test for a specific packet size
} delayData_t;

typedef struct {
	delayData_t			data[MAX_NUM_FRAME_SIZES];	// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	dateAndTime_t		startTime;			// Time and date that the test was started - only valid if test is enabled
	dateAndTime_t		endTime;			// Time and date that the test completed - only valid if test runs
	testStatus_t		status;				// overall status of the delay test
} delayResults_t;

// --------------------- Frame Loss results -----------------
typedef struct {
	uint32_t			elapsedTime;		// Units are seconds - The number of number of seconds the test has been running
	uint32_t			frameRate[MAX_FRAME_RATE_STEPS];			// units are kbps - the throughput rate achieved for this packet size
	uint32_t			frameLoss[MAX_FRAME_RATE_STEPS];			// units are 0.001%
	uint16_t			frameSize;			// The frame size for which these results apply
	uint8_t				numSteps;			// The number of steps recorded during Frame Loss test (max value = MAX_FRAME_RATE_STEPS);
	testStatus_t		status;				// status of the throughput test for a specific packet size
} frameLossData_t;

typedef struct {
	frameLossData_t		data[MAX_NUM_FRAME_SIZES];	// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	dateAndTime_t		startTime;			// Time and date that the test was started - only valid if test is enabled
	dateAndTime_t		endTime;			// Time and date that the test completed - only valid if test runs
	testStatus_t		status;				// overall status of the frameLoss test
} frameLossResults_t;

// --------------------- Back to back results -----------------
typedef struct {
	uint16_t			elapsedTime;		// Units are milliseconds - The number of number of milliseconds the test has been running
	uint16_t			frameSize;			// The frame size for which these results apply
	uint32_t			averageBurstSize;	// An average of the count of received packets for the test for this packet size
	testStatus_t		status;				// status of the test for a specific packet size
} backToBackData_t;

typedef struct {
	backToBackData_t	data[MAX_NUM_FRAME_SIZES];	// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	dateAndTime_t		startTime;			// Time and date that the test was started - only valid if test is enabled
	dateAndTime_t		endTime;			// Time and date that the test completed - only valid if test runs
	testStatus_t		status;				// overall status of the throughput test
} backToBackResults_t;

// --------------------- RFC2544 results -----------------
typedef struct {
	throughPutResults_t	throughPutResults;
	delayResults_t		delayResults;
	frameLossResults_t	frameLossResults;
	backToBackResults_t	backToBackResults;
} rfc2544Results_t;

/**
 * @brief Configure the device to run the RFC2544 tests
 *
 * @param[in] rfc2544Cfg this is a pointer to a rfc2544Cfg_t data structure that must be configured appropriately to run the tests
 * @return
 * \li  1: Operation rejected because rfc2544Cfg is a NULL pointer
 * \li  2: Operation rejected because the MEP identified by 'targetMep' could not be found
 * \li  3: Operation rejected because a SA test is running.
 * \li  4: Operation successful
 *
 */
int rfc2544Configure(rfc2544Cfg_t *rfc2544Cfg);

/**
 * @brief Start the RFC2544 tests using the current configuration
 *
 * @return
 * \li -1: Operation rejected because the target MEP's MAC address is unknown (CCMs must be enabled to learn MAC)
 * \li  1: Operation rejected because the port selected is down.
 * \li  2: Operation rejected because no tests are selected to run.
 * \li  3: Operation rejected because another Service activation test is already running
 * \li  4: Operation successful.
 */
int rfc2544Start(void);

/**
 * @brief Stop the current RFC2544 test
 *
 * @return
 * \li  1: Operation rejected because no RFC2544 test was running.
 * \li  2: Operation successful.
 */
int rfc2544Stop(void);

/**
 * @brief Read the status and results for the RFC2544 tests.
 *
 * @param[in] testStatus this is a pointer to a testStatus_t data type that will indicate the current state of the test.
 * @param[in] rfc2544Results this is a pointer to a rfc2544Results_t data struct that will be updated with any available test results
 * @return
 * \li  1: Operation successful
 *
 * This function can be called at any time while the tests are running or after they have completed.
 * If called while the tests are running:
 * final test results for any completed tests are provided (status = test_completed/test_failed)
 * and partial test results for actively running tests are given (status = test_running).
 * No results will be available for tests that have not yet been run but are due to be run (status = test_pending).
 * Tests that are not enabled to be run will have status = test_disabled.
 *
 */
int rfc2544Read(testStatus_t *testStatus, rfc2544Cfg_t *rfc2544Cfg, rfc2544Results_t *rfc2544Results);

#endif /* RFC2544_H_ */
