release-request-fe3c4418-17ca-4f25-abb0-4ebd39ddf162-for-git_pi-release-4315938 snap-temp-L58200000099370312

Change-Id: Ib1fd36e5f8ebae675b7ceaaa5836109b0cbd9c49
diff --git a/msm8998/ipacm/inc/IPACM_Config.h b/msm8998/ipacm/inc/IPACM_Config.h
index 5bcb4eb..ae66c95 100644
--- a/msm8998/ipacm/inc/IPACM_Config.h
+++ b/msm8998/ipacm/inc/IPACM_Config.h
@@ -234,6 +234,8 @@
 
 	int DelNatIfaces(char *dev_name);
 
+	int CheckNatIfaces(const char *dev_name);
+
 	inline void SetQmapId(uint8_t id)
 	{
 		qmap_id = id;
diff --git a/msm8998/ipacm/inc/IPACM_Defs.h b/msm8998/ipacm/inc/IPACM_Defs.h
index 74ed3bf..9ab0893 100644
--- a/msm8998/ipacm/inc/IPACM_Defs.h
+++ b/msm8998/ipacm/inc/IPACM_Defs.h
@@ -166,6 +166,8 @@
 	IPA_WAN_XLAT_CONNECT_EVENT,               /* ipacm_event_data_fid */
 	IPA_TETHERING_STATS_UPDATE_EVENT,         /* ipacm_event_data_fid */
 	IPA_NETWORK_STATS_UPDATE_EVENT,           /* ipacm_event_data_fid */
+	IPA_DOWNSTREAM_ADD,                       /* ipacm_event_ipahal_stream */
+	IPA_DOWNSTREAM_DEL,                       /* ipacm_event_ipahal_stream */
 
 	IPA_EXTERNAL_EVENT_MAX,
 
@@ -185,8 +187,6 @@
 	IPA_ETH_BRIDGE_CLIENT_DEL,                /* ipacm_event_eth_bridge*/
 	IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH,       /* ipacm_event_eth_bridge*/
 	IPA_LAN_DELETE_SELF,                      /* ipacm_event_data_fid */
-	IPA_DOWNSTREAM_ADD,                       /* ipacm_event_ipahal_stream */
-	IPA_DOWNSTREAM_DEL,                       /* ipacm_event_ipahal_stream */
 	IPACM_EVENT_MAX
 } ipa_cm_event_id;
 
diff --git a/msm8998/ipacm/inc/IPACM_Wan.h b/msm8998/ipacm/inc/IPACM_Wan.h
index fbfaba3..fa4114b 100644
--- a/msm8998/ipacm/inc/IPACM_Wan.h
+++ b/msm8998/ipacm/inc/IPACM_Wan.h
@@ -131,6 +131,11 @@
 	static bool isWanUP_V6(int ipa_if_num_tether)
 	{
 #ifdef FEATURE_IPA_ANDROID
+#ifdef FEATURE_IPACM_HAL
+		/*To avoid -Wall -Werror error */
+		IPACMDBG_H("ipa_if_num_tether: %d\n",ipa_if_num_tether);
+		return wan_up_v6;
+#else
 		uint32_t i;
 		for (i=0; i < ipa_if_num_tether_v6_total;i++)
 		{
@@ -143,6 +148,7 @@
 			}
 		}
 		return false;
+#endif
 #else
 		return wan_up_v6;
 #endif
diff --git a/msm8998/ipacm/src/IPACM_Config.cpp b/msm8998/ipacm/src/IPACM_Config.cpp
index 6218fb6..895005f 100644
--- a/msm8998/ipacm/src/IPACM_Config.cpp
+++ b/msm8998/ipacm/src/IPACM_Config.cpp
@@ -88,6 +88,8 @@
 	__stringify(IPA_WAN_XLAT_CONNECT_EVENT),               /* ipacm_event_data_fid */
 	__stringify(IPA_TETHERING_STATS_UPDATE_EVENT),         /* ipacm_event_data_fid */
 	__stringify(IPA_NETWORK_STATS_UPDATE_EVENT),           /* ipacm_event_data_fid */
+	__stringify(IPA_DOWNSTREAM_ADD),                       /* ipacm_event_ipahal_stream */
+	__stringify(IPA_DOWNSTREAM_DEL),                       /* ipacm_event_ipahal_stream */
 	__stringify(IPA_EXTERNAL_EVENT_MAX),
 	__stringify(IPA_HANDLE_WAN_UP),                        /* ipacm_event_iface_up  */
 	__stringify(IPA_HANDLE_WAN_DOWN),                      /* ipacm_event_iface_up  */
