code changes for IPACM support A2-power-collapse by add/delete
dependency between ifaces (A2/HSIC/ECM)

Change-Id: I19c420446271ecc61b89c0a4f2f60a0ded50ede3
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index 854d255..d9f8989 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -50,11 +50,32 @@
 	uint32_t ipv4_addr;
 }NonNatIfaces;
 
+/* for IPACM rm dependency use*/
+typedef struct _ipa_rm_client
+{
+    ipa_rm_resource_name producer_rm1; 
+    ipa_rm_resource_name consumer_rm1;
+    ipa_rm_resource_name producer_rm2; 
+    ipa_rm_resource_name consumer_rm2;
+    bool producer_up;
+    bool consumer_up;
+	bool rm_set;
+}ipa_rm_client;
+
 /* iface */
 class IPACM_Config
 {
 public:
 
+	/* IPACM ipa_client map to rm_resource*/
+	ipa_rm_resource_name ipa_client_rm_map_tbl[IPA_CLIENT_MAX];
+
+	/* IPACM monitored rm_depency table */
+	ipa_rm_client ipa_rm_tbl[IPA_MAX_RM_ENTRY];
+
+	/* IPACM rm_depency a2 endpoint check*/
+	int ipa_rm_a2_check;
+	
 	/* Store interested interface and their configuration from XML file */
 	ipa_ifi_dev_name_t *iface_table;
 
@@ -90,6 +111,7 @@
 	}
 
 	int GetAlgPorts(int nPorts, ipacm_alg *pAlgPorts);
+
 	inline int GetNatMaxEntries(void)
 	{
 		return ipa_nat_max_entries;
@@ -101,6 +123,11 @@
 	}
 	int GetNonNatIfaces(int nPorts, NonNatIfaces *ifaces);
 
+	/* for IPACM resource manager dependency usage */
+	void AddRmDepend(ipa_rm_resource_name rm1);
+ 
+	void DelRmDepend(ipa_rm_resource_name rm1);
+	
 private:
 	static IPACM_Config *pInstance;
 	IPACM_Config(void);
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 8dd465c..7def2e9 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -63,6 +63,7 @@
 #define IPA_MAX_IFACE_ENTRIES 15
 #define IPA_MAX_PRIVATE_SUBNET_ENTRIES 3
 #define IPA_MAX_ALG_ENTRIES 10
+#define IPA_MAX_RM_ENTRY 6
 
 #define V4_DEFAULT_ROUTE_TABLE_NAME  "ipa_dflt_rt"
 #define V4_LAN_ROUTE_TABLE_NAME  "COMRTBLLANv4"
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index 7834ae0..f75bd68 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -40,6 +40,8 @@
 #include <IPACM_Config.h>
 #include <IPACM_Log.h>
 #include <IPACM_Iface.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
 
 IPACM_Config *IPACM_Config::pInstance = NULL;
 
@@ -48,6 +50,9 @@
 	iface_table = NULL;
 	alg_table = NULL;
 	memset(&private_subnet_table, 0, sizeof(private_subnet_table));
+	memset(&ipa_client_rm_map_tbl, 0, sizeof(ipa_client_rm_map_tbl));
+	memset(&ipa_rm_tbl, 0, sizeof(ipa_rm_tbl));
+        ipa_rm_a2_check=0;
 
 	ipa_num_ipa_interfaces = 0;
 	ipa_num_private_subnet = 0;
@@ -170,6 +175,41 @@
 	rt_tbl_wan_v6.ip = IPA_IP_v6;
 	strncpy(rt_tbl_wan_v6.name, V6_WAN_ROUTE_TABLE_NAME, sizeof(rt_tbl_wan_v6.name));
 
