/*
    Copyright 2000 (c) by Claudio Jeker,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Net/Modules/ARP/NetARP.h,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/
#ifndef _NETARP_H_
#define _NETARP_H_

#include "NetModulesNew.h"
#include "NetHAL.h"
#include "NetEthernetModule.h"

struct arphdr
{
  u16	ar_hrd;	/* format of hardware address */
  u16	ar_pro;	/* format of protocol address */
  u8	ar_hln;	/* lenght of hardware address */
  u8	ar_pln;	/* lenght of protocol address */
  u16	ar_op;	/* ARP/RARP operation */
};

struct ether_arp
{
  struct arphdr	ea_hdr;	/* fixed-size header */
  u8	arp_sha[6];			/* sender hardware address */
  u8	arp_spa[4];			/* sender protocol address */
  u8	arp_tha[6];			/* target hardware address */
  u8	arp_tpa[4];			/* target protocol address */
};

/* useful macros */
#define ARP_HRD ea_hdr.ar_hrd
#define ARP_PRO ea_hdr.ar_pro
#define ARP_HLN ea_hdr.ar_hln
#define ARP_PLN ea_hdr.ar_pln
#define ARP_OP  ea_hdr.ar_op

struct arp_entry
{
  u16	flags;	/* flags */
  u8	pa_len; /* protocol address len (4) */
  u8	ha_len;	/* hardware address len (6) */
  unsigned long timestamp;
  u8  data[40]; /* acctually the size could be bigger or smaller */
  /* first the pa (protocol address) */
  /* then the ha (hardware address) */
  /* XXX both are stored in network byte order */
};

struct arp_cache_header
{
  u32	magic;	/* magic cookie */
  u8	pa_len;
  u8	ha_len;
  u16	pad;
};

struct arp_pending_entry
{
  struct arp_entry *arp_entry;
  ThreadId requestor;
  unsigned long timerId;
  u32 flags;
  u16 proto;
  u16 device;
};

typedef struct arp_cache_header *ArpCacheTableEntry, **ArpCacheTable;

/* bit field flags */
#define ARP_VALID		(1<<15)
#define ARP_INVALID		(1<<14)
#define ARP_STATIC		(1<<13)
#define ARP_PENDING5	(1<<5)
#define ARP_PENDING4	(1<<3)
#define ARP_PENDING3	(1<<2)
#define ARP_PENDING2	(1<<1)
#define ARP_PENDING1	(1<<0)
#define SENT_FAILED		9 /* this is for the arp_pending_entry */
#define SECOND_SENT		6 /* this is for the arp_pending_entry */
#define FIRST_SENT		3 /* this is for the arp_pending_entry */
#define ARP_EMPTY		0

#define IS_ARP_PENDING(x)	( (x) & 0x1F )
#define IS_ARP_PENDING5(x)	( (x) & ARP_PENDING5 )
#define IS_ARP_VALID(x)		( (x) & ARP_VALID )
#define IS_ARP_INVALID(x)	( (x) & ARP_INVALID )
#define IS_ARP_STATIC(x)	( (x) & ARP_STATIC )

#define ARP_CACHEHEADERSIZE sizeof(struct arp_cache_header)
#define ARP_CACHESIZE	((508 - NETBUF_HEADERSIZE) - ARP_CACHEHEADERSIZE)
/* 508 byte NetBuf - 16 Byte NetBuf head - ARP_CACHEHEADERSIZE */
#define ARP_FLAGSLEN 8

/* protocol and hardware definitions */
#define ARP_REQUEST_OP   1
#define ARP_REPLY_OP 2

//#define ARP_PROTO_MAX 1 /* currently only IPv4 */
#define ARP_PROTO_MAX 2 /* (jb) adding IPv6 support*/
#define ARP_PROTO_IPv4 0
#define ARP_PROTO_IPv6 1

#define ARP_MAX_HA_SIZE 6 /* only ethernet hardware addresses */
///#define ARP_MAX_PA_SIZE 4 /* only IPv4 protocol addresses */
#define ARP_MAX_PA_SIZE 16 /* (jb) adding IPv6 support*/

/* types */
#define ARP_TYPE_IPv4 0x0800
#define ARP_TYPE_IPv6 0x0900 /* (jb) adding IPv6 support  XXX needs to be defined */
#define ARP_TYPE_ETHERNET 1

/* hardware address lenght */
#define ARP_ETHER_HA_LEN 6

/* magic cookies */
#define ARP_SUBDEVICETABLE	0x0C20AE70
#define ARP_CHACHETABLE		0x0C580D70

/* error codes */
#define ARP_OK 0
#define ARP_FOUND 1
#define ARP_NOTFOUND 2
#define ARP_FAILED -1
#define ARP_REJECT -2
#define ARP_RACE -3 /* race condition */


/* function for modules (to make lookups faster) */
int arp_send_lookup(int proto, int device, u8 *pa, int pa_len);
int arp_lookup(int proto, int device,
               u8 *pa, u8 pa_len,
               u8 **ha, u8 *ha_len);

extern ThreadId arp_main_thread;

/* main lookup thread */
void arp_main(ThreadArg max_request);
/* async cleanup thread */
void arp_cleanup(ThreadArg nothing);

#endif
