#include "stdio.h"
#include "c:/ixp1200/include/uclo.h"
#include "c:/ixp1200/include/libd.h"
#include "c:/ixp1200/include/hal_sram.h"
#include "c:/ixp1200/include/mem_map.h"


#define SRAM_POLICY_START 0x10000
#define SRAM_POLICY_END 0x15000

#define SRAM_CACHE_START 0x2000
#define SRAM_CACHE_END 0x10000

#define SRAM_LOG_START 0x15000
#define SRAM_LOG_END 0x20000

//Function declarations


#if defined(__cplusplus)
extern "C"
{
extern int forwarding_decision();
extern int make_policy();
extern int add_policy(); //add to policy table; return -1 if error
extern int delete_policy(); 
extern int policy_table_lookup(); // return 0 if allowable; -1 to deny.
extern int flush_cache(); //flush the cache if new policy is added
extern int write_cache(); //called within policy_table_lookup
extern int write_log(); //called within policy_table_lookup
extern int packetize_log_table(); //called within policy_table_lookup()
				  //if after writing a log, the log table is full, 
				  //packetize the table immediately
extern int send_log(); //called by packetize_log_table
}
#endif

struct policy_entry{
	int group_id; //which policy it belongs to
	int policy_id; //type of filter (e.g src port)
	int policy_value; //either contains the value or the address (pointer) to the value
	int policy_mask; //applies if masks are necessary (we know if its necessary by looking at the 			//policy_id
};

struct policy{
	int group_id;
	int num_filters;
	policy *next;
};

struct cache_entry{
	short int src_port; //(2 bytes)
	short int dst_port; //(2 bytes)
	int src_addr; //(4 bytes)
	int dst_addr; //(4 bytes)
	char protocol; //(1 byte)
	
	/* 1st LSB - drop or forward packet
	   2nd LSB - null entry or used
	   6 bits are still free to be used
	*/	   

	char bitvector; (1 byte)
	
	int next; (4 bytes)
	int prev; (4 bytes)
	//we will next extra bits to decide what extended functions to call
	int string_ptr; //(4 bytes) - ptr to the string we want to search for in memory
	int func_ptr; //(4 bytes) - ptr to the function we give the string to, to search
			//for in the packet
};

int forwarding_decision(){
//takes in a packet and decides whether it should:
//1) add a new policy by calling make_policy and then calling add_policy, which then adds to the cache
//2) look at the policy table to decide what to do with the packet (call policy_table_lookup)
//3) delete a policy (call delete_policy)
}

int make_policy(){
//take a packet, and make a policy entry based on the information given.
}

int add_policy(int *next_free,Policy_Entry *item) {
    unsigned int addr= SRAM_POLICY_START+*next_free;         // from mem_map.h
    static SramUnit* sram;
    int status;
    printf("Adding_Policy\n"); 
    // get sram pointers and initialize sram memory
    sram = SRAM_Attach();
    int i =0;
    for (i=0; i < 12 ; i++) {  // 4 bytes= 1 long word
        sram->write(addr+i, 0);
    }  
    //WRITE TO SRAM the policy
    sram->write(addr,item->policy_id);
    sram->write(addr+4,item->policy_value);
    sram->write(addr+8,item->policy_mask);    
    printf(“written $d to sram memory”,item->policy_id);
    insigned int j =0;
    int temp;
    for (j=addr;j<0x15000;j=j+12) {
	sram->read(j,temp);
        if(temp ==0) {
	    *next_free =j;
        }    
    }
    return 1;
}      

int delete_policy(int policy_id) {
    unsigned int addr = SRAM_POLICY_START;
    unsigned int i = 0;
    unsigned int temp =0;
    for(i=addr;i<0x15000;i=i+12) {
	 sram->read(i,temp);
	 if (temp == policy_id) {
		sram->write(i,0);
         }
    }
}

int policy_table_lookup(unsigned int *PACKET,int *order,int size, policy *policy_array) {
	unsigned int addr = SRAM_POLICY_START;
	int type;
        unsigned int policy[52];
        int policy_id;
	int i;
        for(i = addr; i<0x15000;i=i+12) {
		sram->read(addr,policy_id);
                sram->read(addr+4,type);
	        if(match(*PACKET,addr+type)){ 
		    policy[policy_id]++;
		}
        }
        int match =0;
        for(int i = *order[0],j=0;j<size;j++,i=*order[j]) {
		if(policy[i]!=policy_array->num_policies){
			match = 1;
			break;
 		}
		policy_array = policy_array->next;
	}
	if(match ==1 ) update_cache(PACKET,1);
	if(match ==0) update_cache(PACKET,1);

}		

int flush_cache() {
	static SramUnit* sram;
    	printf("Flushing Cache\n"); 
    	// get sram pointers and re-initialize sram memory
    	sram = SRAM_Attach();
    
	//let X be the number of bytes in each cache entry
	for(int i = SRAM_CACHE_START; i< sRAM_CACHE_END; i++){
		sram->write(i, 0);
	}				
	
}

int write_cache() {
	//called by add_policy
	//We need to use the hash function here
	
}

int write_log() {
	//called by policy_table_lookup after deciding if there is a violation
	//takes in a packet descriptor
	//need timestamp functionality (ask Hemant)
	//5-tuple
		
}

int packetize_log_table() {
}

int send_log() {
}
 