+	/* Construct IPACM ipa_client map to rm_resource table */
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC1_PROD]= IPA_RM_RESOURCE_HSIC_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC2_PROD]= IPA_RM_RESOURCE_HSIC_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC3_PROD]= IPA_RM_RESOURCE_HSIC_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC4_PROD]= IPA_RM_RESOURCE_HSIC_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC5_PROD]= IPA_RM_RESOURCE_HSIC_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_USB_PROD]= IPA_RM_RESOURCE_USB_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_A5_WLAN_AMPDU_PROD]= IPA_RM_RESOURCE_HSIC_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_A2_EMBEDDED_PROD]= IPA_RM_RESOURCE_A2_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_A2_TETHERED_PROD]= IPA_RM_RESOURCE_A2_PROD;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC1_CONS]= IPA_RM_RESOURCE_HSIC_CONS;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC2_CONS]= IPA_RM_RESOURCE_HSIC_CONS;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC3_CONS]= IPA_RM_RESOURCE_HSIC_CONS;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC4_CONS]= IPA_RM_RESOURCE_HSIC_CONS;
+	ipa_client_rm_map_tbl[IPA_CLIENT_HSIC5_CONS]= IPA_RM_RESOURCE_HSIC_CONS;
+	ipa_client_rm_map_tbl[IPA_CLIENT_USB_CONS]= IPA_RM_RESOURCE_USB_CONS;
+	ipa_client_rm_map_tbl[IPA_CLIENT_A2_EMBEDDED_CONS]= IPA_RM_RESOURCE_A2_CONS;
+	ipa_client_rm_map_tbl[IPA_CLIENT_A2_TETHERED_CONS]= IPA_RM_RESOURCE_A2_CONS;	
+
+	/* Create the entries which IPACM wants to add dependencies on */ 
+	ipa_rm_tbl[0].producer_rm1 = IPA_RM_RESOURCE_HSIC_PROD;
+	ipa_rm_tbl[0].consumer_rm1 = IPA_RM_RESOURCE_A2_CONS;
+	ipa_rm_tbl[0].producer_rm2 = IPA_RM_RESOURCE_A2_PROD;
+	ipa_rm_tbl[0].consumer_rm2 = IPA_RM_RESOURCE_HSIC_CONS;
+	
+	ipa_rm_tbl[1].producer_rm1 = IPA_RM_RESOURCE_USB_PROD;
+	ipa_rm_tbl[1].consumer_rm1 = IPA_RM_RESOURCE_A2_CONS;
+	ipa_rm_tbl[1].producer_rm2 = IPA_RM_RESOURCE_A2_PROD;
+	ipa_rm_tbl[1].consumer_rm2 = IPA_RM_RESOURCE_USB_CONS;
+
+	ipa_rm_tbl[2].producer_rm1 = IPA_RM_RESOURCE_HSIC_PROD;
+	ipa_rm_tbl[2].consumer_rm1 = IPA_RM_RESOURCE_USB_CONS;
+	ipa_rm_tbl[2].producer_rm2 = IPA_RM_RESOURCE_USB_PROD;
+	ipa_rm_tbl[2].consumer_rm2 = IPA_RM_RESOURCE_HSIC_CONS;
+	
 fail:
 	free(cfg);
 
@@ -229,3 +269,203 @@
 
 	return 0;
 }
