Snap for 6450912 from 75b818f3e48038eca1e083d1afce5f4dcb8e6534 to mainline-release

Change-Id: If712981a69c4be59a00a9b99fe3622671d40abf3
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..9515b25
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,2 @@
+soong_namespace {
+}
diff --git a/hal/Android.bp b/hal/Android.bp
new file mode 100644
index 0000000..14d3745
--- /dev/null
+++ b/hal/Android.bp
@@ -0,0 +1,26 @@
+cc_library_shared {
+    name: "liboffloadhal",
+    srcs: [
+        "src/CtUpdateAmbassador.cpp",
+        "src/HAL.cpp",
+        "src/IpaEventRelay.cpp",
+        "src/LocalLogBuffer.cpp",
+        "src/OffloadStatistics.cpp",
+        "src/PrefixParser.cpp",
+    ],
+
+    shared_libs: [
+        "libhidlbase",
+        "liblog",
+        "libcutils",
+        "libdl",
+        "libbase",
+        "libutils",
+        "libhardware_legacy",
+        "libhardware",
+        "android.hardware.tetheroffload.config@1.0",
+        "android.hardware.tetheroffload.control@1.0",
+    ],
+    export_include_dirs: ["inc"],
+    vendor: true,
+}
diff --git a/hal/Android.mk b/hal/Android.mk
deleted file mode 100644
index e588c68..0000000
--- a/hal/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_ARM_MODE := arm
-LOCAL_SRC_FILES := src/CtUpdateAmbassador.cpp \
-                src/HAL.cpp \
-                src/IpaEventRelay.cpp \
-                src/LocalLogBuffer.cpp \
-                src/OffloadStatistics.cpp \
-                src/PrefixParser.cpp
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc
-LOCAL_MODULE := liboffloadhal
-
-#LOCAL_CPP_FLAGS := -Wall -Werror
-LOCAL_SHARED_LIBRARIES := libhwbinder \
-                        libhidlbase \
-                        liblog \
-                        libcutils \
-                        libdl \
-                        libbase \
-                        libutils \
-                        libhardware_legacy \
-                        libhardware \
-                        android.hardware.tetheroffload.config@1.0 \
-                        android.hardware.tetheroffload.control@1.0
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/inc
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64
-include $(BUILD_SHARED_LIBRARY)
diff --git a/ipacm/Android.bp b/ipacm/Android.bp
new file mode 100644
index 0000000..7c2a0c5
--- /dev/null
+++ b/ipacm/Android.bp
@@ -0,0 +1,72 @@
+
+cc_binary {
+    name: "ipacm",
+
+    local_include_dirs: ["src"] + ["inc"],
+    header_libs: ["device_kernel_headers"],
+    cflags: ["-DFEATURE_IPA_ANDROID"] + ["-DFEATURE_IPACM_RESTART"] + [
+        "-DFEATURE_IPACM_HAL",
+        "-Wall",
+        "-Werror",
+        "-Wno-error=macro-redefined",
+	"-Wno-enum-compare",
+	"-Wno-error=implicit-fallthrough",
+    ],
+
+    srcs: [
+        "src/IPACM_Main.cpp",
+        "src/IPACM_EvtDispatcher.cpp",
+        "src/IPACM_Config.cpp",
+        "src/IPACM_CmdQueue.cpp",
+        "src/IPACM_Filtering.cpp",
+        "src/IPACM_Routing.cpp",
+        "src/IPACM_Header.cpp",
+        "src/IPACM_Lan.cpp",
+        "src/IPACM_Iface.cpp",
+        "src/IPACM_Wlan.cpp",
+        "src/IPACM_Wan.cpp",
+        "src/IPACM_IfaceManager.cpp",
+        "src/IPACM_Neighbor.cpp",
+        "src/IPACM_Netlink.cpp",
+        "src/IPACM_Xml.cpp",
+        "src/IPACM_Conntrack_NATApp.cpp",
+        "src/IPACM_ConntrackClient.cpp",
+        "src/IPACM_ConntrackListener.cpp",
+        "src/IPACM_Log.cpp",
+        "src/IPACM_OffloadManager.cpp",
+        "src/IPACM_LanToLan.cpp",
+    ],
+
+    init_rc: ["src/ipacm.rc"],
+    clang: true,
+    vendor: true,
+
+    shared_libs: [
+	"liboffloadhal",
+	"libipanat",
+	"libxml2",
+	"libnfnetlink",
+	"libnetfilter_conntrack",
+        "libhidlbase",
+        "liblog",
+        "libcutils",
+        "libdl",
+        "libbase",
+        "libutils",
+        "libhardware_legacy",
+        "libhardware",
+        "android.hardware.tetheroffload.config@1.0",
+        "android.hardware.tetheroffload.control@1.0",
+    ],
+}
+
+//###############################################################################
+
+prebuilt_etc {
+    name: "IPACM_cfg.xml",
+
+    vendor: true,
+    owner: "ipacm",
+    src: "src/IPACM_cfg.xml",
+
+}
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index 9230f7d..1915fbc 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -94,7 +94,7 @@
 	ipacm_alg *alg_table;
 
 	/* Store private subnet configuration from XML file */
-	ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES];
+	ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES];
 
 	/* Store the non nat iface names */
 	NatIfaces *pNatIfaces;
@@ -261,6 +261,10 @@
 
 	enum ipa_hw_type GetIPAVer(bool get = false);
 
+	bool isEthBridgingSupported();
+
+	bool isIPAv3Supported();
+
 	int Init(void);
 
 	inline bool isPrivateSubnet(uint32_t ip_addr)
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 65d5ce4..a3cbba1 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -77,6 +77,7 @@
 
 #define IPA_MAX_IFACE_ENTRIES 20
 #define IPA_MAX_PRIVATE_SUBNET_ENTRIES 3
+#define IPA_MAX_MTU_ENTRIES 3
 #define IPA_MAX_ALG_ENTRIES 20
 #define IPA_MAX_RM_ENTRY 6
 
@@ -96,16 +97,13 @@
 #define IPA_DEVICE_NAME "/dev/ipa"
 #define MAX_NUM_PROP 2
 
-#ifndef FEATURE_IPA_V3
-#define IPA_MAX_FLT_RULE 50
-#else
 #define IPA_MAX_FLT_RULE 100
-#endif
 
 #define TCP_FIN_SHIFT 16
 #define TCP_SYN_SHIFT 17
 #define TCP_RST_SHIFT 18
 #define NUM_IPV6_PREFIX_FLT_RULE 1
+#define NUM_IPV6_PREFIX_MTU_RULE 1
 
 /*---------------------------------------------------------------------------
 										Return values indicating error status
@@ -124,6 +122,7 @@
 #define IPA_MAC_ADDR_SIZE  6
 #define IPA_MAX_NUM_SW_PDNS 15
 
+#define DEFAULT_MTU_SIZE 1500
 /*===========================================================================
 										 GLOBAL DEFINITIONS AND DECLARATIONS
 ===========================================================================*/
diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h
index bf815c5..605edb5 100644
--- a/ipacm/inc/IPACM_Lan.h
+++ b/ipacm/inc/IPACM_Lan.h
@@ -113,7 +113,7 @@
 	uint32_t lan_wan_fl_rule_hdl[IPA_WAN_DEFAULT_FILTER_RULE_HANDLES];
 
 	/* store private-subnet filter rule handlers */
-	uint32_t private_fl_rule_hdl[IPA_MAX_PRIVATE_SUBNET_ENTRIES];
+	uint32_t private_fl_rule_hdl[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES];
 
 	/* LAN-iface's callback function */
 	void event_callback(ipa_cm_event_id event, void *data);
@@ -258,7 +258,7 @@
 
 	uint32_t ipv4_icmp_flt_rule_hdl[NUM_IPV4_ICMP_FLT_RULE];
 
-	uint32_t ipv6_prefix_flt_rule_hdl[NUM_IPV6_PREFIX_FLT_RULE];
+	uint32_t ipv6_prefix_flt_rule_hdl[NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE];
 	uint32_t ipv6_icmp_flt_rule_hdl[NUM_IPV6_ICMP_FLT_RULE];
 
 	int num_wan_ul_fl_rule_v4;
@@ -464,6 +464,8 @@
 	/* for pcie modem */
 	virtual int add_connection(int client_index, int v6_num);
 	virtual int del_connection(int client_index, int v6_num);
+
+	int construct_mtu_rule(struct ipa_flt_rule *rule, enum ipa_ip_type iptype, uint16_t mtu);
 };
 
 #endif /* IPACM_LAN_H */
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h
index 684bfb7..31949c5 100644
--- a/ipacm/inc/IPACM_Wan.h
+++ b/ipacm/inc/IPACM_Wan.h
@@ -105,6 +105,8 @@
 	static bool wan_up;
 	static bool wan_up_v6;
 	static uint8_t xlat_mux_id;
+	static uint16_t mtu_default_wan;
+	uint16_t mtu_size;
 	/* IPACM interface name */
 	static char wan_up_dev_name[IF_NAME_LEN];
 	static uint32_t curr_wan_ip;
@@ -137,6 +139,26 @@
 #endif
 	}
 
+	static uint16_t queryMTU(int ipa_if_num_tether, enum ipa_ip_type iptype)
+	{
+		if (iptype == IPA_IP_v4)
+		{
+			if (isWanUP(ipa_if_num_tether))
+			{
+				return mtu_default_wan;
+			}
+		}
+		else if (iptype == IPA_IP_v6)
+		{
+			if (isWanUP_V6(ipa_if_num_tether))
+			{
+				return mtu_default_wan;
+
+			}
+		}
+		return DEFAULT_MTU_SIZE;
+	}
+
 	static bool isWanUP_V6(int ipa_if_num_tether)
 	{
 #ifdef FEATURE_IPA_ANDROID
@@ -653,6 +675,9 @@
 	int add_tcp_fin_rst_exception_rule();
 
 	int delete_tcp_fin_rst_exception_rule();
+
+	/* Query mtu size */
+	int query_mtu_size();
 };
 
 #endif /* IPACM_WAN_H */
diff --git a/ipacm/src/Android.mk b/ipacm/src/Android.mk
deleted file mode 100644
index c8534df..0000000
--- a/ipacm/src/Android.mk
+++ /dev/null
@@ -1,144 +0,0 @@
-TARGET_DISABLE_IPACM := false
-
-ifeq ($(TARGET_USES_QMAA),true)
-ifneq ($(TARGET_USES_QMAA_OVERRIDE_DATA),true)
-	TARGET_DISABLE_IPACM := true
-endif #TARGET_USES_QMAA_OVERRIDE_DATA
-endif #TARGET_USES_QMAA
-
-
-ifneq ($(TARGET_DISABLE_IPACM),true)
-ifneq ($(TARGET_HAS_LOW_RAM),true)
-BOARD_PLATFORM_LIST := msm8909
-BOARD_PLATFORM_LIST += msm8916
-BOARD_PLATFORM_LIST += msm8917
-BOARD_PLATFORM_LIST += qm215
-BOARD_IPAv3_LIST := msm8998
-BOARD_IPAv3_LIST += sdm845
-BOARD_IPAv3_LIST += sdm710
-BOARD_IPAv3_LIST += msmnile
-BOARD_IPAv3_LIST += kona
-BOARD_IPAv3_LIST += lahaina
-BOARD_IPAv3_LIST += $(MSMSTEPPE)
-BOARD_IPAv3_LIST += $(TRINKET)
-BOARD_IPAv3_LIST += lito
-BOARD_IPAv3_LIST += atoll
-BOARD_IPAv3_LIST += bengal
-BOARD_ETH_BRIDGE_LIST := msmnile
-BOARD_ETH_BRIDGE_LIST += kona
-
-ifneq ($(call is-board-platform-in-list,$(BOARD_PLATFORM_LIST)),true)
-ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM)))
-ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH)))
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/../inc
-
-LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
-
-LOCAL_CFLAGS := -DFEATURE_IPA_ANDROID
-LOCAL_CFLAGS += -DFEATURE_IPACM_RESTART
-
-ifeq ($(call is-board-platform-in-list,$(BOARD_ETH_BRIDGE_LIST)),true)
-LOCAL_CFLAGS += -DFEATURE_ETH_BRIDGE_LE
-endif
-
-LOCAL_CFLAGS += -DFEATURE_IPACM_HAL -Wall -Werror -Wno-error=macro-redefined -Wno-enum-compare
-ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
-LOCAL_CFLAGS += -DDEBUG
-endif
-
-ifeq ($(call is-board-platform-in-list,$(BOARD_IPAv3_LIST)),true)
-LOCAL_CFLAGS += -DFEATURE_IPA_V3
-endif
-
-filetoadd = bionic/libc/kernel/arch-arm/asm/posix_types.h
-LOCAL_CFLAGS += $(shell if [ -a $(filetoadd) ] ; then echo -include $(filetoadd) ; fi ;)
-filetoadd = bionic/libc/kernel/arch-arm/asm/byteorder.h
-LOCAL_CFLAGS += $(shell if [ -a $(filetoadd) ] ; then echo -include $(filetoadd) ; fi ;)
-
-# Allow warnings in IPACM_Main.cpp until they are fixed.
-LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
-
-LOCAL_SRC_FILES := IPACM_Main.cpp \
-		IPACM_EvtDispatcher.cpp \
-		IPACM_Config.cpp \
-		IPACM_CmdQueue.cpp \
-		IPACM_Filtering.cpp \
-		IPACM_Routing.cpp \
-		IPACM_Header.cpp \
-		IPACM_Lan.cpp \
-		IPACM_Iface.cpp \
-		IPACM_Wlan.cpp \
-		IPACM_Wan.cpp \
-		IPACM_IfaceManager.cpp \
-		IPACM_Neighbor.cpp \
-		IPACM_Netlink.cpp \
-		IPACM_Xml.cpp \
-		IPACM_Conntrack_NATApp.cpp\
-		IPACM_ConntrackClient.cpp \
-		IPACM_ConntrackListener.cpp \
-		IPACM_Log.cpp \
-		IPACM_OffloadManager.cpp \
-		IPACM_LanToLan.cpp
-
-LOCAL_MODULE := ipacm
-LOCAL_INIT_RC := ipacm.rc
-LOCAL_CLANG := false
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SHARED_LIBRARIES := liboffloadhal
-LOCAL_SHARED_LIBRARIES += libipanat
-LOCAL_SHARED_LIBRARIES += libxml2
-LOCAL_SHARED_LIBRARIES += libnfnetlink
-LOCAL_SHARED_LIBRARIES += libnetfilter_conntrack
-LOCAL_SHARED_LIBRARIES += libhwbinder \
-                libhidlbase \
-                liblog \
-                libcutils \
-                libdl \
-                libbase \
-                libutils \
-                libhardware_legacy \
-                libhardware \
-                android.hardware.tetheroffload.config@1.0 \
-                android.hardware.tetheroffload.control@1.0
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)
-
-LOCAL_CLANG := true
-include $(BUILD_EXECUTABLE)
-
-################################################################################
-
-define ADD_TEST
-
-include $(CLEAR_VARS)
-LOCAL_MODULE       := $1
-LOCAL_SRC_FILES    := $1
-LOCAL_MODULE_CLASS := ipacm
-LOCAL_MODULE_TAGS  := optional
-LOCAL_MODULE_PATH  := $(TARGET_OUT_ETC)
-include $(BUILD_PREBUILT)
-
-endef
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := IPACM_cfg.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_OWNER := ipacm
-include $(BUILD_PREBUILT)
-
-endif # $(TARGET_ARCH)
-endif
-endif
-endif
-endif
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index 781f1cb..c396c6c 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -905,3 +905,26 @@
 	IPACMDBG_H("IPA version is %d.\n", ver);
 	return ver;
 }
