/*
 *  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 "types.h"
#include "layer2.h"
#include "system.h"
#include "module_ipv4.h"
#include "module_ipv6.h"
#include "module_mc6.h"
#include "module_mc4.h"

#if !defined(COMCERTO_2000)
U16 l2_precalculate_header(struct itf *itf, U8 *data, U16 size, U16 ethertype, U8 *dstMac, U8 *output_port)
{
	Metadata mtd;
	U16 l2_hdr_size;

	mtd.data = data;
	mtd.offset = size;
	mtd.length = 0;
	mtd.vlan_pbits = 0;

	l2_hdr_size = __l2_prepend_header(&mtd, itf, dstMac, ethertype, 0);

	*output_port = mtd.output_port;

	return l2_hdr_size;
}
#endif

#if !defined(COMCERTO_2000) || defined(COMCERTO_2000_CONTROL)
/**
 * get_onif_by_name()
 *
 *
 */
POnifDesc get_onif_by_name(U8 *itf_name)
{
	POnifDesc onif_desc = NULL;
	int i;
	
	if (itf_name) {
		/* return pointer on entry of the global ouput nif information database */
		for (i = 0; i < L2_MAX_ONIF; i++)
		{
			onif_desc = &gOnif_DB[i];
			if ((onif_desc->flags & ENTRY_VALID) && !strcmp((const char*)itf_name, (char*)onif_desc->name))
				return onif_desc;
		}
	}
	return NULL;
}


/**
 * add_onif()
 *
 *
 */
POnifDesc add_onif(U8 *input_itf_name, struct itf *itf, struct itf *phys_itf, U8 type)
{
	U32 i;

	/* find free entry (valid = 0) in the table */
	for (i = 0; i < L2_MAX_ONIF; i++)
	{
		if ((gOnif_DB[i].flags & ENTRY_VALID) == 0)
		{
			gOnif_DB[i].itf = itf;
			gOnif_DB[i].flags = ENTRY_VALID;
			strcpy((char*)gOnif_DB[i].name, (char*)input_itf_name);

			itf->phys = phys_itf;
			itf->index = i;
			itf->type = type;

			return &gOnif_DB[i];
		}		
	}

	return NULL;
}


/**
 * remove_onif_by_name()
 *
 *
 */
void remove_onif_by_name(U8 *itf_name)
{
	int i;
	
	for (i = 0; i < L2_MAX_ONIF; i++)
	{
		if(!strcmp((char*)itf_name, (char*)gOnif_DB[i].name))
		{
			remove_onif_by_index(i);
			return; 
		}
	}
}


/**
 * remove_onif_by_index()
 *
 *
 */
void remove_onif_by_index(U32 if_index)
{
	int i;

	IP_deleteCt_from_onif_index(if_index);

	// disable route entries bound to this interface
	for (i = 0 ; i < NUM_ROUTE_ENTRIES ; i++)
	{
		PRouteEntry pRtentry;
		struct slist_entry *entry;

		// find and delete any routes that still use the interface (use counts should be zero)
		slist_for_each_safe(pRtentry, entry, &rt_cache[i], list)
		{
			if (pRtentry->itf->index == if_index)
				L2_route_remove(pRtentry->id);
		}
	}

	// Remove any multicast listener entries that reference this interface
	MC6_interface_purge(if_index);
	MC4_interface_purge(if_index);

	memset(&gOnif_DB[if_index], 0, sizeof(OnifDesc));
}


/**
 * remove_onif()
 *
 *
 */
void remove_onif(POnifDesc onif_desc)
{
	remove_onif_by_index(get_onif_index(onif_desc));
}


PRouteEntry L2_route_find(U32 id)
{
	U32 hash;
	PRouteEntry pRtEntry;
	struct slist_entry *entry;

	hash = HASH_RT(id);
	slist_for_each(pRtEntry, entry, &rt_cache[hash], list)
	{
		if (pRtEntry->id == id)
			return pRtEntry;
	}

	return NULL;
}

U8 itf_get_phys_port(struct itf *itf)
{
	while (itf->phys)
		itf = itf->phys;

	return ((struct physical_port *)itf)->id;
}


/**
 * __L2_route_remove()
 *
 *          This function removes an L2 route entry
 *
 */
int __L2_route_remove(PRouteEntry pRtEntry)
{
	U32 hash;

	hash = HASH_RT(pRtEntry->id);

	slist_remove(&rt_cache[hash], &pRtEntry->list);

	Heap_Free((PVOID)pRtEntry);

	return NO_ERR;
}

