/*
 *  Copyright (c) 2009 Mindspeed Technologies, Inc.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
*/
#include "module_mc4.h"
#include "module_mc6.h"
#include "layer2.h"
#include "fe.h"


/* This function returns total multicast entries 
   configured in a given hash index */
static int MC4_Get_Hash_Entries(int mc4_hash_index)
{
	
	int tot_mc4_entries = 0;
	PMC4Entry  pMC4Entry;
	struct slist_entry *entry;

	slist_for_each(pMC4Entry, entry, &mc4_table_memory[mc4_hash_index], list)
	{
	    tot_mc4_entries++;
	    if((pMC4Entry->mcdest.num_listeners > MCx_MAX_LISTENERS_IN_QUERY) ||
	                       ((pMC4Entry->mcdest.num_listeners == MCx_MAX_LISTENERS_IN_QUERY) && (pMC4Entry->mcdest.flags & MC_ACP_LISTENER)))
	              tot_mc4_entries++;
	 }
		
		
	return tot_mc4_entries;

}


/* This function fills the snapshot of MC4 entries in a given hash index */
static int MC4_Get_Hash_Snapshot(int mc4_hash_index, int mc4_tot_entries, PMC4Command pMC4Snapshot)
{
	
	int tot_mc4_entries = 0, i;
	PMC4Entry  pMC4Entry;
	struct slist_entry *entry;
	int j = 0;

	slist_for_each(pMC4Entry, entry, &mc4_table_memory[mc4_hash_index], list)
	{
		memset(pMC4Snapshot, 0, sizeof(MC4Command));
		pMC4Snapshot->src_addr  	= pMC4Entry->src_addr;
		pMC4Snapshot->src_addr_mask	= pMC4Entry->mcdest.src_mask_len;
		pMC4Snapshot->dst_addr 		= pMC4Entry->dst_addr;
		pMC4Snapshot->queue = pMC4Entry->mcdest.queue_base;
		pMC4Snapshot->num_output = pMC4Entry->mcdest.num_listeners;
		for(i = 0,j = 0; j <pMC4Entry->mcdest.num_listeners; j++)
		{
			unsigned short output_index;
			POnifDesc pOnif;
			output_index = pMC4Entry->mcdest.listeners[j].output_index;
			pOnif = get_onif_by_index(output_index);
			strcpy((char *)pMC4Snapshot->output_list[i].output_device_str, (char *)pOnif->name);	
			pMC4Snapshot->output_list[i].timer = pMC4Entry->mcdest.listeners[j].timer;
			pMC4Snapshot->output_list[i].shaper_mask= pMC4Entry->mcdest.listeners[j].shaper_mask;
                     	pMC4Snapshot->output_list[i].uc_bit = (pMC4Entry->mcdest.listeners[j].uc_bit);
                     	if(pMC4Snapshot->output_list[i].uc_bit)
                             COPY_MACADDR(pMC4Snapshot->output_list[i].uc_mac,pMC4Entry->mcdest.listeners[j].dstmac);
                     	pMC4Snapshot->output_list[i].queue = pMC4Entry->mcdest.listeners[j].queue_base;
                     	if((++i >= MCx_MAX_LISTENERS_IN_QUERY) &&
                             ( (pMC4Entry->mcdest.num_listeners - (j+1)) || (pMC4Entry->mcdest.flags & MC_ACP_LISTENER)))
                     	{
                        	pMC4Snapshot->num_output = MCx_MAX_LISTENERS_IN_QUERY;
                                pMC4Snapshot++;
                                tot_mc4_entries++;
                                mc4_tot_entries--;
                                i = 0;
                                memset(pMC4Snapshot, 0, sizeof(MC4Command));
                     	}
		}
               	pMC4Snapshot->num_output = i;
               	if ((pMC4Entry->mcdest.flags & MC_ACP_LISTENER) && i < MCx_MAX_LISTENERS_IN_QUERY)
               	{
                	pMC4Snapshot->num_output++;
			strcpy((char *)pMC4Snapshot->output_list[i].output_device_str, "ACP");
			pMC4Snapshot->output_list[i].timer = pMC4Entry->mcdest.wifi_listener_timer;
		}
		pMC4Snapshot++;
		tot_mc4_entries++;
		mc4_tot_entries--;
		if (mc4_tot_entries == 0)
			break;
	}
		
	return tot_mc4_entries;

}


/* This function creates the snapshot memory and returns the 
   next MC4 entry from the snapshot of the MC4 entries of a
   single hash to the caller  */
   