+
+bool IPACM_Config::isEthBridgingSupported()
+{
+	enum ipa_hw_type hw_type;
+
+	hw_type = GetIPAVer();
+
+#ifdef IPA_HW_v4_7
+	return ((hw_type >= IPA_HW_v4_5) &&
+		(hw_type != IPA_HW_v4_7));
+#else
+	return (hw_type >= IPA_HW_v4_5);
+#endif
+}
+
+bool IPACM_Config::isIPAv3Supported()
+{
+	enum ipa_hw_type hw_type;
+
+	hw_type = GetIPAVer();
+
+	return (hw_type >= IPA_HW_v3_0);
+}
diff --git a/ipacm/src/IPACM_Conntrack_NATApp.cpp b/ipacm/src/IPACM_Conntrack_NATApp.cpp
index c1f47e1..a9c7140 100644
--- a/ipacm/src/IPACM_Conntrack_NATApp.cpp
+++ b/ipacm/src/IPACM_Conntrack_NATApp.cpp
@@ -546,9 +546,8 @@
 	flt_rule_entry.rule.to_uc = 0;
 	flt_rule_entry.rule.eq_attrib_type = 1;
 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-	flt_rule_entry.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule_entry.rule.hashable = true;
 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_PORT;
 	flt_rule_entry.rule.attrib.src_port = rule->target_port;
 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_PORT;
diff --git a/ipacm/src/IPACM_Filtering.cpp b/ipacm/src/IPACM_Filtering.cpp
index a158d74..8aa25a6 100644
--- a/ipacm/src/IPACM_Filtering.cpp
+++ b/ipacm/src/IPACM_Filtering.cpp
@@ -46,6 +46,7 @@
 #include "IPACM_Filtering.h"
 #include <IPACM_Log.h>
 #include "IPACM_Defs.h"
+#include "IPACM_Iface.h"
 
 
 const char *IPACM_Filtering::DEVICE_NAME = "/dev/ipa";
@@ -234,156 +235,162 @@
 bool IPACM_Filtering::AddFilteringRuleAfter_hw_index(struct ipa_ioc_add_flt_rule_after *ruleTable, int hw_counter_index)
 {
 	bool ret = true;
-#ifdef FEATURE_IPA_V3
 	int retval=0, cnt = 0, len = 0;
 	struct ipa_ioc_add_flt_rule_after_v2 *ruleTable_v2;
 	struct ipa_flt_rule_add_v2 flt_rule_entry;
 
-	IPACMDBG("Printing filter add attributes\n");
-	IPACMDBG("ep: %d\n", ruleTable->ep);
-	IPACMDBG("ip type: %d\n", ruleTable->ip);
-	IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
-	IPACMDBG("add_after_hdl: %d\n", ruleTable->add_after_hdl);
-	IPACMDBG("commit value: %d\n", ruleTable->commit);
-
-	/* change to v2 format*/
-	len = sizeof(struct ipa_ioc_add_flt_rule_after_v2);
-	ruleTable_v2 = (struct ipa_ioc_add_flt_rule_after_v2*)malloc(len);
-	if (ruleTable_v2 == NULL)
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
 	{
-		IPACMERR("Error Locate ipa_ioc_add_flt_rule_after_v2 memory...\n");
-		return false;
-	}
-	memset(ruleTable_v2, 0, len);
-	ruleTable_v2->rules = (uint64_t)calloc(ruleTable->num_rules, sizeof(struct ipa_flt_rule_add_v2));
-	if (!ruleTable_v2->rules) {
-		IPACMERR("Failed to allocate memory for filtering rules\n");
-		ret = false;
-		goto fail_tbl;
-	}
+		IPACMDBG("Printing filter add attributes\n");
+		IPACMDBG("ep: %d\n", ruleTable->ep);
+		IPACMDBG("ip type: %d\n", ruleTable->ip);
+		IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
+		IPACMDBG("add_after_hdl: %d\n", ruleTable->add_after_hdl);
+		IPACMDBG("commit value: %d\n", ruleTable->commit);
 
-	ruleTable_v2->commit = ruleTable->commit;
-	ruleTable_v2->ep = ruleTable->ep;
-	ruleTable_v2->ip = ruleTable->ip;
-	ruleTable_v2->num_rules = ruleTable->num_rules;
-	ruleTable_v2->add_after_hdl = ruleTable->add_after_hdl;
-	ruleTable_v2->flt_rule_size = sizeof(struct ipa_flt_rule_add_v2);
-
-	for (cnt=0; cnt < ruleTable->num_rules; cnt++)
-	{
-		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add_v2));
-		flt_rule_entry.at_rear = ruleTable->rules[cnt].at_rear;
-		flt_rule_entry.rule.retain_hdr = ruleTable->rules[cnt].rule.retain_hdr;
-		flt_rule_entry.rule.to_uc = ruleTable->rules[cnt].rule.to_uc;
-		flt_rule_entry.rule.action = ruleTable->rules[cnt].rule.action;
-		flt_rule_entry.rule.rt_tbl_hdl = ruleTable->rules[cnt].rule.rt_tbl_hdl;
-		flt_rule_entry.rule.rt_tbl_idx = ruleTable->rules[cnt].rule.rt_tbl_idx;
-		flt_rule_entry.rule.eq_attrib_type = ruleTable->rules[cnt].rule.eq_attrib_type;
-		flt_rule_entry.rule.max_prio = ruleTable->rules[cnt].rule.max_prio;
-		flt_rule_entry.rule.hashable = ruleTable->rules[cnt].rule.hashable;
-		flt_rule_entry.rule.rule_id = ruleTable->rules[cnt].rule.rule_id;
-		flt_rule_entry.rule.set_metadata = ruleTable->rules[cnt].rule.set_metadata;
-		flt_rule_entry.rule.pdn_idx = ruleTable->rules[cnt].rule.pdn_idx;
-		memcpy(&flt_rule_entry.rule.eq_attrib,
-					 &ruleTable->rules[cnt].rule.eq_attrib,
-					 sizeof(flt_rule_entry.rule.eq_attrib));
-		memcpy(&flt_rule_entry.rule.attrib,
-					 &ruleTable->rules[cnt].rule.attrib,
-					 sizeof(flt_rule_entry.rule.attrib));
-		IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt,
-				ruleTable->rules[cnt].rule.attrib.attrib_mask);
-		/* 0 means disable hw-counter-sats */
-		if (hw_counter_index != 0)
+		/* change to v2 format*/
+		len = sizeof(struct ipa_ioc_add_flt_rule_after_v2);
+		ruleTable_v2 = (struct ipa_ioc_add_flt_rule_after_v2*)malloc(len);
+		if (ruleTable_v2 == NULL)
 		{
-			flt_rule_entry.rule.enable_stats = 1;
-			flt_rule_entry.rule.cnt_idx = hw_counter_index;
+			IPACMERR("Error Locate ipa_ioc_add_flt_rule_after_v2 memory...\n");
+			return false;
+		}
+		memset(ruleTable_v2, 0, len);
+		ruleTable_v2->rules = (uint64_t)calloc(ruleTable->num_rules, sizeof(struct ipa_flt_rule_add_v2));
+		if (!ruleTable_v2->rules) {
+			IPACMERR("Failed to allocate memory for filtering rules\n");
+			ret = false;
+			goto fail_tbl;
 		}
 
-		/* copy to v2 table*/
-		memcpy((void *)(ruleTable_v2->rules + (cnt * sizeof(struct ipa_flt_rule_add_v2))),
-			&flt_rule_entry, sizeof(flt_rule_entry));
-	}
+		ruleTable_v2->commit = ruleTable->commit;
+		ruleTable_v2->ep = ruleTable->ep;
+		ruleTable_v2->ip = ruleTable->ip;
+		ruleTable_v2->num_rules = ruleTable->num_rules;
+		ruleTable_v2->add_after_hdl = ruleTable->add_after_hdl;
+		ruleTable_v2->flt_rule_size = sizeof(struct ipa_flt_rule_add_v2);
 
-	retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER_V2, ruleTable_v2);
-	if (retval != 0)
-	{
-		IPACMERR("Failed adding Filtering rule %pK\n", ruleTable_v2);
-		PERROR("unable to add filter rule:");
-
-		for (int cnt = 0; cnt < ruleTable_v2->num_rules; cnt++)
+		for (cnt=0; cnt < ruleTable->num_rules; cnt++)
 		{
-			if (((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0)
+			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add_v2));
+			flt_rule_entry.at_rear = ruleTable->rules[cnt].at_rear;
+			flt_rule_entry.rule.retain_hdr = ruleTable->rules[cnt].rule.retain_hdr;
+			flt_rule_entry.rule.to_uc = ruleTable->rules[cnt].rule.to_uc;
+			flt_rule_entry.rule.action = ruleTable->rules[cnt].rule.action;
+			flt_rule_entry.rule.rt_tbl_hdl = ruleTable->rules[cnt].rule.rt_tbl_hdl;
+			flt_rule_entry.rule.rt_tbl_idx = ruleTable->rules[cnt].rule.rt_tbl_idx;
+			flt_rule_entry.rule.eq_attrib_type = ruleTable->rules[cnt].rule.eq_attrib_type;
+			flt_rule_entry.rule.max_prio = ruleTable->rules[cnt].rule.max_prio;
+			flt_rule_entry.rule.hashable = ruleTable->rules[cnt].rule.hashable;
+			flt_rule_entry.rule.rule_id = ruleTable->rules[cnt].rule.rule_id;
+			flt_rule_entry.rule.set_metadata = ruleTable->rules[cnt].rule.set_metadata;
+			flt_rule_entry.rule.pdn_idx = ruleTable->rules[cnt].rule.pdn_idx;
+			memcpy(&flt_rule_entry.rule.eq_attrib,
+						 &ruleTable->rules[cnt].rule.eq_attrib,
+						 sizeof(flt_rule_entry.rule.eq_attrib));
+			memcpy(&flt_rule_entry.rule.attrib,
+						 &ruleTable->rules[cnt].rule.attrib,
+						 sizeof(flt_rule_entry.rule.attrib));
+			IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt,
+					ruleTable->rules[cnt].rule.attrib.attrib_mask);
+			/* 0 means disable hw-counter-sats */
+			if (hw_counter_index != 0)
+			{
+				flt_rule_entry.rule.enable_stats = 1;
+				flt_rule_entry.rule.cnt_idx = hw_counter_index;
+			}
+
+			/* copy to v2 table*/
+			memcpy((void *)(ruleTable_v2->rules + (cnt * sizeof(struct ipa_flt_rule_add_v2))),
+				&flt_rule_entry, sizeof(flt_rule_entry));
+		}
+
+		retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER_V2, ruleTable_v2);
+		if (retval != 0)
+		{
+			IPACMERR("Failed adding Filtering rule %pK\n", ruleTable_v2);
+			PERROR("unable to add filter rule:");
+
+			for (int cnt = 0; cnt < ruleTable_v2->num_rules; cnt++)
+			{
+				if (((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0)
+				{
+					IPACMERR("Adding Filter rule:%d failed with status:%d\n",
+									 cnt, ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status);
+				}
+			}
+			ret = false;
+			goto fail_rule;
+		}
+
+		/* copy results from v2 to v1 format */
+		for (int cnt = 0; cnt < ruleTable->num_rules; cnt++)
+		{
+			/* copy status to v1 format */
+			ruleTable->rules[cnt].status = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status;
+			ruleTable->rules[cnt].flt_rule_hdl = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].flt_rule_hdl;
+
+			if(((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0)
 			{
 				IPACMERR("Adding Filter rule:%d failed with status:%d\n",
-								 cnt, ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status);
+								 cnt, ((struct ipa_flt_rule_add_v2 *) ruleTable_v2->rules)[cnt].status);
 			}
 		}
-		ret = false;
-		goto fail_rule;
-	}
 
-	/* copy results from v2 to v1 format */
-	for (int cnt = 0; cnt < ruleTable->num_rules; cnt++)
+		IPACMDBG("Added Filtering rule %pK\n", ruleTable_v2);
+
+	fail_rule:
+		if((void *)ruleTable_v2->rules != NULL)
+			free((void *)ruleTable_v2->rules);
+	fail_tbl:
+		if (ruleTable_v2 != NULL)
+			free(ruleTable_v2);
+	}
+	else
 	{
-		/* copy status to v1 format */
-		ruleTable->rules[cnt].status = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status;
-		ruleTable->rules[cnt].flt_rule_hdl = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].flt_rule_hdl;
-
-		if(((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0)
-		{
-			IPACMERR("Adding Filter rule:%d failed with status:%d\n",
-							 cnt, ((struct ipa_flt_rule_add_v2 *) ruleTable_v2->rules)[cnt].status);
-		}
+		if (ruleTable)
+			IPACMERR("Not support adding Filtering rule %pK\n", ruleTable);
 	}
-
-	IPACMDBG("Added Filtering rule %pK\n", ruleTable_v2);
-
-fail_rule:
-	if((void *)ruleTable_v2->rules != NULL)
-		free((void *)ruleTable_v2->rules);
-fail_tbl:
-	if (ruleTable_v2 != NULL)
-		free(ruleTable_v2);
-#else
-	if (ruleTable)
-	IPACMERR("Not support adding Filtering rule %pK\n", ruleTable);
-#endif
 	return ret;
 }
 #endif //IPA_IOCTL_SET_FNR_COUNTER_INFO
 
 bool IPACM_Filtering::AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const *ruleTable)
 {
-#ifdef FEATURE_IPA_V3
 	int retval = 0;
 
-	IPACMDBG("Printing filter add attributes\n");
-	IPACMDBG("ip type: %d\n", ruleTable->ip);
-	IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
-	IPACMDBG("End point: %d\n", ruleTable->ep);
-	IPACMDBG("commit value: %d\n", ruleTable->commit);
-
-	retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER, ruleTable);
-
-	for (int cnt = 0; cnt<ruleTable->num_rules; cnt++)
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
 	{
-		if(ruleTable->rules[cnt].status != 0)
+		IPACMDBG("Printing filter add attributes\n");
+		IPACMDBG("ip type: %d\n", ruleTable->ip);
+		IPACMDBG("Number of rules: %d\n", ruleTable->num_rules);
+		IPACMDBG("End point: %d\n", ruleTable->ep);
+		IPACMDBG("commit value: %d\n", ruleTable->commit);
+
+		retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER, ruleTable);
+
+		for (int cnt = 0; cnt<ruleTable->num_rules; cnt++)
 		{
-			IPACMERR("Adding Filter rule:%d failed with status:%d\n",
-							 cnt, ruleTable->rules[cnt].status);
+			if(ruleTable->rules[cnt].status != 0)
+			{
+				IPACMERR("Adding Filter rule:%d failed with status:%d\n",
+								 cnt, ruleTable->rules[cnt].status);
+			}
 		}
