/* lwmpls_data.h 				*/
/* File that defines data structures and constants used	*/
/* for ligh wireles mpls.	*/

/****************************************/
/****************************************/

/* Protect against multiple includes. 	*/
#ifndef	_LWMPLS_DATA_H_INCLUDED_
#define _LWMPLS_DATA_H_INCLUDED_


/*-------------------------------------------------------------------*/

#include <omnetpp.h>
#include <map>
#include <vector>

#define LWMPLS_OUTPUT_LABEL 0
#define LWMPLS_INPUT_LABEL  1
#define LWMPLS_OUTPUT_LABEL_RETURN 2
#define LWMPLS_INPUT_LABEL_RETURN  3
#define	LWMPLS_MAX_LABEL     1000
/* Tiempo para garantizar que si me encuentro un etiqueta */
/*libre esta tambien habr� sido liberada por el resto de los nodos */
#define	LWMPLS_MIN_REUSE_TIME   LWMPLS_MAX_TIME*3

#define LWMPLS_EXTRACT  1
#define	LWMPLS_CHANGE   0
#define	LWMPLS_ACUMULATE   2



#define LWMPLS_STATUS_NOT_USE 0
#define	LWMPLS_STATUS_STBL   1
#define	LWMPLS_STATUS_PROC  2
#define	LWMPLS_STATUS_NOT_INIT 3




typedef struct LWMPLSKey 
{
		int label;
		uint64_t mac_addr;

		inline bool operator<(const LWMPLSKey& b) const
		{
			if (label!=b.label)
				return label<b.label;
			else
				return mac_addr<b.mac_addr;
		}

		inline LWMPLSKey & operator = (const LWMPLSKey& b)
		{
			label=b.label;
			mac_addr=b.mac_addr;
			return *this;
		}

		inline bool operator==(const LWMPLSKey& b) const
		{
			if ((label==b.label) && (mac_addr==b.mac_addr))
				return true;
			else
				return false;
		}
} LWMPLSKey;

typedef std::vector<uint64_t> RouteVector;

typedef struct   LWmpls_Forwarding_Structure : public cOwnedObject
{
		int 	input_label;
		int 	output_label;
		int     order;
		uint64_t     mac_address;
		uint64_t     input_mac_address;
		/* Return label, it's used in the return path */
		int     return_label_input;
		int     return_label_output;
		simtime_t   last_use;
		LWMPLSKey     key_output;
		LWMPLSKey     return_key_output;
		simtime_t     label_life_limit;
		RouteVector path;
		void keyOutput(int label, uint64_t mac_add){ key_output.label = label; key_output.mac_addr= mac_add;}
		void reverseKeyOutput (int label, uint64_t mac_add){ return_key_output.label = label; return_key_output.mac_addr= mac_add;}
		LWmpls_Forwarding_Structure()
		{
			mac_address=0;
			input_mac_address=0;
			last_use=-1;
			order=-1;
			output_label=0;
			input_label=0;
			return_label_input=0; // Acumular 
			return_label_output=0;
			key_output.label=-1;
			key_output.mac_addr=0;
			return_key_output.label=-1;
			return_key_output.mac_addr=0;
			path.clear();

		}
		~LWmpls_Forwarding_Structure()
		{
			path.clear();
			
		}
}LWmpls_Forwarding_Structure;

class LWmpls_data_structure;

class LWmpls_Interface_Structure : public cOwnedObject
{
	 private:
		uint64_t  mac_address;
		simtime_t   last_use;
		int      num_rtr;
		unsigned int      num_labels;
		friend   class LWmpls_data_structure;
	 public:
                LWmpls_Interface_Structure()
		{
			mac_address=0;
			last_use=0;
			num_rtr=0;
			num_labels=0;
		}
		uint64_t  &   macAddress(){return mac_address;}
		simtime_t  & lastUse() {return last_use;}
		int     & numRtr () {return num_rtr;}
		unsigned int & numLabels () {return num_labels;}

};

typedef struct LWmpls_label_list : public cOwnedObject
{
		simtime_t time;
		bool in_use;
		simtime_t capture_time;
		LWmpls_Forwarding_Structure* data_f_ptr;
		inline  LWmpls_label_list & operator = (const  LWmpls_label_list& b)
		{
			time=b.time;
			in_use=b.in_use;
			time=b.time;
			capture_time=b.capture_time;
			data_f_ptr=b.data_f_ptr;
			return *this;
		}
} LWmpls_label_list;