@@ -499,7 +501,7 @@
 	{
 		if (strcmp(dev_name, pNatIfaces[i].iface_name) == 0)
 		{
-			IPACMDBG_H("Find Nat IfaceName: %s ,previous nat-ifaces number: %d\n",
+			IPACMDBG_H("Found Nat IfaceName: %s with nat-ifaces number: %d\n",
 							 pNatIfaces[i].iface_name, ipa_nat_iface_entries);
 
 			/* Reset the matched entry */
@@ -524,6 +526,26 @@
 	return 0;
 }
 
+int IPACM_Config::CheckNatIfaces(const char *dev_name)
+{
+	int i = 0;
+	IPACMDBG_H("Check iface %s from NAT-ifaces, currently it has %d nat ifaces\n",
+					 dev_name, ipa_nat_iface_entries);
+
+	for (i = 0; i < ipa_nat_iface_entries; i++)
+	{
+		if (strcmp(dev_name, pNatIfaces[i].iface_name) == 0)
+		{
+			IPACMDBG_H("Find Nat IfaceName: %s ,previous nat-ifaces number: %d\n",
+							 pNatIfaces[i].iface_name, ipa_nat_iface_entries);
+			return 0;
+		}
+	}
+	IPACMDBG_H("Can't find Nat IfaceName: %s with total nat-ifaces number: %d\n",
+					    dev_name, ipa_nat_iface_entries);
+	return -1;
+}
+
 /* for IPACM resource manager dependency usage
    add either Tx or Rx ipa_rm_resource_name and
    also indicate that endpoint property if valid */
diff --git a/msm8998/ipacm/src/IPACM_Iface.cpp b/msm8998/ipacm/src/IPACM_Iface.cpp
index 0582d67..4e0dc9e 100644
--- a/msm8998/ipacm/src/IPACM_Iface.cpp
+++ b/msm8998/ipacm/src/IPACM_Iface.cpp
@@ -851,7 +851,11 @@
 
 		if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)
 		{
+#ifdef FEATURE_IPA_V3
+			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
+#else
 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14);
+#endif
 			flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
 			flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
 			flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data;
@@ -862,7 +866,11 @@
 		flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
 		flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
 
+#ifdef FEATURE_IPA_V3
+		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
+#else
 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
+#endif
 		flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
 
diff --git a/msm8998/ipacm/src/IPACM_Lan.cpp b/msm8998/ipacm/src/IPACM_Lan.cpp
index 36d4b74..5a8f0e6 100644
--- a/msm8998/ipacm/src/IPACM_Lan.cpp
+++ b/msm8998/ipacm/src/IPACM_Lan.cpp
@@ -183,6 +183,21 @@
 	memset(is_downstream_set, 0, sizeof(is_downstream_set));
 	memset(is_upstream_set, 0, sizeof(is_upstream_set));
 	memset(&prefix, 0, sizeof(prefix));
+
+#ifdef FEATURE_IPACM_HAL
+		/* check if Upstream was set before */
+		if (IPACM_Wan::isWanUP(ipa_if_num))
+		{
+				IPACMDBG_H("Upstream was set previously for ipv4, change is_upstream_set flag\n");
+				is_upstream_set[IPA_IP_v4] = true;
+		}
+
+		if (IPACM_Wan::isWanUP_V6(ipa_if_num))
+		{
+				IPACMDBG_H("Upstream was set previously for ipv6, change is_upstream_set flag\n");
+				is_upstream_set[IPA_IP_v6] = true;
+		}
+#endif
 	return;
 }
 
@@ -368,6 +383,7 @@
 						handle_private_subnet(data->iptype);
 #endif
 
+#ifndef FEATURE_IPACM_HAL
 						if (IPACM_Wan::isWanUP(ipa_if_num))
 						{
 							if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX)
@@ -408,7 +424,7 @@
 						} else {
 							IPACMDBG_H("Wan_V6 haven't up yet\n");
 						}
