/*
 *
 *  Copyright (C) 2014 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
 */
#include "cmm.h"
#include "fpp_private.h"
#include "fpp.h"
#include "cmmd.h"
#include "itf.h"
#include "module_lro.h"

struct lro_interface {
	char ifname[IFNAMSIZ];
	int used;
};

#define LRO_MAX_ITF	4

static struct lro_interface lro_itf[LRO_MAX_ITF];

int lro_interface_add(char *ifname)
{
	int i;

	for (i = 0; i < LRO_MAX_ITF; i++)
	{
		if (lro_itf[i].used)
			continue;

		cmm_print(DEBUG_INFO, "%s: lro interface added\n", ifname);

		strncpy(lro_itf[i].ifname, ifname, IFNAMSIZ);
		lro_itf[i].used = 1;

		return 0;
	}

	return -1;
}

void lro_interface_update(struct interface *itf)
{
	int i;
	char cmd[32 + IFNAMSIZ];

	for (i = 0; i < LRO_MAX_ITF; i++)
	{
		if (lro_itf[i].used && !strcmp(lro_itf[i].ifname, itf->ifname)) {

			cmm_print(DEBUG_INFO, "%s: lro enabled\n", itf->ifname);

			itf->flags |= ITF_LRO;

			snprintf(cmd, 32 + IFNAMSIZ, "ethtool -K %s lro on", itf->ifname);
			system(cmd);

			break;
		}
	}
}

void lro_socket_open(FCI_CLIENT *fci_handle, struct ctTable *ctEntry)
{
	unsigned char proto;
	struct socket *s;
	const unsigned int *daddr, *saddr;
	unsigned short dport, sport;
	struct nf_conntrack *ct = ctEntry->ct;
	int ifindex;
	struct interface *itf;

	if (ctEntry->family != AF_INET)
		return;

	proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
	if (proto != IPPROTO_TCP)
		return;

	if (ctEntry->flags & LOCAL_CONN_ORIG) {
		ifindex = nfct_get_attr_u32(ct, ATTR_REPL_COMCERTO_FP_IFINDEX);

		saddr = nfct_get_attr(ct, ATTR_REPL_IPV4_SRC);
		daddr = nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC);

		sport = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
		dport = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
	} else {
		ifindex = nfct_get_attr_u32(ct, ATTR_ORIG_COMCERTO_FP_IFINDEX);

		saddr = nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC);
		daddr = nfct_get_attr(ct, ATTR_REPL_IPV4_SRC);

		sport = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
		dport = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
	}

	itf = __itf_find(ifindex);
	if (!itf)
		return;

	if (!(itf->flags & ITF_LRO))
		return;

	if (!____itf_is_programmed(itf))
		return;

	__pthread_mutex_lock(&socket_lock);

	s = socket_find_by_addr(AF_INET, saddr, daddr, sport, dport, IPPROTO_TCP);
	if (!s) {
		s = malloc(sizeof(struct socket));
		if (!s) {
			cmm_print(DEBUG_ERROR, "%s: malloc() failed\n", __func__);
			goto unlock;
		}

		memset(s, 0, sizeof(struct socket));

		s->family = AF_INET;

		s->id = new_socket_id();
		if (!s->id) {
			cmm_print(DEBUG_ERROR, "%s: No Socket ID available \n", __func__);

			free(s);

			goto unlock;
		}

		s->type = CMMD_SOCKET_TYPE_LRO;
		s->mode = SOCKET_CONNECTED;
		memcpy(s->saddr, saddr, IPADDRLEN(s->family));
		memcpy(s->daddr, daddr, IPADDRLEN(s->family));
		s->sport = sport;
		s->dport = dport;
		s->proto = IPPROTO_TCP;
		s->dscp = 0;
		s->fwmark = 0;
		s->queue = 0;

		__socket_add(s);
	}

	__socket_open(fci_handle, s);

unlock:
	__pthread_mutex_unlock(&socket_lock);
}


void lro_socket_close(FCI_CLIENT *fci_handle, FCI_CLIENT *fci_key_handle, struct ctTable *ctEntry)
{
	unsigned char proto;
	struct socket *s;
	const unsigned int *daddr, *saddr;
	unsigned short dport, sport;
	struct nf_conntrack *ct = ctEntry->ct;

	if (ctEntry->family != AF_INET)
		return;

	proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
	if (proto != IPPROTO_TCP)
		return;

	if (ctEntry->flags & LOCAL_CONN_ORIG) {
		saddr = nfct_get_attr(ct, ATTR_REPL_IPV4_SRC);
		daddr = nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC);

		sport = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
		dport = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
	} else {
		saddr = nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC);
		daddr = nfct_get_attr(ct, ATTR_REPL_IPV4_SRC);

		sport = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
		dport = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
	}

	__pthread_mutex_lock(&socket_lock);

	s = socket_find_by_addr(AF_INET, saddr, daddr, sport, dport, IPPROTO_TCP);
	if (!s)
		goto unlock;

	__socket_close(fci_handle, fci_key_handle, s);

unlock:
	__pthread_mutex_unlock(&socket_lock);
}