typedef std::map<LWMPLSKey, LWmpls_Forwarding_Structure*> LWmplsFwMap;
typedef std::map<uint64_t,LWmpls_Interface_Structure *> LWmplsInterfaceMap;
typedef std::map<uint64_t,int> DestinationList;
typedef std::map<uint64_t,uint32_t> BroadcastList;
typedef std::vector<LWmpls_label_list> LWmplslabelArray;


class Ieee80211Mesh;

class   LWmpls_data_structure : public cOwnedObject
{
	private:


	simtime_t	LWMPLS_MAX_TIME;
	simtime_t 	LWMPLS_MAX_TIME_MAC;
/* timer limit of initialize forwarding struc after capture label */
	simtime_t 	LWMPLS_MAX_TIME_CAPTURE_LABEL;
/* Limits for break path */
/* Number of reintent before break */
	int	LWMPLS_MAX_RTR;
/* Timer after last message */

		LWmplsFwMap * forwardingTableOutput;
		LWmplsInterfaceMap* interfaceMap;
		LWmplslabelArray label_list;

		int num_label_in_use;
		double bad_pkt_rate;

		// typedef std::vector<int> ListLabel;
		// typedef std::map<uint64_t,listLabel> DestinationList;
		DestinationList destList;
		BroadcastList   broadCastList;
		uint32_t	broadCastCounter;
		friend class Ieee80211Mesh;

		void deleteForwarding(LWmpls_Forwarding_Structure* data_f_ptr);

	public:
		LWmpls_data_structure();
		~LWmpls_data_structure();
		simtime_t & mplsMaxTime() {return LWMPLS_MAX_TIME;}
		simtime_t & mplsMacLimit() {return LWMPLS_MAX_TIME_MAC;}
/* timer limit of initialize forwarding struc after capture label */
		simtime_t & mplsMaxCaptureLimit() {return LWMPLS_MAX_TIME_CAPTURE_LABEL;}
/* Limits for break path */
/* Number of reintent before break */
		int &	mplsMaxMacRetry () {return LWMPLS_MAX_RTR;}
		
		LWmpls_Forwarding_Structure * lwmpls_forwarding_data(int,int,uint64_t );
		LWmpls_Interface_Structure * lwmpls_interface_structure(uint64_t);
		

		void   lwmpls_interface_delete_list_mpls(uint64_t);
		int    lwmpls_get_label();
		void   lwmpls_release_label(int);

		void   lwmpls_init_interface(LWmpls_Interface_Structure** ,int,uint64_t, int );
		void   lwmpls_forwarding_input_data_add(int,LWmpls_Forwarding_Structure *);
		bool   lwmpls_forwarding_output_data_add(int ,uint64_t ,LWmpls_Forwarding_Structure *,bool);
		LWmpls_Forwarding_Structure * lwmpls_interface_delete_label(int);

		void   lwmpls_interface_delete_old_path();

		bool   lwmpls_label_in_use(int );
		bool   lwmpls_mac_last_access (simtime_t &,uint64_t);
		void   lwmpls_refresh_mac (uint64_t ,simtime_t);
		int    lwmpls_nun_labels_in_use ();
		double lwmpls_label_last_use (int); // Return, in double format the time of use
		int    lwmpls_label_status (int label);
		void   lwmpls_check_label (int label,const char * message);
		void   registerRoute(uint64_t destination,int label);
		int    getRegisterRoute(uint64_t destination);
		void   deleteRegisterRoute(uint64_t dest);
		void   deleteRegisterLabel(int dest);

		bool   getBroadCastCounter(uint64_t dest,uint32_t &counter);
		void   setBroadCastCounter(uint64_t dest,uint32_t counter);
		bool   getBroadCastCounter(uint32_t &counter) {counter = broadCastCounter; return true;}
		void   setBroadCastCounter(uint32_t counter) {broadCastCounter = counter;}

};


typedef enum
 {
	label_break,
	label_begin,
	label_delete,
	label_continue,
	label_path,
	label_ack
 } Msg_label_types;


 typedef struct Lwmpls_label_msg : public cOwnedObject
{
	int	 label;
	int label_return;
	Msg_label_types code;
	int src_addr;
	int dest_addr;
}Lwmpls_label_msg;


typedef struct Lwmpls_label_struct : public cOwnedObject
{
	int	label;
	int     in_port;
	int	out_port;
	double	percentage;
	double	ocupation;
	int dest_addr;
	int src_addr;
	int next_addr;
}Lwmpls_label_struct;
/*-------------------------------------------------------------------*/
/* End if for protection against multiple includes. */
#endif /* _LWMPLS_DATA_H_INCLUDED_ */