+
+/* for IPACM resource manager dependency usage
+   add either Tx or Rx ipa_rm_resource_name */
+void IPACM_Config::AddRmDepend(ipa_rm_resource_name rm1)
+{
+   int retval = 0;
+   int m_fd; /* File descriptor of the IPA device node /dev/ipa */
+   struct ipa_ioc_rm_dependency dep;
+   char *DEVICE_NAME = "/dev/ipa";
+
+   m_fd = open(DEVICE_NAME, O_RDWR);
+   if (0 == m_fd)
+   {
+   	IPACMERR("Failed opening %s.\n", DEVICE_NAME);
+   }
+
+   /* ipa_rm_a2_check: IPA_RM_RESOURCE_A2_CONS*/
+   if(rm1 == IPA_RM_RESOURCE_A2_CONS)
+   {
+     ipa_rm_a2_check+=1;
+	 IPACMDBG("got %d times default RT routing from A2 \n", ipa_rm_a2_check);
+   }
+   
+   for(int i=0;i<IPA_MAX_PRIVATE_SUBNET_ENTRIES;i++)
+   {
+       if(rm1 == ipa_rm_tbl[i].producer_rm1)
+	   { 
+	       ipa_rm_tbl[i].producer_up = true;
+	       IPACMDBG("Matched RM_table entry: %d's producer_rm1 \n", i);
+	     
+           if(ipa_rm_tbl[i].consumer_up == true && ipa_rm_tbl[i].rm_set == false)
+           {
+              IPACMDBG("SETUP RM_table entry %d's bi-direction dependency  \n", i);
+	          /* add bi-directional dependency*/
+	          memset(&dep, 0, sizeof(dep));
+	          dep.resource_name = ipa_rm_tbl[i].producer_rm1;
+	          dep.depends_on_name = ipa_rm_tbl[i].consumer_rm1;
+	          retval = ioctl(m_fd, IPA_IOC_RM_ADD_DEPENDENCY, &dep);
+			  IPACMDBG("ADD entry %d's dependency between Pro: %d, Con: %d \n", i,dep.resource_name,dep.depends_on_name);
+	          if (retval)
+	          {
+	          	 IPACMERR("Failed adding dependecny for RM_table entry %d's bi-direction dependency (error:%d) \n", i,retval);
+	          }
+	          
+	          memset(&dep, 0, sizeof(dep));
+	          dep.resource_name = ipa_rm_tbl[i].producer_rm2;
+	          dep.depends_on_name = ipa_rm_tbl[i].consumer_rm2;
+	          retval = ioctl(m_fd, IPA_IOC_RM_ADD_DEPENDENCY, &dep);
+			  IPACMDBG("ADD entry %d's dependency between Pro: %d, Con: %d \n", i,dep.resource_name,dep.depends_on_name);
+	          if (retval)
+	          {
+	          	 IPACMERR("Failed adding dependecny for RM_table entry %d's bi-direction dependency (error:%d)  \n", i,retval);
+	          }
+	          ipa_rm_tbl[i].rm_set = true;
+           }
+           else
+           {
+              IPACMDBG("Not SETUP RM_table entry %d: prod_up:%d, cons_up:%d, rm_set: %d \n", i,ipa_rm_tbl[i].producer_up, ipa_rm_tbl[i].consumer_up, ipa_rm_tbl[i].rm_set);   
+           }	   
+	   }
+	   
+       if(rm1 == ipa_rm_tbl[i].consumer_rm1)
+	   {
+	       ipa_rm_tbl[i].consumer_up = true;
+	       IPACMDBG("Matched RM_table entry: %d's consumer_rm1 \n", i);
+       
+           if(ipa_rm_tbl[i].producer_up == true && ipa_rm_tbl[i].rm_set == false)
+           {
+              IPACMDBG("SETUP RM_table entry %d's bi-direction dependency  \n", i);
+	          /* add bi-directional dependency*/
+	          memset(&dep, 0, sizeof(dep));
+	          dep.resource_name = ipa_rm_tbl[i].producer_rm1;
+	          dep.depends_on_name = ipa_rm_tbl[i].consumer_rm1;
+	          retval = ioctl(m_fd, IPA_IOC_RM_ADD_DEPENDENCY, &dep);
+			  IPACMDBG("ADD entry %d's dependency between Pro: %d, Con: %d \n", i,dep.resource_name,dep.depends_on_name);
+	          if (retval)
+	          {
+	          	 IPACMERR("Failed adding dependecny for RM_table entry %d's bi-direction dependency (error:%d)  \n", i,retval);
+	          }
+	          
+	          memset(&dep, 0, sizeof(dep));
+	          dep.resource_name = ipa_rm_tbl[i].producer_rm2;
+	          dep.depends_on_name = ipa_rm_tbl[i].consumer_rm2;
+	          retval = ioctl(m_fd, IPA_IOC_RM_ADD_DEPENDENCY, &dep);
+			  IPACMDBG("ADD entry %d's dependency between Pro: %d, Con: %d \n", i,dep.resource_name,dep.depends_on_name);
+	          if (retval)
+	          {
+	          	 IPACMERR("Failed adding dependecny for RM_table entry %d's bi-direction dependency (error:%d)  \n", i,retval);
+	          }
+	          ipa_rm_tbl[i].rm_set = true;
+           }
+           else
+           {
+              IPACMDBG("Not SETUP RM_table entry %d: prod_up:%d, cons_up:%d, rm_set: %d \n", i,ipa_rm_tbl[i].producer_up, ipa_rm_tbl[i].consumer_up, ipa_rm_tbl[i].rm_set);   
+           }
+       
+	   }	 
+   }
+
+   return ;
+}
+
+/* for IPACM resource manager dependency usage
+   delete either Tx or Rx ipa_rm_resource_name */
+
+void IPACM_Config::DelRmDepend(ipa_rm_resource_name rm1)
+{
+   int retval = 0;
+   int m_fd; /* File descriptor of the IPA device node /dev/ipa */
+   struct ipa_ioc_rm_dependency dep;
+   char *DEVICE_NAME = "/dev/ipa";
+
+   m_fd = open(DEVICE_NAME, O_RDWR);
+   if (0 == m_fd)
+   {
+   	IPACMERR("Failed opening %s.\n", DEVICE_NAME);
+   }
+
+   /* ipa_rm_a2_check: IPA_RM_RESOURCE_A2_CONS*/
+   if(rm1 == IPA_RM_RESOURCE_A2_CONS)
+   {
+     ipa_rm_a2_check-=1;
+	 IPACMDBG("Left %d times default RT routing from A2 \n", ipa_rm_a2_check);
+   }   
+   
+   for(int i=0;i<IPA_MAX_PRIVATE_SUBNET_ENTRIES;i++)
+   {
+   
+     if(rm1 == ipa_rm_tbl[i].producer_rm1)
+	 { 
+	     if(ipa_rm_tbl[i].rm_set == true)
+		 {
+	        IPACMDBG("Matched RM_table entry: %d's producer_rm1 and dependency is up \n", i);
+	        ipa_rm_tbl[i].rm_set = false;            
+		    /* delete bi-directional dependency*/
+	        memset(&dep, 0, sizeof(dep));
+	        dep.resource_name = ipa_rm_tbl[i].producer_rm1;
+	        dep.depends_on_name = ipa_rm_tbl[i].consumer_rm1;
+	        retval = ioctl(m_fd, IPA_IOC_RM_DEL_DEPENDENCY, &dep);
+			IPACMDBG("Delete entry %d's dependency between Pro: %d, Con: %d \n", i,dep.resource_name,dep.depends_on_name);
+	        if (retval)
+	        {
+	        	  IPACMERR("Failed deleting dependecny for RM_table entry %d's bi-direction dependency (error:%d) \n", i,retval);
+	        }
+            
+	        memset(&dep, 0, sizeof(dep));
+	        dep.resource_name = ipa_rm_tbl[i].producer_rm2;
+	        dep.depends_on_name = ipa_rm_tbl[i].consumer_rm2;
+	        retval = ioctl(m_fd, IPA_IOC_RM_DEL_DEPENDENCY, &dep);
+			IPACMDBG("Delete entry %d's dependency between Pro: %d, Con: %d \n", i,dep.resource_name,dep.depends_on_name);
+	        if (retval)
+	        {
+	        	  IPACMERR("Failed deleting dependecny for RM_table entry %d's bi-direction dependency (error:%d) \n", i,retval);
+	        }
+	     }
+	     ipa_rm_tbl[i].producer_up = false;
+	     
+	 }
+	 
+     if(rm1 == ipa_rm_tbl[i].consumer_rm1)
+	 {
+	 
+	     /* ipa_rm_a2_check: IPA_RM_RESOURCE_A2_CONS*/
+         if(ipa_rm_tbl[i].consumer_rm1 == IPA_RM_RESOURCE_A2_CONS && ipa_rm_a2_check == 1)
+         {
+	       IPACMDBG(" still have %d default RT routing from A2 \n", ipa_rm_a2_check);
+           continue;
+         }  	 
+	 
+	     if(ipa_rm_tbl[i].rm_set == true)
+		 {
+	         IPACMDBG("Matched RM_table entry: %d's consumer_rm1 and dependency is up \n", i);
+             ipa_rm_tbl[i].rm_set = false;
+             /* delete bi-directional dependency*/
+	         memset(&dep, 0, sizeof(dep));
+	         dep.resource_name = ipa_rm_tbl[i].producer_rm1;
+	         dep.depends_on_name = ipa_rm_tbl[i].consumer_rm1;
+	         retval = ioctl(m_fd, IPA_IOC_RM_DEL_DEPENDENCY, &dep);
+			 IPACMDBG("Delete entry %d's dependency between Pro: %d, Con: %d \n", i,dep.resource_name,dep.depends_on_name);
+	         if (retval)
+	         {
+	         	  IPACMERR("Failed deleting dependecny for RM_table entry %d's bi-direction dependency (error:%d) \n", i,retval);
+	         }
+             
+	         memset(&dep, 0, sizeof(dep));
+	         dep.resource_name = ipa_rm_tbl[i].producer_rm2;
+	         dep.depends_on_name = ipa_rm_tbl[i].consumer_rm2;
+	         retval = ioctl(m_fd, IPA_IOC_RM_DEL_DEPENDENCY, &dep);
+			 IPACMDBG("Delete entry %d's dependency between Pro: %d, Con: %d \n", i,dep.resource_name,dep.depends_on_name);
+	         if (retval)
+	         {
+	         	  IPACMERR("Failed deleting dependecny for RM_table entry %d's bi-direction dependency (error:%d) \n", i,retval);
+	         }
+		 }
+ 	     ipa_rm_tbl[i].consumer_up = false;		 
+	 }	 
+   }
+
+   return ;
+}
\ No newline at end of file
diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp
index a713679..2a9e144 100644
--- a/ipacm/src/IPACM_Iface.cpp
+++ b/ipacm/src/IPACM_Iface.cpp
@@ -451,7 +451,9 @@
 	int res = IPACM_SUCCESS, len = 0;
 	struct ipa_flt_rule_add flt_rule_entry;
 	ipa_ioc_add_flt_rule *m_pFilteringTable;