int MC4_Get_Next_Hash_Entry(PMC4Command pMC4Cmd, int reset_action)
{
	int mc4_hash_entries;
	PMC4Command pMC4;
	static PMC4Command pMC4Snapshot = NULL;
	static int mc4_hash_index = 0, mc4_snapshot_entries =0, mc4_snapshot_index=0, mc4_snapshot_buf_entries = 0;
	
	if(reset_action)
	{
		mc4_hash_index = 0;
		mc4_snapshot_entries =0;
		mc4_snapshot_index=0;
		if(pMC4Snapshot)
		{
			Heap_Free(pMC4Snapshot);
			pMC4Snapshot = NULL;
		}
		mc4_snapshot_buf_entries = 0;
	}
	
	if (mc4_snapshot_index == 0)
	{
		
		while( mc4_hash_index <  MC4_NUM_HASH_ENTRIES)
		{
		
			mc4_hash_entries = MC4_Get_Hash_Entries(mc4_hash_index);
			if(mc4_hash_entries == 0)
			{
				mc4_hash_index++;
				continue;
			}
		   	
		   	if(mc4_hash_entries > mc4_snapshot_buf_entries)
		   	{
		   		if(pMC4Snapshot)
		   			Heap_Free(pMC4Snapshot);
				pMC4Snapshot = Heap_Alloc(mc4_hash_entries * sizeof(MC4Command));
			
				if (!pMC4Snapshot)
				{
			    	mc4_hash_index = 0;
			    	mc4_snapshot_buf_entries = 0;
					return ERR_NOT_ENOUGH_MEMORY;
				}
				mc4_snapshot_buf_entries = mc4_hash_entries;
		   	}
				
			mc4_snapshot_entries = MC4_Get_Hash_Snapshot(mc4_hash_index ,mc4_hash_entries, pMC4Snapshot);
			
			break;
		}
		
		if (mc4_hash_index >= MC4_NUM_HASH_ENTRIES)
		{
			mc4_hash_index = 0;
			if(pMC4Snapshot)
			{
				Heap_Free(pMC4Snapshot);
				pMC4Snapshot = NULL;
			}
			mc4_snapshot_buf_entries = 0;
			return ERR_MC_ENTRY_NOT_FOUND;
		}
		   
	}
	
	pMC4 = &pMC4Snapshot[mc4_snapshot_index++];
	SFL_memcpy(pMC4Cmd, pMC4, sizeof(MC4Command));
	if (mc4_snapshot_index == mc4_snapshot_entries)
	{
		mc4_snapshot_index = 0;
		mc4_hash_index ++;
	}
		
	
	return NO_ERR;	
		
}


/* This function returns total multicastv6 entries 
   configured in a given hash index */
static int MC6_Get_Hash_Entries(int mc6_hash_index)
{
	
	int tot_mc6_entries = 0;
	PMC6Entry  pMC6Entry;
	struct slist_entry *entry;

	slist_for_each(pMC6Entry, entry, &mc6_table_memory[mc6_hash_index], list)
	{
	    tot_mc6_entries++;
	    if((pMC6Entry->mcdest.num_listeners > MCx_MAX_LISTENERS_IN_QUERY) ||
		           ((pMC6Entry->mcdest.num_listeners == MCx_MAX_LISTENERS_IN_QUERY) && (pMC6Entry->mcdest.flags & MC_ACP_LISTENER)))
	       tot_mc6_entries++;
	 }
		
	return tot_mc6_entries;

}