-
+#endif
 						/* Post event to NAT */
 						if (data->iptype == IPA_IP_v4)
 						{
@@ -656,7 +672,13 @@
 					if (ip_type == IPA_IP_MAX || ip_type == data->prefix.iptype)
 					{
 						if (data->prefix.iptype == IPA_IP_v6) /* ipv6 only */
-							install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
+						{
+							/* Only offload clients has same prefix as Android gave */
+							ipv6_prefix[0] = data->prefix.v6Addr[0];
+							ipv6_prefix[1] = data->prefix.v6Addr[1];
+							IPACMDBG_H("ipv6_prefix0x%x:%x\n", ipv6_prefix[0], ipv6_prefix[1]);
+							install_ipv6_prefix_flt_rule(ipv6_prefix);
+						}
 
 						if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */
 						{
@@ -1033,7 +1055,7 @@
 		return IPACM_FAILURE;
 	}
 
-	if(is_sta_mode == false)
+	if(is_sta_mode == false && modem_ul_v4_set == true) //sky
 	{
 		if (num_wan_ul_fl_rule_v4 > MAX_WAN_UL_FILTER_RULES)
 		{
@@ -1511,14 +1533,14 @@
 /* only offload UL traffic of certain clients */
 #ifdef FEATURE_IPACM_HAL
 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
-		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = prefix[IPA_IP_v6].v6Mask[0];
-		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = prefix[IPA_IP_v6].v6Mask[1];
-		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = prefix[IPA_IP_v6].v6Mask[2];
-		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = prefix[IPA_IP_v6].v6Mask[3];
-		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[IPA_IP_v6].v6Addr[0];
-		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = prefix[IPA_IP_v6].v6Addr[1];
-		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = prefix[IPA_IP_v6].v6Addr[2];
-		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = prefix[IPA_IP_v6].v6Addr[3];
+		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[0] = ntohl(prefix[IPA_IP_v6].v6Mask[0]);
+		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[1] = ntohl(prefix[IPA_IP_v6].v6Mask[1]);
+		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[2] = ntohl(prefix[IPA_IP_v6].v6Mask[2]);
+		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[3] = ntohl(prefix[IPA_IP_v6].v6Mask[3]);
+		flt_rule_entry.rule.attrib.u.v6.src_addr[0] = ntohl(prefix[IPA_IP_v6].v6Addr[0]);
+		flt_rule_entry.rule.attrib.u.v6.src_addr[1] = ntohl(prefix[IPA_IP_v6].v6Addr[1]);
+		flt_rule_entry.rule.attrib.u.v6.src_addr[2] = ntohl(prefix[IPA_IP_v6].v6Addr[2]);
+		flt_rule_entry.rule.attrib.u.v6.src_addr[3] = ntohl(prefix[IPA_IP_v6].v6Addr[3]);
 
 #endif
 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
@@ -1575,7 +1597,7 @@
 	}
 
 	/* check only add static UL filter rule once */
-	if (num_dft_rt_v6 ==1 && iptype ==IPA_IP_v6 && modem_ul_v6_set == false)
+	if (iptype ==IPA_IP_v6 && modem_ul_v6_set == false)
 	{
 		IPACMDBG_H("IPA_IP_v6 num_dft_rt_v6 %d xlat_mux_id: %d modem_ul_v6_set: %d\n", num_dft_rt_v6, xlat_mux_id, modem_ul_v6_set);
 		ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id);
@@ -3056,6 +3078,7 @@
 			if(flt_rule_entry.rule.eq_attrib.num_offset_meq_32 <= IPA_IPFLTR_NUM_MEQ_32_EQNS)
 			{
 				eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_32 - 1;
+#ifdef FEATURE_IPA_V3
 				if(eq_index == 0)
 				{
 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<5);
@@ -3064,6 +3087,16 @@
 				{
 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<6);
 				}
+#else
+				if(eq_index == 0)
+				{
+					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<2);
+				}
+				else
+				{
+					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<3);
+				}
+#endif
 				flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].offset = 12;
 				flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].mask = prefix[IPA_IP_v4].v4Mask;
 				flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].value = prefix[IPA_IP_v4].v4Addr;
@@ -3080,6 +3113,7 @@
 			if(flt_rule_entry.rule.eq_attrib.num_offset_meq_128 <= IPA_IPFLTR_NUM_MEQ_128_EQNS)
 			{
 				eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_128 - 1;
+#ifdef FEATURE_IPA_V3
 				if(eq_index == 0)
 				{
 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<3);
@@ -3088,23 +3122,33 @@
 				{
 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<4);
 				}
+#else
+				if(eq_index == 0)
+				{
+					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
+				}
+				else
+				{
+					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<10);
+				}
+#endif
 				flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].offset = 8;
 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 0)