-	}
 
-	if (retval != 0)
-	{
-		IPACMERR("Failed adding Filtering rule %pK\n", ruleTable);
-		return false;
+		if (retval != 0)
+		{
+			IPACMERR("Failed adding Filtering rule %pK\n", ruleTable);
+			return false;
+		}
+		IPACMDBG("Added Filtering rule %pK\n", ruleTable);
 	}
-	IPACMDBG("Added Filtering rule %pK\n", ruleTable);
-#else
-	if (ruleTable)
-	IPACMERR("Not support adding Filtering rule %pK\n", ruleTable);
-#endif
+	else
+	{
+		if (ruleTable)
+			IPACMERR("Not support adding Filtering rule %pK\n", ruleTable);
+	}
 	return true;
 }
 
@@ -501,9 +508,7 @@
 {
 	int ret = 0, cnt, num_rules = 0, pos = 0;
 	ipa_install_fltr_rule_req_msg_v01 qmi_rule_msg;
-#ifdef FEATURE_IPA_V3
 	ipa_install_fltr_rule_req_ex_msg_v01 qmi_rule_ex_msg;
-#endif
 
 	memset(&qmi_rule_msg, 0, sizeof(qmi_rule_msg));
 	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
@@ -525,175 +530,178 @@
 	}
 
 	/* if it is not IPA v3, use old QMI format */
-#ifndef FEATURE_IPA_V3
-	if(num_rules > QMI_IPA_MAX_FILTERS_V01)
+	if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
 	{
-		IPACMERR("The number of filtering rules exceed limit.\n");
-		close(fd_wwan_ioctl);
-		return false;
-	}
-	else
-	{
-		if (num_rules > 0)
+		if(num_rules > QMI_IPA_MAX_FILTERS_V01)
 		{
-			qmi_rule_msg.filter_spec_list_valid = true;
-		}
-		else
-		{
-			qmi_rule_msg.filter_spec_list_valid = false;
-		}
-
-		qmi_rule_msg.filter_spec_list_len = num_rules;
-		qmi_rule_msg.source_pipe_index_valid = 0;
-
-		IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
-
-		if(rule_table_v4 != NULL)
-		{
-			for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
-			{
-				if (pos < QMI_IPA_MAX_FILTERS_V01)
-				{
-					qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
-					qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
-					qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
-					qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1;
-					qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
-					qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1;
-					qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id;
-					memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
-						&rule_table_v4->rules[cnt].rule.eq_attrib,
-						sizeof(struct ipa_filter_rule_type_v01));
-					pos++;
-				}
-				else
-				{
-					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
-				}
-			}
-		}
-
-		if(rule_table_v6 != NULL)
-		{
-			for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
-			{
-				if (pos < QMI_IPA_MAX_FILTERS_V01)
-				{
-					qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
-					qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
-					qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
-					qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1;
-					qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
-					qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1;
-					qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id;
-					memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
-						&rule_table_v6->rules[cnt].rule.eq_attrib,
-						sizeof(struct ipa_filter_rule_type_v01));
-					pos++;
-				}
-				else
-				{
-					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
-				}
-			}
-		}
-
-		ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE, &qmi_rule_msg);
-		if (ret != 0)
-		{
-			IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_msg, ret);
+			IPACMERR("The number of filtering rules exceed limit.\n");
 			close(fd_wwan_ioctl);
 			return false;
 		}
-	}
+		else
+		{
+			if (num_rules > 0)
+			{
+				qmi_rule_msg.filter_spec_list_valid = true;
+			}
+			else
+			{
+				qmi_rule_msg.filter_spec_list_valid = false;
+			}
+
+			qmi_rule_msg.filter_spec_list_len = num_rules;
+			qmi_rule_msg.source_pipe_index_valid = 0;
+
+			IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
+
+			if(rule_table_v4 != NULL)
+			{
+				for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
+				{
+					if (pos < QMI_IPA_MAX_FILTERS_V01)
+					{
+						qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
+						qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
+						qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
+						qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1;
+						qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
+						qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1;
+						qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id;
+						memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
+							&rule_table_v4->rules[cnt].rule.eq_attrib,
+							sizeof(struct ipa_filter_rule_type_v01));
+						pos++;
+					}
+					else
+					{
+						IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
+					}
+				}
+			}
+
+			if(rule_table_v6 != NULL)
+			{
+				for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
+				{
+					if (pos < QMI_IPA_MAX_FILTERS_V01)
+					{
+						qmi_rule_msg.filter_spec_list[pos].filter_spec_identifier = pos;
+						qmi_rule_msg.filter_spec_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
+						qmi_rule_msg.filter_spec_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
+						qmi_rule_msg.filter_spec_list[pos].is_routing_table_index_valid = 1;
+						qmi_rule_msg.filter_spec_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
+						qmi_rule_msg.filter_spec_list[pos].is_mux_id_valid = 1;
+						qmi_rule_msg.filter_spec_list[pos].mux_id = mux_id;
+						memcpy(&qmi_rule_msg.filter_spec_list[pos].filter_rule,
+							&rule_table_v6->rules[cnt].rule.eq_attrib,
+							sizeof(struct ipa_filter_rule_type_v01));
+						pos++;
+					}
+					else
+					{
+						IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos);
+					}
+				}
+			}
+
+			ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE, &qmi_rule_msg);
+			if (ret != 0)
+			{
+				IPACMERR("Failed adding Filtering rule %p with ret %d\n ", &qmi_rule_msg, ret);
+				close(fd_wwan_ioctl);
+				return false;
+			}
+		}
 	/* if it is IPA v3, use new QMI format */
-#else
-	if(num_rules > QMI_IPA_MAX_FILTERS_EX_V01)
-	{
-		IPACMERR("The number of filtering rules exceed limit.\n");
-		close(fd_wwan_ioctl);
-		return false;
 	}
 	else
 	{
-		memset(&qmi_rule_ex_msg, 0, sizeof(qmi_rule_ex_msg));
-
-		if (num_rules > 0)
+		if(num_rules > QMI_IPA_MAX_FILTERS_EX_V01)
 		{
-			qmi_rule_ex_msg.filter_spec_ex_list_valid = true;
-		}
-		else
-		{
-			qmi_rule_ex_msg.filter_spec_ex_list_valid = false;
-		}
-		qmi_rule_ex_msg.filter_spec_ex_list_len = num_rules;
-		qmi_rule_ex_msg.source_pipe_index_valid = 0;
-
-		IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
-
-		if(rule_table_v4 != NULL)
-		{
-			for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
-			{
-				if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
-				{
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v4->rules[cnt].rule.rule_id;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v4->rules[cnt].rule.hashable;
-					memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
-						&rule_table_v4->rules[cnt].rule.eq_attrib,
-						sizeof(struct ipa_filter_rule_type_v01));
-
-					pos++;
-				}
-				else
-				{
-					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
-				}
-			}
-		}
-
-		if(rule_table_v6 != NULL)
-		{
-			for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
-			{
-				if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
-				{
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v6->rules[cnt].rule.rule_id;
-					qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v6->rules[cnt].rule.hashable;
-					memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
-						&rule_table_v6->rules[cnt].rule.eq_attrib,
-						sizeof(struct ipa_filter_rule_type_v01));
-
-					pos++;
-				}
-				else
-				{
-					IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
-				}
-			}
-		}
-
-		ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_EX, &qmi_rule_ex_msg);
-		if (ret != 0)
-		{
-			IPACMERR("Failed adding Filtering rule %pK with ret %d\n ", &qmi_rule_ex_msg, ret);
+			IPACMERR("The number of filtering rules exceed limit.\n");
 			close(fd_wwan_ioctl);
 			return false;
 		}
+		else
+		{
+			memset(&qmi_rule_ex_msg, 0, sizeof(qmi_rule_ex_msg));
+
+			if (num_rules > 0)
+			{
+				qmi_rule_ex_msg.filter_spec_ex_list_valid = true;
+			}
+			else
+			{
+				qmi_rule_ex_msg.filter_spec_ex_list_valid = false;
+			}
+			qmi_rule_ex_msg.filter_spec_ex_list_len = num_rules;
+			qmi_rule_ex_msg.source_pipe_index_valid = 0;
+
+			IPACMDBG_H("Get %d WAN DL filtering rules in total.\n", num_rules);
+
+			if(rule_table_v4 != NULL)
+			{
+				for(cnt = rule_table_v4->num_rules - 1; cnt >= 0; cnt--)
+				{
+					if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
+					{
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v4->rules[cnt].rule.action);
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v4->rules[cnt].rule.rt_tbl_idx;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v4->rules[cnt].rule.rule_id;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v4->rules[cnt].rule.hashable;
+						memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
+							&rule_table_v4->rules[cnt].rule.eq_attrib,
+							sizeof(struct ipa_filter_rule_type_v01));
+
+						pos++;
+					}
+					else
+					{
+						IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
+					}
+				}
+			}
+
+			if(rule_table_v6 != NULL)
+			{
+				for(cnt = rule_table_v6->num_rules - 1; cnt >= 0; cnt--)
+				{
+					if (pos < QMI_IPA_MAX_FILTERS_EX_V01)
+					{
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_action = GetQmiFilterAction(rule_table_v6->rules[cnt].rule.action);
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].is_routing_table_index_valid = 1;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].route_table_index = rule_table_v6->rules[cnt].rule.rt_tbl_idx;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].is_mux_id_valid = 1;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].mux_id = mux_id;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].rule_id = rule_table_v6->rules[cnt].rule.rule_id;
+						qmi_rule_ex_msg.filter_spec_ex_list[pos].is_rule_hashable = rule_table_v6->rules[cnt].rule.hashable;
+						memcpy(&qmi_rule_ex_msg.filter_spec_ex_list[pos].filter_rule,
+							&rule_table_v6->rules[cnt].rule.eq_attrib,
+							sizeof(struct ipa_filter_rule_type_v01));
+
+						pos++;
+					}
+					else
+					{
+						IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_EX_V01, pos);
+					}
+				}
+			}
+
+			ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_FLT_RULE_EX, &qmi_rule_ex_msg);
+			if (ret != 0)
+			{
+				IPACMERR("Failed adding Filtering rule %pK with ret %d\n ", &qmi_rule_ex_msg, ret);
+				close(fd_wwan_ioctl);
+				return false;
+			}
+		}
 	}
-#endif
 
 	close(fd_wwan_ioctl);
 	return true;
diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp
index ec4a9ea..0d4f54f 100644
--- a/ipacm/src/IPACM_Iface.cpp
+++ b/ipacm/src/IPACM_Iface.cpp
@@ -133,9 +133,8 @@
 	flt_rule_entry.flt_rule_hdl = -1;
 	flt_rule_entry.status = -1;
 	flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-	flt_rule_entry.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule_entry.rule.hashable = true;
 	memcpy(&flt_rule_entry.rule.attrib,
 				 &rx_prop->rx[0].attrib,
 				 sizeof(flt_rule_entry.rule.attrib));
@@ -772,10 +771,11 @@
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = false;
-		flt_rule_entry.rule.hashable = false;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = false;
+			flt_rule_entry.rule.hashable = false;
+		}
 		IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
 		memcpy(&flt_rule_entry.rule.attrib,
 					 &rx_prop->rx[0].attrib,
@@ -791,19 +791,21 @@
 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = true;
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = true;
+			flt_rule_entry.rule.hashable = true;
+		}
 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
 
 		/* Configuring Broadcast Filtering Rule */
 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = true;
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = true;
+			flt_rule_entry.rule.hashable = true;
+		}
 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
 
 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
@@ -886,10 +888,11 @@
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = true;
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = true;
+			flt_rule_entry.rule.hashable = true;
+		}
 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
 
 		/* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
@@ -901,10 +904,11 @@
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = true;
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = true;
+			flt_rule_entry.rule.hashable = true;
+		}
 		memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
 
 		/* Configuring fec0::/10 Reserved by IETF Filtering Rule */
@@ -916,10 +920,11 @@
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = true;
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = true;
+			flt_rule_entry.rule.hashable = true;
+		}
 		memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
 
 		/* Configuring fd00::/8 Unique Local Ipv6 Address */
@@ -931,22 +936,20 @@
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = true;
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = true;
+			flt_rule_entry.rule.hashable = true;
+		}
 		memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
 
 #ifdef FEATURE_IPA_ANDROID
-		/* Add the ipv6 tcp fragment filtering rule. */
+		/* Add the ipv6 tcp/udp fragment filtering rule for MTU */
 
-		IPACMDBG_H("Adding IPv6 TCP fragment filter rule\n");
+		IPACMDBG_H("Adding IPv6 fragment filter rule\n");
 
 		flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_DST_ADDR);
 
-		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
-		flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
-
 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
 
 		memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry,
@@ -967,11 +970,10 @@
 
 		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
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
+			else
+				flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14);
 			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;
@@ -982,11 +984,10 @@
 		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
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
+		else
+			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
 		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/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index 3e825dd..2857f39 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -406,9 +406,8 @@
 				IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, wl);
 #endif
 				IPACM_EvtDispatcher::registr(IPA_PRIVATE_SUBNET_CHANGE_EVENT, wl); 	// register for IPA_PRIVATE_SUBNET_CHANGE_EVENT event
