/* 
 * sim_i.h
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1996,1993,1991,1990  Arizona Board of Regents
 *
 * $Revision: 1.5 $
 * $Date: 1997/07/02 00:57:34 $
 */

#ifndef sim_i_h
#define sim_i_h

#define XSIM_PROFILE

#include "eth_i.h"
#include "ip_i.h"
#include "arp_i.h"
#include "ethd.h"
#include "xsim.h"
#define TRACE_ON
#include "evtrace.h"
#include "simul.h"

#define ARP_TYPE		0x0806
#define RARP_TYPE		0x8035
#define TYPE_ETH		1
#define TYPE_IP			2
#define OBJTYPE_XOBJ		1
#define OBJTYPE_FUN		2

#define MAX_NETS		800
/* VENKAT: Changed this from 100 */
#define MAX_KEYS		800
#define MAX_ROUTERS		100
#define MAX_ROUTERS_ADDR	100
#define DEFNUM_PORTS		100

#define TRACE_TYPE_DETAILED	0
#define TRACE_TYPE_SHORT	1
#define TRACE_TYPE_PKT          2

#define PKT_FLAG_BCAST		0x1
#define PKT_FLAG_SMALL		0x2

typedef unsigned int tcp_seq;

typedef struct {
        u_short th_sport;               /* source port */
        u_short th_dport;               /* destination port */
        tcp_seq th_seq;                 /* sequence number */
        tcp_seq th_ack;                 /* acknowledgement number */
#if ENDIAN == LITTLE
        u_char  th_x2:4,                /* (unused) */
                th_off:4;               /* data offset */
#endif
#if ENDIAN == BIG
        u_char  th_off:4,               /* data offset */
                th_x2:4;                /* (unused) */
#endif
        u_char  th_flags;
#define TH_FIN  0x01
#define TH_SYN  0x02
#define TH_RST  0x04
#define TH_PUSH 0x08
#define TH_ACK  0x10
#define TH_URG  0x20
#define TH_SS 0x40                    /* for simulator, slow-start pkt */
#define TH_SA 0x80                    /* for simulator, in a row pkt */
        u_short th_win;                 /* window */
        u_short th_sum;                 /* checksum */
        u_short th_urp;                 /* urgent pointer */
} tcpHDR;

typedef struct {
  int		type;
  union {
    ETHhost	eth;
    IPhost	ip;
  } addr;
} Simhost;

typedef struct {
  char		*name;
  ETHhost	ethAddr;
  IPhost	ipAddr;
  int		inPort;
  int		net;
  int		host;
  int		objType;
  char		*obj;
  void		(*cbFun)(Event, void *);
} Key;

typedef struct callback {
  struct callback *next;
  void		(*fun)(Event, void *);
  void		*state;
  int		host;
  int		op;
  int		rv;
  void		*arg1;
  void		*arg2;
  void		*arg3;
} CallBack;

typedef struct simnet {
  int		id;
  int		type;
  int		busy;
  long		sendTime; /* VENKAT */
  int		curDelay;
  int		collisionCnt;
  int		collisionDelay;
  long		time2bBusy; /* VENKAT */
  void		(*handler)(Event, void *);
  int		(*control)(struct simnet *, int, void (*)(), void *, void *, 
			   void *);
  int		rate;		/* how fast can put data into it (bytes/sec) */
  int		delay;		/* usecs */
  int		delayVar;
  int		(*delayFun)(int);	/* if NULL, use delay */
  long 		busyUntil;	/* VENKAT */
  long		timeUsed;	/* keeps track of total time busy */ /*VENKAT*/
  long		byteCnt; /* VENKAT */
  int		numHosts;
  int		minPacketSize;
  int		packetOverhead;
  int           packetHeader;
  int		maxPacket;
  Simhost	*allHosts;	/* used for broadcasting */
  Simhost	**allGroups;	/* used for multicasting */
  IPhost	net;
  IPhost	mask;
  CallBack	*notBusyBeg, *notBusyEnd;
  CallBack	*sent;
  Event		notBusyEv;
  struct sim_pstate	*ps;
  TraceStruct	ts;
} Net;

typedef struct sim_pstate {
  Net		*Nets[MAX_NETS];
  int		numNets;
  int		numHosts;
  Key		keyMap[MAX_KEYS];
  int		arpFlag;
  int		rarpFlag;
  int		seed;
  Map           ethAddr2Key;
  Map           ipAddr2Key;
  TraceStruct	ts;
} SIM_PSTATE;

typedef struct simPacket {
  struct simPacket *next;
  int		type;
  long		id; /* VENKAT */
  Net		*net;
  Msg		msg;
  int		len;
  int           bwLen;
  int		flags;
  int           prot;
  Simhost	origSrc;
  Simhost	src;
  Simhost	dst;
  Simhost	hop;
  ETHhdr	ehdr;
  SIM_PSTATE	*ps;
  void          *routerData;
/* unsigned int  flowID;
  u_int         atmLen;
  u_long        atmTime;
*/
} SimPacket;