/* This function fills the snapshot of MC6 entries in a given hash index */
static int MC6_Get_Hash_Snapshot(int mc6_hash_index, int mc6_tot_entries, PMC6Command pMC6Snapshot)
{
	
	int tot_mc6_entries = 0,i;
	PMC6Entry  pMC6Entry;
	struct slist_entry *entry;
	int j =0;

	slist_for_each(pMC6Entry, entry, &mc6_table_memory[mc6_hash_index], list)
	{
		memset(pMC6Snapshot, 0, sizeof(MC6Command));
		SFL_memcpy(pMC6Snapshot->src_addr, pMC6Entry->src_addr, IPV6_ADDRESS_LENGTH);
		pMC6Snapshot->src_mask_len	= pMC6Entry->mcdest.src_mask_len;
		SFL_memcpy(pMC6Snapshot->dst_addr, pMC6Entry->dst_addr, IPV6_ADDRESS_LENGTH);
		pMC6Snapshot->queue = pMC6Entry->mcdest.queue_base;
		for(i = 0,j = 0; j <pMC6Entry->mcdest.num_listeners; j++)
		{
			unsigned short output_index;
			POnifDesc pOnif;
			output_index = pMC6Entry->mcdest.listeners[j].output_index;
			pOnif = get_onif_by_index(output_index);
			strcpy((char *)pMC6Snapshot->output_list[i].output_device_str, (char *)pOnif->name);	
			pMC6Snapshot->output_list[i].timer = pMC6Entry->mcdest.listeners[j].timer;
	              	pMC6Snapshot->output_list[i].shaper_mask= pMC6Entry->mcdest.listeners[j].shaper_mask;
			pMC6Snapshot->output_list[i].uc_bit = pMC6Entry->mcdest.listeners[j].uc_bit;
                    	if(pMC6Snapshot->output_list[i].uc_bit)
	                    COPY_MACADDR(pMC6Snapshot->output_list[i].uc_mac,pMC6Entry->mcdest.listeners[j].dstmac);
                    	pMC6Snapshot->output_list[i].queue = pMC6Entry->mcdest.listeners[j].queue_base;
                    	if((++i >= MCx_MAX_LISTENERS_IN_QUERY) &&
                             ( (pMC6Entry->mcdest.num_listeners - (j+1)) || (pMC6Entry->mcdest.flags & MC_ACP_LISTENER)))
                     	{
                        	pMC6Snapshot->num_output = MCx_MAX_LISTENERS_IN_QUERY;
                                pMC6Snapshot++;
                                tot_mc6_entries++;
                                mc6_tot_entries--;
                                i = 0;
                                memset(pMC6Snapshot, 0, sizeof(MC6Command));
                    	}
		}
		pMC6Snapshot->num_output = i;
              	if ((pMC6Entry->mcdest.flags & MC_ACP_LISTENER) && i < MCx_MAX_LISTENERS_IN_QUERY)
		{
			pMC6Snapshot->num_output++;
			strcpy((char *)pMC6Snapshot->output_list[i].output_device_str, "ACP");
			pMC6Snapshot->output_list[i].timer = pMC6Entry->mcdest.wifi_listener_timer;
		}
		pMC6Snapshot++;
		tot_mc6_entries++;
		mc6_tot_entries--;
		if (mc6_tot_entries == 0)
			break;
	}

	return tot_mc6_entries;

}


/* This function creates the snapshot memory and returns the 
   next MC6 entry from the snapshot of the MC4 entries of a
   single hash to the caller  */
   
int MC6_Get_Next_Hash_Entry(PMC6Command pMC6Cmd, int reset_action)
{
	int mc6_hash_entries;
	PMC6Command pMC6;
	static PMC6Command pMC6Snapshot = NULL;
	static int mc6_hash_index = 0, mc6_snapshot_entries =0, mc6_snapshot_index=0, mc6_snapshot_buf_entries = 0;
	
	if(reset_action)
	{
		mc6_hash_index = 0;
		mc6_snapshot_entries =0;
		mc6_snapshot_index=0;
		if(pMC6Snapshot)
		{
			Heap_Free(pMC6Snapshot);
			pMC6Snapshot = NULL;	
		}
		mc6_snapshot_buf_entries = 0;
	}
	
	if (mc6_snapshot_index == 0)
	{
		while( mc6_hash_index <  MC6_NUM_HASH_ENTRIES)
		{
		
			mc6_hash_entries = MC6_Get_Hash_Entries(mc6_hash_index);
			if(mc6_hash_entries == 0)
			{
				mc6_hash_index++;
				continue;
			}
		   	
		   	if(mc6_hash_entries > mc6_snapshot_buf_entries)
		   	{
		   		if(pMC6Snapshot)
		   			Heap_Free(pMC6Snapshot);
				pMC6Snapshot = Heap_Alloc(mc6_hash_entries * sizeof(MC6Command));
			
				if (!pMC6Snapshot)
				{
			    	mc6_hash_index = 0;
			    	mc6_snapshot_buf_entries = 0;
					return ERR_NOT_ENOUGH_MEMORY;
				}
				mc6_snapshot_buf_entries = mc6_hash_entries;
		   	}
		
			mc6_snapshot_entries = MC6_Get_Hash_Snapshot(mc6_hash_index , mc6_hash_entries, pMC6Snapshot);
				
			break;
		}
		
		if (mc6_hash_index >= MC6_NUM_HASH_ENTRIES)
		{
			mc6_hash_index = 0;
			if(pMC6Snapshot)
			{
				Heap_Free(pMC6Snapshot);
				pMC6Snapshot = NULL;	
			}
			mc6_snapshot_buf_entries =  0;
			return ERR_MC_ENTRY_NOT_FOUND;
		}
		   
	}
	
	pMC6 = &pMC6Snapshot[mc6_snapshot_index++];
	SFL_memcpy(pMC6Cmd, pMC6, sizeof(MC6Command));
	if (mc6_snapshot_index == mc6_snapshot_entries)
	{
		mc6_snapshot_index = 0;
		mc6_hash_index ++;
	}
		
	
	return NO_ERR;	
		
}
