[ipq806x] : New API format

Change-Id: Id53f3e7ed872ee5fb9891714d707d00473354eea
Signed-off-by: Radha krishna Simha Jiguru <rjiguru@codeaurora.org>
diff --git a/Makefile b/Makefile
index fa15b9a..9de95ff 100755
--- a/Makefile
+++ b/Makefile
@@ -18,23 +18,24 @@
 
 obj-m += qca-nss-drv.o
 qca-nss-drv-objs := nss_init.o nss_core.o nss_stats.o nss_pm.o nss_tx_rx_ipv4.o nss_tx_rx_ipv6.o \
-		    nss_tx_rx_tun6rd.o nss_tx_rx_tunipip6.o nss_tx_rx_virt_if.o nss_tx_rx_phys_if.o \
+		    nss_tx_rx_virt_if.o nss_tx_rx_phys_if.o \
 		    nss_tx_rx_crypto.o nss_tx_rx_ipsec.o nss_tx_rx_n2h.o nss_tx_rx_pppoe.o nss_tx_rx_generic.o \
 		    nss_tx_rx_freq.o nss_tx_rx_eth_rx.o nss_cmn.o nss_virt_if.o nss_ipv4.o \
+		    nss_tun6rd.o nss_tunipip6.o
 
 obj-m += qca-nss-connmgr-ipv4.o
 obj-m += qca-nss-connmgr-ipv6.o
 obj-m += qca-nss-tunipip6.o
 ifeq "$(CONFIG_IPV6_SIT_6RD)" "y"
 obj-m += qca-nss-tun6rd.o
-qca-nss-tun6rd-objs := nss_tun6rd.o
+qca-nss-tun6rd-objs := nss_connmgr_tun6rd.o
 ccflags-y += -DNSS_TUN6RD_DEBUG_LEVEL=0
 endif
 obj-m += qca-nss-qdisc.o
 
 qca-nss-connmgr-ipv4-objs := nss_connmgr_ipv4.o
 qca-nss-connmgr-ipv6-objs := nss_connmgr_ipv6.o
-qca-nss-tunipip6-objs := nss_tunipip6.o
+qca-nss-tunipip6-objs := nss_connmgr_tunipip6.o
 qca-nss-qdisc-objs := nss_qdisc.o
 
 ccflags-y += -I$(obj)/nss_hal/include -DNSS_DEBUG_LEVEL=4 -DNSS_EMPTY_BUFFER_SIZE=1792 -DNSS_PKT_STATS_ENABLED=0
diff --git a/nss_api_if.h b/nss_api_if.h
index 5351748..92382da 100755
--- a/nss_api_if.h
+++ b/nss_api_if.h
@@ -38,7 +38,8 @@
 #include <linux/netdevice.h>
 #include "nss_cmn.h"
 #include "nss_virt_if.h"
-
+#include "nss_tun6rd.h"
+#include "nss_tunipip6.h"
 /*
  * Interface numbers are reserved in the
  * following sequence of interface types:
@@ -86,8 +87,8 @@
  */
 #define NSS_IPSEC_ENCAP_IF_NUMBER (NSS_TUNNEL_IF_START + 0)
 #define NSS_IPSEC_DECAP_IF_NUMBER (NSS_TUNNEL_IF_START + 1)
-#define NSS_TUNRD_IF_NUMBER (NSS_TUNNEL_IF_START + 2)
-#define NSS_TUNIPIP6_IF_NUMBER (NSS_TUNNEL_IF_START + 3)
+#define NSS_TUN6RD_INTERFACE (NSS_TUNNEL_IF_START + 2)
+#define NSS_TUNIPIP6_INTERFACE (NSS_TUNNEL_IF_START + 3)
 
 /**
  * This macro converts format for IPv6 address (from Linux to NSS)
@@ -602,54 +603,6 @@
 };
 
 /**
- * 6rd configuration command structure
- */
-struct nss_tun6rd_cfg {
-	uint32_t prefix[4]; 		/* 6rd prefix */
-	uint32_t relay_prefix;		/* Relay prefix */
-	uint16_t prefixlen;		/* 6rd prefix len */
-	uint16_t relay_prefixlen;	/* Relay prefix length*/
-	uint32_t saddr; 		/* Tunnel source address */
-	uint32_t daddr; 		/* Tunnel destination addresss */
-	uint8_t  tos; 			/* Tunnel tos field */
-	uint8_t  ttl; 			/* Tunnel ttl field */
-	uint16_t reserved;		/* Reserved */
-};
-
-/**
- * 6rd tunnel stats
- */
-struct nss_tun6rd_stats {
-	uint32_t rx_packets;		/* Number of received packets */
-	uint32_t rx_bytes;		/* Number of received bytes */
-	uint32_t tx_packets;		/* Number of transmitted packets */
-	uint32_t tx_bytes;		/* Number of transmitted bytes */
-};
-
-/**
- * DS-lite and ipip6 configuration command structure
- */
-struct nss_tunipip6_cfg {
-	uint32_t saddr[4];		/* Tunnel source address */
-	uint32_t daddr[4];		/* Tunnel destination address */
-	uint32_t flowlabel;		/* Tunnel ipv6 flowlabel */
-	uint32_t flags;			/* Tunnel additional flags */
-	uint8_t  hop_limit;		/* Tunnel ipv6 hop limit */
-	uint8_t reserved;		/* Place holder */
-	uint16_t reserved1;		/* Place holder */
-};
-
-/**
- *  tunipip6 stats structure
- */
-struct nss_tunipip6_stats {
-	uint32_t rx_packets;		/* Number of received packets */
-	uint32_t rx_bytes;		/* Number of received bytes */
-	uint32_t tx_packets;		/* Number of transmitted packets */
-	uint32_t tx_bytes;		/* Number of transmitted bytes */
-};
-
-/**
  * PM Client interface status
  */
 typedef enum {
@@ -667,22 +620,6 @@
 } nss_gmac_event_t;
 
 /**
- * NSS 6rd tunnel event type
- */
-typedef enum {
-	NSS_TUN6RD_EVENT_STATS,
-	NSS_TUN6RD_EVENT_MAX
-} nss_tun6rd_event_t;
-
-/**
- * NSS ipip6 tunnel event type
- */
-typedef enum {
-	NSS_TUNIPIP6_EVENT_STATS,
-	NSS_TUNIPIP6_EVENT_MAX
-} nss_tunipip6_event_t;
-
-/**
  * NSS Shaping
  */
 
@@ -1512,76 +1449,6 @@
  * Methods provided by NSS driver for use by 6rd tunnel
  */
 