typedef struct {
  IPhost	net;
  IPhost	mask;
  int		outPort;
  Simhost	hop;
} RouteEntry;

typedef struct routerState {
  char		*name;
  SIM_PSTATE	*ps;
  void		(*inFun)(struct routerState *, SimPacket *, int); 
  void		(*cbFun)(Event, void *);
  int		delay; 
  int		traceType;
  unsigned long       pktTraceBeginTime;
  unsigned long       pktTraceEndTime;
  char                pktTracePortOut[DEFNUM_PORTS];
  char                pktTracePortIn[DEFNUM_PORTS];
  int		connectCnt;
  Simhost	myAddr[DEFNUM_PORTS];
  Net		*inPortNets[DEFNUM_PORTS];
  Net		*outPortNets[DEFNUM_PORTS];
  int		defBufferCnt;
  int		defQueueLen;
  int		smallPktSize;
  int		outQueueCnt[DEFNUM_PORTS];
  int		outQueueLen[DEFNUM_PORTS];
  int		outQueueSmallCnt[DEFNUM_PORTS];
  SimPacket	*outQueueBeg[DEFNUM_PORTS];
  SimPacket	*outQueueEnd[DEFNUM_PORTS];
  int		outRetryCnt[DEFNUM_PORTS];
  int		outRetryDelay[DEFNUM_PORTS];
  ITrace	*traceInOut[DEFNUM_PORTS];
  ITrace	*traceOut[DEFNUM_PORTS];
  ITrace	*traceIn[DEFNUM_PORTS];
  MaxMinTrace	*traceQueue[DEFNUM_PORTS];
  MaxMinTrace	*traceQueueLen[DEFNUM_PORTS];
  void          *rState;
  void          *outState[DEFNUM_PORTS];
  void          *inState[DEFNUM_PORTS]; 
  int		numRoutes;
  RouteEntry	*Routes;
  TraceStruct	ts;
} ROUTER_STATE;

typedef struct nameAddr {
  char		*name;
  void		*addr;
} NameAddr;

#define IP_AND_EQUAL(x, y, z) ( \
  (( (x).a & (y).a) == (z).a)  && \
  (( (x).b & (y).b) == (z).b)  && \
  (( (x).c & (y).c) == (z).c)  && \
  (( (x).d & (y).d) == (z).d) )

#define SIMHOST_EQ(x, y) ( \
  !bcmp(&(x), &(y), sizeof(Simhost)))

/* --- sim.c */
int		xsimBegTest(void);
int		xsimEndTest(void);
void		xsimInsertRouterFun(char *, void (*)());
void		*xsimGetRouterFun(char *);
void            sim_init(Protl);
extern XTime	sim_begTime;
extern SIM_PSTATE *SimPstate;

/* --- sim_util.c */
Key		*sim_obj2key(SIM_PSTATE *, char *);
Key		*sim_addr2key(SIM_PSTATE *, char *, int);
Key		*sim_name2key(SIM_PSTATE *, char *);
void		xsimAddHostMap(Key *);
int		xsimGetIPaddr(char *, IPhost *);
int		xsimGetETHaddr(char *, ETHhost *);
char 		*sim_getTime(void);
char		*sim_addr2str(void *, int);
char		*sim_simaddr2str(Simhost *);
void		sim_print_packet(SimPacket *);
char		*xMallocZero(int);

/* --- sim_inet.c */
/* void		sim_createNetwork(SIM_PSTATE *); */

/* --- sim_net.c */
void 		sim_ethHandler(Event, void *);
void		sim_ipHandler(Event, void *);
int		defaultNetControl(Net *, int, void (*)(), void *, void *, 
				  void *);
int		sim_getNextHop(ROUTER_STATE *, IPhost *, int *, Simhost *);
void		sim_FCFS_input(ROUTER_STATE *, SimPacket *, int);
void		sim_FCFS_callback(Event, void *);
void            sim_RED_input(ROUTER_STATE *, SimPacket *, int);
void            sim_RED_callback(Event, void *);
SimPacket	*sim_create_eth_packet(SIM_PSTATE *, Net *, Msg *, ETHhdr *);
void		sim_send_on_net(SimPacket *);
void		freeSimPacket(SimPacket *);
void		freeCallBack(CallBack *);
int		simGetHost(SIM_PSTATE *, Simhost *);

/* --- sim_init.c --- */
int  getHostCnt(void);
int  getRouterCnt(void);
void getHostArray(int, char *, IPhost *);

extern void	ipHdrStore(void *hdr, char *dst, long len, void *arg);
extern long	lrand48(void);
extern void 	srand48(long);
extern void	xsimSetCurHost(int);
extern int	xsimGetCurHost(void);
extern int	xsimAddHost(char *);
extern int	CurHost;

#endif
