#ifndef _fec_decoder_h
#define _fec_decoder_h

#include <stdio.h>
#include <stdint.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>

#include <linux/errqueue.h>
#include <linux/sockios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <fcntl.h>
#include <errno.h>


#include <ctype.h>
#include <math.h>

#define DEMO__
//#define DEMO__ // makes a binary for the demo

#include <asm/socket.h>
#define PTPD_SOCK_RAW_ETHERNET 	1
#define PTPD_SOCK_UDP 		2
#define PACKET_SIZE 1518
#define IFACE_NAME_LEN 16
#define ETHER_MTU 1518
#define PACKED __attribute__((packed))


#define DEBUG_DETAIL 2
#define DEBUG_LIGHT  1
#define DEBUG_NO     0
// FECed frame header size [bytes]
#define FEC_HEADE_SIZE 8
#define ETHER_TYPE 0xDEED
#define MAX_BURST 10000000
typedef uint32_t ipv4_addr_t;

typedef char Octet;

typedef uint8_t mac_addr_t[6];

const mac_addr_t FEC_ADDR = {0x76, 0x54, 0xba, 0x98 , 0xfe, 0xdc};


const mac_addr_t DEFAULT_UNICAST_MAC  = {0x00,0x01,0x02,0x03,004,0x05 };

const mac_addr_t UNICAST_MAC_ETH_5 = {0x00,0x1b,0x21,0x8e,0xd7,0x44 };
const mac_addr_t UNICAST_MAC_ETH_4_RENAME = {0x00,0x1b,0x21,0x8e,0xd7,0x45 };
const mac_addr_t DEFAULT_MULTICAST_MAC= {0x01,0x01,0x02,0x03,004,0x05 };
const mac_addr_t BROADCAST_MAC        = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF };

PACKED struct etherpacket {
	struct ethhdr ether;
	char data[ETHER_MTU];
};
PACKED struct bench_pkt {
    uint32_t burst_id;
    uint32_t seq;
    uint16_t size, size2;
    struct timeval tx;
    struct timeval xx;
    struct timeval rx;
    char payload[0];
};

typedef struct bench_pkt bench_pkt_t;

enum rxfrom_mode {
    RETURN_SEQ_NUM,
    RETURN_DATA};

typedef struct timeval timeval_t;
typedef void *wr_socket_t;

typedef struct{
  int rx_seq_id;
  timeval_t rx; //reception timestamp
  timeval_t tx; //transmision timestamp
  timeval_t xx; //latency time tx-to-rx
} rx_data_t;

typedef struct {
// Network interface name (eth0, ...)
    char if_name[IFACE_NAME_LEN];
// Socket family (RAW ethernet/UDP)
    int family;   
// MAC address
    mac_addr_t mac;
// Destination MASC address, filled by recvfrom() function on interfaces bound to multiple addresses
    mac_addr_t mac_dest;
// IP address
    ipv4_addr_t ip;
// UDP port
    uint16_t port;
// RAW ethertype
    uint16_t ethertype;
// physical port to bind socket to
    uint16_t physical_port;
} wr_sockaddr_t;

struct my_socket {
	int fd;
	wr_sockaddr_t bind_addr;
	mac_addr_t local_mac;
	int if_index;
} ;

typedef struct my_socket my_socket_t;

typedef struct {
   char               rx_if_name[IFACE_NAME_LEN];
   char               tx_if_name[IFACE_NAME_LEN];
   int                rx_do;
   int                rx_burst_do;
   int                tx_burst_do;
   int                tx_do;   
   uint16_t           ethertype;
   mac_addr_t         dst_mac;
   int                pkt_time_interval;
   int                pkt_number_in_burst;
   size_t             pkt_payload_size;
   int                show_rxtx_data;
   int randomized;	
} RunTimeOpts;

#endif