-#ifdef FEATURE_ETH_BRIDGE_LE
-				IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, wl);
-#endif
+				if (IPACM_Iface::ipacmcfg->isEthBridgingSupported())
+					IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, wl);
 				IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, wl);
 				IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, wl);
 #ifndef FEATURE_IPA_ANDROID
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index 755d730..0a532fd 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -129,8 +129,8 @@
 
 	memset(ipv4_icmp_flt_rule_hdl, 0, NUM_IPV4_ICMP_FLT_RULE * sizeof(uint32_t));
 
-	memset(private_fl_rule_hdl, 0, IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(uint32_t));
-	memset(ipv6_prefix_flt_rule_hdl, 0, NUM_IPV6_PREFIX_FLT_RULE * sizeof(uint32_t));
+	memset(private_fl_rule_hdl, 0, (IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) * sizeof(uint32_t));
+	memset(ipv6_prefix_flt_rule_hdl, 0, (NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE) * sizeof(uint32_t));
 	memset(ipv6_icmp_flt_rule_hdl, 0, NUM_IPV6_ICMP_FLT_RULE * sizeof(uint32_t));
 	memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
 
@@ -342,20 +342,21 @@
 			}
 #endif
 
-#ifdef FEATURE_ETH_BRIDGE_LE
-			if(rx_prop != NULL)
+			if (IPACM_Iface::ipacmcfg->isEthBridgingSupported())
 			{
-				free(rx_prop);
+				if(rx_prop != NULL)
+				{
+					free(rx_prop);
+				}
+				if(tx_prop != NULL)
+				{
+					free(tx_prop);
+				}
+				if(iface_query != NULL)
+				{
+					free(iface_query);
+				}
 			}
-			if(tx_prop != NULL)
-			{
-				free(tx_prop);
-			}
-			if(iface_query != NULL)
-			{
-				free(iface_query);
-			}
-#endif
 			delete this;
 		}
 		break;
@@ -881,6 +882,11 @@
 		{
 			memcpy(ipv6_prefix, data_wan->ipv6_prefix, sizeof(ipv6_prefix));
 			install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix);
+
+			/* MTU might have changed. Need to update ipv4 MTU rule if up */
+			if (IPACM_Wan::isWanUP(ipa_if_num))
+				handle_private_subnet_android(IPA_IP_v4);
+
 			if (data_wan->backhaul_type == Q6_WAN)
 			{
 				ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
@@ -1268,12 +1274,15 @@
 			return IPACM_FAILURE;
 		}
 		flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01;
-#ifndef FEATURE_IPA_V3
-		flt_index.filter_index_list_len = 0;
-#else /* defined (FEATURE_IPA_V3) */
-		flt_index.rule_id_valid = 1;
-		flt_index.rule_id_len = 0;
-#endif
+		if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_index.filter_index_list_len = 0;
+		}
+		else /* IPAv3 */
+		{
+			flt_index.rule_id_valid = 1;
+			flt_index.rule_id_len = 0;
+		}
 		flt_index.embedded_pipe_index_valid = 1;
 		flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD);
 		if ((int)flt_index.embedded_pipe_index == -1)
@@ -1306,6 +1315,9 @@
 		sta_ul_v4_set = false;
 	}
 
+	/* clean MTU rules if needed */
+	handle_private_subnet_android(IPA_IP_v4);
+
 	close(fd);
 	return IPACM_SUCCESS;
 }
@@ -1363,9 +1375,8 @@
 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
 		rt_rule_entry->rule.attrib.u.v4.dst_addr      = data->ipv4_addr;
 		rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-		rt_rule_entry->rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			rt_rule_entry->rule.hashable = true;
 		if (false == m_routing.AddRoutingRule(rt_rule))
 		{
 			IPACMERR("Routing rule addition failed!\n");
@@ -1441,9 +1452,8 @@
 		ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1];
 		ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2];
 		ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3];
-#ifdef FEATURE_IPA_V3
-		rt_rule_entry->rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			rt_rule_entry->rule.hashable = true;
 		if (false == m_routing.AddRoutingRule(rt_rule))
 		{
 			IPACMERR("Routing rule addition failed!\n");
@@ -1573,9 +1583,8 @@
 			flt_rule_entry.flt_rule_hdl = -1;
 			flt_rule_entry.status = -1;
 			flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-			flt_rule_entry.rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				flt_rule_entry.rule.hashable = true;
                         /* Support private subnet feature including guest-AP can't talk to primary AP etc */
 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl;
 			IPACMDBG_H(" private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name);
@@ -1644,6 +1653,18 @@
 
 	if(ip_type == IPA_IP_v4)
 	{
+		/* add MTU rules for ipv4 */
+		handle_private_subnet_android(IPA_IP_v4);
+
+		/* Update ipv6 MTU here if WAN_v6 is up and filter rules were installed */
+		if (IPACM_Wan::isWanUP_V6(ipa_if_num))
+		{
+			if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1] ) {
+				delete_ipv6_prefix_flt_rule();
+				install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
+			}
+		}
+
 		if(sta_ul_v4_set == true)
 		{
 			IPACMDBG_H("Filetring rule for IPV4 of STA mode is already configured, sta_ul_v4_set: %d\n",sta_ul_v4_set);
@@ -1687,9 +1708,8 @@
 		{
 			flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING
 		}
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl;
 
 		memcpy(&flt_rule_entry.rule.attrib,
@@ -1776,9 +1796,8 @@
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_v6.hdl;
 
 		memcpy(&flt_rule_entry.rule.attrib,
@@ -1886,6 +1905,18 @@
 		ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id);
 		modem_ul_v6_set = true;
 	} else if (iptype ==IPA_IP_v4 && modem_ul_v4_set == false) {
+		/* add MTU rules for ipv4 */
+		handle_private_subnet_android(IPA_IP_v4);
+
+		/* Update ipv6 MTU here if WAN_v6 is up and filter rules were installed */
+		if (IPACM_Wan::isWanUP_V6(ipa_if_num))
+		{
+			if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1] ) {
+				delete_ipv6_prefix_flt_rule();
+				install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
+			}
+		}
+
 		IPACMDBG_H("check getXlat_Mux_Id:%d\n", IPACM_Wan::getXlat_Mux_Id());
 		IPACMDBG_H("IPA_IP_v4 xlat_mux_id: %d, modem_ul_v4_set %d\n", xlat_mux_id, modem_ul_v4_set);
 		ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id);
@@ -2426,9 +2457,8 @@
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-					rt_rule_entry->rule.hashable = true;
-#endif
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						rt_rule_entry->rule.hashable = true;
 			if (false == m_routing.AddRoutingRule(rt_rule))
 			{
 				IPACMERR("Routing rule addition failed!\n");
@@ -2458,9 +2488,8 @@
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-					rt_rule_entry->rule.hashable = true;
-#endif
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						rt_rule_entry->rule.hashable = true;
 		            if (false == m_routing.AddRoutingRule(rt_rule))
 		            {
 							IPACMERR("Routing rule addition failed!\n");
@@ -2741,9 +2770,8 @@
 		{
 			rt_rule_entry->rule.attrib.u.v4.dst_addr      = 0;
 			rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0;
-#ifdef FEATURE_IPA_V3
-			rt_rule_entry->rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				rt_rule_entry->rule.hashable = true;
 			if (false == m_routing.AddRoutingRule(rt_rule))
 			{
 				IPACMERR("Routing rule addition failed!\n");
@@ -2766,9 +2794,8 @@
 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
-#ifdef FEATURE_IPA_V3
-			rt_rule_entry->rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				rt_rule_entry->rule.hashable = true;
 			if (false == m_routing.AddRoutingRule(rt_rule))
 			{
 				IPACMERR("Routing rule addition failed!\n");
@@ -3059,13 +3086,13 @@
 		}
 
 #ifdef FEATURE_IPA_ANDROID
-		if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES) == false)
+		if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) == false)
 		{
 			IPACMERR("Error deleting private subnet IPv4 flt rules.\n");
 			res = IPACM_FAILURE;
 			goto fail;
 		}
-		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES);
+		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES);
 #else
 		if (m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet) == false)
 		{
@@ -3249,25 +3276,25 @@
 			IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);
 			IPACMDBG_H("Finished delete dependency \n ");
 		}
-#ifndef FEATURE_ETH_BRIDGE_LE
-		free(rx_prop);
-#endif
+		if (!(IPACM_Iface::ipacmcfg->isEthBridgingSupported()))
+				free(rx_prop);
 	}
 
 	if (eth_client != NULL)
 	{
 		free(eth_client);
 	}
-#ifndef FEATURE_ETH_BRIDGE_LE
-	if (tx_prop != NULL)
+	if (!(IPACM_Iface::ipacmcfg->isEthBridgingSupported()))
 	{
-		free(tx_prop);
+		if (tx_prop != NULL)
+		{
+			free(tx_prop);
+		}
+		if (iface_query != NULL)
+		{
+			free(iface_query);
+		}
 	}
-	if (iface_query != NULL)
-	{
-		free(iface_query);
-	}
-#endif
 	is_active = false;
 	post_del_self_evt();
 
@@ -3324,12 +3351,15 @@
 	}
 
 	flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01;
-#ifndef FEATURE_IPA_V3
-	flt_index.filter_index_list_len = prop->num_ext_props;
-#else /* defined (FEATURE_IPA_V3) */
-	flt_index.rule_id_valid = 1;
-	flt_index.rule_id_len = prop->num_ext_props;
-#endif
+	if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
+	{
+		flt_index.filter_index_list_len = prop->num_ext_props;
+	}
+	else /* IPAv3 */
+	{
+		flt_index.rule_id_valid = 1;
+		flt_index.rule_id_len = prop->num_ext_props;
+	}
 	flt_index.embedded_pipe_index_valid = 1;
 	flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD);
 	if ((int)flt_index.embedded_pipe_index == -1)
@@ -3345,13 +3375,16 @@
 	qmap_id = IPACM_Iface::ipacmcfg->GetQmapId();
 	xlat_debug = IPACM_Wan::getXlat_Mux_Id();
 	flt_index.embedded_call_mux_id = qmap_id;
-#ifndef FEATURE_IPA_V3
-	IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d, xlat_mux id: %d, wan-debug %d\n",
-		flt_index.source_pipe_index, flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id, xlat_mux_id, xlat_debug);
-#else /* defined (FEATURE_IPA_V3) */
-	IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d, xlat_mux id: %d, wan-debug %d\n",
-		flt_index.source_pipe_index, flt_index.rule_id_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id, xlat_mux_id, xlat_debug);
-#endif
+	if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
+	{
+		IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d, xlat_mux id: %d, wan-debug %d\n",
+			flt_index.source_pipe_index, flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id, xlat_mux_id, xlat_debug);
+	}
+	else /* IPAv3 */
+	{
+		IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d, xlat_mux id: %d, wan-debug %d\n",
+			flt_index.source_pipe_index, flt_index.rule_id_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id, xlat_mux_id, xlat_debug);
+	}
 	len = sizeof(struct ipa_ioc_add_flt_rule) + prop->num_ext_props * sizeof(struct ipa_flt_rule_add);
 	pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len);
 	if (pFilteringTable == NULL)
@@ -3370,10 +3403,9 @@
 
 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields
 	flt_rule_entry.at_rear = 1;
-#ifdef FEATURE_IPA_V3
-	if (flt_rule_entry.rule.eq_attrib.ipv4_frag_eq_present)
-		flt_rule_entry.at_rear = 0;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		if (flt_rule_entry.rule.eq_attrib.ipv4_frag_eq_present)
+			flt_rule_entry.at_rear = 0;
 	flt_rule_entry.flt_rule_hdl = -1;
 	flt_rule_entry.status = -1;
 
@@ -3450,25 +3482,28 @@
 		{
 			flt_rule_entry.rule.eq_attrib.num_offset_meq_32++;
 			eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_32 - 1;
-#ifdef FEATURE_IPA_V3
-			if(eq_index == 0)
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
 			{
-				flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<5);
+				if(eq_index == 0)
+				{
+					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<5);
+				}
+				else
+				{
+					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<6);
+				}
 			}
 			else
 			{
-				flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<6);
+				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);
+				}
 			}
-#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;
@@ -3486,88 +3521,95 @@
 			{
 				flt_rule_entry.rule.eq_attrib.num_offset_meq_128++;
 				eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_128 - 1;
-#ifdef FEATURE_IPA_V3
-				if(eq_index == 0)
+				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
 				{
-					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<3);
+					if(eq_index == 0)
+					{
+						flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<3);
+					}
+					else
+					{
+						flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<4);
+					}
+					*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 0)
+							= 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[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
 				{
-					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<4);
+					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);
+					}
+					*(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].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].mask + 0)
-						= 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[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
-				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);
-				}
-				*(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].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];
-#endif
 				flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].offset = 8;
 			}
 			else
 			{
 				IPACMERR("Run out of MEQ128 equation.\n");
-				flt_rule_entry.rule.eq_attrib.num_offset_meq_128--;
+					flt_rule_entry.rule.eq_attrib.num_offset_meq_128--;
 			}
 		}
-#endif
 
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = prop->prop[cnt].is_rule_hashable;
-		flt_rule_entry.rule.rule_id = prop->prop[cnt].rule_id;
-		if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)	//turn on meta-data equation
-		{
-			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
-			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;
-			flt_rule_entry.rule.eq_attrib.metadata_meq32.mask |= rx_prop->rx[0].attrib.meta_data_mask;
-		}
 #endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.rule.hashable = prop->prop[cnt].is_rule_hashable;
+			flt_rule_entry.rule.rule_id = prop->prop[cnt].rule_id;
+			if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)	//turn on meta-data equation
+			{
+				flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
+				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;
+				flt_rule_entry.rule.eq_attrib.metadata_meq32.mask |= rx_prop->rx[0].attrib.meta_data_mask;
+			}
+		}
 		memcpy(&pFilteringTable->rules[cnt], &flt_rule_entry, sizeof(flt_rule_entry));
 
 		IPACMDBG_H("Modem UL filtering rule %d has index %d\n", cnt, index);
-#ifndef FEATURE_IPA_V3
-		flt_index.filter_index_list[cnt].filter_index = index;
-		flt_index.filter_index_list[cnt].filter_handle = prop->prop[cnt].filter_hdl;
-#else /* defined (FEATURE_IPA_V3) */
-		flt_index.rule_id[cnt] = prop->prop[cnt].rule_id;
-#endif
+		if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_index.filter_index_list[cnt].filter_index = index;
+			flt_index.filter_index_list[cnt].filter_handle = prop->prop[cnt].filter_hdl;
+		}
+		else /* IPAv3 */
+		{
+			flt_index.rule_id[cnt] = prop->prop[cnt].rule_id;
+		}
 		index++;
 	}
 