-
+#if 1
+	char *dev2="wlan0";
+#endif
 	/* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
 	if (iptype == IPA_IP_v4)
 	{
@@ -494,6 +496,20 @@
 		IPACMDBG(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
 	}
 	
+        /* Add corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
+#if 1
+	if(strcmp(dev_name,dev2))
+	{
+	  IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);		
+	}
+	else
+	{
+	  /* dev_name ==  dev2 (wlan0)*/
+	  IPACMDBG(" work-around setup iface %s rx property\n", dev2);
+	  IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD);	
+	}
+#endif
+	
 	if (rx_prop == NULL)
 	{
 		IPACMDBG("No rx properties registered for iface %s\n", dev_name);
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index 6934c13..4da105c 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -288,6 +288,9 @@
 			  	  }  
 			   }	   
 		   
+	               /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
+	               IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
+		   
 		       /* not see this ipv6 before for LAN client*/
 			   v6_addr[ipv6_set][0] = data->ipv6_addr[0];
 			   v6_addr[ipv6_set][1] = data->ipv6_addr[1];
@@ -442,6 +445,9 @@
                     }
 	    }
 
+                /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV4 RT-rule set */
+	        IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
+
 		/* unicast RT rule add start */
 		rt_rule = (struct ipa_ioc_add_rt_rule *)
 			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