-					= prefix[IPA_IP_v6].v6Mask[0];
-				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 4)
-					= prefix[IPA_IP_v6].v6Mask[1];
-				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 8)
-					= prefix[IPA_IP_v6].v6Mask[2];
-				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 12)
 					= prefix[IPA_IP_v6].v6Mask[3];
+				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 4)
+					= prefix[IPA_IP_v6].v6Mask[2];
+				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 8)
+					= prefix[IPA_IP_v6].v6Mask[1];
+				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 12)
+					= prefix[IPA_IP_v6].v6Mask[0];
 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 0)
-					= prefix[IPA_IP_v6].v6Addr[0];
-				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 4)
-					= prefix[IPA_IP_v6].v6Addr[1];
-				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 8)
-					= prefix[IPA_IP_v6].v6Addr[2];
-				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 12)
 					= prefix[IPA_IP_v6].v6Addr[3];
+				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 4)
+					= prefix[IPA_IP_v6].v6Addr[2];
+				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 8)
+					= prefix[IPA_IP_v6].v6Addr[1];
+				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 12)
+					= prefix[IPA_IP_v6].v6Addr[0];
 			}
 			else
 			{
@@ -3200,7 +3244,7 @@
 
 	memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
 
-	if(is_sta_mode == false)
+	if(is_sta_mode == false && modem_ul_v6_set == true)
 	{
 		if (num_wan_ul_fl_rule_v6 > MAX_WAN_UL_FILTER_RULES)
 		{
diff --git a/msm8998/ipacm/src/IPACM_OffloadManager.cpp b/msm8998/ipacm/src/IPACM_OffloadManager.cpp
index 95e44bf..3679669 100644
--- a/msm8998/ipacm/src/IPACM_OffloadManager.cpp
+++ b/msm8998/ipacm/src/IPACM_OffloadManager.cpp
@@ -45,6 +45,7 @@
 #include "IPACM_ConntrackListener.h"
 #include "IPACM_Iface.h"
 #include "IPACM_Config.h"
+#include <unistd.h>
 
 const char *IPACM_OffloadManager::DEVICE_NAME = "/dev/wwan_ioctl";
 
@@ -120,8 +121,14 @@
 		return FAIL_HARDWARE;
 	}
 
+	/* add the check if getting FDs already or not */
+	if(cc->fd_tcp > -1 && cc->fd_udp > -1) {
+		IPACMDBG_H("has valid FDs fd_tcp %d, fd_udp %d, ignore fd %d.\n", cc->fd_tcp, cc->fd_udp, fd);
+		return SUCCESS;
+	}
+
 	if (groups == cc->subscrips_tcp) {
-		cc->fd_tcp = fd;
+		cc->fd_tcp = dup(fd);
 		IPACMDBG_H("Received fd %d with groups %d.\n", fd, groups);
 		/* set netlink buf */
 		rel = setsockopt(cc->fd_tcp, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(int) );
@@ -130,7 +137,7 @@
 			IPACMERR( "setsockopt returned error code %d ( %s )", errno, strerror( errno ) );
 		}
 	} else if (groups == cc->subscrips_udp) {
-		cc->fd_udp = fd;
+		cc->fd_udp = dup(fd);
 		IPACMDBG_H("Received fd %d with groups %d.\n", fd, groups);
 		/* set netlink buf */
 		rel = setsockopt(cc->fd_tcp, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(int) );
@@ -150,16 +157,9 @@
 
 RET IPACM_OffloadManager::clearAllFds()
 {
-	IPACM_ConntrackClient *cc;
 
-	cc = IPACM_ConntrackClient::GetInstance();
-	if(!cc)
-	{
-		IPACMERR("Init clear: cc %p \n", cc);
-		return FAIL_HARDWARE;
-	}
-	cc->UNRegisterWithConnTrack();
-
+	/* IPACM needs to kee old FDs, can't clear */
+	IPACMDBG_H("Still use old Fds, can't clear \n");
 	return SUCCESS;
 }
 
@@ -181,6 +181,14 @@
 	ipacm_event_ipahal_stream *evt_data;
 
 	IPACMDBG_H("addDownstream name(%s), ip-family(%d) \n", downstream_name, prefix.fam);
+
+	/* ideal behavior: ipacm should return try-again if downstream netdev driver not ready */
+	if (IPACM_Iface::ipacmcfg->CheckNatIfaces(downstream_name))
+	{
+		IPACMDBG_H("addDownstream name(%s) currently not support in ipa \n", downstream_name);
+		return FAIL_TRY_AGAIN;
+	}
+
 	if (prefix.fam == V4) {
 		IPACMDBG_H("subnet info v4Addr (%x) v4Mask (%x)\n", prefix.v4Addr, prefix.v4Mask);
 	} else {
@@ -265,7 +273,6 @@
 			IPACMERR("no previous upstream set before\n");
 			return FAIL_INPUT_CHECK;
 		}
-
 		if (gw_addr_v4.fam == V4 && upstream_v4_up == true) {
 			IPACMDBG_H("clean upstream(%s) for ipv4-fam(%d) upstream_v4_up(%d)\n", upstream_name, gw_addr_v4.fam, upstream_v4_up);
 			post_route_evt(IPA_IP_v4, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v4);
@@ -280,6 +287,14 @@
 	}
 	else
 	{
+
+		/* ideal behavior: ipacm should return try-again if upstream netdev driver not ready */
+		if (IPACM_Iface::ipacmcfg->CheckNatIfaces(upstream_name))
+		{
+			IPACMDBG_H("addDownstream name(%s) currently not support in ipa \n", upstream_name);
+			return FAIL_TRY_AGAIN;
+		}
+
 		if(ipa_get_if_index(upstream_name, &index))
 		{
 			IPACMERR("fail to get iface index.\n");
@@ -360,7 +375,13 @@
 
 RET IPACM_OffloadManager::stopAllOffload()
 {
-	return SUCCESS;
+	Prefix v4gw, v6gw;
+	memset(&v4gw, 0, sizeof(v4gw));
+	memset(&v6gw, 0, sizeof(v6gw));
+	v4gw.fam = V4;
+	v6gw.fam = V6;
+	IPACMDBG_H("posting setUpstream(NULL), ipv4-fam(%d) ipv6-fam(%d)\n", v4gw.fam, v6gw.fam);
+	return setUpstream(NULL, v4gw, v6gw);
 }
 
 RET IPACM_OffloadManager::setQuota(const char * upstream_name /* upstream */, uint64_t mb/* limit */)
diff --git a/msm8998/ipacm/src/IPACM_Wan.cpp b/msm8998/ipacm/src/IPACM_Wan.cpp
index 4c4ad69..968f562 100644
--- a/msm8998/ipacm/src/IPACM_Wan.cpp
+++ b/msm8998/ipacm/src/IPACM_Wan.cpp
@@ -3769,7 +3769,11 @@
 		flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
 		flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
 
+#ifdef FEATURE_IPA_V3
+		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
+#else
 		flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
+#endif
 		flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
 		flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
 
diff --git a/msm8998/ipacm/src/IPACM_Wlan.cpp b/msm8998/ipacm/src/IPACM_Wlan.cpp
index 887e9ee..53e56cf 100644
--- a/msm8998/ipacm/src/IPACM_Wlan.cpp
+++ b/msm8998/ipacm/src/IPACM_Wlan.cpp
@@ -267,6 +267,7 @@
 					handle_private_subnet(data->iptype);
 #endif
 
+#ifndef FEATURE_IPACM_HAL
 					if (IPACM_Wan::isWanUP(ipa_if_num))
 					{
 						if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX)
@@ -308,6 +309,7 @@
 					} else {
 						IPACMDBG_H("Wan_V6 haven't up yet \n");
 					}
+#endif
 					/* checking if SW-RT_enable */
 					if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true)
 					{
@@ -535,7 +537,13 @@
 					if(ip_type == IPA_IP_MAX || ip_type == data->prefix.iptype)
 					{
 						if (data->prefix.iptype == IPA_IP_v6) /* ipv6 only */
-							install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
+						{
+							/* Only offload clients has same prefix as Andorid gave */
+							ipv6_prefix[0] = data->prefix.v6Addr[0];
+							ipv6_prefix[1] = data->prefix.v6Addr[1];
+							IPACMDBG_H("ipv6_prefix0x%x:%x\n", ipv6_prefix[0], ipv6_prefix[1]);
+							install_ipv6_prefix_flt_rule(ipv6_prefix);
+						}
 
 						if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */
 						{
@@ -1257,6 +1265,7 @@
 				memcmp(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix)) != 0)
 			{
 				IPACMDBG_H("This IPv6 address is not global IPv6 address with correct prefix, ignore.\n");
+				IPACMDBG_H("ipv6 address: 0x%x:%x ipv6_prefix0x%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], ipv6_prefix[0], ipv6_prefix[1]);
 				return IPACM_FAILURE;
 			}