@@ -3685,12 +3727,15 @@
 			return IPACM_FAILURE;
 		}
 		flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01;
-#ifndef FEATURE_IPA_V3
-		flt_index.filter_index_list_len = 0;
-#else /* defined (FEATURE_IPA_V3) */
-		flt_index.rule_id_valid = 1;
-		flt_index.rule_id_len = 0;
-#endif
+		if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_index.filter_index_list_len = 0;
+		}
+		else /* IPAv3 */
+		{
+			flt_index.rule_id_valid = 1;
+			flt_index.rule_id_len = 0;
+		}
 		flt_index.embedded_pipe_index_valid = 1;
 		flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD);
 		if ((int)flt_index.embedded_pipe_index == -1)
@@ -3915,9 +3960,8 @@
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
 
 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
@@ -3988,9 +4032,8 @@
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = false;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = false;
 		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
 		flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
@@ -4044,7 +4087,7 @@
 	ipa_ioc_add_flt_rule* pFilteringTable;
 	bool result;
 
-	len = sizeof(struct ipa_ioc_add_flt_rule) +	IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(struct ipa_flt_rule_add);
+	len = sizeof(struct ipa_ioc_add_flt_rule) + (IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) * sizeof(struct ipa_flt_rule_add);
 
 	pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len);
 	if (pFilteringTable == NULL)
@@ -4058,7 +4101,7 @@
 	pFilteringTable->ep = rx_prop->rx[0].src_pipe;
 	pFilteringTable->global = false;
 	pFilteringTable->ip = iptype;
-	pFilteringTable->num_rules = IPA_MAX_PRIVATE_SUBNET_ENTRIES;
+	pFilteringTable->num_rules = IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES;
 
 	memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add));
 
@@ -4067,9 +4110,8 @@
 	flt_rule.flt_rule_hdl = -1;
 	flt_rule.status = -1;
 	flt_rule.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-	flt_rule.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule.rule.hashable = true;
 	memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib,
 			sizeof(flt_rule.rule.attrib));
 
@@ -4081,7 +4123,7 @@
 		flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0;
 		flt_rule.rule.attrib.u.v4.dst_addr = ~0;
 
-		for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
+		for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES; i++)
 		{
 			memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add));
 		}
@@ -4107,9 +4149,9 @@
 		}
 		else
 		{
-			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES);
+			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES);
 			/* copy filter rule hdls */
-			for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
+			for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES; i++)
 			{
 				if (pFilteringTable->rules[i].status == 0)
 				{
@@ -4135,6 +4177,9 @@
 	int i, len, res = IPACM_SUCCESS;
 	struct ipa_flt_rule_mdfy flt_rule;
 	struct ipa_ioc_mdfy_flt_rule* pFilteringTable;
+	int mtu_rule_cnt = 0;
+	uint16_t mtu[IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES] = { };
+	int mtu_rule_idx = IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
 
 	if (rx_prop == NULL)
 	{
@@ -4149,12 +4194,24 @@
 	}
 	else
 	{
-		for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
+		for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES; i++)
 		{
 			reset_to_dummy_flt_rule(IPA_IP_v4, private_fl_rule_hdl[i]);
 		}
 
-		len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_mdfy);
+		/* check how many MTU rules we need to add */
+		for(i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++)
+		{
+			mtu[i] = IPACM_Wan::queryMTU(ipa_if_num, IPA_IP_v4);
+
+			if (mtu[i] > 0)
+				mtu_rule_cnt++;
+			else
+				IPACMERR("MTU is zero\n");
+		}
+		IPACMDBG_H("total %d MTU rules are needed\n", mtu_rule_cnt);
+
+		len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet + mtu_rule_cnt) * sizeof(struct ipa_flt_rule_mdfy);
 		pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len);
 		if (!pFilteringTable)
 		{
@@ -4165,7 +4222,7 @@
 
 		pFilteringTable->commit = 1;
 		pFilteringTable->ip = iptype;
-		pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
+		pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet + mtu_rule_cnt;
 
 		/* Make LAN-traffic always go A5, use default IPA-RT table */
 		if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4))
@@ -4185,16 +4242,32 @@
 		flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl;
 		IPACMDBG_H("Private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name);
 
-		memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib));
-		flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
-
 		for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++)
 		{
+			/* add private subnet rule for ipv4 */
+			flt_rule.rule.action = IPA_PASS_TO_ROUTING;
+			flt_rule.rule.eq_attrib_type = 0;
 			flt_rule.rule_hdl = private_fl_rule_hdl[i];
+			memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib));
+			flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 			flt_rule.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask;
 			flt_rule.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr;
 			memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy));
 			IPACMDBG_H(" IPACM private subnet_addr as: 0x%x entry(%d)\n", flt_rule.rule.attrib.u.v4.dst_addr, i);
+
+			/* add corresponding MTU rule for ipv4 */
+			if (mtu[i] > 0)
+			{
+				flt_rule.rule_hdl = private_fl_rule_hdl[mtu_rule_idx + i];
+				memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib));
+				flt_rule.rule.attrib.u.v4.src_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask;
+				flt_rule.rule.attrib.u.v4.src_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr;
+				flt_rule.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
+				if (construct_mtu_rule(&flt_rule.rule, IPA_IP_v4, mtu[i]))
+					IPACMERR("Failed to modify MTU filtering rule.\n");
+				memcpy(&(pFilteringTable->rules[mtu_rule_idx + i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy));
+				IPACMDBG_H("Adding MTU rule for private subnet 0x%x.\n", flt_rule.rule.attrib.u.v4.src_addr);
+			}
 		}
 
 		if (false == m_filtering.ModifyFilteringRule(pFilteringTable))
@@ -4225,12 +4298,17 @@
 	struct ipa_ioc_add_flt_rule* flt_rule;
 	struct ipa_flt_rule_add flt_rule_entry;
 	bool result;
+	int rule_cnt = 1;
+
+	uint16_t mtu = IPACM_Wan::queryMTU(ipa_if_num, IPA_IP_v6);
+	if (mtu > 0)
+		rule_cnt ++;
 
 	if(rx_prop != NULL)
 	{
-		len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
+		len = sizeof(struct ipa_ioc_add_flt_rule) + rule_cnt * sizeof(struct ipa_flt_rule_add);
 
-		flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
+		flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(rule_cnt, len);
 		if (!flt_rule)
 		{
 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
@@ -4241,7 +4319,7 @@
 		flt_rule->ep = rx_prop->rx[0].src_pipe;
 		flt_rule->global = false;
 		flt_rule->ip = IPA_IP_v6;
-		flt_rule->num_rules = 1;
+		flt_rule->num_rules = rule_cnt;
 
 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
 
@@ -4252,9 +4330,8 @@
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[0];
@@ -4267,6 +4344,30 @@
 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x0;
 		memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
 
+		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); // this will remove the IPA_FLT_DST_ADDR
+		flt_rule_entry.rule.attrib.u.v6.src_addr[3] = prefix[0];
+		flt_rule_entry.rule.attrib.u.v6.src_addr[2] = prefix[1];
+		flt_rule_entry.rule.attrib.u.v6.src_addr[1] = 0x0;
+		flt_rule_entry.rule.attrib.u.v6.src_addr[0] = 0x0;
+		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[3] = 0xFFFFFFFF;
+		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[2] = 0xFFFFFFFF;
+		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[1] = 0x0;
+		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[0] = 0x0;
+		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
+
+		/* Add an MTU rule with every new private prefix */
+		if (mtu > 0)
+		{
+			if (construct_mtu_rule(&flt_rule_entry.rule, IPA_IP_v6, mtu))
+			{
+				IPACMERR("Failed to add MTU filtering rule.\n")
+			}
+			else
+			{
+				memcpy(&(flt_rule->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
+			}
+		}
+
 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
 		/* use index hw-counter */
 		if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
@@ -4288,9 +4389,14 @@
 		}
 		else
 		{
-			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
+			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 2);
 			ipv6_prefix_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl;
 			IPACMDBG_H("IPv6 prefix filter rule HDL:0x%x\n", ipv6_prefix_flt_rule_hdl[0]);
+			if (rule_cnt > 1)
+			{
+				ipv6_prefix_flt_rule_hdl[1] = flt_rule->rules[1].flt_rule_hdl;
+				IPACMDBG_H("IPv6 prefix MTU filter rule HDL:0x%x\n", ipv6_prefix_flt_rule_hdl[1]);
+			}
 			free(flt_rule);
 		}
 	}
@@ -4299,12 +4405,12 @@
 
 void IPACM_Lan::delete_ipv6_prefix_flt_rule()
 {
-	if(m_filtering.DeleteFilteringHdls(ipv6_prefix_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE) == false)
+	if(m_filtering.DeleteFilteringHdls(ipv6_prefix_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE) == false)
 	{
-		IPACMERR("Failed to delete ipv6 prefix flt rule.\n");
+		IPACMERR("Failed to delete ipv6 prefix flt rules.\n");
 		return;
 	}
-	IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE);
+	IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE + NUM_IPV6_PREFIX_MTU_RULE);
 	return;
 }
 
@@ -4939,9 +5045,8 @@
 	rt_rule.at_rear = false;
 	rt_rule.status = -1;
 	rt_rule.rt_rule_hdl = -1;
-#ifdef FEATURE_IPA_V3
-	rt_rule.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		rt_rule.rule.hashable = true;
 	rt_rule.rule.hdr_hdl = 0;
 	rt_rule.rule.hdr_proc_ctx_hdl = hdr_proc_ctx_hdl;
 
@@ -5073,9 +5178,8 @@
 
 			rt_rule_entry->rule.hdr_hdl = 0;
 			rt_rule_entry->rule.hdr_proc_ctx_hdl = hdr_proc_ctx_hdl;
-#ifdef FEATURE_IPA_V3
-			rt_rule_entry->rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				rt_rule_entry->rule.hashable = true;
 			memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[index].attrib,
 					sizeof(rt_rule_entry->rule.attrib));
 			if(peer_l2_hdr_type == IPA_HDR_L2_ETHERNET_II)
@@ -5114,90 +5218,92 @@
 int IPACM_Lan::eth_bridge_add_flt_rule(uint8_t *mac, uint32_t rt_tbl_hdl, ipa_ip_type iptype, uint32_t *flt_rule_hdl)
 {
 	int res = IPACM_SUCCESS;
-
-	IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-	IPACMDBG_H("Received rt_tbl_hdl :%d iptype %d\n", rt_tbl_hdl,iptype);
-	*flt_rule_hdl = 0;
-
-#ifdef FEATURE_IPA_V3
 	int len;
 	struct ipa_flt_rule_add flt_rule_entry;
 	struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL;
 	bool result;
 
-	if (rx_prop == NULL || tx_prop == NULL)
+	IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	IPACMDBG_H("Received rt_tbl_hdl :%d iptype %d\n", rt_tbl_hdl,iptype);
+	*flt_rule_hdl = 0;
+
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
 	{
-		IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
-		return IPACM_FAILURE;
-	}
+		if (rx_prop == NULL || tx_prop == NULL)
+		{
+			IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
+			return IPACM_FAILURE;
+		}
 
 
-	len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
-	pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
-	if (!pFilteringTable)
-	{
-		IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
-		return IPACM_FAILURE;
-	}
-	memset(pFilteringTable, 0, len);
+		len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
+		pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
+		if (!pFilteringTable)
+		{
+			IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
+			return IPACM_FAILURE;
+		}
+		memset(pFilteringTable, 0, len);
 
-	/* add mac based rule*/
-	pFilteringTable->commit = 1;
-	pFilteringTable->ep = rx_prop->rx[0].src_pipe;
-	pFilteringTable->ip = iptype;
-	pFilteringTable->num_rules = 1;
-	pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[iptype];
+		/* add mac based rule*/
+		pFilteringTable->commit = 1;
+		pFilteringTable->ep = rx_prop->rx[0].src_pipe;
+		pFilteringTable->ip = iptype;
+		pFilteringTable->num_rules = 1;
+		pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[iptype];
 
-	memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
-	flt_rule_entry.at_rear = 1;
+		memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
+		flt_rule_entry.at_rear = 1;
 
-	flt_rule_entry.rule.retain_hdr = 0;
-	flt_rule_entry.rule.to_uc = 0;
-	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-	flt_rule_entry.rule.eq_attrib_type = 0;
-	flt_rule_entry.rule.rt_tbl_hdl = rt_tbl_hdl;
-	flt_rule_entry.rule.hashable = true;
+		flt_rule_entry.rule.retain_hdr = 0;
+		flt_rule_entry.rule.to_uc = 0;
+		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+		flt_rule_entry.rule.eq_attrib_type = 0;
+		flt_rule_entry.rule.rt_tbl_hdl = rt_tbl_hdl;
+		flt_rule_entry.rule.hashable = true;
 
-	memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
-	if(tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_ETHERNET_II)
-	{
-		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
+		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
+		if(tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_ETHERNET_II)
+		{
+			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
+		}
+		else
+		{
+			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
+		}
+
+		memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
+		memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
+
+		memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
+#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
+		/* use index hw-counter */
+		if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
+		{
+			IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL);
+			result = m_filtering.AddFilteringRuleAfter_hw_index(pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL);
+		} else {
+			result = m_filtering.AddFilteringRuleAfter(pFilteringTable);
+		}
+#else
+		result = m_filtering.AddFilteringRuleAfter(pFilteringTable);
+#endif
+		if (result == false)
+		{
+			IPACMERR("Failed to add client filtering rules.\n");
+			res = IPACM_FAILURE;
+			goto end;
+		}
+		*flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
+
+end:
+		free(pFilteringTable);
 	}
 	else
 	{
-		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
+		IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+		IPACMDBG_H("Not support rt_tbl_hdl %d flt_rule_hdl %p ip-type %d\n", rt_tbl_hdl, flt_rule_hdl, iptype);
 	}
-
-	memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
-	memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
-
-	memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
-#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
-	/* use index hw-counter */
-	if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
-	{
-		IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL);
-		result = m_filtering.AddFilteringRuleAfter_hw_index(pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL);
-	} else {
-		result = m_filtering.AddFilteringRuleAfter(pFilteringTable);
-	}
-#else
-	result = m_filtering.AddFilteringRuleAfter(pFilteringTable);
-#endif
-	if (result == false)
-	{
-		IPACMERR("Failed to add client filtering rules.\n");
-		res = IPACM_FAILURE;
-		goto end;
-	}
-	*flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
-
-end:
-	free(pFilteringTable);
-#else
-	IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-	IPACMDBG_H("Not support rt_tbl_hdl %d flt_rule_hdl %p ip-type %d\n", rt_tbl_hdl, flt_rule_hdl, iptype);
-#endif
 	return res;
 }
 