@@ -586,6 +592,14 @@
 				}
 
 				num_uni_rt -= 1;
+				
+		                /* Del v4 RM dependency */
+	                        if(num_uni_rt == 0)
+				{
+				   /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule*/ 
+				   IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
+				}
+				
 				return IPACM_SUCCESS;
 			}
 		}
@@ -678,6 +692,13 @@
 			  		    break;
 			  	    }  
 			    }	
+
+		            /* Del v6 RM dependency */
+	                    if(num_uni_rt == 0)
+				{
+				   /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule */ 
+				   IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
+				}				
 				return IPACM_SUCCESS;
 			}
 		}
@@ -1159,6 +1180,9 @@
 		}
 	}
 
+        /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule */ 
+        IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);				
+
 	/* check software routing fl rule hdl */
 	if (softwarerouting_act == true && rx_prop != NULL)
 	{
@@ -1209,6 +1233,9 @@
 		handle_wan_down();
 	}
 
+	/* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */ 
+	IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);	
+
 fail:
 	if (tx_prop != NULL)
 	{
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp
index a3312e2..8309f0c 100644
--- a/ipacm/src/IPACM_Wan.cpp
+++ b/ipacm/src/IPACM_Wan.cpp
@@ -316,14 +316,14 @@
 			if (ipa_interface_index == ipa_if_num)
 			{
 				IPACMDBG("Received IPA_ROUTE_DEL_EVENT\n");
-				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask))
+				if ((data->iptype == IPA_IP_v4) && (!data->ipv4_addr) && (!data->ipv4_addr_mask) && (active_v4 == true))
 				{
 					IPACMDBG("get del default v4 route (dst:0.0.0.0)\n");
 					del_dft_firewall_rules(IPA_IP_v4);
 					handle_route_del_evt(data->iptype);
 					IPACM_Wan::wan_up = false;
 				}