-/**
- * Tun6rd interface create message
- */
-extern nss_tx_status_t nss_tx_tun6rd_if_create(void *nss_ctx, struct nss_tun6rd_cfg *tuncfg, uint32_t if_num);
-
-/**
- * Tun6rd interface destroy meesage
- */
-extern nss_tx_status_t nss_tx_tun6rd_if_destroy(void *nss_ctx, struct nss_tun6rd_cfg *tuncfg, uint32_t if_num);
-
-/**
- * Callback to receive tun6rd events
- */
-typedef void (*nss_tun6rd_if_event_callback_t)(void *if_ctx, nss_tun6rd_event_t ev_type, void *buf, uint32_t len);
-
-/**
- * Callback to receive 6rd callback
- */
-typedef void (*nss_tun6rd_callback_t)(void *ctx, void *os_buf);
-
-/**
- * Tunipip6 interface create message
- */
-extern nss_tx_status_t nss_tx_tunipip6_if_create(void *nss_ctx, struct nss_tunipip6_cfg *tuncfg, uint32_t if_num);
-
-/**
- * Tunipip6 interface destroy meesage
- */
-extern nss_tx_status_t nss_tx_tunipip6_if_destroy(void *nss_ctx, struct nss_tunipip6_cfg *tuncfg, uint32_t if_num);
-
-/**
- * Callback to receive tunipip6 events
- */
-typedef void (*nss_tunipip6_if_event_callback_t)(void *if_ctx, nss_tunipip6_event_t ev_type, void *buf, uint32_t len);
-
-/**
- * Callback to receive ipip6 callback
- */
-typedef void (*nss_tunipip6_callback_t)(void *ctx, void *os_buf);
-
-/**
- * @brief Register to send/receive 6rd tunnel messages to NSS
- *
- * @param tun6rd_callback Callback
- * @param ctx 6rd tunnel context
- *
- * @return void* NSS context
- */
-extern void *nss_register_tun6rd_if(uint32_t if_num, nss_tun6rd_callback_t tun6rd_callback, nss_tun6rd_if_event_callback_t event_callback, void *ctx);
-
-/**
- * @brief Unregister 6rd tunnel interface with NSS
- */
-extern void nss_unregister_tun6rd_if(uint32_t if_num);
-
-/**
- * @brief Register to send/receive ipip6 tunnel messages to NSS
- *
- * @param tunipip6_callback Callback
- * @param ctx ipip6 tunnel context
- *
- * @return void* NSS context
- */
-extern void *nss_register_tunipip6_if(uint32_t if_num, nss_tunipip6_callback_t tunipip6_callback, nss_tunipip6_if_event_callback_t event_callback, void *ctx);
-
-/**
- * @brief Unregister ipip6 tunnel interface with NSS
- */
-extern void nss_unregister_tunipip6_if(uint32_t if_num);
-
 /*
  * @brief NSS Frequency Change
  * @ param ctx NSS context
diff --git a/nss_connmgr_tun6rd.c b/nss_connmgr_tun6rd.c
new file mode 100755
index 0000000..1a239d8
--- /dev/null
+++ b/nss_connmgr_tun6rd.c
@@ -0,0 +1,470 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/*
+ * nss_tun6rd.c
+ *
+ * This file is the NSS 6rd tunnel module
+ * ------------------------REVISION HISTORY-----------------------------
+ * Qualcomm Atheros         15/sep/2013              Created
+ */
+
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/ipv6.h>
+#include <net/ipip.h>
+#include <linux/if_arp.h>
+#include "nss_api_if.h"
+
+/*
+ * NSS tun6rd debug macros
+ */
+#if (NSS_TUN6RD_DEBUG_LEVEL < 1)
+#define nss_tun6rd_assert(fmt, args...)
+#else
+#define nss_tun6d_assert(c) if (!(c)) { BUG_ON(!(c)); }
+#endif
+
+#if (NSS_TUN6RD_DEBUG_LEVEL < 2)
+#define nss_tun6rd_error(fmt, args...)
+#else
+#define nss_tun6rd_error(fmt, args...) printk(KERN_WARNING "nss tun6rd:"fmt, ##args)
+#endif
+
+#if (NSS_TUN6RD_DEBUG_LEVEL < 3)
+#define nss_tun6rd_warning(fmt, args...)
+#else
+#define nss_tun6rd_warning(fmt, args...) printk(KERN_WARNING "nss tun6rd:"fmt, ##args)
+#endif
+
+#if (NSS_TUN6RD_DEBUG_LEVEL < 4)
+#define nss_tun6rd_info(fmt, args...)
+#else
+#define nss_tun6rd_info(fmt, args...) printk(KERN_INFO "nss tun6rd :"fmt, ##args)
+#endif
+
+#if (NSS_TUN6RD_DEBUG_LEVEL < 5)
+#define nss_tun6rd_trace(fmt, args...)
+#else
+#define nss_tun6rd_trace(fmt, args...) printk(KERN_DEBUG "nss tun6rd :"fmt, ##args)
+#endif
+
+void nss_tun6rd_exception(void *ctx, void *buf);
+void nss_tun6rd_event_receive(void *ctx, struct nss_tun6rd_msg *msg);
+
+/*
+ * 6rd tunnel host instance
+ */
+struct nss_tun6rd_tunnel{
+	struct nss_ctx_instance *nss_ctx;
+	uint32_t if_num;
+	struct net_device *netdev;
+	uint32_t device_up;
+};
+
+/*
+ * 6rd tunnel stats
+ */
+struct nss_tun6rd_stats {
+	uint32_t rx_packets;	/* Number of received packets */
+	uint32_t rx_bytes;	/* Number of received bytes */
+	uint32_t tx_packets;	/* Number of transmitted packets */
+	uint32_t tx_bytes;	/* Number of transmitted bytes */
+};
+
+
+struct nss_tun6rd_tunnel g_tun6rd;
+
+/*
+ * Internal function
+ */
+static int
+nss_tun6rd_dev_event(struct notifier_block  *nb,
+			unsigned long event,
+			void  *dev);
+
+/*
+ * Linux Net device Notifier
+ */
+struct notifier_block nss_tun6rd_notifier = {
+	.notifier_call = nss_tun6rd_dev_event,
+};
+
+/*
+ * nss_tun6rd_dev_up()
+ *	6RD Tunnel device i/f up handler
+ */
+void nss_tun6rd_dev_up( struct net_device * netdev)
+{
+	struct ip_tunnel *tunnel;
+	struct ip_tunnel_6rd_parm *ip6rd;
+	const struct iphdr  *tiph;
+	struct nss_tun6rd_msg tun6rdmsg;
+	struct nss_tun6rd_create_msg *tun6rdcfg;
+	nss_tx_status_t status;
+
+
+
+	/*
+	 * Validate netdev for ipv6-in-ipv4  Tunnel
+	 */
+	if (netdev->type != ARPHRD_SIT ) {
+		return;
+	}
+
+	tunnel = (struct ip_tunnel*)netdev_priv(netdev);
+	ip6rd =  &tunnel->ip6rd;
+
+	/*
+	 * Valid 6rd Tunnel Check
+	 * 1. 6rd Prefix len should be non zero
+	 * 2. Relay prefix length should not be greater then 32
+	 * 3. To allow for stateless address auto-configuration on the CE LAN side,
+	 *    6rd delegated prefix SHOULD be /64 or shorter.
+	 */
+	if ((ip6rd->prefixlen == 0 )
+			|| (ip6rd->relay_prefixlen > 32)
+			|| (ip6rd->prefixlen
+				+ (32 - ip6rd->relay_prefixlen) > 64)){
+
+		nss_tun6rd_error("Invalid 6rd argument prefix len %d     \
+				relayprefix len %d \n",
+				ip6rd->prefixlen,ip6rd->relay_prefixlen);
+		return;
+	}
+
+	nss_tun6rd_info(" Valid 6rd Tunnel Prefix %x %x %x %x  \n        \
+			prefix len %d  relay_prefix %d relay_prefixlen %d \n",
+			ip6rd->prefix.s6_addr32[0],ip6rd->prefix.s6_addr32[1],
+			ip6rd->prefix.s6_addr32[2],ip6rd->prefix.s6_addr32[3],
+			ip6rd->prefixlen, ip6rd->relay_prefix,
+			ip6rd->relay_prefixlen);
+
+	/*
+	 * Find the Tunnel device ipHeader info
+	 */
+	tiph = &tunnel->parms.iph ;
+	nss_tun6rd_trace(" Tunnel Param srcaddr %x daddr %x ttl %d tos %x\n",
+			tiph->saddr, tiph->daddr,tiph->ttl,tiph->tos);
+
+	if(tiph->saddr == 0) {
+		nss_tun6rd_error("Tunnel src address not configured  %x\n",
+				tiph->saddr);
+		return;
+	}
+
+	if (tiph->daddr == 0) {
+		nss_tun6rd_error("Tunnel dest address not configured  %x\n",
+				tiph->daddr);
+		return;
+	}
+
+	/*
+	 * Register 6rd tunnel with NSS
+	 */
+	g_tun6rd.nss_ctx = nss_register_tun6rd_if(g_tun6rd.if_num,
+				nss_tun6rd_exception,
+				nss_tun6rd_event_receive,
+				netdev);
+	if (g_tun6rd.nss_ctx == NULL) {
+		nss_tun6rd_trace("nss_register_tun6rd_if Failed \n");
+		return;
+	} else {
+		nss_tun6rd_trace("nss_register_tun6rd_if Success \n");
+	}
+
+	/*
+	 * Prepare The Tunnel configuration parameter to send to nss
+	 */
+	memset(&tun6rdmsg, 0, sizeof(struct nss_tun6rd_msg));
+	tun6rdcfg = &tun6rdmsg.msg.tun6rd_create;
+
+	tun6rdcfg->prefixlen       = ip6rd->prefixlen;
+	tun6rdcfg->relay_prefix    = ip6rd->relay_prefix;
+	tun6rdcfg->relay_prefixlen = ip6rd->relay_prefixlen;
+	tun6rdcfg->saddr           = ntohl(tiph->saddr);
+	tun6rdcfg->daddr           = ntohl(tiph->daddr);
+	tun6rdcfg->prefix[0]       = ntohl(ip6rd->prefix.s6_addr32[0]);
+	tun6rdcfg->prefix[1]       = ntohl(ip6rd->prefix.s6_addr32[1]);
+	tun6rdcfg->prefix[2]       = ntohl(ip6rd->prefix.s6_addr32[2]);
+	tun6rdcfg->prefix[3]       = ntohl(ip6rd->prefix.s6_addr32[3]);
+	tun6rdcfg->ttl             = tiph->ttl;
+	tun6rdcfg->tos             = tiph->tos;
+
+        nss_tun6rd_trace(" 6rd Tunnel info \n");
+        nss_tun6rd_trace(" saddr %x daddr %d ttl %x  tos %x \n",
+			tiph->saddr, tiph->daddr, tiph->ttl, tiph->tos);
+	nss_tun6rd_trace(" Prefix %x:%x:%x:%x  Prefix len %d \n",
+			ip6rd->prefix.s6_addr32[0], ip6rd->prefix.s6_addr32[1],
+			ip6rd->prefix.s6_addr32[2], ip6rd->prefix.s6_addr32[3],
+			ip6rd->prefixlen);
+	nss_tun6rd_trace("Relay Prefix %x Len %d\n",
+			ip6rd->relay_prefix, ip6rd->relay_prefixlen);
+
+	nss_tun6rd_trace("Sending 6rd tunnel i/f up command to NSS  %x \n",
+			(int)g_tun6rd.nss_ctx);
+
+	/*
+	 * Send 6rd Tunnel UP command to NSS
+	 */
+	nss_cmn_msg_init(&tun6rdmsg.cm, NSS_TUN6RD_INTERFACE, NSS_TUN6RD_TX_IF_CREATE,
+			sizeof(struct nss_tun6rd_create_msg), NULL, NULL);
+
+	status = nss_tun6rd_tx(g_tun6rd.nss_ctx, &tun6rdmsg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_tun6rd_error("Tunnel up command error %d \n", status);
+		return;
+	}
+
+	g_tun6rd.device_up = 1;
+}
+
+/*
+ * nss_tun6rd_dev_down()
+ *	6RD Tunnel device i/f down handler
+ */
+void nss_tun6rd_dev_down(struct net_device *netdev)
+{
+	struct ip_tunnel *tunnel;
+	struct ip_tunnel_6rd_parm *ip6rd;
+	struct nss_tun6rd_msg tun6rdmsg;
+	struct nss_tun6rd_destroy_msg *tun6rdcfg;
+	nss_tx_status_t status;
+
+	/*
+	 * Check if tunnel 6rd is registered ?
+	 */
+	if (g_tun6rd.nss_ctx == NULL) {
+		return;
+	}
+
+	/*
+	 * Validate netdev for ipv6-in-ipv4  Tunnel
+	 */
+	if (netdev->type != ARPHRD_SIT ) {
+		return;
+	}
+
+	tunnel = (struct ip_tunnel*)netdev_priv(netdev);
+	ip6rd =  &tunnel->ip6rd;
+
+	/*
+	 * Valid 6rd Tunnel Check
+	 */
+	if ((ip6rd->prefixlen == 0 )
+			|| (ip6rd->relay_prefixlen > 32 )
+			|| (ip6rd->prefixlen
+				+ (32 - ip6rd->relay_prefixlen) > 64)){
+
+		nss_tun6rd_error("Invalid 6rd argument prefix len %d  \
+				relayprefix len %d \n",
+				ip6rd->prefixlen,ip6rd->relay_prefixlen);
+		return;
+	}
+
+	/*
+	 * Prepare The Tunnel configuration parameter to send to nss
+	 */
+	memset(&tun6rdmsg, 0, sizeof(struct nss_tun6rd_msg));
+	tun6rdcfg = &tun6rdmsg.msg.tun6rd_destroy;
+
+	tun6rdcfg->prefix[0]   = ntohl(ip6rd->prefix.s6_addr32[0]);
+	tun6rdcfg->prefix[1]   = ntohl(ip6rd->prefix.s6_addr32[1]);
+	tun6rdcfg->prefix[2]   = ntohl(ip6rd->prefix.s6_addr32[2]);
+	tun6rdcfg->prefix[3]   = ntohl(ip6rd->prefix.s6_addr32[3]);
+
+	nss_tun6rd_trace(" Prefix %x:%x:%x:%x  Prefix len %d \n",
+			ip6rd->prefix.s6_addr32[0], ip6rd->prefix.s6_addr32[1],
+			ip6rd->prefix.s6_addr32[2], ip6rd->prefix.s6_addr32[3],
+			ip6rd->prefixlen);
+
+	nss_tun6rd_trace("Sending Tunnle 6rd Down command %x \n",g_tun6rd.if_num);
+
+	/*
+	 * Send 6rd Tunnel DESTROY command to NSS
+	 */
+	nss_cmn_msg_init(&tun6rdmsg.cm, NSS_TUN6RD_INTERFACE, NSS_TUN6RD_TX_IF_DESTROY,
+			sizeof(struct nss_tun6rd_destroy_msg), NULL, NULL);
+
+	status = nss_tun6rd_tx(g_tun6rd.nss_ctx, &tun6rdmsg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_tun6rd_error("Tunnel down command error %d \n", status);
+		return;
+	}
+
+	/*
+	 * Un-Register 6rd tunnel with NSS
+	 */
+	nss_unregister_tun6rd_if(g_tun6rd.if_num);
+	g_tun6rd.nss_ctx = NULL;
+	g_tun6rd.device_up = 0;
+	return;
+}
+
+/*
+ * nss_tun6rd_dev_event()
+ *	Net device notifier for 6rd module
+ */
+static int nss_tun6rd_dev_event(struct notifier_block  *nb,
+		unsigned long event, void  *dev)
+{
+	struct net_device *netdev = (struct net_device *)dev;
+
+	nss_tun6rd_trace("%s\n",__FUNCTION__);
+	switch (event) {
+	case NETDEV_UP:
+		nss_tun6rd_trace(" NETDEV_UP :event %lu name %s \n",
+				event,netdev->name);
+		nss_tun6rd_dev_up(netdev);
+		break;
+
+	case NETDEV_DOWN:
+		nss_tun6rd_trace(" NETDEV_DOWN :event %lu name %s \n",
+				event,netdev->name);
+		nss_tun6rd_dev_down(netdev);
+		break;
+
+	default:
+		nss_tun6rd_trace("Unhandled notifier dev %s  event %x  \n",
+				netdev->name,(int)event);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+/*
+ * nss_tun6rd_exception()
+ *	Exception handler registered to NSS driver
+ */
+void nss_tun6rd_exception(void *ctx, void *buf)
+{
+	struct net_device *dev = (struct net_device *)ctx;
+	struct sk_buff *skb = (struct sk_buff *)buf;
+	const struct iphdr *iph;
+
+	skb->dev = dev;
+	nss_tun6rd_info("received - %d bytes name %s ver %x \n",
+			skb->len,dev->name,skb->data[0]);
+
+	iph = (const struct iphdr *)skb->data;
+
+	/*
+	 * Packet after Decap/Encap Did not find the Rule.
+	 */
+	if (iph->version == 4) {
+		if(iph->protocol == IPPROTO_IPV6){
+			skb_pull(skb, sizeof(struct iphdr));
+			skb->protocol = htons(ETH_P_IPV6);
+			skb_reset_network_header(skb);
+			skb->pkt_type = PACKET_HOST;
+			skb->ip_summed = CHECKSUM_NONE;
+			dev_queue_xmit(skb);
+			return;
+		}
+		skb->protocol = htons(ETH_P_IP);
+	} else {
+		skb->protocol = htons(ETH_P_IPV6);
+	}
+
+	skb_reset_network_header(skb);
+	skb->pkt_type = PACKET_HOST;
+	skb->skb_iif = dev->ifindex;
+	skb->ip_summed = CHECKSUM_NONE;
+	netif_receive_skb(skb);
+}
+
+/*
+ *  nss_tun6rd_update_dev_stats
+ *	Update the Dev stats received from NetAp
+ */
+static void nss_tun6rd_update_dev_stats(struct net_device *dev,
+					struct nss_tun6rd_stats_sync_msg *sync_stats)
+{
+	struct nss_tun6rd_stats stats;
+	void *ptr;
+
+	stats.rx_packets = sync_stats->node_stats.rx_packets;
+	stats.rx_bytes = sync_stats->node_stats.rx_bytes;
+	stats.tx_packets = sync_stats->node_stats.tx_packets;
+	stats.tx_bytes = sync_stats->node_stats.tx_bytes;
+
+	ptr = (void *)&stats;
+	ipip6_update_offload_stats(dev, ptr);
+}
+
+/**
+ * @brief Event Callback to receive events from NSS
+ * @param[in] pointer to net device context
+ * @param[in] pointer to buffer
+ * @return Returns void
+ */
+void nss_tun6rd_event_receive(void *if_ctx, struct nss_tun6rd_msg *tnlmsg)
+{
+	struct net_device *netdev = NULL;
+	netdev = (struct net_device *)if_ctx;
+
+	switch (tnlmsg->cm.type) {
+	case NSS_TUN6RD_RX_STATS_SYNC:
+		nss_tun6rd_update_dev_stats(netdev, (struct nss_tun6rd_stats_sync_msg *)&tnlmsg->msg.stats_sync);
+		break;
+
+	default:
+		nss_tun6rd_info("%s: Unknown Event from NSS",
+			      __FUNCTION__);
+		break;
+	}
+}
+
+/*
+ * nss_tun6rd_init_module()
+ *	Tunnel 6rd module init function
+ */
+int __init nss_tun6rd_init_module(void)
+{
+	nss_tun6rd_info("module (platform - IPQ806x , Build - %s:%s) loaded\n",
+			__DATE__, __TIME__);
+
+	register_netdevice_notifier(&nss_tun6rd_notifier);
+	nss_tun6rd_trace("Netdev Notifier registerd \n");
+
+	g_tun6rd.if_num = NSS_TUN6RD_INTERFACE;
+	g_tun6rd.netdev = NULL;
+	g_tun6rd.device_up = 0;
+	g_tun6rd.nss_ctx = NULL;
+
+	return 0;
+}
+
+/*
+ * nss_tun6rd_exit_module()
+ *	Tunnel 6rd module exit function
+ */
+void __exit nss_tun6rd_exit_module(void)
+{
+
+	unregister_netdevice_notifier(&nss_tun6rd_notifier);
+	nss_tun6rd_info("module unloaded\n");
+}
+
+module_init(nss_tun6rd_init_module);
+module_exit(nss_tun6rd_exit_module);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("NSS tun6rd offload manager");
diff --git a/nss_connmgr_tunipip6.c b/nss_connmgr_tunipip6.c
new file mode 100755
index 0000000..0c8fe0f
--- /dev/null
+++ b/nss_connmgr_tunipip6.c
@@ -0,0 +1,401 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/*
+ * nss_tunipip6.c
+ *
+ * This file is the NSS DS-lit and IPP6  tunnel module
+ * ------------------------REVISION HISTORY-----------------------------
+ * Qualcomm Atheros	    15/sep/2013		     Created
+ */
+
+#include <linux/types.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/ipv6.h>
+#include <net/ipip.h>
+#include <net/ip6_tunnel.h>
+#include <linux/if_arp.h>
+#include "nss_api_if.h"
+#include "nss_hlos_if.h"
+#include "nss_tunipip6.h"
+
+/*
+ * NSS tunipip6 debug macros
+ */
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 1)
+#define nss_tunipip6_assert(fmt, args...)
+#else
+#define nss_tunipip6_assert(c) if (!(c)) { BUG_ON(!(c)); }
+#endif
+
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 2)
+#define nss_tunipip6_error(fmt, args...)
+#else
+#define nss_tunipip6_error(fmt, args...) printk(KERN_WARNING "nss tunipip6:"fmt, ##args)
+#endif
+
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 3)
+#define nss_tunipip6_warning(fmt, args...)
+#else
+#define nss_tunipip6_warning(fmt, args...) printk(KERN_WARNING "nss tunipip6:"fmt, ##args)
+#endif
+
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 4)
+#define nss_tunipip6_info(fmt, args...)
+#else
+#define nss_tunipip6_info(fmt, args...) printk(KERN_INFO "nss tunipip6 :"fmt, ##args)
+#endif
+
+#if (NSS_TUNIPIP6_DEBUG_LEVEL < 5)
+#define nss_tunipip6_trace(fmt, args...)
+#else
+#define nss_tunipip6_trace(fmt, args...) printk(KERN_DEBUG "nss tunipip6 :"fmt, ##args)
+#endif
+
+void nss_tunipip6_exception(void *ctx, void *buf);
+void nss_tunipip6_event_receive(void *ctx, struct nss_tunipip6_msg *msg);
+
+/*
+ * nss_tunipip6_tunnel
+ *	DS-lite and ipip 6tunnel host instance
+ */
+struct nss_tunipip6_tunnel{
+	struct nss_ctx_instance *nss_ctx;
+	uint32_t if_num;
+	struct net_device *netdev;
+	uint32_t device_up;
+};
+
+/*
+ *  tunipip6 stats structure
+ */
+struct nss_tunipip6_stats {
+	uint32_t rx_packets;	/* Number of received packets */
+	uint32_t rx_bytes;	/* Number of received bytes */
+	uint32_t tx_packets;	/* Number of transmitted packets */
+	uint32_t tx_bytes;	/* Number of transmitted bytes */
+};
+
+struct nss_tunipip6_tunnel g_tunipip6;
+
+/*
+ * Internal function
+ */
+static int
+nss_tunipip6_dev_event(struct notifier_block  *nb,
+			unsigned long event,
+			void  *dev);
+
+/*
+ * Linux Net device Notifier
+ */
+struct notifier_block nss_tunipip6_notifier = {
+	.notifier_call = nss_tunipip6_dev_event,
+};
+
+/*
+ * nss_tunipip6_dev_up()
+ *	IPIP6 Tunnel device i/f up handler
+ */
+void nss_tunipip6_dev_up( struct net_device * netdev)
+{
+	struct ip6_tnl *tunnel;
+	struct nss_tunipip6_msg tnlmsg;
+	struct nss_tunipip6_create_msg *tnlcfg;
+	struct flowi6 *fl6;
+	nss_tx_status_t status;
+
+	/*
+	 * Validate netdev for ipv6-in-ipv4  Tunnel
+	 */
+	if (netdev->type != ARPHRD_TUNNEL6 ) {
+		return;
+	}
+
+	tunnel = (struct ip6_tnl *)netdev_priv(netdev);
+
+	/*
+	 * Find he Tunnel device flow information
+	 */
+
+	fl6  = &tunnel->fl.u.ip6;
+
+	nss_tunipip6_trace(" Tunnel Param srcaddr %x:%x:%x:%x  daddr %x:%x:%x:%x \n",
+			fl6->saddr.s6_addr32[0], fl6->saddr.s6_addr32[1],
+			fl6->saddr.s6_addr32[2], fl6->saddr.s6_addr32[3],
+			fl6->daddr.s6_addr32[0], fl6->daddr.s6_addr32[1],
+			fl6->daddr.s6_addr32[2], fl6->daddr.s6_addr32[3] );
+	nss_tunipip6_trace(" hop limit %d \n", tunnel->parms.hop_limit);
+	nss_tunipip6_trace(" tunnel param flag %x  fl6.flowlabel %x  \n", tunnel->parms.flags, fl6->flowlabel);
+
+	/*
+	 * Register ipip6 tunnel with NSS
+	 */
+	g_tunipip6.nss_ctx = nss_register_tunipip6_if(g_tunipip6.if_num,
+				nss_tunipip6_exception,
+				nss_tunipip6_event_receive,
+				netdev);
+	if (g_tunipip6.nss_ctx == NULL) {
+		nss_tunipip6_trace("nss_register_tunipip6_if Failed \n");
+		return;
+	} else {
+		nss_tunipip6_trace("nss_register_tunipip6_if Success \n");
+	}
+
+	/*
+	 *Prepare The Tunnel configuration parameter to send to nss
+	 */
+	memset(&tnlmsg, 0, sizeof(struct nss_tunipip6_msg));
+	tnlcfg = &tnlmsg.msg.tunipip6_create;
+
+	tnlcfg->saddr[0] = ntohl(fl6->saddr.s6_addr32[0]);
+	tnlcfg->saddr[1] = ntohl(fl6->saddr.s6_addr32[1]);
+	tnlcfg->saddr[2] = ntohl(fl6->saddr.s6_addr32[2]);
+	tnlcfg->saddr[3] = ntohl(fl6->saddr.s6_addr32[3]);
+	tnlcfg->daddr[0] = ntohl(fl6->daddr.s6_addr32[0]);
+	tnlcfg->daddr[1] = ntohl(fl6->daddr.s6_addr32[1]);
+	tnlcfg->daddr[2] = ntohl(fl6->daddr.s6_addr32[2]);
+	tnlcfg->daddr[3] = ntohl(fl6->daddr.s6_addr32[3]);
+	tnlcfg->hop_limit = tunnel->parms.hop_limit;
+	tnlcfg->flags = ntohl(tunnel->parms.flags);
+	tnlcfg->flowlabel = fl6->flowlabel;  /*flow Label In kernel is stored in big endian format*/
+	nss_tunipip6_trace(" Tunnel Param srcaddr %x:%x:%x:%x  daddr %x:%x:%x:%x \n",
+			tnlcfg->saddr[0], tnlcfg->saddr[1],
+			tnlcfg->saddr[2], tnlcfg->saddr[3],
+			tnlcfg->daddr[0], tnlcfg->daddr[1],
+			tnlcfg->daddr[2], tnlcfg->daddr[3] );
+
+
+	nss_tunipip6_trace("Sending IPIP6 tunnel i/f up command to NSS	%x \n",
+			(int)g_tunipip6.nss_ctx);
+
+	/*
+	 * Send IPIP6 Tunnel UP command to NSS
+	 */
+	nss_cmn_msg_init(&tnlmsg.cm, NSS_TUNIPIP6_INTERFACE, NSS_TUNIPIP6_TX_IF_CREATE,
+			sizeof(struct nss_tunipip6_create_msg), NULL, NULL);
+
+	status = nss_tunipip6_tx(g_tunipip6.nss_ctx, &tnlmsg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_tunipip6_error("Tunnel up command error %d \n", status);
+		return;
+	}
+
+	g_tunipip6.device_up = 1;
+}
+
+/*
+ * nss_tunipip6_dev_down()
+ *	IPP6 Tunnel device i/f down handler
+ */
+void nss_tunipip6_dev_down( struct net_device * netdev)
+{
+	struct nss_tunipip6_msg tnlmsg;
+	struct nss_tunipip6_destroy_msg *tnlcfg;
+	nss_tx_status_t status;
+
+	/*
+	 * Check if tunnel ipip6 is registered ?
+	 */
+	if(g_tunipip6.nss_ctx == NULL){
+		return;
+	}
+
+	/*
+	 * Validate netdev for ipv6-in-ipv4  Tunnel
+	 */
+	if (netdev->type != ARPHRD_TUNNEL6) {
+		return;
+	}
+
+	/*
+	 * TODO: Strick check required if its the same tunnel
+	 * registerd with us
+	 */
+
+	memset(&tnlmsg, 0, sizeof(struct nss_tunipip6_msg));
+	tnlcfg = &tnlmsg.msg.tunipip6_destroy;
+
+	nss_tunipip6_trace("Sending Tunnel ipip6 Down command %x \n",g_tunipip6.if_num);
+
+	/*
+	 * Send IPIP6 Tunnel DOWN command to NSS
+	 */
+	nss_cmn_msg_init(&tnlmsg.cm, NSS_TUNIPIP6_INTERFACE, NSS_TUNIPIP6_TX_IF_DESTROY,
+			sizeof(struct nss_tunipip6_destroy_msg), NULL, NULL);
+
+	status = nss_tunipip6_tx(g_tunipip6.nss_ctx, &tnlmsg);
+	if (status != NSS_TX_SUCCESS) {
+		nss_tunipip6_error("Tunnel down command error %d \n", status);
+		return;
+	}
+
+	/*
+	 * Un-Register IPIP6 tunnel with NSS
+	 */
+	nss_unregister_tunipip6_if(g_tunipip6.if_num);
+	g_tunipip6.nss_ctx = NULL;
+	g_tunipip6.device_up = 0;
+}
+
+/*
+ * nss_tun6rd_dev_event()
+ *	Net device notifier for ipip6 module
+ */
+static int nss_tunipip6_dev_event(struct notifier_block  *nb,
+		unsigned long event, void  *dev)
+{
+	struct net_device *netdev = (struct net_device *)dev;
+
+	nss_tunipip6_trace("%s\n",__FUNCTION__);
+	switch (event) {
+	case NETDEV_UP:
+		nss_tunipip6_trace(" NETDEV_UP :event %lu name %s \n",
+				event,netdev->name);
+		nss_tunipip6_dev_up(netdev);
+		break;
+
+	case NETDEV_DOWN:
+		nss_tunipip6_trace(" NETDEV_DOWN :event %lu name %s \n",
+				event,netdev->name);
+		nss_tunipip6_dev_down(netdev);
+		break;
+
+	default:
+		nss_tunipip6_trace("Unhandled notifier dev %s  event %x  \n",
+				netdev->name,(int)event);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+/*
+ * nss_tunipip6_exception()
+ *	Exception handler registered to NSS driver
+ */
+void nss_tunipip6_exception(void *ctx, void *buf)
+{
+	struct net_device *dev = (struct net_device *)ctx;
+	struct sk_buff *skb = (struct sk_buff *)buf;
+	const struct iphdr *iph;
+
+	skb->dev = dev;
+	nss_tunipip6_info("received - %d bytes name %s ver %x \n",
+			skb->len,dev->name,skb->data[0]);
+
+	iph = (const struct iphdr *)skb->data;
+
+	/*
+	 *Packet after Decap/Encap Did not find the Rule.
+	 */
+	if (iph->version == 4) {
+		skb->protocol = htons(ETH_P_IP);
+	} else {
+		skb->protocol = htons(ETH_P_IPV6);
+	}
+
+	skb_reset_network_header(skb);
+	skb->pkt_type = PACKET_HOST;
+	skb->skb_iif = dev->ifindex;
+	skb->ip_summed = CHECKSUM_NONE;
+	netif_receive_skb(skb);
+}
+
+/*
+ *  nss_tunipip6_update_dev_stats
+ *	Update the Dev stats received from NetAp
+ */
+static void nss_tunipip6_update_dev_stats(struct net_device *dev,
+					struct nss_tunipip6_stats_sync_msg *sync_stats)
+{
+	void *ptr;
+	struct nss_tunipip6_stats stats;
+
+	stats.rx_packets = sync_stats->node_stats.rx_packets;
+	stats.rx_bytes = sync_stats->node_stats.rx_bytes;
+	stats.tx_packets = sync_stats->node_stats.tx_packets;
+	stats.tx_bytes = sync_stats->node_stats.tx_bytes;
+
+	ptr = (void *)&stats;
+	ip6_update_offload_stats(dev, ptr);
+
+}
+
+/**
+ * @brief Event Callback to receive events from NSS
+ * @param[in] pointer to net device context
+ * @param[in] event type
+ * @param[in] pointer to buffer
+ * @param[in] length of buffer
+ * @return Returns void
+ */
+void nss_tunipip6_event_receive(void *if_ctx, struct nss_tunipip6_msg *tnlmsg)
+{
+	struct net_device *netdev = NULL;
+	netdev = (struct net_device *)if_ctx;
+
+	switch (tnlmsg->cm.type) {
+	case NSS_TUNIPIP6_RX_STATS_SYNC:
+		 nss_tunipip6_update_dev_stats(netdev, (struct nss_tunipip6_stats_sync_msg *)&tnlmsg->msg.stats_sync );
+		break;
+
+	default:
+		nss_tunipip6_info("%s: Unknown Event from NSS",
+			      __FUNCTION__);
+		break;
+	}
+}
+
+/*
+ * nss_tunipip6_init_module()
+ *	Tunnel ipip6 module init function
+ */
+int __init nss_tunipip6_init_module(void)
+{
+	nss_tunipip6_info("module (platform - IPQ806x , Build - %s:%s) loaded\n",
+			__DATE__, __TIME__);
+
+	register_netdevice_notifier(&nss_tunipip6_notifier);
+	nss_tunipip6_trace("Netdev Notifier registerd \n");
+
+	g_tunipip6.if_num = NSS_TUNIPIP6_INTERFACE;
+	g_tunipip6.netdev = NULL;
+	g_tunipip6.device_up = 0;
+	g_tunipip6.nss_ctx = NULL;
+
+	return 0;
+}
+
+/*
+ * nss_tunipip6_exit_module()
+ *	Tunnel ipip6 module exit function
+ */
+void __exit nss_tunipip6_exit_module(void)
+{
+
+	unregister_netdevice_notifier(&nss_tunipip6_notifier);
+	nss_tunipip6_info("module unloaded\n");
+}
+
+module_init(nss_tunipip6_init_module);
+module_exit(nss_tunipip6_exit_module);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("NSS tunipip6 offload manager");
diff --git a/nss_core.h b/nss_core.h
index 2b3b507..3baa7a3 100755
--- a/nss_core.h
+++ b/nss_core.h
@@ -484,9 +484,9 @@
 					/* Physical interface event callback functions */
 	nss_profiler_callback_t profiler_callback[NSS_MAX_CORES];
 					/* Profiler interface callback function */
-	nss_tun6rd_if_event_callback_t tun6rd_if_event_callback;
+	nss_tun6rd_msg_callback_t tun6rd_msg_callback;
 					/* 6rd tunnel interface event callback function */
-	nss_tunipip6_if_event_callback_t tunipip6_if_event_callback;
+	nss_tunipip6_msg_callback_t tunipip6_msg_callback;
 					/* ipip6 tunnel interface event callback function */
 	struct nss_shaper_bounce_registrant bounce_interface_registrants[NSS_MAX_NET_INTERFACES];
 					/* Registrants for interface shaper bounce operations */
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index 0ebf910..2a1f443 100755
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -546,114 +546,6 @@
 };
 
 /*
- * 6RD (IPv6 in IPv4) tunnel messages
- */
-
-/*
- * Request/Response types
- */
-enum nss_tun6rd_metadata_types {
-	NSS_TX_METADATA_TYPE_TUN6RD_IF_CREATE,
-	NSS_TX_METADATA_TYPE_TUN6RD_IF_DESTROY,
-	NSS_RX_METADATA_TYPE_TUN6RD_STATS_SYNC,
-	NSS_METADATA_TYPE_TUN6RD_MAX,
-};
-
-/*
- * 6rd configuration command structure
- */
-struct nss_tun6rd_create {
-	uint32_t prefix[4];		/* 6rd prefix */
-	uint32_t relay_prefix;		/* Relay prefix */
-	uint16_t prefixlen;		/* 6rd prefix len */
-	uint16_t relay_prefixlen;	/* Relay prefix length*/
-	uint32_t saddr;			/* Tunnel source address */
-	uint32_t daddr;			/* Tunnel destination addresss */
-	uint8_t  tos;			/* Tunnel tos field */
-	uint8_t  ttl;			/* Tunnel ttl field */
-	uint16_t reserved;		/* Reserved field */
-};
-
-/*
- * 6rd tunnel interface down command structure
- */
-struct nss_tun6rd_destroy {
-	uint32_t reserved;	/* Place holder */
-};
-
-/*
- *  The NSS tun6rd statistics sync structure.
- */
-struct nss_tun6rd_stats_sync {
-	struct nss_cmn_node_stats node_stats;
-};
-
-/*
- * Message structure to send/receive 6rd commands
- */
-struct nss_tun6rd_msg {
-	struct nss_cmn_msg cm;			/* Message Header */
-	union {
-		struct nss_tun6rd_create tun6rd_create;			/* Message: Create 6rd tunnel */
-		struct nss_tun6rd_destroy tun6rd_destroy;		/* Message: Destroy 6rd tunnel */
-		struct nss_tun6rd_stats_sync stats_sync;		/* Message: interface stats sync */
-	} msg;
-};
-
-/*
- * DS-Lite (IPv4 in IPv6) tunnel messages
- */
-
-/*
- * Request/Response types
- */
-enum nss_tunipip6_metadata_types {
-	NSS_TX_METADATA_TYPE_TUNIPIP6_IF_CREATE,
-	NSS_TX_METADATA_TYPE_TUNIPIP6_IF_DESTROY,
-	NSS_RX_METADATA_TYPE_TUNIPIP6_STATS_SYNC,
-	NSS_METADATA_TYPE_TUNIPIP6_MAX,
-};
-
-/*
- * DS-lite and ipip6 configuration command structure
- */
-struct nss_tunipip6_create {
-	uint32_t saddr[4];	/* Tunnel source address */
-	uint32_t daddr[4];	/* Tunnel destination address */
-	uint32_t flowlabel;	/* Tunnel ipv6 flowlabel */
-	uint32_t flags;		/* Tunnel additional flags */
-	uint8_t  hop_limit;	/* Tunnel ipv6 hop limit */
-	uint8_t	 reserved;	/* Place holder */
-	uint16_t reserved1;	/* Place holder */
-};
-
-/*
- * tunipip6 tunnel interface down command structure
- */
-struct nss_tunipip6_destroy {
-	uint32_t reserved;	/* Place holder */
-};
-
-/*
- * The NSS tunipip6 statistics sync structure.
- */
-struct nss_tunipip6_stats_sync {
-	struct nss_cmn_node_stats node_stats;
-};
-
-/*
- * Message structure to send/receive DS-Lite commands
- */
-struct nss_tunipip6_msg {
-	struct nss_cmn_msg cm;			/* Message Header */
-	union {
-		struct nss_tunipip6_create tunipip6_create;	/* Message: Create tunipip6 tunnel */
-		struct nss_tunipip6_destroy tunipip6_destroy;	/* Message: Destory ipip6 tunnel */
-		struct nss_tunipip6_stats_sync stats_sync;	/* Message: NSS stats sync */
-	} msg;
-};
-
-/*
  * Crypto messages
  */
 
diff --git a/nss_tun6rd.c b/nss_tun6rd.c
old mode 100755
new mode 100644
index 4977cd3..23f8530
--- a/nss_tun6rd.c
+++ b/nss_tun6rd.c
@@ -1,9 +1,9 @@
 /*
- **************************************************************************
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  **************************************************************************
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all copies.
+ * above copyright notice and this permission notice appear in all copies
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -11,437 +11,181 @@
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- **************************************************************************
+ * *************************************************************************
  */
 
-/*
- * nss_tun6rd.c
- *
- * This file is the NSS 6rd tunnel module
- * ------------------------REVISION HISTORY-----------------------------
- * Qualcomm Atheros         15/sep/2013              Created
- */
-
-#include <linux/types.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <net/ipv6.h>
-#include <net/ipip.h>
-#include <linux/if_arp.h>
+#include "nss_tx_rx_common.h"
 #include "nss_api_if.h"
 
 /*
- * NSS tun6rd debug macros
+ * nss_tun6rd_handler()
+ * 	Handle NSS -> HLOS messages for 6rd tunnel
  */
-#if (NSS_TUN6RD_DEBUG_LEVEL < 1)
-#define nss_tun6rd_assert(fmt, args...)
-#else
-#define nss_tun6d_assert(c) if (!(c)) { BUG_ON(!(c)); }
-#endif
-
-#if (NSS_TUN6RD_DEBUG_LEVEL < 2)
-#define nss_tun6rd_error(fmt, args...)
-#else
-#define nss_tun6rd_error(fmt, args...) printk(KERN_WARNING "nss tun6rd:"fmt, ##args)
-#endif
-
-#if (NSS_TUN6RD_DEBUG_LEVEL < 3)
-#define nss_tun6rd_warning(fmt, args...)
-#else
-#define nss_tun6rd_warning(fmt, args...) printk(KERN_WARNING "nss tun6rd:"fmt, ##args)
-#endif
-
-#if (NSS_TUN6RD_DEBUG_LEVEL < 4)
-#define nss_tun6rd_info(fmt, args...)
-#else
-#define nss_tun6rd_info(fmt, args...) printk(KERN_INFO "nss tun6rd :"fmt, ##args)
-#endif
-
-#if (NSS_TUN6RD_DEBUG_LEVEL < 5)
-#define nss_tun6rd_trace(fmt, args...)
-#else
-#define nss_tun6rd_trace(fmt, args...) printk(KERN_DEBUG "nss tun6rd :"fmt, ##args)
-#endif
-
-void nss_tun6rd_exception(void *ctx, void *buf);
-void nss_tun6rd_event_receive(void *ctx, nss_tun6rd_event_t ev_type,
-			      void *os_buf, uint32_t len);
-
-/*
- * 6rd tunnel host instance
- */
-struct nss_tun6rd_tunnel{
-	void *nss_ctx;
-	uint32_t if_num;
-	struct net_device *netdev;
-	uint32_t device_up;
-};
-
-struct nss_tun6rd_tunnel g_tun6rd;
-
-/*
- * Internal function
- */
-static int
-nss_tun6rd_dev_event(struct notifier_block  *nb,
-			unsigned long event,
-			void  *dev);
-
-/*
- * Linux Net device Notifier
- */
-struct notifier_block nss_tun6rd_notifier = {
-	.notifier_call = nss_tun6rd_dev_event,
-};
-
-/*
- * nss_tun6rd_dev_up()
- *	6RD Tunnel device i/f up handler
- */
-void nss_tun6rd_dev_up( struct net_device * netdev)
+static void nss_tun6rd_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
 {
-	struct ip_tunnel *tunnel;
-	struct ip_tunnel_6rd_parm *ip6rd;
-	const struct iphdr  *tiph;
-	struct nss_tun6rd_cfg tun6rdcfg;
-	nss_tx_status_t status;
+	struct nss_tun6rd_msg *ntm = (struct nss_tun6rd_msg *)ncm;
+	void *ctx;
+	nss_tun6rd_msg_callback_t cb;
 
+	BUG_ON(ncm->interface != NSS_TUN6RD_INTERFACE);
 	/*
-	 * Validate netdev for ipv6-in-ipv4  Tunnel
+	 * Is this a valid request/response packet?
 	 */
-	if (netdev->type != ARPHRD_SIT ) {
+	if (ncm->type >= NSS_TUN6RD_MAX) {
+		nss_warning("%p: received invalid message %d for Tun6RD interface", nss_ctx, ncm->type);
 		return;
 	}
 
-	tunnel = (struct ip_tunnel*)netdev_priv(netdev);
-	ip6rd =  &tunnel->ip6rd;
-
-	/*
-	 * Valid 6rd Tunnel Check
-	 * 1. 6rd Prefix len should be non zero
-	 * 2. Relay prefix length should not be greater then 32
-	 * 3. To allow for stateless address auto-configuration on the CE LAN side,
-	 *    6rd delegated prefix SHOULD be /64 or shorter.
-	 */
-	if ((ip6rd->prefixlen == 0 )
-			|| (ip6rd->relay_prefixlen > 32)
-			|| (ip6rd->prefixlen
-				+ (32 - ip6rd->relay_prefixlen) > 64)){
-
-		nss_tun6rd_error("Invalid 6rd argument prefix len %d     \
-				relayprefix len %d \n",
-				ip6rd->prefixlen,ip6rd->relay_prefixlen);
+	if (ncm->len > sizeof(struct nss_tun6rd_msg)) {
+		nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
 		return;
 	}
 
-	nss_tun6rd_info(" Valid 6rd Tunnel Prefix %x %x %x %x  \n        \
-			prefix len %d  relay_prefix %d relay_prefixlen %d \n",
-			ip6rd->prefix.s6_addr32[0],ip6rd->prefix.s6_addr32[1],
-			ip6rd->prefix.s6_addr32[2],ip6rd->prefix.s6_addr32[3],
-			ip6rd->prefixlen, ip6rd->relay_prefix,
-			ip6rd->relay_prefixlen);
+	/*
+ 	 * Update the callback and app_data for NOTIFY messages, tun6rd sends all notify messages
+ 	 * to the same callback/app_data.
+ 	 */
+	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+		ncm->cb = (uint32_t)nss_ctx->nss_top->tun6rd_msg_callback;
+	}
 
 	/*
-	 * Prepare The Tunnel configuration parameter to send to nss
+	 * Log failures
 	 */
-	memset( &tun6rdcfg, 0, sizeof(struct nss_tun6rd_cfg));
+	nss_core_log_msg_failures(nss_ctx, ncm);
 
 	/*
-	 * Find the Tunnel device ipHeader info
+	 * Do we have a call back
 	 */
-	tiph = &tunnel->parms.iph ;
-	nss_tun6rd_trace(" Tunnel Param srcaddr %x daddr %x ttl %d tos %x\n",
-			tiph->saddr, tiph->daddr,tiph->ttl,tiph->tos);
-
-	if(tiph->saddr == 0) {
-		nss_tun6rd_error("Tunnel src address not configured  %x\n",
-				tiph->saddr);
+	if (!ncm->cb) {
 		return;
 	}
 
-	if (tiph->daddr == 0) {
-		nss_tun6rd_error("Tunnel dest address not configured  %x\n",
-				tiph->daddr);
-		return;
-	}
-
-	tun6rdcfg.prefixlen       = ip6rd->prefixlen;
-	tun6rdcfg.relay_prefix    = ip6rd->relay_prefix;
-	tun6rdcfg.relay_prefixlen = ip6rd->relay_prefixlen;
-	tun6rdcfg.saddr           = ntohl(tiph->saddr);
-	tun6rdcfg.daddr           = ntohl(tiph->daddr);
-	tun6rdcfg.prefix[0]       = ntohl(ip6rd->prefix.s6_addr32[0]);
-	tun6rdcfg.prefix[1]       = ntohl(ip6rd->prefix.s6_addr32[1]);
-	tun6rdcfg.prefix[2]       = ntohl(ip6rd->prefix.s6_addr32[2]);
-	tun6rdcfg.prefix[3]       = ntohl(ip6rd->prefix.s6_addr32[3]);
-	tun6rdcfg.ttl             = tiph->ttl;
-	tun6rdcfg.tos             = tiph->tos;
-
-        nss_tun6rd_trace(" 6rd Tunnel info \n");
-        nss_tun6rd_trace(" saddr %x daddr %d ttl %x  tos %x \n",
-			tiph->saddr, tiph->daddr, tiph->ttl, tiph->tos);
-	nss_tun6rd_trace(" Prefix %x:%x:%x:%x  Prefix len %d \n",
-			ip6rd->prefix.s6_addr32[0], ip6rd->prefix.s6_addr32[1],
-			ip6rd->prefix.s6_addr32[2], ip6rd->prefix.s6_addr32[3],
-			ip6rd->prefixlen);
-	nss_tun6rd_trace("Relay Prefix %x Len %d\n",
-			ip6rd->relay_prefix, ip6rd->relay_prefixlen);
+	/*
+	 * callback
+	 */
+	cb = (nss_tun6rd_msg_callback_t)ncm->cb;
+	ctx =  nss_ctx->nss_top->if_ctx[ncm->interface];
 
 	/*
-	 * Register 6rd tunnel with NSS
+	 * call 6rd tunnel callback
 	 */
-	g_tun6rd.nss_ctx = nss_register_tun6rd_if(g_tun6rd.if_num,
-				nss_tun6rd_exception,
-				nss_tun6rd_event_receive,
-				netdev);
-	if (g_tun6rd.nss_ctx == NULL) {
-		nss_tun6rd_trace("nss_register_tun6rd_if Failed \n");
+	if (!ctx) {
+		nss_warning("%p: Event received for 6rd tunnel interface %d before registration", nss_ctx, ncm->interface);
 		return;
-	} else {
-		nss_tun6rd_trace("nss_register_tun6rd_if Success \n");
 	}
 
-	nss_tun6rd_trace("Sending 6rd tunnel i/f up command to NSS  %x \n",
-			(int)g_tun6rd.nss_ctx);
+	cb(ctx, ntm);
+}
+
+
+/*
+ * nss_tun6rd_tx()
+ * 	Transmit a tun6rd message to NSSFW
+ */
+nss_tx_status_t nss_tun6rd_tx(struct nss_ctx_instance *nss_ctx, struct nss_tun6rd_msg *msg)
+{
+	struct nss_tun6rd_msg *nm;
+	struct nss_cmn_msg *ncm = &msg->cm;
+	struct sk_buff *nbuf;
+	int32_t status;
+
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: tun6rd msg dropped as core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
+	}
 
 	/*
-	 * Send 6rd Tunnel UP command to NSS
+	 * Sanity check the message
 	 */
-	status = nss_tx_tun6rd_if_create(g_tun6rd.nss_ctx,
-				&tun6rdcfg,
-				g_tun6rd.if_num);
-
-	if (status != NSS_TX_SUCCESS) {
-		nss_tun6rd_error("Tunnel up command error %d \n", status);
-		return;
+	if (ncm->interface != NSS_TUN6RD_INTERFACE) {
+		nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
+		return NSS_TX_FAILURE;
 	}
 
-	g_tun6rd.device_up = 1;
+	if (ncm->type > NSS_TUN6RD_MAX) {
+		nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+		return NSS_TX_FAILURE;
+	}
+
+	if (ncm->len > sizeof(struct nss_tun6rd_msg)) {
+		nss_warning("%p: message length is invalid: %d", nss_ctx, ncm->len);
+		return NSS_TX_FAILURE;
+	}
+
+	nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+	if (unlikely(!nbuf)) {
+		spin_lock_bh(&nss_ctx->nss_top->stats_lock);
+		nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
+		spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
+		nss_warning("%p: msg dropped as command allocation failed", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Copy the message to our skb
+	 */
+	nm = (struct nss_tun6rd_msg *)skb_put(nbuf, sizeof(struct nss_tun6rd_msg));
+	memcpy(nm, msg, sizeof(struct nss_tun6rd_msg));
+
+	status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
+	if (status != NSS_CORE_STATUS_SUCCESS) {
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: Unable to enqueue 'tun6rd message' \n", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
+				NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
+
+	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
+	return NSS_TX_SUCCESS;
 }
 
 /*
- * nss_tun6rd_dev_down()
- *	6RD Tunnel device i/f down handler
+ ***********************************
+ * Register/Unregister/Miscellaneous APIs
+ ***********************************
  */
-void nss_tun6rd_dev_down( struct net_device * netdev)
+
+/*
+ * nss_register_tun6rd_if()
+ */
+struct nss_ctx_instance *nss_register_tun6rd_if(uint32_t if_num,
+                                nss_tun6rd_callback_t tun6rd_callback,
+                                nss_tun6rd_msg_callback_t event_callback, struct net_device *netdev)
 {
-	struct ip_tunnel *tunnel;
-	struct ip_tunnel_6rd_parm *ip6rd;
-	struct nss_tun6rd_cfg tun6rdcfg;
-	nss_tx_status_t status;
+        nss_assert((if_num >= NSS_MAX_VIRTUAL_INTERFACES) && (if_num < NSS_MAX_NET_INTERFACES));
 
-	/*
-	 * Check if tunnel 6rd is registered ?
-	 */
-	if (g_tun6rd.nss_ctx == NULL) {
-		return;
-	}
+        nss_top_main.if_ctx[if_num] = netdev;
+        nss_top_main.if_rx_callback[if_num] = tun6rd_callback;
+        nss_top_main.tun6rd_msg_callback = event_callback;
 
-	/*
-	 * Validate netdev for ipv6-in-ipv4  Tunnel
-	 */
-	if (netdev->type != ARPHRD_SIT ) {
-		return;
-	}
-
-	tunnel = (struct ip_tunnel*)netdev_priv(netdev);
-	ip6rd =  &tunnel->ip6rd;
-
-	/*
-	 * Valid 6rd Tunnel Check
-	 */
-	if ((ip6rd->prefixlen == 0 )
-			|| (ip6rd->relay_prefixlen > 32 )
-			|| (ip6rd->prefixlen
-				+ (32 - ip6rd->relay_prefixlen) > 64)){
-
-		nss_tun6rd_error("Invalid 6rd argument prefix len %d  \
-				relayprefix len %d \n",
-				ip6rd->prefixlen,ip6rd->relay_prefixlen);
-		return;
-	}
-
-	/*
-	 * Prepare The Tunnel configuration parameter to send to nss
-	 */
-	memset(&tun6rdcfg, 0, sizeof(struct nss_tun6rd_cfg));
-
-	tun6rdcfg.prefix[0]   = ntohl(ip6rd->prefix.s6_addr32[0]);
-	tun6rdcfg.prefix[1]   = ntohl(ip6rd->prefix.s6_addr32[1]);
-	tun6rdcfg.prefix[2]   = ntohl(ip6rd->prefix.s6_addr32[2]);
-	tun6rdcfg.prefix[3]   = ntohl(ip6rd->prefix.s6_addr32[3]);
-
-	nss_tun6rd_trace(" Prefix %x:%x:%x:%x  Prefix len %d \n",
-			ip6rd->prefix.s6_addr32[0], ip6rd->prefix.s6_addr32[1],
-			ip6rd->prefix.s6_addr32[2], ip6rd->prefix.s6_addr32[3],
-			ip6rd->prefixlen);
-
-
-	nss_tun6rd_trace("Sending Tunnle 6rd Down command %x \n",g_tun6rd.if_num);
-	status = nss_tx_tun6rd_if_destroy(g_tun6rd.nss_ctx,
-				&tun6rdcfg,
-				g_tun6rd.if_num);
-
-	if (status != NSS_TX_SUCCESS) {
-		nss_tun6rd_error("Tunnel down command error %d \n", status);
-		return;
-	}
-
-	/*
-	 * Un-Register 6rd tunnel with NSS
-	 */
-	nss_unregister_tun6rd_if(g_tun6rd.if_num);
-	g_tun6rd.nss_ctx = NULL;
-	g_tun6rd.device_up = 0;
-	return;
+        return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.tun6rd_handler_id];
 }
 
 /*
- * nss_tun6rd_dev_event()
- *	Net device notifier for 6rd module
+ * nss_unregister_tun6rd_if()
  */
-static int nss_tun6rd_dev_event(struct notifier_block  *nb,
-		unsigned long event, void  *dev)
+void nss_unregister_tun6rd_if(uint32_t if_num)
 {
-	struct net_device *netdev = (struct net_device *)dev;
+        nss_assert((if_num >= NSS_MAX_VIRTUAL_INTERFACES) && (if_num < NSS_MAX_NET_INTERFACES));
 
-	nss_tun6rd_trace("%s\n",__FUNCTION__);
-	switch (event) {
-	case NETDEV_UP:
-		nss_tun6rd_trace(" NETDEV_UP :event %lu name %s \n",
-				event,netdev->name);
-		nss_tun6rd_dev_up(netdev);
-		break;
-
-	case NETDEV_DOWN:
-		nss_tun6rd_trace(" NETDEV_DOWN :event %lu name %s \n",
-				event,netdev->name);
-		nss_tun6rd_dev_down(netdev);
-		break;
-
-	default:
-		nss_tun6rd_trace("Unhandled notifier dev %s  event %x  \n",
-				netdev->name,(int)event);
-		break;
-	}
-
-	return NOTIFY_DONE;
+        nss_top_main.if_rx_callback[if_num] = NULL;
+        nss_top_main.if_ctx[if_num] = NULL;
+        nss_top_main.tun6rd_msg_callback = NULL;
 }
 
 /*
- * nss_tun6rd_exception()
- *	Exception handler registered to NSS driver
+ * nss_tun6rd_register_handler()
  */
-void nss_tun6rd_exception(void *ctx, void *buf)
+void nss_tun6rd_register_handler()
 {
-	struct net_device *dev = (struct net_device *)ctx;
-	struct sk_buff *skb = (struct sk_buff *)buf;
-	const struct iphdr *iph;
-
-	skb->dev = dev;
-	nss_tun6rd_info("received - %d bytes name %s ver %x \n",
-			skb->len,dev->name,skb->data[0]);
-
-	iph = (const struct iphdr *)skb->data;
-
-	/*
-	 * Packet after Decap/Encap Did not find the Rule.
-	 */
-	if (iph->version == 4) {
-		if(iph->protocol == IPPROTO_IPV6){
-			skb_pull(skb, sizeof(struct iphdr));
-			skb->protocol = htons(ETH_P_IPV6);
-			skb_reset_network_header(skb);
-			skb->pkt_type = PACKET_HOST;
-			skb->ip_summed = CHECKSUM_NONE;
-			dev_queue_xmit(skb);
-			return;
-		}
-		skb->protocol = htons(ETH_P_IP);
-	} else {
-		skb->protocol = htons(ETH_P_IPV6);
-	}
-
-	skb_reset_network_header(skb);
-	skb->pkt_type = PACKET_HOST;
-	skb->skb_iif = dev->ifindex;
-	skb->ip_summed = CHECKSUM_NONE;
-	netif_receive_skb(skb);
+	nss_core_register_handler(NSS_TUN6RD_INTERFACE, nss_tun6rd_handler, NULL);
 }
 
-/*
- *  nss_tun6rd_update_dev_stats
- *	Update the Dev stats received from NetAp
- */
-static void nss_tun6rd_update_dev_stats(struct net_device *dev,
-					struct nss_tun6rd_stats *stats)
-{
-	void *ptr;
-	ptr = (void *)stats;
-	ipip6_update_offload_stats(dev, ptr);
-}
 
-/**
- * @brief Event Callback to receive events from NSS
- * @param[in] pointer to net device context
- * @param[in] event type
- * @param[in] pointer to buffer
- * @param[in] length of buffer
- * @return Returns void
- */
-void nss_tun6rd_event_receive(void *if_ctx, nss_tun6rd_event_t ev_type,
-			    void *os_buf, uint32_t len)
-{
-	struct net_device *netdev = NULL;
-	netdev = (struct net_device *)if_ctx;
-
-	switch (ev_type) {
-	case NSS_TUN6RD_EVENT_STATS:
-		nss_tun6rd_update_dev_stats(netdev, (struct nss_tun6rd_stats *)os_buf );
-		break;
-
-	default:
-		nss_tun6rd_info("%s: Unknown Event from NSS",
-			      __FUNCTION__);
-		break;
-	}
-}
-
-/*
- * nss_tun6rd_init_module()
- *	Tunnel 6rd module init function
- */
-int __init nss_tun6rd_init_module(void)
-{
-	nss_tun6rd_info("module (platform - IPQ806x , Build - %s:%s) loaded\n",
-			__DATE__, __TIME__);
-
-	register_netdevice_notifier(&nss_tun6rd_notifier);
-	nss_tun6rd_trace("Netdev Notifier registerd \n");
-
-	g_tun6rd.if_num = NSS_TUNRD_IF_NUMBER;
-	g_tun6rd.netdev = NULL;
-	g_tun6rd.device_up = 0;
-	g_tun6rd.nss_ctx = NULL;
-
-	return 0;
-}
-
-/*
- * nss_tun6rd_exit_module()
- *	Tunnel 6rd module exit function
- */
-void __exit nss_tun6rd_exit_module(void)
-{
-
-	unregister_netdevice_notifier(&nss_tun6rd_notifier);
-	nss_tun6rd_info("module unloaded\n");
-}
-
-module_init(nss_tun6rd_init_module);
-module_exit(nss_tun6rd_exit_module);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("NSS tun6rd offload manager");
+EXPORT_SYMBOL(nss_tun6rd_tx);
+EXPORT_SYMBOL(nss_register_tun6rd_if);
+EXPORT_SYMBOL(nss_unregister_tun6rd_if);
diff --git a/nss_tun6rd.h b/nss_tun6rd.h
new file mode 100644
index 0000000..af54d19
--- /dev/null
+++ b/nss_tun6rd.h
@@ -0,0 +1,111 @@
+/*
+ *  **************************************************************************
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * *************************************************************************
+ */
+
+ /*
+  * nss_tun6rd.h
+  * 	NSS TO HLOS interface definitions.
+  */
+
+#ifndef __NSS_TUN6RD_H
+#define __NSS_TUN6RD_H
+
+/*
+ * 6RD (IPv6 in IPv4) tunnel messages
+ */
+
+/**
+ * Request/Response types
+ */
+enum nss_tun6rd_metadata_types {
+	NSS_TUN6RD_TX_IF_CREATE,
+	NSS_TUN6RD_TX_IF_DESTROY,
+	NSS_TUN6RD_RX_STATS_SYNC,
+	NSS_TUN6RD_MAX,
+};
+
+/**
+ * 6rd configuration command structure
+ */
+struct nss_tun6rd_create_msg {
+	uint32_t prefix[4];	/* 6rd prefix */
+	uint32_t relay_prefix;	/* Relay prefix */
+	uint16_t prefixlen;	/* 6rd prefix len */
+	uint16_t relay_prefixlen;/* Relay prefix length*/
+	uint32_t saddr;		/* Tunnel source address */
+	uint32_t daddr;		/* Tunnel destination addresss */
+	uint8_t  tos;		/* Tunnel tos field */
+	uint8_t  ttl;		/* Tunnel ttl field */
+	uint16_t reserved;	/* Reserved field */
+};
+
+/**
+ * 6rd tunnel interface down command structure
+ */
+struct nss_tun6rd_destroy_msg {
+	uint32_t prefix[4];	/* Place holder */
+};
+
+/**
+ * The NSS tun6rd statistics sync structure.
+ */
+struct nss_tun6rd_stats_sync_msg {
+	struct nss_cmn_node_stats node_stats;
+};
+
+/**
+ * Message structure to send/receive 6rd commands
+ */
+struct nss_tun6rd_msg {
+	struct nss_cmn_msg cm;		/* Message Header */
+	union {
+		struct nss_tun6rd_create_msg tun6rd_create;		/* Message: Create 6rd tunnel */
+		struct nss_tun6rd_destroy_msg tun6rd_destroy;	/* Message: Destroy 6rd tunnel */
+		struct nss_tun6rd_stats_sync_msg stats_sync;	/* Message: interface stats sync */
+	} msg;
+};
+
+/**
+ * Callback to receive tun6rd messages
+ */
+typedef void (*nss_tun6rd_msg_callback_t)(void *app_data, struct nss_tun6rd_msg *msg);
+
+/**
+ *  API to send tun6rd messages
+ **/
+extern nss_tx_status_t nss_tun6rd_tx(struct nss_ctx_instance *nss_ctx, struct nss_tun6rd_msg *msg);
+
+/**
+ * Callback to receive 6rd callback
+ */
+typedef void (*nss_tun6rd_callback_t)(void *app_data, void *os_buf);
+
+/**
+ * @brief Register to send/receive 6rd tunnel messages to NSS
+ *
+ * @param tun6rd_callback Callback
+ * @param ctx 6rd tunnel context
+ *
+ * @return void* NSS context
+ */
+extern struct nss_ctx_instance *nss_register_tun6rd_if(uint32_t if_num, nss_tun6rd_callback_t tun6rd_callback,
+							nss_tun6rd_msg_callback_t msg_callback, struct net_device *netdev);
+
+/**
+ * @brief Unregister 6rd tunnel interface with NSS
+ */
+extern void nss_unregister_tun6rd_if(uint32_t if_num);
+
+#endif /* __NSS_TUN6RD_H */
diff --git a/nss_tunipip6.c b/nss_tunipip6.c
index 5fd965f..77680f4 100755
--- a/nss_tunipip6.c
+++ b/nss_tunipip6.c
@@ -1,9 +1,9 @@
 /*
- **************************************************************************
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  **************************************************************************
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all copies.
+ * above copyright notice and this permission notice appear in all copies
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -11,364 +11,179 @@
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- **************************************************************************
+ * *************************************************************************
  */
 
-/*
- * nss_tunipip6.c
- *
- * This file is the NSS DS-lit and IPP6  tunnel module
- * ------------------------REVISION HISTORY-----------------------------
- * Qualcomm Atheros	    15/sep/2013		     Created
- */
-
-#include <linux/types.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <net/ipv6.h>
-#include <net/ipip.h>
-#include <net/ip6_tunnel.h>
-#include <linux/if_arp.h>
+#include "nss_tx_rx_common.h"
 #include "nss_api_if.h"
-#include "nss_hlos_if.h"
 
 /*
- * NSS tunipip6 debug macros
+ * nss_tunipip6_handler()
+ *      Handle NSS -> HLOS messages for 6rd tunnel
  */
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 1)
-#define nss_tunipip6_assert(fmt, args...)
-#else
-#define nss_tunipip6_assert(c) if (!(c)) { BUG_ON(!(c)); }
-#endif
-
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 2)
-#define nss_tunipip6_error(fmt, args...)
-#else
-#define nss_tunipip6_error(fmt, args...) printk(KERN_WARNING "nss tunipip6:"fmt, ##args)
-#endif
-
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 3)
-#define nss_tunipip6_warning(fmt, args...)
-#else
-#define nss_tunipip6_warning(fmt, args...) printk(KERN_WARNING "nss tunipip6:"fmt, ##args)
-#endif
-
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 4)
-#define nss_tunipip6_info(fmt, args...)
-#else
-#define nss_tunipip6_info(fmt, args...) printk(KERN_INFO "nss tunipip6 :"fmt, ##args)
-#endif
-
-#if (NSS_TUNIPIP6_DEBUG_LEVEL < 5)
-#define nss_tunipip6_trace(fmt, args...)
-#else
-#define nss_tunipip6_trace(fmt, args...) printk(KERN_DEBUG "nss tunipip6 :"fmt, ##args)
-#endif
-
-void nss_tunipip6_exception(void *ctx, void *buf);
-void nss_tunipip6_event_receive(void *ctx, nss_tunipip6_event_t ev_type,
-			      void *os_buf, uint32_t len);
-
-/*
- * nss_tunipip6_tunnel
- *	DS-lite and ipip 6tunnel host instance
- */
-struct nss_tunipip6_tunnel{
-	void *nss_ctx;
-	uint32_t if_num;
-	struct net_device *netdev;
-	uint32_t device_up;
-};
-
-struct nss_tunipip6_tunnel g_tunipip6;
-
-/*
- * Internal function
- */
-static int
-nss_tunipip6_dev_event(struct notifier_block  *nb,
-			unsigned long event,
-			void  *dev);
-
-/*
- * Linux Net device Notifier
- */
-struct notifier_block nss_tunipip6_notifier = {
-	.notifier_call = nss_tunipip6_dev_event,
-};
-
-/*
- * nss_tunipip6_dev_up()
- *	IPIP6 Tunnel device i/f up handler
- */
-void nss_tunipip6_dev_up( struct net_device * netdev)
+static void nss_tunipip6_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data)
 {
-	struct ip6_tnl *tunnel;
-	struct nss_tunipip6_cfg tnlcfg;
-	struct flowi6 *fl6;
-	nss_tx_status_t status;
+	struct nss_tunipip6_msg *ntm = (struct nss_tunipip6_msg *)ncm;
+	void *ctx;
+	nss_tunipip6_msg_callback_t cb;
 
+	BUG_ON(ncm->interface != NSS_TUNIPIP6_INTERFACE);
 	/*
-	 * Validate netdev for ipv6-in-ipv4  Tunnel
+	 * Is this a valid request/response packet?
 	 */
-	if (netdev->type != ARPHRD_TUNNEL6 ) {
+	if (ncm->type >= NSS_TUNIPIP6_MAX) {
+		nss_warning("%p: received invalid message %d for DS-Lite interface", nss_ctx, ncm->type);
 		return;
 	}
 
-	tunnel = (struct ip6_tnl *)netdev_priv(netdev);
-
-	/*
-	 * Find he Tunnel device flow information
-	 */
-
-	fl6  = &tunnel->fl.u.ip6;
-
-	nss_tunipip6_trace(" Tunnel Param srcaddr %x:%x:%x:%x  daddr %x:%x:%x:%x \n",
-			fl6->saddr.s6_addr32[0], fl6->saddr.s6_addr32[1],
-			fl6->saddr.s6_addr32[2], fl6->saddr.s6_addr32[3],
-			fl6->daddr.s6_addr32[0], fl6->daddr.s6_addr32[1],
-			fl6->daddr.s6_addr32[2], fl6->daddr.s6_addr32[3] );
-	nss_tunipip6_trace(" hop limit %d \n", tunnel->parms.hop_limit);
-	nss_tunipip6_trace(" tunnel param flag %x  fl6.flowlabel %x  \n", tunnel->parms.flags, fl6->flowlabel);
-
-	/*
-	 *Prepare The Tunnel configuration parameter to send to nss
-	 */
-	memset(&tnlcfg, 0, sizeof(struct nss_tunipip6_cfg));
-
-	tnlcfg.saddr[0] = ntohl(fl6->saddr.s6_addr32[0]);
-	tnlcfg.saddr[1] = ntohl(fl6->saddr.s6_addr32[1]);
-	tnlcfg.saddr[2] = ntohl(fl6->saddr.s6_addr32[2]);
-	tnlcfg.saddr[3] = ntohl(fl6->saddr.s6_addr32[3]);
-	tnlcfg.daddr[0] = ntohl(fl6->daddr.s6_addr32[0]);
-	tnlcfg.daddr[1] = ntohl(fl6->daddr.s6_addr32[1]);
-	tnlcfg.daddr[2] = ntohl(fl6->daddr.s6_addr32[2]);
-	tnlcfg.daddr[3] = ntohl(fl6->daddr.s6_addr32[3]);
-	tnlcfg.hop_limit = tunnel->parms.hop_limit;
-	tnlcfg.flags = ntohl(tunnel->parms.flags);
-	tnlcfg.flowlabel = fl6->flowlabel;  /*flow Label In kernel is stored in big endian format*/
-	nss_tunipip6_trace(" Tunnel Param srcaddr %x:%x:%x:%x  daddr %x:%x:%x:%x \n",
-			tnlcfg.saddr[0], tnlcfg.saddr[1],
-			tnlcfg.saddr[2], tnlcfg.saddr[3],
-			tnlcfg.daddr[0], tnlcfg.daddr[1],
-			tnlcfg.daddr[2], tnlcfg.daddr[3] );
-
-	/*
-	 * Register ipip6 tunnel with NSS
-	 */
-	g_tunipip6.nss_ctx = nss_register_tunipip6_if(g_tunipip6.if_num,
-				nss_tunipip6_exception,
-				nss_tunipip6_event_receive,
-				netdev);
-	if (g_tunipip6.nss_ctx == NULL) {
-		nss_tunipip6_trace("nss_register_tunipip6_if Failed \n");
-		return;
-	} else {
-		nss_tunipip6_trace("nss_register_tunipip6_if Success \n");
-	}
-
-	nss_tunipip6_trace("Sending IPIP6 tunnel i/f up command to NSS	%x \n",
-			(int)g_tunipip6.nss_ctx);
-
-	/*
-	 * Send IPIP6 Tunnel UP command to NSS
-	 */
-	status = nss_tx_tunipip6_if_create(g_tunipip6.nss_ctx,
-			&tnlcfg,
-			g_tunipip6.if_num);
-	if (status != NSS_TX_SUCCESS) {
-		nss_tunipip6_error("Tunnel up command error %d \n", status);
-		return;
-	}
-
-	g_tunipip6.device_up = 1;
-}
-
-/*
- * nss_tunipip6_dev_down()
- *	IPP6 Tunnel device i/f down handler
- */
-void nss_tunipip6_dev_down( struct net_device * netdev)
-{
-	struct nss_tunipip6_cfg tnlcfg;
-	nss_tx_status_t status;
-
-	/*
-	 * Check if tunnel ipip6 is registered ?
-	 */
-	if(g_tunipip6.nss_ctx == NULL){
+	if (ncm->len > sizeof(struct nss_tunipip6_msg)) {
+		nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
 		return;
 	}
 
 	/*
-	 * Validate netdev for ipv6-in-ipv4  Tunnel
+	 * Update the callback and app_data for NOTIFY messages, tun6rd sends all notify messages
+	 * to the same callback/app_data.
 	 */
-	if (netdev->type != ARPHRD_TUNNEL6 ) {
+	if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+		ncm->cb = (uint32_t)nss_ctx->nss_top->tunipip6_msg_callback;
+	}
+
+	/*
+	 * Log failures
+	 */
+	nss_core_log_msg_failures(nss_ctx, ncm);
+
+	/*
+	 * Do we have a call back
+	 */
+	if (!ncm->cb) {
 		return;
 	}
 
 	/*
-	 * TODO: Strick check required if its the same tunnel
-	 * registerd with us
+	 * callback
 	 */
+	cb = (nss_tunipip6_msg_callback_t)ncm->cb;
+	ctx =  nss_ctx->nss_top->if_ctx[ncm->interface];
 
-	memset(&tnlcfg, 0, sizeof(struct nss_tunipip6_cfg));
-
-	nss_tunipip6_trace("Sending Tunnel ipip6 Down command %x \n",g_tunipip6.if_num);
-	status = nss_tx_tunipip6_if_destroy(g_tunipip6.nss_ctx,
-			&tnlcfg,
-			g_tunipip6.if_num);
-	if (status != NSS_TX_SUCCESS) {
-		nss_tunipip6_error("Tunnel down command error %d \n", status);
+	/*
+	 * call ipip6 tunnel callback
+	 */
+	if (!ctx) {
+		 nss_warning("%p: Event received for DS-Lite tunnel interface %d before registration", nss_ctx, ncm->interface);
 		return;
 	}
 
-	/*
-	 * Un-Register IPIP6 tunnel with NSS
-	 */
-	nss_unregister_tunipip6_if(g_tunipip6.if_num);
-	g_tunipip6.nss_ctx = NULL;
-	g_tunipip6.device_up = 0;
+	cb(ctx, ntm);
 }
 
 /*
- * nss_tun6rd_dev_event()
- *	Net device notifier for ipip6 module
+ * nss_tunipip6_tx()
+ * 	Transmit a tun6rd message to NSSFW
  */
-static int nss_tunipip6_dev_event(struct notifier_block  *nb,
-		unsigned long event, void  *dev)
+nss_tx_status_t nss_tunipip6_tx(struct nss_ctx_instance *nss_ctx, struct nss_tunipip6_msg *msg)
 {
-	struct net_device *netdev = (struct net_device *)dev;
+	struct nss_tunipip6_msg *nm;
+	struct nss_cmn_msg *ncm = &msg->cm;
+	struct sk_buff *nbuf;
+	int32_t status;
 
-	nss_tunipip6_trace("%s\n",__FUNCTION__);
-	switch (event) {
-	case NETDEV_UP:
-		nss_tunipip6_trace(" NETDEV_UP :event %lu name %s \n",
-				event,netdev->name);
-		nss_tunipip6_dev_up(netdev);
-		break;
-
-	case NETDEV_DOWN:
-		nss_tunipip6_trace(" NETDEV_DOWN :event %lu name %s \n",
-				event,netdev->name);
-		nss_tunipip6_dev_down(netdev);
-		break;
-
-	default:
-		nss_tunipip6_trace("Unhandled notifier dev %s  event %x  \n",
-				netdev->name,(int)event);
-		break;
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+		nss_warning("%p: tun6rd msg dropped as core not ready", nss_ctx);
+		return NSS_TX_FAILURE_NOT_READY;
 	}
 
-	return NOTIFY_DONE;
-}
-
-/*
- * nss_tunipip6_exception()
- *	Exception handler registered to NSS driver
- */
-void nss_tunipip6_exception(void *ctx, void *buf)
-{
-	struct net_device *dev = (struct net_device *)ctx;
-	struct sk_buff *skb = (struct sk_buff *)buf;
-	const struct iphdr *iph;
-
-	skb->dev = dev;
-	nss_tunipip6_info("received - %d bytes name %s ver %x \n",
-			skb->len,dev->name,skb->data[0]);
-
-	iph = (const struct iphdr *)skb->data;
-
 	/*
-	 *Packet after Decap/Encap Did not find the Rule.
+	 * Sanity check the message
 	 */
-	if (iph->version == 4) {
-		skb->protocol = htons(ETH_P_IP);
-	} else {
-		skb->protocol = htons(ETH_P_IPV6);
+	if (ncm->interface != NSS_TUNIPIP6_INTERFACE) {
+		nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface);
+		return NSS_TX_FAILURE;
 	}
 
-	skb_reset_network_header(skb);
-	skb->pkt_type = PACKET_HOST;
-	skb->skb_iif = dev->ifindex;
-	skb->ip_summed = CHECKSUM_NONE;
-	netif_receive_skb(skb);
-}
-
-/*
- *  nss_tunipip6_update_dev_stats
- *	Update the Dev stats received from NetAp
- */
-static void nss_tunipip6_update_dev_stats(struct net_device *dev,
-					struct nss_tunipip6_stats *stats)
-{
-	void *ptr;
-	ptr = (void *)stats;
-	ip6_update_offload_stats(dev, ptr);
-
-}
-
-/**
- * @brief Event Callback to receive events from NSS
- * @param[in] pointer to net device context
- * @param[in] event type
- * @param[in] pointer to buffer
- * @param[in] length of buffer
- * @return Returns void
- */
-void nss_tunipip6_event_receive(void *if_ctx, nss_tunipip6_event_t ev_type,
-			    void *os_buf, uint32_t len)
-{
-	struct net_device *netdev = NULL;
-	netdev = (struct net_device *)if_ctx;
-
-	switch (ev_type) {
-	case NSS_TUNIPIP6_EVENT_STATS:
-		 nss_tunipip6_update_dev_stats(netdev, (struct nss_tunipip6_stats *)os_buf );
-		break;
-
-	default:
-		nss_tunipip6_info("%s: Unknown Event from NSS",
-			      __FUNCTION__);
-		break;
+	if (ncm->type > NSS_TUNIPIP6_MAX) {
+		nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+		return NSS_TX_FAILURE;
 	}
+
+	if (ncm->len > sizeof(struct nss_tunipip6_msg)) {
+		nss_warning("%p: message length is invalid: %d", nss_ctx, ncm->len);
+		return NSS_TX_FAILURE;
+	}
+
+	nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+	if (unlikely(!nbuf)) {
+		spin_lock_bh(&nss_ctx->nss_top->stats_lock);
+		nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]++;
+		spin_unlock_bh(&nss_ctx->nss_top->stats_lock);
+		nss_warning("%p: msg dropped as command allocation failed", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	/*
+	 * Copy the message to our skb
+	 */
+	nm = (struct nss_tunipip6_msg *)skb_put(nbuf, sizeof(struct nss_tunipip6_msg));
+	memcpy(nm, msg, sizeof(struct nss_tunipip6_msg));
+
+	status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
+	if (status != NSS_CORE_STATUS_SUCCESS) {
+		dev_kfree_skb_any(nbuf);
+		nss_warning("%p: Unable to enqueue 'tun6rd message' \n", nss_ctx);
+		return NSS_TX_FAILURE;
+	}
+
+	nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit,
+				NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE);
+
+	NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
+	return NSS_TX_SUCCESS;
 }
 
 /*
- * nss_tunipip6_init_module()
- *	Tunnel ipip6 module init function
+ * **********************************
+ *  Register/Unregister/Miscellaneous APIs
+ * **********************************
  */
-int __init nss_tunipip6_init_module(void)
+
+/*
+ * nss_register_tunipip6_if()
+ */
+struct nss_ctx_instance *nss_register_tunipip6_if(uint32_t if_num,
+			nss_tunipip6_callback_t tunipip6_callback,
+			nss_tunipip6_msg_callback_t event_callback, struct net_device *netdev)
 {
-	nss_tunipip6_info("module (platform - IPQ806x , Build - %s:%s) loaded\n",
-			__DATE__, __TIME__);
+	nss_assert((if_num >= NSS_MAX_VIRTUAL_INTERFACES) && (if_num < NSS_MAX_NET_INTERFACES));
 
-	register_netdevice_notifier(&nss_tunipip6_notifier);
-	nss_tunipip6_trace("Netdev Notifier registerd \n");
+	nss_top_main.if_ctx[if_num] = netdev;
+	nss_top_main.if_rx_callback[if_num] = tunipip6_callback;
+	nss_top_main.tunipip6_msg_callback = event_callback;
 
-	g_tunipip6.if_num = NSS_TUNIPIP6_IF_NUMBER;
-	g_tunipip6.netdev = NULL;
-	g_tunipip6.device_up = 0;
-	g_tunipip6.nss_ctx = NULL;
-
-	return 0;
+	return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.tunipip6_handler_id];
 }
 
 /*
- * nss_tunipip6_exit_module()
- *	Tunnel ipip6 module exit function
+ * nss_unregister_tunipip6_if()
  */
-void __exit nss_tunipip6_exit_module(void)
+void nss_unregister_tunipip6_if(uint32_t if_num)
 {
+	nss_assert((if_num >= NSS_MAX_VIRTUAL_INTERFACES) && (if_num < NSS_MAX_NET_INTERFACES));
 
-	unregister_netdevice_notifier(&nss_tunipip6_notifier);
-	nss_tunipip6_info("module unloaded\n");
+	nss_top_main.if_rx_callback[if_num] = NULL;
+	nss_top_main.if_ctx[if_num] = NULL;
+	nss_top_main.tunipip6_msg_callback = NULL;
 }
 
-module_init(nss_tunipip6_init_module);
-module_exit(nss_tunipip6_exit_module);
+/*
+ * nss_tunipip6_register_handler()
+ */
+void nss_tunipip6_register_handler()
+{
+	nss_core_register_handler(NSS_TUNIPIP6_INTERFACE, nss_tunipip6_handler, NULL);
+}
 
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("NSS tunipip6 offload manager");
+EXPORT_SYMBOL(nss_tunipip6_tx);
+EXPORT_SYMBOL(nss_register_tunipip6_if);
+EXPORT_SYMBOL(nss_unregister_tunipip6_if);
diff --git a/nss_tunipip6.h b/nss_tunipip6.h
new file mode 100644
index 0000000..bbbcea2
--- /dev/null
+++ b/nss_tunipip6.h
@@ -0,0 +1,109 @@
+/*
+ *  **************************************************************************
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * *************************************************************************
+ */
+
+ /*
+  * nss_tunipip6.h
+  * 	NSS TO HLOS interface definitions.
+  */
+
+#ifndef __NSS_TUNIPIP6_H
+#define __NSS_TUNIPIP6_H
+
+/*
+ * DS-Lite (IPv4 in IPv6) tunnel messages
+ */
+
+/**
+ * Request/Response types
+ */
+enum nss_tunipip6_metadata_types {
+	NSS_TUNIPIP6_TX_IF_CREATE,
+	NSS_TUNIPIP6_TX_IF_DESTROY,
+	NSS_TUNIPIP6_RX_STATS_SYNC,
+	NSS_TUNIPIP6_MAX,
+};
+
+/**
+ * DS-Lite  configuration command structure
+ */
+struct nss_tunipip6_create_msg {
+	uint32_t saddr[4];	/* Tunnel source address */
+	uint32_t daddr[4];	/* Tunnel destination address */
+	uint32_t flowlabel;	/* Tunnel ipv6 flowlabel */
+	uint32_t flags;		/* Tunnel additional flags */
+	uint8_t  hop_limit;	/* Tunnel ipv6 hop limit */
+	uint8_t reserved;	/* Place holder */
+	uint16_t reserved1;	/* Place holder */
+};
+
+/**
+ * DS-Lite tunnel interface down command structure
+ */
+struct nss_tunipip6_destroy_msg {
+	uint32_t reserved;	/* Place holder */
+};
+
+/**
+ * The NSS DS-Lite statistics sync structure.
+ */
+struct nss_tunipip6_stats_sync_msg {
+	struct nss_cmn_node_stats node_stats;
+};
+
+/**
+ * Message structure to send/receive DS-Lite commands
+ */
+struct nss_tunipip6_msg {
+	struct nss_cmn_msg cm;		/* Message Header */
+	union {
+		struct nss_tunipip6_create_msg tunipip6_create;	/* Message: Create DS-Lite tunnel */
+		struct nss_tunipip6_destroy_msg tunipip6_destroy;	/* Message: Destroy DS-Lite tunnel */
+		struct nss_tunipip6_stats_sync_msg stats_sync;	/* Message: interface stats sync */
+	} msg;
+};
+
+/**
+ * Callback to receive tun6rd messages
+ */
+typedef void (*nss_tunipip6_msg_callback_t)(void *app_data, struct nss_tunipip6_msg *msg);
+
+/**
+ *  API to send tun6rd messages
+ */
+extern nss_tx_status_t nss_tunipip6_tx(struct nss_ctx_instance *nss_ctx, struct nss_tunipip6_msg *msg);
+
+/**
+ * Callback to receive ipip6 callback
+ */
+typedef void (*nss_tunipip6_callback_t)(void *app_data, void *os_buf);
+
+/*
+ * @brief Register to send/receive ipip6 tunnel messages to NSS
+ *
+ * @param tunipip6_callback Callback
+ * @param ctx ipip6 tunnel context
+ *
+ * @return void* NSS context
+ */
+extern struct nss_ctx_instance *nss_register_tunipip6_if(uint32_t if_num, nss_tunipip6_callback_t tunipip6_callback,
+					nss_tunipip6_msg_callback_t event_callback, struct net_device *netdev);
+
+/**
+ * @brief Unregister ipip6 tunnel interface with NSS
+ */
+extern void nss_unregister_tunipip6_if(uint32_t if_num);
+
+#endif /* __NSS_TUN6RD_H */