@@ -5798,78 +5904,79 @@
 	struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL;
 	ipa_ioc_get_rt_tbl rt_tbl;
 
-#ifdef FEATURE_IPA_V3
-	if (rx_prop == NULL || tx_prop == NULL)
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
 	{
-		IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
-		return IPACM_FAILURE;
-	}
+		if (rx_prop == NULL || tx_prop == NULL)
+		{
+			IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
+			return IPACM_FAILURE;
+		}
 
-	len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
-	pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
-	if (!pFilteringTable)
-	{
-		IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
-		return IPACM_FAILURE;
-	}
-	memset(pFilteringTable, 0, len);
+		len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
+		pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
+		if (!pFilteringTable)
+		{
+			IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
+			return IPACM_FAILURE;
+		}
+		memset(pFilteringTable, 0, len);
 
-	pFilteringTable->commit = 1;
-	pFilteringTable->ep = rx_prop->rx[0].src_pipe;
-	pFilteringTable->ip = IPA_IP_v6;
-	pFilteringTable->num_rules = 1;
-	pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[IPA_IP_v6];
+		pFilteringTable->commit = 1;
+		pFilteringTable->ep = rx_prop->rx[0].src_pipe;
+		pFilteringTable->ip = IPA_IP_v6;
+		pFilteringTable->num_rules = 1;
+		pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[IPA_IP_v6];
 
-	fd_ipa = open(IPA_DEVICE_NAME, O_RDWR);
-	if(fd_ipa == 0)
-	{
-		IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME);
-		free(pFilteringTable);
-		return IPACM_FAILURE;
-	}
+		fd_ipa = open(IPA_DEVICE_NAME, O_RDWR);
+		if(fd_ipa == 0)
+		{
+			IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME);
+			free(pFilteringTable);
+			return IPACM_FAILURE;
+		}
 
-	rt_tbl.ip = IPA_IP_v6;
-	snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
-	rt_tbl.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
-	IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
-	if(m_routing.GetRoutingTable(&rt_tbl) == false)
-	{
-		IPACMERR("Failed to get routing table from name\n");
+		rt_tbl.ip = IPA_IP_v6;
+		snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
+		rt_tbl.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
+		IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
+		if(m_routing.GetRoutingTable(&rt_tbl) == false)
+		{
+			IPACMERR("Failed to get routing table from name\n");
+			free(pFilteringTable);
+			close(fd_ipa);
+			return IPACM_FAILURE;
+		}
+
+		memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
+		flt_rule_entry.at_rear = 1;
+
+		flt_rule_entry.rule.retain_hdr = 0;
+		flt_rule_entry.rule.to_uc = 0;
+		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+		flt_rule_entry.rule.eq_attrib_type = 0;
+		flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
+		flt_rule_entry.rule.hashable = false;	//ETH->WLAN direction rules need to be non-hashable due to encapsulation
+
+		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
+
+		/* flt rule is matching dst MAC within 62 bytes header */
+		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_L2TP;
+		memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
+		memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, dst_mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
+
+		memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
+		if(m_filtering.AddFilteringRuleAfter(pFilteringTable) == false)
+		{
+			IPACMERR("Failed to add client filtering rules.\n");
+			free(pFilteringTable);
+			close(fd_ipa);
+			return IPACM_FAILURE;
+		}
+		*flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
+
 		free(pFilteringTable);
 		close(fd_ipa);
-		return IPACM_FAILURE;
 	}
-
-	memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
-	flt_rule_entry.at_rear = 1;
-
-	flt_rule_entry.rule.retain_hdr = 0;
-	flt_rule_entry.rule.to_uc = 0;
-	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-	flt_rule_entry.rule.eq_attrib_type = 0;
-	flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
-	flt_rule_entry.rule.hashable = false;	//ETH->WLAN direction rules need to be non-hashable due to encapsulation
-
-	memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
-
-	/* flt rule is matching dst MAC within 62 bytes header */
-	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_L2TP;
-	memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
-	memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, dst_mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
-
-	memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
-	if(m_filtering.AddFilteringRuleAfter(pFilteringTable) == false)
-	{
-		IPACMERR("Failed to add client filtering rules.\n");
-		free(pFilteringTable);
-		close(fd_ipa);
-		return IPACM_FAILURE;
-	}
-	*flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
-
-	free(pFilteringTable);
-	close(fd_ipa);
-#endif
 	return IPACM_SUCCESS;
 }
 
@@ -5893,122 +6000,123 @@
 	struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL;
 	ipa_ioc_get_rt_tbl rt_tbl;
 
-#ifdef FEATURE_IPA_V3
-	if (rx_prop == NULL || tx_prop == NULL)
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
 	{
-		IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
-		return IPACM_FAILURE;
-	}
+		if (rx_prop == NULL || tx_prop == NULL)
+		{
+			IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
+			return IPACM_FAILURE;
+		}
 
-	IPACMDBG_H("Dst client MAC 0x%02x%02x%02x%02x%02x%02x.\n", dst_mac[0], dst_mac[1],
-		dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]);
+		IPACMDBG_H("Dst client MAC 0x%02x%02x%02x%02x%02x%02x.\n", dst_mac[0], dst_mac[1],
+			dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5]);
 
-	len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
-	pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
-	if (!pFilteringTable)
-	{
-		IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
-		return IPACM_FAILURE;
-	}
-	memset(pFilteringTable, 0, len);
+		len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
+		pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
+		if (!pFilteringTable)
+		{
+			IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
+			return IPACM_FAILURE;
+		}
+		memset(pFilteringTable, 0, len);
 
-	pFilteringTable->commit = 1;
-	pFilteringTable->ep = rx_prop->rx[0].src_pipe;
-	pFilteringTable->ip = iptype;
-	pFilteringTable->num_rules = 1;
-	pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[iptype];
+		pFilteringTable->commit = 1;
+		pFilteringTable->ep = rx_prop->rx[0].src_pipe;
+		pFilteringTable->ip = iptype;
+		pFilteringTable->num_rules = 1;
+		pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[iptype];
 
-	/* =========== add first pass flt rule (match dst MAC) ============= */
-	rt_tbl.ip = iptype;
-	snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
-	IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
+		/* =========== add first pass flt rule (match dst MAC) ============= */
+		rt_tbl.ip = iptype;
+		snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
+		IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
 
-	if(m_routing.GetRoutingTable(&rt_tbl) == false)
-	{
-		IPACMERR("Failed to get routing table.\n");
-		return IPACM_FAILURE;
-	}
+		if(m_routing.GetRoutingTable(&rt_tbl) == false)
+		{
+			IPACMERR("Failed to get routing table.\n");
+			return IPACM_FAILURE;
+		}
 
-	memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
-	flt_rule_entry.at_rear = 1;
+		memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
+		flt_rule_entry.at_rear = 1;
 
-	flt_rule_entry.rule.retain_hdr = 0;
-	flt_rule_entry.rule.to_uc = 0;
-	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-	flt_rule_entry.rule.eq_attrib_type = 0;
-	flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
-	flt_rule_entry.rule.hashable = false;	//WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction
+		flt_rule_entry.rule.retain_hdr = 0;
+		flt_rule_entry.rule.to_uc = 0;
+		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+		flt_rule_entry.rule.eq_attrib_type = 0;
+		flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
+		flt_rule_entry.rule.hashable = false;	//WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction
 
-	memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
-	if(tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_ETHERNET_II)
-	{
-		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
-	}
-	else
-	{
-		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
-	}
+		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
+		if(tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_ETHERNET_II)
+		{
+			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
+		}
+		else
+		{
+			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
+		}
 
-	memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, dst_mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
-	memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
+		memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, dst_mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
+		memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
 
-	memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
-	if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable))
-	{
-		IPACMERR("Failed to add first pass filtering rules.\n");
+		memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
+		if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable))
+		{
+			IPACMERR("Failed to add first pass filtering rules.\n");
+			free(pFilteringTable);
+			return IPACM_FAILURE;
+		}
+		*first_pass_flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
+
+		/* =========== add second pass flt rule (match VLAN interface IPv6 address at client side) ============= */
+		if(*second_pass_flt_rule_hdl != 0)
+		{
+			IPACMDBG_H("Second pass flt rule was added before, return.\n");
+			free(pFilteringTable);
+			return IPACM_SUCCESS;
+		}
+
+		rt_tbl.ip = IPA_IP_v6;
+		snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
+		IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
+
+		if(m_routing.GetRoutingTable(&rt_tbl) == false)
+		{
+			IPACMERR("Failed to get routing table.\n");
+			return IPACM_FAILURE;
+		}
+
+		pFilteringTable->ip = IPA_IP_v6;
+		pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[IPA_IP_v6];
+
+		memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
+		flt_rule_entry.at_rear = 1;
+
+		flt_rule_entry.rule.retain_hdr = 0;
+		flt_rule_entry.rule.to_uc = 0;
+		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
+		flt_rule_entry.rule.eq_attrib_type = 0;
+		flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
+		flt_rule_entry.rule.hashable = false;	//WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction
+
+		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
+		flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
+
+		memcpy(flt_rule_entry.rule.attrib.u.v6.dst_addr, vlan_client_ipv6_addr, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr));
+		memset(flt_rule_entry.rule.attrib.u.v6.dst_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr_mask));
+
+		memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
+		if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable))
+		{
+			IPACMERR("Failed to add client filtering rules.\n");
+			free(pFilteringTable);
+			return IPACM_FAILURE;
+		}
+		*second_pass_flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
+
 		free(pFilteringTable);
-		return IPACM_FAILURE;
 	}
-	*first_pass_flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
-
-	/* =========== add second pass flt rule (match VLAN interface IPv6 address at client side) ============= */
-	if(*second_pass_flt_rule_hdl != 0)
-	{
-		IPACMDBG_H("Second pass flt rule was added before, return.\n");
-		free(pFilteringTable);
-		return IPACM_SUCCESS;
-	}
-
-	rt_tbl.ip = IPA_IP_v6;
-	snprintf(rt_tbl.name, sizeof(rt_tbl.name), "l2tp");
-	IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
-
-	if(m_routing.GetRoutingTable(&rt_tbl) == false)
-	{
-		IPACMERR("Failed to get routing table.\n");
-		return IPACM_FAILURE;
-	}
-
-	pFilteringTable->ip = IPA_IP_v6;
-	pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[IPA_IP_v6];
-
-	memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
-	flt_rule_entry.at_rear = 1;
-
-	flt_rule_entry.rule.retain_hdr = 0;
-	flt_rule_entry.rule.to_uc = 0;
-	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-	flt_rule_entry.rule.eq_attrib_type = 0;
-	flt_rule_entry.rule.rt_tbl_hdl = rt_tbl.hdl;
-	flt_rule_entry.rule.hashable = false;	//WLAN->ETH direction rules are set to non-hashable to keep consistent with the other direction
-
-	memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
-	flt_rule_entry.rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
-
-	memcpy(flt_rule_entry.rule.attrib.u.v6.dst_addr, vlan_client_ipv6_addr, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr));
-	memset(flt_rule_entry.rule.attrib.u.v6.dst_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.u.v6.dst_addr_mask));
-
-	memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
-	if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable))
-	{
-		IPACMERR("Failed to add client filtering rules.\n");
-		free(pFilteringTable);
-		return IPACM_FAILURE;
-	}
-	*second_pass_flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
-
-	free(pFilteringTable);
-#endif
 	return IPACM_SUCCESS;
 }
 
@@ -6231,9 +6339,8 @@
 	flt_rule_entry.rule.to_uc = 0;
 	flt_rule_entry.rule.eq_attrib_type = 1;
 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-	flt_rule_entry.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule_entry.rule.hashable = true;
 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 	flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = get_client_memptr(eth_client, client_index)->v6_addr[v6_num][0];
 	flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, client_index)->v6_addr[v6_num][1];
@@ -6336,3 +6443,63 @@
 	}
 	return res;
 }
+
+int IPACM_Lan::construct_mtu_rule(struct ipa_flt_rule *rule, ipa_ip_type iptype, uint16_t mtu)
+{
+	int res = IPACM_SUCCESS;
+	int fd;
+	ipa_ioc_generate_flt_eq flt_eq;
+
+	if (rule == NULL)
+	{
+		IPACMERR("rule is empty");
+		return IPACM_FAILURE;
+	}
+
+	if (mtu == 0)
+	{
+		IPACMERR("mtu is uninitialized");
+		return IPACM_FAILURE;
+	}
+
+	IPACMDBG_H("Adding MTU rule for iptype = %d\n", iptype);
+
+	rule->eq_attrib_type = 1;
+	rule->eq_attrib.rule_eq_bitmap = 0;
+	rule->action = IPA_PASS_TO_EXCEPTION;
+
+	/* generate eq */
+	memset(&flt_eq, 0, sizeof(flt_eq));
+	memcpy(&flt_eq.attrib, &rule->attrib, sizeof(flt_eq.attrib));
+	flt_eq.ip = iptype;
+
+	fd = open(IPA_DEVICE_NAME, O_RDWR);
+	if (fd < 0)
+	{
+		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
+		return IPACM_FAILURE;
+	}
+
+	if (0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct
+	{
+		IPACMERR("Failed to get eq_attrib\n");
+		res = IPACM_FAILURE;
+		goto fail;
+	}
+	memcpy(&rule->eq_attrib,
+		&flt_eq.eq_attrib, sizeof(rule->eq_attrib));
+
+	//add IHL offsets
+	rule->eq_attrib.rule_eq_bitmap |= (1<<10);
+	rule->eq_attrib.num_ihl_offset_range_16 = 1;
+	if (iptype == IPA_IP_v4)
+		rule->eq_attrib.ihl_offset_range_16[0].offset = 0x82;
+	else
+		rule->eq_attrib.ihl_offset_range_16[0].offset = 0x84;
+	rule->eq_attrib.ihl_offset_range_16[0].range_low = mtu + 1;
+	rule->eq_attrib.ihl_offset_range_16[0].range_high = UINT16_MAX; //0xFFFF
+
+fail:
+	close(fd);
+	return res;
+}
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index afdf26d..696f518 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -951,11 +951,11 @@
 	IPACMDBG_H(" START IPACM_OffloadManager and link to android framework\n");
 #endif
 
-#ifdef FEATURE_ETH_BRIDGE_LE
-	IPACM_LanToLan* lan2lan = IPACM_LanToLan::get_instance();
-	IPACMDBG_H("Staring IPACM_LanToLan instance %p\n", lan2lan);
-#endif
-
+	if (IPACM_Iface::ipacmcfg->isEthBridgingSupported())
+	{
+		IPACM_LanToLan* lan2lan = IPACM_LanToLan::get_instance();
+		IPACMDBG_H("Staring IPACM_LanToLan instance %p\n", lan2lan);
+	}
 	CtList = new IPACM_ConntrackListener();
 
 	IPACMDBG_H("Staring IPA main\n");
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index db0304a..847e08d 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -52,6 +52,7 @@
 #include "linux/ipa_qmi_service_v01.h"
 #ifdef FEATURE_IPACM_HAL
 #include "IPACM_OffloadManager.h"
+#include <IPACM_Netlink.h>
 #endif
 
 bool IPACM_Wan::wan_up = false;
@@ -91,6 +92,8 @@
 int	IPACM_Wan::ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES];
 #endif
 