/**
 * L2_route_remove()
 *
 *          This function removes an L2 route entry
 *
 */
int L2_route_remove(U32 id)
{
	PRouteEntry pRtEntry;

	pRtEntry = L2_route_find(id);
	if (pRtEntry == NULL)
		return ERR_RT_ENTRY_NOT_FOUND;

	if (pRtEntry->nbref)
		return ERR_RT_ENTRY_LINKED;

	return __L2_route_remove(pRtEntry);
}


#if !defined(COMCERTO_2000)
/**
 * L2_route_to_ARAM()
 *
 *
 */
static inline PRouteEntry L2_route_to_ARAM(PRouteEntry pRtEntryDDR)
{
	PRouteEntry pRtEntryARAM;
	U32 hash;

	/* Don't move routes with extra info to ARAM */
	if (pRtEntryDDR->flags & RT_F_EXTRA_INFO)
		return pRtEntryDDR;

	pRtEntryARAM = __Heap_Alloc(hGlobalAramHeap, sizeof(RouteEntry));
	if (pRtEntryARAM == NULL)
		return pRtEntryDDR;

	SFL_memcpy(pRtEntryARAM, pRtEntryDDR, sizeof(RouteEntry));

	__L2_route_remove(pRtEntryDDR);

	hash = HASH_RT(pRtEntryARAM->id);

	slist_add(&rt_cache[hash], &pRtEntryARAM->list);

	return pRtEntryARAM;
}


/**
 * L2_route_to_DDR()
 *
 *
 */
static inline void L2_route_to_DDR(PRouteEntry pRtEntryARAM)
{
	PRouteEntry pRtEntryDDR;
	U32 hash;

	if (!IS_ARAM_ROUTE(pRtEntryARAM))
		return;

	pRtEntryDDR = __Heap_Alloc(hGlobalHeap, sizeof(RouteEntry));
	if (pRtEntryDDR == NULL)
		return;

	SFL_memcpy(pRtEntryDDR, pRtEntryARAM, sizeof(RouteEntry));

	__L2_route_remove(pRtEntryARAM);

	hash = HASH_RT(pRtEntryDDR->id);

	slist_add(&rt_cache[hash], &pRtEntryDDR->list);
}
#else
#define L2_route_to_ARAM(pRtEntry)	(pRtEntry)
#define L2_route_to_DDR(pRtEntry)	do {} while(0)
#endif

/**
 * L2_route_get()
 *
 *
 */
PRouteEntry L2_route_get(U32 id)
{
	PRouteEntry pRtEntry;

	pRtEntry = L2_route_find(id);
	if (pRtEntry == NULL)
	{
		return NULL;
	}

	if (pRtEntry->nbref == 0xFFFF)
	{
		return NULL;
	}

	if (pRtEntry->itf == NULL)
	{
		return NULL;
	}

	if (!pRtEntry->nbref)
		pRtEntry = L2_route_to_ARAM(pRtEntry);

	pRtEntry->nbref++;

	return pRtEntry;
}

/**
 * L2_route_put()
 *
 *
 */
void L2_route_put(PRouteEntry pRtEntry)
{
	if (pRtEntry == NULL)
 		return;

	pRtEntry->nbref--;

	if (!pRtEntry->nbref)
		L2_route_to_DDR(pRtEntry);
}
 
/**
 * L2_route_add()
 *
 *          This function removes an L2 route entry
 *
 */
PRouteEntry L2_route_add(U32 id, int info_size)
{
	PRouteEntry pRtEntry;
	int size;
	U32 hash;

	size = ROUND_UP32(sizeof (RouteEntry)) + info_size;

	pRtEntry = (PRouteEntry)__Heap_Alloc(hGlobalHeap, size);
	if (!pRtEntry)
		return NULL;

	memset(pRtEntry, 0, size);

	hash = HASH_RT(id);

	pRtEntry->id = id;

	if (info_size)
		pRtEntry->flags |= RT_F_EXTRA_INFO;

	pRtEntry->nbref = 0;

	slist_add(&rt_cache[hash], &pRtEntry->list);

	return pRtEntry;
}
#endif /* !defined(COMCERTO_2000) || defined(COMCERTO_2000_CONTROL) */
#if !defined(COMCERTO_2000_UTIL) && !defined(COMCERTO_2000_CONTROL)
U16 l2_prepend_header(PMetadata mtd, PRouteEntry pRtEntry, U16 family)
{
	U16 ethertype = l2_get_tid(family);

	return __l2_prepend_header(mtd, pRtEntry->itf, pRtEntry->dstmac, ethertype, 1);
}
#endif