-				else if ((data->iptype == IPA_IP_v6) && (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]))
+				else if ((data->iptype == IPA_IP_v6) && (!data->ipv6_addr[0]) && (!data->ipv6_addr[1]) && (!data->ipv6_addr[2]) && (!data->ipv6_addr[3]) && (active_v6 == true))
 				{
 					IPACMDBG("get del default v6 route (dst:00.00.00.00)\n");
 					del_dft_firewall_rules(IPA_IP_v6);
@@ -608,6 +608,9 @@
 		config_dft_firewall_rules(IPA_IP_v6);
 	}
 
+	/* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
+    IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
+	
 	return IPACM_SUCCESS;
 }
 
@@ -624,6 +627,9 @@
 			((iptype == IPA_IP_v6) && (active_v6 == true)))
 	{
 
+		/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */
+	    IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);	
+	
 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
 		{
 		
@@ -693,7 +699,7 @@
 		}
 		else
 		{
-			IPACMDBG("setup active_v6= false \n");
+			IPACMDBG("setup wan_up_v6/active_v6= false \n");
 			active_v6 = false; 
 		}
 	}
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index 828ad15..f9ff921 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -267,12 +267,12 @@
 				}
 				
 				
-				if (ip_type != IPA_IP_v6) /* for ipv4 */
+                                if(get_client_memptr(wlan_client, wlan_index)->ipv4_set == true) /* for ipv4 */
 				{
 					handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v4);
 				}				
 
-				if (ip_type != IPA_IP_v4) /* for ipv6 */
+				if(get_client_memptr(wlan_client, wlan_index)->ipv6_set == true) /* for ipv6 */
 				{
 					handle_wlan_client_route_rule(data->mac_addr, IPA_IP_v6);
 				}
@@ -1788,6 +1788,11 @@
 	/* free the wlan clients cache */
 	IPACMDBG("Free wlan clients cache\n");
 
+	/* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */ 
+#if 0
+	IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);	
+#endif
+	IPACM_Iface::ipacmcfg->DelRmDepend(IPA_RM_RESOURCE_HSIC_PROD);
 fail:
 	free(wlan_client);
 	if (tx_prop != NULL)