+uint16_t IPACM_Wan::mtu_default_wan = DEFAULT_MTU_SIZE;
+
 IPACM_Wan::IPACM_Wan(int iface_index,
 	ipacm_wan_iface_type is_sta_mode,
 	uint8_t *mac_addr) : IPACM_Iface(iface_index)
@@ -129,6 +132,7 @@
 	ext_prop = NULL;
 	is_ipv6_frag_firewall_flt_rule_installed = false;
 	ipv6_frag_firewall_flt_rule_hdl = 0;
+	mtu_size = DEFAULT_MTU_SIZE;
 
 	num_wan_client = 0;
 	header_name_count = 0;
@@ -291,9 +295,8 @@
 		ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1];
 		ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2];
 		ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3];
-#ifdef FEATURE_IPA_V3
-		rt_rule_entry->rule.hashable = false;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			rt_rule_entry->rule.hashable = false;
 		if(m_is_sta_mode == Q6_WAN)
 		{
 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
@@ -487,9 +490,8 @@
 				flt_rule_entry.flt_rule_hdl = -1;
 				flt_rule_entry.status = -1;
 				flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-				flt_rule_entry.rule.hashable = true;
-#endif
+				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+					flt_rule_entry.rule.hashable = true;
 				memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
 
 				flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
@@ -595,9 +597,8 @@
 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
 		rt_rule_entry->rule.attrib.u.v4.dst_addr      = data->ipv4_addr;
 		rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-		rt_rule_entry->rule.hashable = false;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			rt_rule_entry->rule.hashable = false;
 		if(m_is_sta_mode == Q6_WAN)
 		{
 			/* query qmap header*/
@@ -850,9 +851,8 @@
 			ipv6_addr[0][1] = data->ipv6_addr[1];
 			ipv6_addr[0][2] = data->ipv6_addr[2];
 			ipv6_addr[0][3] = data->ipv6_addr[3];
-#ifdef FEATURE_IPA_V3
-			rt_rule_entry->rule.hashable = false;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				rt_rule_entry->rule.hashable = false;
 			if (false == m_routing.AddRoutingRule(rt_rule))
 			{
 				IPACMERR("Routing rule addition failed!\n");
@@ -931,9 +931,8 @@
 			strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
 			rt_rule_entry->rule.attrib.u.v4.dst_addr      = data->ipv4_addr;
 			rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-			rt_rule_entry->rule.hashable = false;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				rt_rule_entry->rule.hashable = false;
 			if (false == m_routing.AddRoutingRule(rt_rule))
 			{
 				IPACMERR("Routing rule addition failed!\n");
@@ -1818,6 +1817,9 @@
 	}
 	IPACMDBG_H("backhaul_is_wan_bridge ?: %d \n", IPACM_Wan::backhaul_is_wan_bridge);
 
+	/* query MTU size of the interface */
+	query_mtu_size();
+
 	if (m_is_sta_mode ==Q6_WAN)
 	{
 		IPACM_Wan::backhaul_mode = m_is_sta_mode;
@@ -1980,9 +1982,8 @@
 			{
 				rt_rule_entry->rule.attrib.u.v4.dst_addr      = 0;
 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0;
-#ifdef FEATURE_IPA_V3
-				rt_rule_entry->rule.hashable = true;
-#endif
+				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+					rt_rule_entry->rule.hashable = true;
 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
 				/* use index hw-counter */
 				if((m_is_sta_mode == WLAN_WAN) && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
@@ -1990,7 +1991,7 @@
 					IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW);
 					result = m_routing.AddRoutingRule_hw_index(rt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW);
 				} else {
-					result = m_routing.AddRoutingRule(rt_rule);			
+					result = m_routing.AddRoutingRule(rt_rule);
 				}
 #else
 				result = m_routing.AddRoutingRule(rt_rule);
@@ -2017,9 +2018,8 @@
 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
 				rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
-#ifdef FEATURE_IPA_V3
-				rt_rule_entry->rule.hashable = true;
-#endif
+				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+					rt_rule_entry->rule.hashable = true;
 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
 				/* use index hw-counter */
 				if((m_is_sta_mode == WLAN_WAN) && IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
@@ -2091,9 +2091,8 @@
 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
-#ifdef FEATURE_IPA_V3
-		rt_rule_entry->rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			rt_rule_entry->rule.hashable = true;
 		if (false == m_routing.AddRoutingRule(rt_rule))
 		{
 			IPACMERR("Routing rule addition failed!\n");
@@ -2105,6 +2104,11 @@
 				wan_route_rule_v6_hdl_a5[0], 0, iptype);
 	}
 
+	/* set mtu_default_wan to current default wan instance */
+	mtu_default_wan = mtu_size;
+
+	IPACMDBG_H("replace the mtu_default_wan to %d\n", mtu_default_wan);
+
 	ipacm_event_iface_up *wanup_data;
 	wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up));
 	if (wanup_data == NULL)
@@ -2218,8 +2222,9 @@
 			IPACMDBG_H("dev %s add producer dependency\n", dev_name);
 			IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
 			IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
+	}
 #ifdef WAN_IOC_NOTIFY_WAN_STATE
-	} else {
+	else {
 			if ((m_is_sta_mode == Q6_WAN && ipa_pm_q6_check == 0 ) || (m_is_sta_mode == Q6_MHI_WAN))
 			{
 				fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
@@ -2240,9 +2245,8 @@
 			ipa_pm_q6_check++;
 			IPACMDBG_H("update ipa_pm_q6_check to %d\n", ipa_pm_q6_check);
 	}
-#else
-	}
 #endif
+
 	if(rt_rule != NULL)
 	{
 		free(rt_rule);
@@ -2579,10 +2583,11 @@
 
 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
 		flt_rule_entry.at_rear = true;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = false;
-		flt_rule_entry.rule.hashable = false;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = false;
+			flt_rule_entry.rule.hashable = false;
+		}
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
@@ -2674,10 +2679,11 @@
 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
 				}
             }
-#ifdef FEATURE_IPA_V3
-			flt_rule_entry.at_rear = true;
-			flt_rule_entry.rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			{
+				flt_rule_entry.at_rear = true;
+				flt_rule_entry.rule.hashable = true;
+			}
 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
 			memcpy(&flt_rule_entry.rule.attrib,
 						 &rx_prop->rx[0].attrib,
@@ -2771,9 +2777,8 @@
 			        {
 			            flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
                     }
-#ifdef FEATURE_IPA_V3
-					flt_rule_entry.rule.hashable = true;
-#endif
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						flt_rule_entry.rule.hashable = true;
 					memcpy(&flt_rule_entry.rule.attrib,
 								 &firewall_config.extd_firewall_entries[i].attrib,
 								 sizeof(struct ipa_rule_attrib));
@@ -2941,9 +2946,8 @@
 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
 				}
             }
-#ifdef FEATURE_IPA_V3
-			flt_rule_entry.rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				flt_rule_entry.rule.hashable = true;
 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.hdl;
 			memcpy(&flt_rule_entry.rule.attrib,
 						 &rx_prop->rx[0].attrib,
@@ -3008,9 +3012,8 @@
 				flt_rule_entry.rule.retain_hdr = 1;
 				flt_rule_entry.rule.eq_attrib_type = 0;
 				flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-			flt_rule_entry.rule.hashable = true;
-#endif
+				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+					flt_rule_entry.rule.hashable = true;
 				memcpy(&flt_rule_entry.rule.attrib,
 						&rx_prop->rx[0].attrib,
 						sizeof(struct ipa_rule_attrib));
@@ -3081,9 +3084,8 @@
 			  flt_rule_entry.at_rear = true;
 			  flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
 			}
-#ifdef FEATURE_IPA_V3
-			flt_rule_entry.rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				flt_rule_entry.rule.hashable = true;
 			memcpy(&flt_rule_entry.rule.attrib,
 						 &rx_prop->rx[0].attrib,
 						 sizeof(struct ipa_rule_attrib));
@@ -3171,10 +3173,9 @@
 			            {
 					flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
                                     }
-#ifdef FEATURE_IPA_V3
-					flt_rule_entry.rule.hashable = true;
-#endif
-		    			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						flt_rule_entry.rule.hashable = true;
+		    		flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl;
 					memcpy(&flt_rule_entry.rule.attrib,
 								 &firewall_config.extd_firewall_entries[i].attrib,
 								 sizeof(struct ipa_rule_attrib));
@@ -3292,9 +3293,8 @@
 			flt_rule_entry.rule.retain_hdr = 1;
 			flt_rule_entry.rule.eq_attrib_type = 0;
 			flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-			flt_rule_entry.rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				flt_rule_entry.rule.hashable = true;
 			memcpy(&flt_rule_entry.rule.attrib,
 					 &rx_prop->rx[0].attrib,
 					 sizeof(struct ipa_rule_attrib));
@@ -3356,9 +3356,8 @@
 			  flt_rule_entry.at_rear = true;
 			  flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
                         }
-#ifdef FEATURE_IPA_V3
-			flt_rule_entry.rule.hashable = true;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				flt_rule_entry.rule.hashable = true;
 			memcpy(&flt_rule_entry.rule.attrib,
 						 &rx_prop->rx[0].attrib,
 						 sizeof(struct ipa_rule_attrib));
@@ -3455,9 +3454,8 @@
 	{
 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
 		flt_rule_entry.at_rear = true;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = false;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.at_rear = false;
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 
@@ -3465,10 +3463,11 @@
 		flt_rule_entry.rule.to_uc = 0;
 		flt_rule_entry.rule.eq_attrib_type = 1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.at_rear = false;
-		flt_rule_entry.rule.hashable = false;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		{
+			flt_rule_entry.at_rear = false;
+			flt_rule_entry.rule.hashable = false;
+		}
 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
 		rt_tbl_idx.ip = IPA_IP_v6;
 		strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX);
@@ -3534,9 +3533,8 @@
 					{
 						flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
 					}
-#ifdef FEATURE_IPA_V3
-					flt_rule_entry.rule.hashable = true;
-#endif
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						flt_rule_entry.rule.hashable = true;
 					memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
 					rt_tbl_idx.ip = iptype;
 					if(flt_rule_entry.rule.action == IPA_PASS_TO_ROUTING)
@@ -3671,9 +3669,8 @@
 				flt_rule_entry.rule.action = IPA_PASS_TO_DST_NAT;
 			}
 		}
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
 		rt_tbl_idx.ip = iptype;
 
@@ -3746,9 +3743,8 @@
 					flt_rule_entry.rule.to_uc = 0;
 					flt_rule_entry.rule.eq_attrib_type = 1;
 					flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-					flt_rule_entry.rule.hashable = true;
-#endif
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						flt_rule_entry.rule.hashable = true;
 					memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
 					rt_tbl_idx.ip = iptype;
 
@@ -3859,9 +3855,8 @@
 		flt_rule_entry.rule.to_uc = 0;
 		flt_rule_entry.rule.eq_attrib_type = 1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx));
 		rt_tbl_idx.ip = iptype;
 		/* firewall disable, all traffic are allowed */
@@ -4013,9 +4008,8 @@
 		flt_rule_entry.rule.to_uc = 0;
 		flt_rule_entry.rule.eq_attrib_type = 1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
 
 		/* Configuring ICMP filtering rule */
@@ -4131,9 +4125,8 @@
 		flt_rule_entry.rule.to_uc = 0;
 		flt_rule_entry.rule.eq_attrib_type = 1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
 
 		/* Configuring ICMP filtering rule */
@@ -4213,15 +4206,18 @@
 
 		for (cnt = 0; cnt < ext_prop->num_ext_props; cnt++)
 		{
-#ifndef FEATURE_IPA_V3
-			IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d flt_hdl: %d\n",
-				cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action,
-				ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].filter_hdl);
-#else /* defined (FEATURE_IPA_V3) */
-			IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d rule_id: %d\n",
-				cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action,
-				ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].rule_id);
-#endif
+			if (!IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			{
+				IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d flt_hdl: %d\n",
+					cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action,
+					ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].filter_hdl);
+			}
+			else /* IPA_V3 */
+			{
+				IPACMDBG_H("Ex(%d): ip-type: %d, mux_id: %d, flt_action: %d\n, rt_tbl_idx: %d, is_xlat_rule: %d rule_id: %d\n",
+					cnt, ext_prop->ext[cnt].ip, ext_prop->ext[cnt].mux_id, ext_prop->ext[cnt].action,
+					ext_prop->ext[cnt].rt_tbl_idx, ext_prop->ext[cnt].is_xlat_rule, ext_prop->ext[cnt].rule_id);
+			}
 		}
 
 		if(IPACM_Wan::is_ext_prop_set == false)
@@ -4334,9 +4330,8 @@
 		flt_rule_entry.rule.to_uc = 0;
 		flt_rule_entry.rule.eq_attrib_type = 1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
 
 		IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
@@ -4417,9 +4412,8 @@
 		flt_rule_entry.rule.to_uc = 0;
 		flt_rule_entry.rule.eq_attrib_type = 1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
 
 		/* Configuring Multicast Filtering Rule */
@@ -4616,11 +4610,10 @@
 		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
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
+		else
+			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
 		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;
 
@@ -4989,8 +4982,9 @@
 			IPACMDBG_H("dev %s delete producer dependency\n", dev_name);
 			IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
 			IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
+		}
 #ifdef WAN_IOC_NOTIFY_WAN_STATE
