/*
 *
 *  Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#ifndef __ROUTE_CACHE_H__
#define __ROUTE_CACHE_H__

#include "jhash.h"

	#define ROUTE_HASH_TABLE_SIZE	2048

	#ifndef RTA_FWMARK
	#define RTA_FWMARK 16
	#endif

	#define ROUTE_MAX_ID	0x10000

	struct fpp_rt {
		struct list_head list;

		int oifindex;
		unsigned short mtu;
		unsigned char dst_mac[ETH_ALEN];
		unsigned int dst_addr[4];
		int dst_addr_len;

		int count;

		int flags;

		int id;
	};

	/*Structure representing  a route (internally to cmm)*/
	struct RtEntry {
		struct list_head list;
		struct list_head list_by_gw_ip;

		int count;						/*Number of time the route is used*/

		struct NeighborEntry *neighEntry;

		unsigned int sAddr[4];
		unsigned short sAddrLen;

		unsigned int dAddr[4];
		unsigned short dAddrLen;

		int oifindex;
		int phys_oifindex;

		unsigned int gwAddr[4];
		unsigned short gwAddrLen;

		unsigned short mtu;
		int family;

		unsigned char table;
		unsigned char scope;
		unsigned char type;

		int flags;

		unsigned int fwmark;

		int iifindex;
	};

	struct ct_route {
		struct RtEntry	*route;
		struct fpp_rt	*fpp_route;
		int		fpp_route_id;
	};

	struct flow {
		int family;
		const unsigned int *sAddr;
		const unsigned int *dAddr;
		unsigned int fwmark;
		int iifindex;
	};

	extern struct list_head rt_table[2 * ROUTE_HASH_TABLE_SIZE];
	extern struct list_head fpp_rt_table[ROUTE_HASH_TABLE_SIZE];
	extern struct list_head rt_table_by_gw_ip[2 * NEIGHBOR_HASH_TABLE_SIZE];
	extern pthread_mutex_t rtMutex;

	struct RtEntry *__cmmRouteFind(struct flow *flow);
	void __cmmRouteRemove(struct RtEntry *route);
	void __cmmRoutePut(struct RtEntry *route);
	struct RtEntry *__cmmRouteAdd(struct flow *flow);
	struct RtEntry *__cmmRouteGet(struct flow *flow);

	void __cmmFFPRouteUpdate(struct fpp_rt *route, int oifindex, const unsigned char *dst_mac, int mtu, const unsigned int *dst_addr, int dst_addr_len);
	struct fpp_rt *__cmmFPPRouteFind(int oifindex, const unsigned char *dst_mac, int mtu, const unsigned int *dst_addr, int dst_addr_len);
	void __cmmFPPRouteRemove(struct fpp_rt *route);
	void __cmmFPPRoutePut(struct fpp_rt *route);
	struct fpp_rt *__cmmFPPRouteAdd(int oifindex, const unsigned char *dst_mac, int mtu, const unsigned int *dst_addr, int dst_addr_len);
	struct fpp_rt *__cmmFPPRouteGet(int oifindex, const unsigned char *dst_mac, int mtu, const unsigned int *dst_addr, int dst_addr_len);

	int cmmRtShow(struct cli_def * cli, char *command, char *argv[], int argc);
	int cmmFPPRtShow(struct cli_def * cli, char *command, char *argv[], int argc);

	int cmmRtnlRoute(const struct sockaddr_nl *who, struct nlmsghdr *nlh, void *arg);
	int cmmRtnlRule(const struct sockaddr_nl *who, struct nlmsghdr *nlh, void *arg);

#define cmmRouteEqual(route, flow, len) (!memcmp((route)->sAddr, (flow)->sAddr, (len)) && !memcmp((route)->dAddr, (flow)->dAddr, (len)) && ((route)->fwmark == (flow)->fwmark) && ((route)->iifindex == (flow)->iifindex))

static inline int cmmPrefixEqual(const u_int32_t *daddr1, const u_int32_t *daddr2, int lenbits)
{
	unsigned pdw, pbi;

	/* check complete u32 in prefix */
	pdw = lenbits >> 5;
	if (pdw && memcmp(daddr1, daddr2, pdw << 2))
		return 0;

	pbi = lenbits & 0x1f;
	if (pbi && ((daddr1[pdw] ^ daddr2[pdw]) & htonl((0xffffffff) << (32 - pbi))))
		return 0;

	return 1;
}

static inline u_int32_t HASH_RT(int family, const unsigned int *sAddr, const unsigned int *dAddr)
{
	u_int32_t key1, key2;

	if (family == AF_INET)
	{
		key1 = sAddr[0];
		key2 = dAddr[0];

		return (jhash_2words(key2, key1, 0x12563478) & (ROUTE_HASH_TABLE_SIZE - 1));
	}
	else
	{
		key1 = sAddr[0] ^ sAddr[1] ^ sAddr[2] ^ sAddr[3];
		key2 = dAddr[0] ^ dAddr[1] ^ dAddr[2] ^ dAddr[3];

		return (jhash_2words(key2, key1, 0x12563478) & (ROUTE_HASH_TABLE_SIZE - 1)) + ROUTE_HASH_TABLE_SIZE;
	}
}

static inline u_int32_t HASH_FPP_RT(u_int32_t ifindex, const u_int8_t *macaddr)
{
	u_int32_t key;

	key = ((u_int32_t *)macaddr)[0] ^ ((u_int16_t *)macaddr)[2];

	return (jhash_2words(key, ifindex, 0x12345678) & (ROUTE_HASH_TABLE_SIZE - 1));
}

#endif