-		} else {
+		else {
 			IPACMDBG_H("ipa_pm_q6_check to %d\n", ipa_pm_q6_check);
 			if(ipa_pm_q6_check == 1)
 			{
@@ -5012,8 +5006,6 @@
 			else
 				IPACMERR(" ipa_pm_q6_check becomes negative !!!\n");
 		}
-#else
-}
 #endif
 		/* Delete the default route*/
 		if (iptype == IPA_IP_v6)
@@ -5131,9 +5123,8 @@
 	flt_rule_entry.rule.to_uc = 0;
 	flt_rule_entry.rule.eq_attrib_type = 1;
 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-	flt_rule_entry.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule_entry.rule.hashable = true;
 	flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
 
 	memcpy(&flt_rule_entry.rule.attrib,
@@ -5180,9 +5171,8 @@
 	flt_rule_entry.rule.to_uc = 0;
 	flt_rule_entry.rule.eq_attrib_type = 1;
 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-	flt_rule_entry.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule_entry.rule.hashable = true;
 	flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
 
 	memcpy(&flt_rule_entry.rule.attrib,
@@ -5554,6 +5544,9 @@
 		goto fail;
 	}
 
+	/* reset the mtu size */
+	mtu_size = DEFAULT_MTU_SIZE;
+
 	if(ip_type == IPA_IP_v4)
 	{
 		num_ipv4_modem_pdn--;
@@ -5912,9 +5905,8 @@
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 
 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
 
@@ -5974,9 +5966,8 @@
 		flt_rule_entry.flt_rule_hdl = -1;
 		flt_rule_entry.status = -1;
 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-		flt_rule_entry.rule.hashable = true;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.hashable = true;
 		flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx;
 		memcpy(&flt_rule_entry.rule.attrib,
 					&rx_prop->rx[0].attrib,
@@ -6604,9 +6595,8 @@
 				rt_rule_entry->rule.hdr_hdl = get_client_memptr(wan_client, wan_index)->hdr_hdl_v4;
 				rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(wan_client, wan_index)->v4_addr;
 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-				rt_rule_entry->rule.hashable = true;
-#endif
+				if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+					rt_rule_entry->rule.hashable = true;
 				if (false == m_routing.AddRoutingRule(rt_rule))
 				{
 					IPACMERR("Routing rule addition failed!\n");
@@ -6654,9 +6644,8 @@
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-					rt_rule_entry->rule.hashable = true;
-#endif
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						rt_rule_entry->rule.hashable = true;
 					if (false == m_routing.AddRoutingRule(rt_rule))
 					{
 						IPACMERR("Routing rule addition failed!\n");
@@ -7230,9 +7219,8 @@
 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
 		rt_rule_entry->rule.attrib.u.v4.dst_addr = wan_v4_addr;
 		rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-		rt_rule_entry->rule.hashable = false;
-#endif
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			rt_rule_entry->rule.hashable = false;
 		/* query qmap header*/
 		memset(&hdr, 0, sizeof(hdr));
 		strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
@@ -7362,9 +7350,8 @@
 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-			rt_rule_entry->rule.hashable = false;
-#endif
+			if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+				rt_rule_entry->rule.hashable = false;
 			strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
 			hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0';
 			if(m_header.GetHeaderHandle(&hdr) == false)
@@ -7505,9 +7492,8 @@
 	flt_rule_entry.rule.to_uc = 0;
 	flt_rule_entry.rule.eq_attrib_type = 1;
 	flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-	flt_rule_entry.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule_entry.rule.hashable = true;
 	IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
 	memcpy(&flt_rule_entry.rule.attrib,
 				&rx_prop->rx[0].attrib,
@@ -7646,9 +7632,8 @@
 	flt_rule_entry.flt_rule_hdl = -1;
 	flt_rule_entry.status = -1;
 	flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
-#ifdef FEATURE_IPA_V3
-	flt_rule_entry.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule_entry.rule.hashable = true;
 	IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
 	memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
@@ -7819,11 +7804,10 @@
 		sizeof(flt_rule_entry.rule.eq_attrib));
 
 	/* set the bit mask to use MEQ32_IHL offset */
-	#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
+		if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
+		else
+			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
 
 	/* add offset to compare TCP flags */
 	flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
@@ -7913,3 +7897,33 @@
 	}
 	return res;
 }
+
+int IPACM_Wan::query_mtu_size()
+{
+	int fd;
+	struct ifreq if_mtu;
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if ( fd < 0 ) {
+		IPACMERR("ipacm: socket open failed [%d]\n", fd);
+		return IPACM_FAILURE;
+	}
+
+	strlcpy(if_mtu.ifr_name, dev_name, IFNAMSIZ);
+	IPACMDBG_H("device name: %s\n", dev_name);
+	if_mtu.ifr_name[IFNAMSIZ - 1] = '\0';
+
+	if ( ioctl(fd, SIOCGIFMTU, &if_mtu) < 0 ) {
+		IPACMERR("ioctl failed to get mtu\n");
+		close(fd);
+		return IPACM_FAILURE;
+	}
+	IPACMDBG_H("mtu=[%d]\n", if_mtu.ifr_mtu);
+	if (if_mtu.ifr_mtu < DEFAULT_MTU_SIZE) {
+		mtu_size = if_mtu.ifr_mtu;
+		IPACMDBG_H("replaced mtu=[%d] for (%s)\n", mtu_size, dev_name);
+	}
+
+	close(fd);
+	return IPACM_SUCCESS;
+}
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index 395f951..689cc78 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -206,20 +206,21 @@
 
 			IPACMDBG_H("Received IPA_LAN_DELETE_SELF event.\n");
 			IPACMDBG_H("ipa_WLAN (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
-#ifdef FEATURE_ETH_BRIDGE_LE
-			if(rx_prop != NULL)
+			if (IPACM_Iface::ipacmcfg->isEthBridgingSupported())
 			{
-				free(rx_prop);
+				if(rx_prop != NULL)
+				{
+					free(rx_prop);
+				}
+				if(tx_prop != NULL)
+				{
+					free(tx_prop);
+				}
+				if(iface_query != NULL)
+				{
+					free(iface_query);
+				}
 			}
-			if(tx_prop != NULL)
-			{
-				free(tx_prop);
-			}
-			if(iface_query != NULL)
-			{
-				free(iface_query);
-			}
-#endif
 			delete this;
 		}
 		break;
@@ -1633,9 +1634,8 @@
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-					rt_rule_entry->rule.hashable = true;
-#endif
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						rt_rule_entry->rule.hashable = true;
 					if (false == m_routing.AddRoutingRule(rt_rule))
 					{
 						IPACMERR("Routing rule addition failed!\n");
@@ -1685,9 +1685,8 @@
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
-#ifdef FEATURE_IPA_V3
-					rt_rule_entry->rule.hashable = true;
-#endif
+					if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+						rt_rule_entry->rule.hashable = true;
 #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO
 					/* use index hw-counter */
 					if(IPACM_Iface::ipacmcfg->hw_fnr_stats_support)
@@ -1955,16 +1954,16 @@
 		}
 		/* delete private-ipv4 filter rules */
 #ifdef FEATURE_IPA_ANDROID
-		if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES) == false)
+		if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) == false)
 		{
 			IPACMERR("Error deleting private subnet IPv4 flt rules.\n");
 			res = IPACM_FAILURE;
 			goto fail;
 		}
-		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES);
+		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES);
 #else
-		num_private_subnet_fl_rule = IPACM_Iface::ipacmcfg->ipa_num_private_subnet > IPA_MAX_PRIVATE_SUBNET_ENTRIES?
-			IPA_MAX_PRIVATE_SUBNET_ENTRIES : IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
+		num_private_subnet_fl_rule = IPACM_Iface::ipacmcfg->ipa_num_private_subnet > (IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES)?
+			(IPA_MAX_PRIVATE_SUBNET_ENTRIES + IPA_MAX_MTU_ENTRIES) : IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
 		if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, num_private_subnet_fl_rule) == false)
 		{
 			IPACMERR("Error deleting private subnet flt rules, aborting...\n");
@@ -2137,9 +2136,8 @@
 			IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);
 			IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);
 		}
-#ifndef FEATURE_ETH_BRIDGE_LE
-		free(rx_prop);
-#endif
+		if (!(IPACM_Iface::ipacmcfg->isEthBridgingSupported()))
+			free(rx_prop);
 	}
 
 	for (i = 0; i < num_wifi_client; i++)
@@ -2153,17 +2151,18 @@
 	{
 		free(wlan_client);
 	}
-#ifndef FEATURE_ETH_BRIDGE_LE
-	if (tx_prop != NULL)
+	if (!(IPACM_Iface::ipacmcfg->isEthBridgingSupported()))
 	{
-		free(tx_prop);
-	}
+		if (tx_prop != NULL)
+		{
+			free(tx_prop);
+		}
 
-	if (iface_query != NULL)
-	{
-		free(iface_query);
+		if (iface_query != NULL)
+		{
+			free(iface_query);
+		}
 	}
-#endif
 
 	is_active = false;
 	post_del_self_evt();
@@ -2504,9 +2503,8 @@
 	flt_rule_entry.rule.to_uc = 0;
 	flt_rule_entry.rule.eq_attrib_type = 1;
 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
-#ifdef FEATURE_IPA_V3
-	flt_rule_entry.rule.hashable = true;
-#endif
+	if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
+		flt_rule_entry.rule.hashable = true;
 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
 	flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][0];
 	flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][1];
diff --git a/ipacm_vendor_product.mk b/ipacm_vendor_product.mk
index 96c6116..9fe88b1 100644
--- a/ipacm_vendor_product.mk
+++ b/ipacm_vendor_product.mk
@@ -1,6 +1,43 @@
+TARGET_DISABLE_IPACM := false
+
 #IPACM_DATA
 IPACM_DATA += IPACM_cfg.xml
 IPACM_DATA += ipacm
 IPACM_DATA += ipacm.rc
 
+ifeq ($(TARGET_USES_QMAA),true)
+ifneq ($(TARGET_USES_QMAA_OVERRIDE_DATA),true)
+	TARGET_DISABLE_IPACM := true
+endif #TARGET_USES_QMAA_OVERRIDE_DATA
+endif #TARGET_USES_QMAA
+
+ifneq ($(TARGET_DISABLE_IPACM),true)
+ifneq ($(TARGET_HAS_LOW_RAM),true)
+BOARD_PLATFORM_LIST := msm8909
+BOARD_PLATFORM_LIST += msm8916
+BOARD_PLATFORM_LIST += msm8917
+BOARD_PLATFORM_LIST += qm215
+BOARD_IPAv3_LIST := msm8998
+BOARD_IPAv3_LIST += sdm845
+BOARD_IPAv3_LIST += sdm710
+BOARD_IPAv3_LIST += msmnile
+BOARD_IPAv3_LIST += kona
+BOARD_IPAv3_LIST += $(MSMSTEPPE)
+BOARD_IPAv3_LIST += $(TRINKET)
+BOARD_IPAv3_LIST += lito
+BOARD_IPAv3_LIST += atoll
+BOARD_IPAv3_LIST += bengal
+BOARD_ETH_BRIDGE_LIST := msmnile
+BOARD_ETH_BRIDGE_LIST += kona
+
+ifneq ($(call is-board-platform-in-list,$(BOARD_PLATFORM_LIST)),true)
+ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM)))
+ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH)))
+
 PRODUCT_PACKAGES += $(IPACM_DATA)
+
+endif # $(TARGET_ARCH)
+endif
+endif
+endif
+endif
\ No newline at end of file
diff --git a/ipanat/Android.bp b/ipanat/Android.bp
new file mode 100644
index 0000000..eefd266
--- /dev/null
+++ b/ipanat/Android.bp
@@ -0,0 +1,28 @@
+
+
+cc_library_shared {
+    name: "libipanat",
+
+     header_libs: ["device_kernel_headers"],
+
+    srcs: [
+        "src/ipa_nat_drv.c",
+        "src/ipa_nat_drvi.c",
+    ],
+
+   shared_libs:
+        ["libcutils",
+        "libdl",
+        "libbase",
+        "libutils",
+    ],
+    export_include_dirs: ["inc"],
+    vendor: true,
+    cflags: [
+        "-DDEBUG",
+        "-Wall",
+        "-Werror",
+    ] + ["-DFEATURE_IPA_ANDROID"],
+
+    clang: true,
+}
diff --git a/ipanat/inc/ipa_nat_drvi.h b/ipanat/inc/ipa_nat_drvi.h
index 8015c98..292a47b 100644
--- a/ipanat/inc/ipa_nat_drvi.h
+++ b/ipanat/inc/ipa_nat_drvi.h
@@ -30,9 +30,9 @@
 #ifndef IPA_NAT_DRVI_H
 #define IPA_NAT_DRVI_H
 
-#include <unistd.h>
 #include <stdio.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <linux/msm_ipa.h>
@@ -40,6 +40,7 @@
 #include <sys/inotify.h>
 #include <errno.h>
 #include <pthread.h>
+#include <unistd.h>
 
 #include "ipa_nat_logi.h"
 
diff --git a/ipanat/src/Android.mk b/ipanat/src/Android.mk
deleted file mode 100644
index aaa8409..0000000
--- a/ipanat/src/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-BOARD_PLATFORM_LIST := msm8909
-BOARD_PLATFORM_LIST += msm8916
-BOARD_PLATFORM_LIST += msm8917
-TARGET_DISABLE_IPANAT := false
-
-ifeq ($(TARGET_USES_QMAA),true)
-ifneq ($(TARGET_USES_QMAA_OVERRIDE_DATA),true)
-	TARGET_DISABLE_IPANAT := true
-endif #TARGET_USES_QMAA_OVERRIDE_DATA
-endif #TARGET_USES_QMAA
-
-ifneq ($(TARGET_DISABLE_IPANAT),true)
-ifneq ($(call is-board-platform-in-list,$(BOARD_PLATFORM_LIST)),true)
-ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM)))
-ifneq (, $(filter aarch64 arm arm64, $(TARGET_ARCH)))
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc
-LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
-
-LOCAL_SRC_FILES := ipa_nat_drv.c \
-                   ipa_nat_drvi.c
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../inc
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64
-LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib
-LOCAL_CFLAGS := -DDEBUG -Wall -Werror
-LOCAL_CFLAGS += -DFEATURE_IPA_ANDROID
-LOCAL_MODULE := libipanat
-LOCAL_MODULE_TAGS := optional
-LOCAL_PRELINK_MODULE := false
-LOCAL_CLANG := true
-include $(BUILD_SHARED_LIBRARY)
-
-endif # $(TARGET_ARCH)
-endif
-endif
-endif