Merge "IPACM: handle multiple ETH usb clients"
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index a43e41d..9df0c10 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -95,6 +95,7 @@
 #define IPACM_INVALID_INDEX (ipa_ip_type)0xFF
 
 #define IPA_MAX_NUM_WIFI_CLIENTS  32
+#define IPA_MAX_NUM_ETH_CLIENTS  15
 #define IPA_MAX_NUM_AMPDU_RULE  15
 #define IPA_MAC_ADDR_SIZE  6
 
diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h
index 6f66a62..b84df97 100644
--- a/ipacm/inc/IPACM_Lan.h
+++ b/ipacm/inc/IPACM_Lan.h
@@ -48,8 +48,8 @@
 #include "IPACM_Routing.h"
 #include "IPACM_Filtering.h"
 #include "IPACM_Config.h"
+#include "IPACM_Conntrack_NATApp.h"
 
-#define IPA_MAX_NUM_UNICAST_ROUTE_RULES  6
 #define IPA_WAN_DEFAULT_FILTER_RULE_HANDLES  1
 #define IPA_PRIV_SUBNET_FILTER_RULE_HANDLES  3
 #define MAX_WAN_UL_FILTER_RULES 20
@@ -64,6 +64,30 @@
 	uint32_t rt_rule_hdl[0];
 };
 
+/* Support multiple eth client */
+typedef struct _eth_client_rt_hdl
+{
+	uint32_t eth_rt_rule_hdl_v4;
+	uint32_t eth_rt_rule_hdl_v6[IPV6_NUM_ADDR];
+	uint32_t eth_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR];
+}eth_client_rt_hdl;
+
+typedef struct _ipa_eth_client
+{
+	uint8_t mac[IPA_MAC_ADDR_SIZE];
+	uint32_t v4_addr;
+	uint32_t v6_addr[IPV6_NUM_ADDR][4];
+	uint32_t hdr_hdl_v4;
+	uint32_t hdr_hdl_v6;
+	bool route_rule_set_v4;
+	int route_rule_set_v6;
+	bool ipv4_set;
+	int ipv6_set;
+	bool ipv4_header_set;
+	bool ipv6_header_set;
+	eth_client_rt_hdl eth_rt_hdl[0]; /* depends on number of tx properties */
+}ipa_eth_client;
+
 /* lan iface */
 class IPACM_Lan : public IPACM_Iface
 {
@@ -107,45 +131,131 @@
 private:
 
 	/* dynamically allocate lan iface's unicast routing rule structure */
-	int rt_rule_len;
-
-	ipa_lan_rt_rule *route_rule;
-
-	uint32_t v6_addr[IPV6_NUM_ADDR][4];
-
-        int ipv6_set;
-
-	uint32_t ETH_hdr_hdl_v4, ETH_hdr_hdl_v6;
 	
-	bool ipv4_header_set;
-	
-	bool ipv6_header_set;	
-		
-	/* store the number of lan-iface's unicast routing rule */
-	int num_uni_rt;
+	int eth_client_len;
 
-	inline ipa_lan_rt_rule* get_rt_ruleptr(ipa_lan_rt_rule *param, int cnt)
+	ipa_eth_client *eth_client;
+	
+	int header_name_count; 
+
+	int num_eth_client;
+
+	NatApp *Nat_App;
+
+	inline ipa_eth_client* get_client_memptr(ipa_eth_client *param, int cnt)
 	{
-	    char *ret = ((char *)param) + (rt_rule_len * cnt);
-	    return (ipa_lan_rt_rule *)ret;
+	    char *ret = ((char *)param) + (eth_client_len * cnt);
+		return (ipa_eth_client *)ret;
+	}	
+
+	inline int get_eth_client_index(uint8_t *mac_addr)
+	{
+		int cnt;
+		int num_eth_client_tmp = num_eth_client;
+
+		IPACMDBG("Passed MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+						 mac_addr[0], mac_addr[1], mac_addr[2],
+						 mac_addr[3], mac_addr[4], mac_addr[5]);
+
+		for(cnt = 0; cnt < num_eth_client_tmp; cnt++)
+		{
+			IPACMDBG("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+							 get_client_memptr(eth_client, cnt)->mac[0],
+							 get_client_memptr(eth_client, cnt)->mac[1],
+							 get_client_memptr(eth_client, cnt)->mac[2],
+							 get_client_memptr(eth_client, cnt)->mac[3],
+							 get_client_memptr(eth_client, cnt)->mac[4],
+							 get_client_memptr(eth_client, cnt)->mac[5]);
+
+			if(memcmp(get_client_memptr(eth_client, cnt)->mac,
+								mac_addr,
+								sizeof(get_client_memptr(eth_client, cnt)->mac)) == 0)
+			{
+				IPACMDBG("Matched client index: %d\n", cnt);
+				return cnt;
+			}
+		}
+
+		return IPACM_INVALID_INDEX;
+	}
+	
+	inline int delete_eth_rtrules(int clt_indx, ipa_ip_type iptype)
+	{
+		uint32_t tx_index;
+		uint32_t rt_hdl;
+		int num_v6;
+
+		if(iptype == IPA_IP_v4)
+		{
+		    for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+		    {
+		        if((tx_prop->tx[tx_index].ip == IPA_IP_v4) && (get_client_memptr(eth_client, clt_indx)->route_rule_set_v4==true)) /* for ipv4 */
+				{
+					IPACMDBG("Delete client index %d ipv4 RT-rules for tx:%d \n", clt_indx,tx_index);
+					rt_hdl = get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4;
+
+					if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v4) == false)
+					{
+						return IPACM_FAILURE;
+					}
+				}
+		    } /* end of for loop */
+
+		     /* clean the ipv4 RT rules for eth-client:clt_indx */
+		     if(get_client_memptr(eth_client, clt_indx)->route_rule_set_v4==true) /* for ipv4 */
+		     {
+				get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = false;
+		     }
+		}
+
+		if(iptype == IPA_IP_v6)
+		{
+		    for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+		    {
+		    		
+		            if((tx_prop->tx[tx_index].ip == IPA_IP_v6) && (get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 != 0)) /* for ipv6 */
+		            {
+		    	        for(num_v6 =0;num_v6 < get_client_memptr(eth_client, clt_indx)->route_rule_set_v6;num_v6++)	
+		    	        {
+ 		    	            IPACMDBG("Delete client index %d ipv6 RT-rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index);
+		    	        	rt_hdl = get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6];                        
+		    	        	if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false)
+							{
+		    	        		return IPACM_FAILURE;
+		    	        	}
+
+							rt_hdl = get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6];
+							if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false)
+							{
+								return IPACM_FAILURE;
+							}
+						}
+                    }
+		    } /* end of for loop */
+		
+		    /* clean the ipv6 RT rules for eth-client:clt_indx */
+		    if(get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 != 0) /* for ipv6 */
+		    {
+		        get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = 0;
+            }
+		}
+		
+		return IPACM_SUCCESS;
 	}
 
-	/* handle unicast routing rule add event for ipv4 */
-	int handle_route_add_evt(ipacm_event_data_addr *data);
-
-	/* handle unicast routing rule add event for ipv6 */
-	int handle_route_add_evt_v6(ipacm_event_data_all *data);
-
-	/* handle unicast routing rule del event for ipv4 */
-	int handle_route_del_evt(ipacm_event_data_addr *data);
-
-	/* handle unicast routing rule del event for ipv6 */
-	int handle_route_del_evt_v6(ipacm_event_data_all *data);
-
-	/* handle ETH client initial, construct full headers (tx property) */
+	/* handle eth client initial, construct full headers (tx property) */
 	int handle_eth_hdr_init(uint8_t *mac_addr);
+
+	/* handle eth client ip-address */
+	int handle_eth_client_ipaddr(ipacm_event_data_all *data);
+
+	/* handle eth client routing rule*/
+	int handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype);	
+
+	/*handle eth client del mode*/
+	int handle_eth_client_down_evt(uint8_t *mac_addr);
 	
-	/*handle wlan iface down event*/
+	/*handle lan iface down event*/
 	int handle_down_evt();
 
 	/* store ipv4 UL filter rule handlers from Q6*/
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index 43ab371..a125a13 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -52,15 +52,21 @@
 
 IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index)
 {
-	num_uni_rt = 0;
-        ipv6_set = 0;
-	ipv4_header_set = false;
-	ipv6_header_set = false;
-	int ret = IPACM_SUCCESS;
 
-	rt_rule_len = sizeof(struct ipa_lan_rt_rule) + (iface_query->num_tx_props * sizeof(uint32_t));
-	route_rule = (struct ipa_lan_rt_rule *)calloc(IPA_MAX_NUM_UNICAST_ROUTE_RULES, rt_rule_len);
-	if (route_rule == NULL)
+	num_eth_client = 0;
+	header_name_count = 0;
+
+	Nat_App = NatApp::GetInstance();
+	if (Nat_App == NULL)
+	{
+		IPACMERR("unable to get Nat App instance \n");
+		return;
+	}
+	
+	/* support eth multiple clients */
+	eth_client_len = (sizeof(ipa_eth_client)) + (iface_query->num_tx_props * sizeof(eth_client_rt_hdl));
+	eth_client = (ipa_eth_client *)calloc(IPA_MAX_NUM_ETH_CLIENTS, eth_client_len);
+	if (eth_client == NULL)
 	{
 		IPACMERR("unable to allocate memory\n");
 		return;
@@ -235,20 +241,6 @@
 		}
 		break;
 
-	case IPA_ROUTE_ADD_EVENT:
-		{
-			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
-			ipa_interface_index = iface_ipa_index_query(data->if_index);
-
-			/* unicast routing rule add */
-			if (ipa_interface_index == ipa_if_num)
-			{
-				IPACMDBG("Received IPA_ROUTE_ADD_EVENT\n");
-				handle_route_add_evt(data);
-			}
-		}
-		break;
-
 	case IPA_HANDLE_WAN_DOWN:
 		IPACMDBG("Received IPA_HANDLE_WAN_DOWN event\n");
 		handle_wan_down(IPACM_Wan::backhaul_is_sta_mode);
@@ -259,63 +251,26 @@
 		handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode);
 		break;
 
-	case IPA_ROUTE_DEL_EVENT:
-		{
-			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
-			ipa_interface_index = iface_ipa_index_query(data->if_index);
-
-			/* unicast routing rule del */
-			if (ipa_interface_index == ipa_if_num)
-			{
-				IPACMDBG("Received IPA_ROUTE_DEL_EVENT\n");
-				handle_route_del_evt(data);
-			}
-		}
-		break;
-
 	case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
 		{
 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;
 			ipa_interface_index = iface_ipa_index_query(data->if_index);
 
 			IPACMDBG("check iface %s category: %d\n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat);
-			if ((ipa_interface_index == ipa_if_num) && (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ETH_IF))
+			if (ipa_interface_index == ipa_if_num)
 			{
-				IPACMDBG("ETH iface got v4-ip \n");
+				IPACMDBG("ETH iface got client \n");
 				/* first construc ETH full header */
-				if ((ipv4_header_set == false) && (ipv6_header_set == false))
-				{
 					handle_eth_hdr_init(data->mac_addr);
 					IPACMDBG("construct ETH header and route rules \n");
-				}
-			}
-
-			if ((ipa_interface_index == ipa_if_num) && (data->iptype == IPA_IP_v6))
-			{
-				IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT for ipv6\n");
-				handle_route_add_evt_v6(data);
-			}
-			/* support ipv4 unicast route add coming from bridge0 via new_neighbor event */
-                        if ((ipa_interface_index == ipa_if_num) && (data->iptype == IPA_IP_v4))
-	                {
-				IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT for ipv4 \n");
-                                ipacm_event_data_addr *data2;				
-				data2 = (ipacm_event_data_addr *)
-							 malloc(sizeof(ipacm_event_data_addr));				
-				if (data2 == NULL)
+				/* Associate with IP and construct RT-rule */
+				if (handle_eth_client_ipaddr(data) == IPACM_FAILURE)
 				{
-							IPACMERR("Unable to allocate memory\n");
-							return;
+					return;
 				}
-				memset(data2, 0, sizeof(data2));
-				data2->iptype = IPA_IP_v4;
-                                data2->ipv4_addr = data->ipv4_addr;
-                                data2->ipv4_addr_mask = 0xFFFFFFFF;
-				IPACMDBG("IPv4 address:0x%x, mask:0x%x\n",
-										 data2->ipv4_addr, data2->ipv4_addr_mask);
-                                handle_route_add_evt(data2);
-				free(data2);
-			}	
+				handle_eth_client_route_rule(data->mac_addr, data->iptype);
+				return;
+			}
 		}
 		break;
 
@@ -323,31 +278,13 @@
 		{
 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;
 			ipa_interface_index = iface_ipa_index_query(data->if_index);
-			if ((ipa_interface_index == ipa_if_num) && (data->iptype == IPA_IP_v6) )
-				{
-				IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT for ipv6\n");
-				handle_route_del_evt_v6(data);
-			}
-			/* support ipv4 unicast route delete coming from bridge0 via new_neighbor event */
-                        if ((ipa_interface_index == ipa_if_num) && (data->iptype == IPA_IP_v4))
-		        {
-				IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT for ipv4 \n");
-                                ipacm_event_data_addr *data2;				
-				data2 = (ipacm_event_data_addr *)
-							 malloc(sizeof(ipacm_event_data_addr));				
-				if (data2 == NULL)
-				{
-							IPACMERR("Unable to allocate memory\n");
-							return;
-				}
-				memset(data2, 0, sizeof(data2));
-				data2->iptype = IPA_IP_v4;
-                                data2->ipv4_addr = data->ipv4_addr;
-                                data2->ipv4_addr_mask = 0xFFFFFFFF;
-				IPACMDBG("IPv4 address:0x%x, mask:0x%x\n",
-										 data2->iptype, data2->ipv4_addr_mask);
-                                handle_route_add_evt(data2);
-				free(data2);
+			
+			IPACMDBG("check iface %s category: %d\n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat);
+			if (ipa_interface_index == ipa_if_num)
+			{
+				IPACMDBG("ETH iface delete client \n");
+				handle_eth_client_down_evt(data->mac_addr);
+				return;
 			}	
 		}
 		break;
@@ -371,518 +308,6 @@
 	return;
 }
 
-
-/*handle USB client IPv6*/
-int IPACM_Lan::handle_route_add_evt_v6(ipacm_event_data_all *data)
-{
-	/* add unicate route for LAN */
-	struct ipa_ioc_add_rt_rule *rt_rule;
-	struct ipa_rt_rule_add *rt_rule_entry;
-	struct ipa_ioc_get_hdr sRetHeader;
-	uint32_t tx_index;
-	int v6_num;
-
-	IPACMDBG(" usb MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
-					 data->mac_addr[0],
-					 data->mac_addr[1],
-					 data->mac_addr[2],
-					 data->mac_addr[3],
-					 data->mac_addr[4],
-					 data->mac_addr[5]);
-
-	if (tx_prop == NULL)
-	{
-		IPACMDBG("No Tx properties registered for iface %s\n", dev_name);
-		return IPACM_SUCCESS;
-	}					 
-					 
-	IPACMDBG("Ip-type received %d, ipv6_set: %d\n", data->iptype,ipv6_set);
-	if (data->iptype == IPA_IP_v6)
-	{
-	    /* check if all 0 not valid ipv6 address */
-		if ((data->ipv6_addr[0]!= 0) || (data->ipv6_addr[1]!= 0) ||
-				(data->ipv6_addr[2]!= 0) || (data->ipv6_addr[3] || 0))
-		{
-		   IPACMDBG("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
-           if(ipv6_set<IPV6_NUM_ADDR)		
-		   {
-		       /* check if see that before or not*/
-		       for(v6_num = 0;v6_num < ipv6_set;v6_num++)
-	           {
-			      if( data->ipv6_addr[0] == v6_addr[v6_num][0] && 
-			           data->ipv6_addr[1] == v6_addr[v6_num][1] &&
-			  	        data->ipv6_addr[2]== v6_addr[v6_num][2] && 
-			  	         data->ipv6_addr[3] == v6_addr[v6_num][3])
-			      {
-			  	    IPACMDBG("Already see this ipv6 addr for LAN iface \n");
-			  	    return IPACM_SUCCESS; /* not setup the RT rules*/
-			  		break;
-			  	  }  
-			   }	   
-		   
-	               /* 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],false);
-		   
-		       /* 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];
-			   v6_addr[ipv6_set][2] = data->ipv6_addr[2];
-			   v6_addr[ipv6_set][3] = data->ipv6_addr[3];
-
-	           /* unicast RT rule add start */
-		       rt_rule = (struct ipa_ioc_add_rt_rule *)
-		       	 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
-		       					1 * sizeof(struct ipa_rt_rule_add));
-		       if (!rt_rule)
-		       {
-		       	  IPACMERR("fail\n");
-		       	  return IPACM_FAILURE;
-		       }
-
-			   rt_rule->commit = 1;
-		       rt_rule->num_rules = (uint8_t)1;
-		       rt_rule->ip = data->iptype;
-		       rt_rule_entry = &rt_rule->rules[0];
-		       rt_rule_entry->at_rear = false;
-
-
-		       for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
-		       {
-		       
-		           if(data->iptype != tx_prop->tx[tx_index].ip)
-		           {
-		           	IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule added\n", 
-		           					    tx_index, tx_prop->tx[tx_index].ip,data->iptype);		
-		           	continue;
-		           }		
-
-		           strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name);
-				   
-		           /* Support QCMAP LAN traffic feature, send to A5 */
-                           rt_rule_entry->rule.dst = iface_query->excp_pipe;
-				   memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
-				   rt_rule_entry->rule.hdr_hdl = 0;
-		       	   rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0];
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1];
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2];
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3];
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
-		       	   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;
-		       	   
-		       	   if (false == m_routing.AddRoutingRule(rt_rule))
-		       	   {
-		       	   	IPACMERR("Routing rule addition failed!\n");
-		       	   	free(rt_rule);
-		       	   	return IPACM_FAILURE;
-		       	   }				   
-		       	   get_rt_ruleptr(route_rule, num_uni_rt)->rt_rule_hdl[tx_index]
-		       		  = rt_rule_entry->rt_rule_hdl;
-		       	   IPACMDBG("ipv6 rt rule hdl1 for LAN-table=0x%x, entry:0x%x\n", rt_rule_entry->rt_rule_hdl,get_rt_ruleptr(route_rule, num_uni_rt)->rt_rule_hdl[tx_index]);
-
-			       /* Construct same v6 rule for rt_tbl_wan_v6              */
-		       	   if (tx_prop->tx[tx_index].hdr_name)
-		       	   {
-		       	   	memset(&sRetHeader, 0, sizeof(sRetHeader));
-		       	   	strncpy(sRetHeader.name,
-		       	   					tx_prop->tx[tx_index].hdr_name,
-		       	   					sizeof(tx_prop->tx[tx_index].hdr_name));
-                   
-		       	   	if (false == m_header.GetHeaderHandle(&sRetHeader))
-		       	   	{
-		       	   		IPACMERR(" ioctl failed\n");
-		       	   	    free(rt_rule);
-		       	   	    return IPACM_FAILURE;
-		       	   	}
-                   
-		       	   	rt_rule_entry->rule.hdr_hdl = sRetHeader.hdl;
-		       	   }
-
-				   /* Replace v6 header in ETH interface */
-				   if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ETH_IF)
-						rt_rule_entry->rule.hdr_hdl = ETH_hdr_hdl_v6;
-
-		           /* Downlink traffic from Wan iface, directly through IPA */
-		       	   rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
-		       	   memcpy(&rt_rule_entry->rule.attrib,
-		       	   			 &tx_prop->tx[tx_index].attrib,
-		       	   			 sizeof(rt_rule_entry->rule.attrib));
-		       	   rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0];
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1];
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2];
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3];
-		       	   rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
-		       	   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;
-		       	   
-		           strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name);
-		       	   if (false == m_routing.AddRoutingRule(rt_rule))
-		       	   {
-		       	   	IPACMERR("Routing rule addition failed!\n");
-		       	   	free(rt_rule);
-		       	   	return IPACM_FAILURE;
-		       	   }				   
-		       	   get_rt_ruleptr(route_rule, (num_uni_rt+1))->rt_rule_hdl[tx_index]
-		       		  = rt_rule_entry->rt_rule_hdl;
-		       	   IPACMDBG("ipv6 rt rule hdl1 for WAN-table=0x%x, entry:0x%x\n", rt_rule_entry->rt_rule_hdl,get_rt_ruleptr(route_rule, (num_uni_rt+1))->rt_rule_hdl[tx_index]);
-
-			   }
-
-		           get_rt_ruleptr(route_rule, num_uni_rt)->ip = IPA_IP_v6;
-		           get_rt_ruleptr(route_rule, num_uni_rt)->v6_addr[0] = data->ipv6_addr[0];
-		           get_rt_ruleptr(route_rule, num_uni_rt)->v6_addr[1] = data->ipv6_addr[1];
-		           get_rt_ruleptr(route_rule, num_uni_rt)->v6_addr[2] = data->ipv6_addr[2];
-		           get_rt_ruleptr(route_rule, num_uni_rt)->v6_addr[3] = data->ipv6_addr[3];
-
-		           get_rt_ruleptr(route_rule, (num_uni_rt+1))->ip = IPA_IP_v6;
-		           get_rt_ruleptr(route_rule, (num_uni_rt+1))->v6_addr[0] = data->ipv6_addr[0];
-		           get_rt_ruleptr(route_rule, (num_uni_rt+1))->v6_addr[1] = data->ipv6_addr[1];
-		           get_rt_ruleptr(route_rule, (num_uni_rt+1))->v6_addr[2] = data->ipv6_addr[2];
-		           get_rt_ruleptr(route_rule, (num_uni_rt+1))->v6_addr[3] = data->ipv6_addr[3];
-
-		           num_uni_rt=num_uni_rt+2;
-		       free(rt_rule);
-			   ipv6_set++;
-			   IPACMDBG("Total unicast Rt rules: %d\n", num_uni_rt);
-           }
-		   else
-		   {
-		     IPACMDBG("Already got 3 ipv6 addr for LAN usb-client:\n");
-			 return IPACM_SUCCESS; /* not setup the RT rules*/
-		   } 		   
-		}
-	}
-
-	return IPACM_SUCCESS;
-}
-
-
-/* handle unicast routing rule add event */
-int IPACM_Lan::handle_route_add_evt(ipacm_event_data_addr *data)
-{
-	/* add unicate route for LAN */
-	struct ipa_ioc_add_rt_rule *rt_rule;
-	struct ipa_rt_rule_add *rt_rule_entry;
-	struct ipa_ioc_get_hdr sRetHeader;
-	uint32_t tx_index;
-	int i;
-
-	IPACMDBG("LAN callback: unicast IPA_ROUTE_ADD_EVENT\n");
-
-	if (tx_prop == NULL)
-	{
-		IPACMDBG("No Tx properties registered for iface %s\n", dev_name);
-		return IPACM_SUCCESS;
-	}
-
-	if (data->iptype == IPA_IP_v6)
-	{
-		IPACMDBG("Not setup v6 unicast RT-rule with new_route event for iface %s\n", dev_name);
-		return IPACM_SUCCESS;
-	}
-
-
-	if (num_uni_rt < IPA_MAX_NUM_UNICAST_ROUTE_RULES)
-	{
-        /* check the unicast RT rule is set or not*/
-	    for (i = 0; i < num_uni_rt; i++)
-	    {
-
-		   if ( data->iptype == IPA_IP_v4 && 
-		         (data->ipv4_addr == get_rt_ruleptr(route_rule, i)->v4_addr) &&
-					(data->ipv4_addr_mask == get_rt_ruleptr(route_rule, i)->v4_addr_mask) )
-		   {
- 		       IPACMDBG("find previous-added ipv4 unicast RT entry as index: %d, ignore adding\n",i);		       
-		       return IPACM_SUCCESS;
-			   break;
-                    }
-	    }
-
-                /* 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],false);
-
-		/* unicast RT rule add start */
-		rt_rule = (struct ipa_ioc_add_rt_rule *)
-			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
-							1 * sizeof(struct ipa_rt_rule_add));
-		if (!rt_rule)
-		{
-			IPACMERR("fail\n");
-			return IPACM_FAILURE;
-		}
-
-		rt_rule->commit = 1;
-		rt_rule->num_rules = (uint8_t)1;
-		rt_rule->ip = data->iptype;
-
-		if (data->iptype == IPA_IP_v4) 
-		{  
-		   strcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name);
-		}
-
-		rt_rule_entry = &rt_rule->rules[0];
-		rt_rule_entry->at_rear = false;
-
-		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
-		{
-		
-		    if(data->iptype != tx_prop->tx[tx_index].ip)
-		    {
-		    	IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule added\n", 
-		    					    tx_index, tx_prop->tx[tx_index].ip,data->iptype);		
-		    	continue;
-		    }		
-		
-			if (tx_prop->tx[tx_index].hdr_name)
-			{
-				memset(&sRetHeader, 0, sizeof(sRetHeader));
-				strncpy(sRetHeader.name,
-								tx_prop->tx[tx_index].hdr_name,
-								sizeof(tx_prop->tx[tx_index].hdr_name));
-
-				if (false == m_header.GetHeaderHandle(&sRetHeader))
-				{
-					IPACMERR(" ioctl failed\n");
-				        free(rt_rule);
-				        return IPACM_FAILURE;
-				}
-
-				rt_rule_entry->rule.hdr_hdl = sRetHeader.hdl;
-			}
-
-			/* Replace the v4 header in ETH interface */
-			if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ETH_IF)
-				rt_rule_entry->rule.hdr_hdl = ETH_hdr_hdl_v4;
-
-			rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
-			memcpy(&rt_rule_entry->rule.attrib,
-						 &tx_prop->tx[tx_index].attrib,
-						 sizeof(rt_rule_entry->rule.attrib));
-			rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
-			if (data->iptype == IPA_IP_v4)
-			{
-				rt_rule_entry->rule.attrib.u.v4.dst_addr      = data->ipv4_addr;
-				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = data->ipv4_addr_mask;
-			}
-
-			if (false == m_routing.AddRoutingRule(rt_rule))
-			{
-				IPACMERR("Routing rule addition failed!\n");
-				free(rt_rule);
-				return IPACM_FAILURE;
-			}
-
-			IPACMDBG("rt rule hdl1=0x%x\n", rt_rule_entry->rt_rule_hdl);
-			get_rt_ruleptr(route_rule, num_uni_rt)->rt_rule_hdl[tx_index]
-				 = rt_rule_entry->rt_rule_hdl;
-		}
-
-		get_rt_ruleptr(route_rule, num_uni_rt)->ip = IPA_IP_v4;
-		get_rt_ruleptr(route_rule, num_uni_rt)->v4_addr = data->ipv4_addr;
-		get_rt_ruleptr(route_rule, num_uni_rt)->v4_addr_mask = data->ipv4_addr_mask;
-                IPACMDBG("index: %d, ip-family: %d, IPv4 address:0x%x, IPv4 address mask:0x%x   \n", 
-	    	            num_uni_rt, get_rt_ruleptr(route_rule, num_uni_rt)->ip,
-				  get_rt_ruleptr(route_rule, num_uni_rt)->v4_addr,
-			          get_rt_ruleptr(route_rule, num_uni_rt)->v4_addr_mask);				
-			
-
-		free(rt_rule);
-		num_uni_rt++;
-	}
-	else
-	{
-		IPACMDBG("unicast rule oversize\n");
-		return IPACM_FAILURE;
-	}
-
-	return IPACM_SUCCESS;
-}
-
-/* handle unicast routing rule del event */
-int IPACM_Lan::handle_route_del_evt(ipacm_event_data_addr *data)
-{
-	int i;
-	uint32_t tx_index;
-
-	if (tx_prop == NULL)
-	{
-		IPACMDBG("No Tx properties registered for iface %s\n", dev_name);
-		return IPACM_SUCCESS;
-	}
-
-	if (data->iptype == IPA_IP_v6)
-	{
-		IPACMDBG("Not setup v6 unicast RT-rule with new_route event for iface %s\n", dev_name);
-		return IPACM_SUCCESS;
-	}
-	
-	/* delete 1 unicast RT rule */
-	for (i = 0; i < num_uni_rt; i++)
-	{
-
-		if (data->iptype == IPA_IP_v4)
-		{
-			if ((data->ipv4_addr == get_rt_ruleptr(route_rule, i)->v4_addr) &&
-					(data->ipv4_addr_mask == get_rt_ruleptr(route_rule, i)->v4_addr_mask))
-			{
-				for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
-				{
-		            if(data->iptype != tx_prop->tx[tx_index].ip)
-		            {
-		            	IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule added\n", 
-		            					    tx_index, tx_prop->tx[tx_index].ip,data->iptype);		
-		            	continue;
-		            }		
-
-					if (m_routing.DeleteRoutingHdl(get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index],
-																				 IPA_IP_v4) == false)
-					{
-						IPACMERR("Routing rule deletion failed!\n");
-						return IPACM_FAILURE;
-					}
-				}
-
-				/* remove that delted route rule entry*/
-				for (; i < num_uni_rt; i++)
-				{
-					get_rt_ruleptr(route_rule, i)->v4_addr = get_rt_ruleptr(route_rule, (i + 1))->v4_addr;
-					get_rt_ruleptr(route_rule, i)->v4_addr_mask = get_rt_ruleptr(route_rule, (i + 1))->v4_addr_mask;
-					get_rt_ruleptr(route_rule, i)->v6_addr[0] = get_rt_ruleptr(route_rule, (i + 1))->v6_addr[0];
-					get_rt_ruleptr(route_rule, i)->v6_addr[1] = get_rt_ruleptr(route_rule, (i + 1))->v6_addr[1];
-					get_rt_ruleptr(route_rule, i)->v6_addr[2] = get_rt_ruleptr(route_rule, (i + 1))->v6_addr[2];
-					get_rt_ruleptr(route_rule, i)->v6_addr[3] = get_rt_ruleptr(route_rule, (i + 1))->v6_addr[3];
-					get_rt_ruleptr(route_rule, i)->ip = get_rt_ruleptr(route_rule, (i + 1))->ip;
-
-					for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
-					{
-						get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index] = get_rt_ruleptr(route_rule, (i + 1))->rt_rule_hdl[tx_index];
-					}
-				}
-
-				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;
-			}
-		}
-	
-	}
-
-	return IPACM_FAILURE;
-}
-
-/* handle unicast routing rule del event */
-int IPACM_Lan::handle_route_del_evt_v6(ipacm_event_data_all *data)
-{
-	int i,v6_num;
-	uint32_t tx_index;
-
-	if (tx_prop == NULL)
-	{
-		IPACMDBG("No Tx properties registered for iface %s\n", dev_name);
-		return IPACM_SUCCESS;
-	}
-
-	/* delete 1 unicast RT rule with 2 entries */
-	for (i = 0; i < num_uni_rt; i++)
-	{
-	    if (data->iptype == IPA_IP_v6)
-		{
-			if ((data->ipv6_addr[0] == get_rt_ruleptr(route_rule, i)->v6_addr[0]) &&
-					(data->ipv6_addr[1] == get_rt_ruleptr(route_rule, i)->v6_addr[1]) &&
-					(data->ipv6_addr[2] == get_rt_ruleptr(route_rule, i)->v6_addr[2]) &&
-					(data->ipv6_addr[3] == get_rt_ruleptr(route_rule, i)->v6_addr[3]))
-			{
-				for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
-				{
-		                        if(data->iptype != tx_prop->tx[tx_index].ip)
-		                        {
-		            	               IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule added\n", 
-		            					    tx_index, tx_prop->tx[tx_index].ip,data->iptype);		
-		            	               continue;
-		                        }		
-
-					if (m_routing.DeleteRoutingHdl(get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index],
-																				 IPA_IP_v6) == false)
-					{
-						IPACMERR("Routing rule deletion failed!\n");
-						return IPACM_FAILURE;
-					}
-				
-					/* also delete the v6 rules for rt_tbl_wan_v6*/
-					if (m_routing.DeleteRoutingHdl(get_rt_ruleptr(route_rule, i+1)->rt_rule_hdl[tx_index],
-																				 IPA_IP_v6) == false)
-					{
-						IPACMERR("Routing rule deletion failed!\n");
-						return IPACM_FAILURE;
-					}				
-				}
-
-				/* remove that delted route rule entry*/
-				for (; i < num_uni_rt; i++)
-				{
-					for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
-					{
-						get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index] = get_rt_ruleptr(route_rule, (i + 2))->rt_rule_hdl[tx_index];
-					}
-					get_rt_ruleptr(route_rule, i)->v4_addr = get_rt_ruleptr(route_rule, (i + 2))->v4_addr;
-					get_rt_ruleptr(route_rule, i)->v4_addr_mask = get_rt_ruleptr(route_rule, (i + 2))->v4_addr_mask;
-					get_rt_ruleptr(route_rule, i)->v6_addr[0] = get_rt_ruleptr(route_rule, (i + 2))->v6_addr[0];
-					get_rt_ruleptr(route_rule, i)->v6_addr[1] = get_rt_ruleptr(route_rule, (i + 2))->v6_addr[1];
-					get_rt_ruleptr(route_rule, i)->v6_addr[2] = get_rt_ruleptr(route_rule, (i + 2))->v6_addr[2];
-					get_rt_ruleptr(route_rule, i)->v6_addr[3] = get_rt_ruleptr(route_rule, (i + 2))->v6_addr[3];
-					get_rt_ruleptr(route_rule, i)->ip = get_rt_ruleptr(route_rule, (i + 2))->ip;
-
-				}
-
-				num_uni_rt -= 2;
-				
-				/* remove this ipv6-address from LAN client*/
-				for(v6_num = 0;v6_num < ipv6_set;v6_num++)
-	            {
-			        if( data->ipv6_addr[0] == v6_addr[v6_num][0] && 
-			             data->ipv6_addr[1] == v6_addr[v6_num][1] &&
-			  	          data->ipv6_addr[2]== v6_addr[v6_num][2] && 
-			  	           data->ipv6_addr[3] == v6_addr[v6_num][3])
-			        {
-			  	        IPACMDBG("Delete this ipv6 addr for LAN iface \n");						
-						/* remove that delted route rule entry*/
-				        for (; v6_num <= ipv6_set; v6_num++)
-				        {
-					       v6_addr[v6_num][0] = v6_addr[v6_num+1][0];
-					       v6_addr[v6_num][1] = v6_addr[v6_num+1][1];
-					       v6_addr[v6_num][2] = v6_addr[v6_num+1][2];
-					       v6_addr[v6_num][3] = v6_addr[v6_num+1][3];				        	
-				        }						
-						ipv6_set-=1;						
-			  	        IPACMDBG("left %d ipv6-addr for LAN iface \n",ipv6_set);						
-			  		    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;
-			}
-		}
-	}
-	return IPACM_FAILURE;
-}
-
 /* delete filter rule for wan_down event for IPv4*/
 int IPACM_Lan::handle_wan_down(bool is_sta_mode)
 {
@@ -1369,16 +794,51 @@
 /* handle ETH client initial, construct full headers (tx property) */
 int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr)
 {
+
+#define ETH_IFACE_INDEX_LEN 2
+
 	int res = IPACM_SUCCESS, len = 0;
+	char index[ETH_IFACE_INDEX_LEN];
 	struct ipa_ioc_copy_hdr sCopyHeader;
 	struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
     uint32_t cnt;
+	int clnt_indx;
+	
+	clnt_indx = get_eth_client_index(mac_addr);
+	
+	if (clnt_indx != IPACM_INVALID_INDEX)
+	{
+		IPACMERR("eth client is found/attached already with index %d \n", clnt_indx);
+		return IPACM_FAILURE;
+	}	
 
+	/* add header to IPA */
+	if (num_eth_client >= IPA_MAX_NUM_ETH_CLIENTS)
+	{
+		IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_ETH_CLIENTS);
+		return IPACM_FAILURE;
+	}
+
+	IPACMDBG("ETH client number: %d\n", num_eth_client);	
+	
+	memcpy(get_client_memptr(eth_client, num_eth_client)->mac,
+				 mac_addr,
+				 sizeof(get_client_memptr(eth_client, num_eth_client)->mac));
+	
+	
 	IPACMDBG("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
 					 mac_addr[0], mac_addr[1], mac_addr[2],
 					 mac_addr[3], mac_addr[4], mac_addr[5]);
 
-	/* add header to IPA */
+	IPACMDBG("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+					 get_client_memptr(eth_client, num_eth_client)->mac[0],
+					 get_client_memptr(eth_client, num_eth_client)->mac[1],
+					 get_client_memptr(eth_client, num_eth_client)->mac[2],
+					 get_client_memptr(eth_client, num_eth_client)->mac[3],
+					 get_client_memptr(eth_client, num_eth_client)->mac[4],
+					 get_client_memptr(eth_client, num_eth_client)->mac[5]);
+
+	/* add header to IPA */ 
 	if(tx_prop != NULL)
 	{
 		len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
@@ -1437,10 +897,16 @@
 								memset(pHeaderDescriptor->hdr[0].name, 0,
 											 sizeof(pHeaderDescriptor->hdr[0].name));
 
+								sprintf(index, "%d", ipa_if_num);
+								strncpy(pHeaderDescriptor->hdr[0].name, index, sizeof(index));
+								
 								strncat(pHeaderDescriptor->hdr[0].name,
 												IPA_ETH_HDR_NAME_v4,
 												sizeof(IPA_ETH_HDR_NAME_v4));
 
+								sprintf(index, "%d", header_name_count);
+								strncat(pHeaderDescriptor->hdr[0].name, index, sizeof(index));
+
 								pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
 								pHeaderDescriptor->hdr[0].hdr_hdl = -1;
 								pHeaderDescriptor->hdr[0].is_partial = 0;
@@ -1454,11 +920,13 @@
 						goto fail;
 					 }
 
-					ETH_hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
-					ipv4_header_set = true ;
-					IPACMDBG(" ETH v4 full header name:%s header handle:(0x%x)\n",
-										 pHeaderDescriptor->hdr[0].name,
-												 ETH_hdr_hdl_v4);
+					get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
+					IPACMDBG("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n",
+												 num_eth_client,
+												 pHeaderDescriptor->hdr[0].name,
+												 get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v4);
+									get_client_memptr(eth_client, num_eth_client)->ipv4_header_set=true;	
+
 					break;  
 				 }
 		}
@@ -1512,10 +980,16 @@
 				memset(pHeaderDescriptor->hdr[0].name, 0,
 					 sizeof(pHeaderDescriptor->hdr[0].name));
 
+				sprintf(index, "%d", ipa_if_num);
+				strncpy(pHeaderDescriptor->hdr[0].name, index, sizeof(index));
+
 				strncat(pHeaderDescriptor->hdr[0].name,
 						IPA_ETH_HDR_NAME_v6,
 						sizeof(IPA_ETH_HDR_NAME_v6));
 
+				sprintf(index, "%d", header_name_count);
+				strncat(pHeaderDescriptor->hdr[0].name, index, sizeof(index));
+						
 				pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
 				pHeaderDescriptor->hdr[0].hdr_hdl = -1;
 				pHeaderDescriptor->hdr[0].is_partial = 0;
@@ -1529,60 +1003,457 @@
 					goto fail;
 				}
 
-				ETH_hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
-				ipv6_header_set = true ;
-				IPACMDBG(" ETH v4 full header name:%s header handle:(0x%x)\n",
-									 pHeaderDescriptor->hdr[0].name,
-											 ETH_hdr_hdl_v6);	
+				get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
+				IPACMDBG("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n",
+						 num_eth_client,
+						 pHeaderDescriptor->hdr[0].name,
+									 get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v6);
+						 
+									get_client_memptr(eth_client, num_eth_client)->ipv6_header_set=true;			   
+
 				break;  
 
 			}
 		}
 	}
+	/* initialize wifi client*/
+	get_client_memptr(eth_client, num_eth_client)->route_rule_set_v4 = false;
+    get_client_memptr(eth_client, num_eth_client)->route_rule_set_v6 = 0;
+	get_client_memptr(eth_client, num_eth_client)->ipv4_set = false;
+    get_client_memptr(eth_client, num_eth_client)->ipv6_set = 0;
+	num_eth_client++;
+	header_name_count++; //keep increasing header_name_count
+	res = IPACM_SUCCESS;
+	IPACMDBG("eth client number: %d\n", num_eth_client);
+
 fail:
 	free(pHeaderDescriptor);
 
 	return res;
 }
 
-/*handle wlan iface down event*/
+/*handle eth client */
+int IPACM_Lan::handle_eth_client_ipaddr(ipacm_event_data_all *data)
+{
+	int clnt_indx;
+	int v6_num;
+
+	IPACMDBG("number of eth clients: %d\n", num_eth_client);
+	IPACMDBG(" event MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+					 data->mac_addr[0],
+					 data->mac_addr[1],
+					 data->mac_addr[2],
+					 data->mac_addr[3],
+					 data->mac_addr[4],
+					 data->mac_addr[5]);
+
+	clnt_indx = get_eth_client_index(data->mac_addr);
+
+		if (clnt_indx == IPACM_INVALID_INDEX)
+		{
+			IPACMERR("eth client not found/attached \n");
+			return IPACM_FAILURE;
+		}
+
+	IPACMDBG("Ip-type received %d\n", data->iptype);
+	if (data->iptype == IPA_IP_v4)
+	{
+		IPACMDBG("ipv4 address: 0x%x\n", data->ipv4_addr);
+		if (data->ipv4_addr != 0) /* not 0.0.0.0 */
+		{
+			if (get_client_memptr(eth_client, clnt_indx)->ipv4_set == false)
+			{
+				get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr;
+				get_client_memptr(eth_client, clnt_indx)->ipv4_set = true;
+			}
+			else
+			{
+			   /* check if client got new IPv4 address*/
+			   if(data->ipv4_addr == get_client_memptr(eth_client, clnt_indx)->v4_addr)
+			   {
+			     IPACMDBG("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx);
+				 return IPACM_FAILURE;
+			   }
+			   else
+			   {
+			     IPACMDBG("ipv4 addr for client:%d is changed \n", clnt_indx);
+			     delete_eth_rtrules(clnt_indx,IPA_IP_v4);
+		         get_client_memptr(eth_client, clnt_indx)->route_rule_set_v4 = false;
+			     get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr;
+			}
+		}
+	}
+	else
+	{
+		    IPACMDBG("Invalid client IPv4 address \n");
+		    return IPACM_FAILURE;
+		}
+	}
+	else
+	{
+		if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) ||
+				(data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] || 0)) /* check if all 0 not valid ipv6 address */
+		{
+		   IPACMDBG("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
+                   if(get_client_memptr(eth_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR)		
+		   {
+		   
+		       for(v6_num=0;v6_num < get_client_memptr(eth_client, clnt_indx)->ipv6_set;v6_num++)
+	               {
+			      if( data->ipv6_addr[0] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][0] && 
+			           data->ipv6_addr[1] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][1] &&
+			  	        data->ipv6_addr[2]== get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][2] && 
+			  	         data->ipv6_addr[3] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][3])
+			      {
+			  	    IPACMDBG("Already see this ipv6 addr for client:%d\n", clnt_indx);
+			  	    return IPACM_FAILURE; /* not setup the RT rules*/
+			  		break;
+			      }  
+		       }	   
+		   
+		       /* not see this ipv6 before for wifi client*/
+			   get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0];
+			   get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1];
+			   get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2];
+			   get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3];
+			   get_client_memptr(eth_client, clnt_indx)->ipv6_set++;
+		    }
+		    else
+		    {
+		         IPACMDBG("Already got 3 ipv6 addr for client:%d\n", clnt_indx);
+			 return IPACM_FAILURE; /* not setup the RT rules*/
+		    }
+		}
+	}
+
+	return IPACM_SUCCESS;
+}
+
+/*handle eth client routing rule*/
+int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype)
+{
+	struct ipa_ioc_add_rt_rule *rt_rule;
+	struct ipa_rt_rule_add *rt_rule_entry;
+	uint32_t tx_index;
+	int eth_index,v6_num;
+	const int NUM = 1;
+
+	if(tx_prop == NULL)
+	{
+		IPACMDBG("No rx properties registered for iface %s\n", dev_name);
+		return IPACM_SUCCESS;
+	}
+
+	IPACMDBG("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+					 mac_addr[0], mac_addr[1], mac_addr[2],
+					 mac_addr[3], mac_addr[4], mac_addr[5]);
+
+	eth_index = get_eth_client_index(mac_addr);
+	if (eth_index == IPACM_INVALID_INDEX)
+	{
+		IPACMDBG("eth client not found/attached \n");
+		return IPACM_SUCCESS;
+	}
+
+	if (iptype==IPA_IP_v4) {
+		IPACMDBG("eth client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", eth_index, iptype,
+					 get_client_memptr(eth_client, eth_index)->ipv4_set,
+					 get_client_memptr(eth_client, eth_index)->route_rule_set_v4);
+	} else {
+		IPACMDBG("eth client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", eth_index, iptype,
+					 get_client_memptr(eth_client, eth_index)->ipv6_set,
+					 get_client_memptr(eth_client, eth_index)->route_rule_set_v6);
+	}
+	
+	/* Add default routing rules if not set yet */
+	if ((iptype == IPA_IP_v4
+			 && get_client_memptr(eth_client, eth_index)->route_rule_set_v4 == false
+			 && get_client_memptr(eth_client, eth_index)->ipv4_set == true)
+			|| (iptype == IPA_IP_v6
+		            && get_client_memptr(eth_client, eth_index)->route_rule_set_v6 < get_client_memptr(eth_client, eth_index)->ipv6_set
+					))
+	{
+	
+        /* 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],false);	
+	
+		rt_rule = (struct ipa_ioc_add_rt_rule *)
+			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
+						NUM * sizeof(struct ipa_rt_rule_add));
+
+		if (rt_rule == NULL)
+		{
+			PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n");
+			return IPACM_FAILURE;
+		}
+
+		rt_rule->commit = 1;
+		rt_rule->num_rules = (uint8_t)NUM;
+		rt_rule->ip = iptype;
+
+		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+		{
+			if(iptype != tx_prop->tx[tx_index].ip)
+		    {
+				IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n", 
+						tx_index, tx_prop->tx[tx_index].ip,iptype);		
+		   	        continue;
+		    }	   
+			
+  	   	    rt_rule_entry = &rt_rule->rules[0];
+			rt_rule_entry->at_rear = 0;
+
+			if (iptype == IPA_IP_v4)
+			{
+		        IPACMDBG("client index(%d):ipv4 address: 0x%x\n", eth_index, 
+		  		        get_client_memptr(eth_client, eth_index)->v4_addr);
+          
+                IPACMDBG("client(%d): v4 header handle:(0x%x)\n",
+		  				 eth_index,
+		  				 get_client_memptr(eth_client, eth_index)->hdr_hdl_v4);
+				strncpy(rt_rule->rt_tbl_name,
+								IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name,
+								sizeof(rt_rule->rt_tbl_name));
+	   
+
+			    rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+			    memcpy(&rt_rule_entry->rule.attrib,
+						 &tx_prop->tx[tx_index].attrib,
+						 sizeof(rt_rule_entry->rule.attrib));
+			    rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+		   	    rt_rule_entry->rule.hdr_hdl = get_client_memptr(eth_client, eth_index)->hdr_hdl_v4;
+				rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(eth_client, eth_index)->v4_addr;
+				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
+
+			    if (false == m_routing.AddRoutingRule(rt_rule))
+  	            {
+  	          	            IPACMERR("Routing rule addition failed!\n");
+  	          	            free(rt_rule);
+  	          	            return IPACM_FAILURE;
+			    }
+			  
+			    /* copy ipv4 RT hdl */
+		        get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4 =
+  	   	        rt_rule->rules[0].rt_rule_hdl;
+		        IPACMDBG("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, 
+		      	get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4, iptype);
+		  
+  	   	    } else {
+		   
+		        for(v6_num = get_client_memptr(eth_client, eth_index)->route_rule_set_v6;v6_num < get_client_memptr(eth_client, eth_index)->ipv6_set;v6_num++)
+			    {
+                    IPACMDBG("client(%d): v6 header handle:(0x%x)\n",
+		  	    			 eth_index,
+		  	    			 get_client_memptr(eth_client, eth_index)->hdr_hdl_v6);
+	            
+		            /* v6 LAN_RT_TBL */
+			    	strncpy(rt_rule->rt_tbl_name,
+			    					IPACM_Iface::ipacmcfg->rt_tbl_v6.name,
+			    					sizeof(rt_rule->rt_tbl_name));
+					
+		            /* Support QCMAP LAN traffic feature, send to A5 */
+					rt_rule_entry->rule.dst = iface_query->excp_pipe;
+			        memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
+		   	        rt_rule_entry->rule.hdr_hdl = 0;
+			        rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][0];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][1];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][2];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][3];
+					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
+					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;
+                    
+   	                if (false == m_routing.AddRoutingRule(rt_rule))
+  	                {
+  	                	    IPACMERR("Routing rule addition failed!\n");
+  	                	    free(rt_rule);
+  	                	    return IPACM_FAILURE;
+			        }
+
+		            get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[v6_num] = rt_rule->rules[0].rt_rule_hdl;
+		            IPACMDBG("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, 
+		            				 get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[v6_num], iptype);
+			        
+			        /*Copy same rule to v6 WAN RT TBL*/
+  	                strncpy(rt_rule->rt_tbl_name,
+  	                 					IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name,
+  	                 					sizeof(rt_rule->rt_tbl_name));
+   	                
+                    /* Downlink traffic from Wan iface, directly through IPA */
+					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+			        memcpy(&rt_rule_entry->rule.attrib,
+						 &tx_prop->tx[tx_index].attrib,
+						 sizeof(rt_rule_entry->rule.attrib));
+		   	        rt_rule_entry->rule.hdr_hdl = get_client_memptr(eth_client, eth_index)->hdr_hdl_v6;
+			        rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][0];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][1];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][2];
+		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][3];
+					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
+					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;
+   	                
+		            if (false == m_routing.AddRoutingRule(rt_rule))
+		            {
+							IPACMERR("Routing rule addition failed!\n");
+							free(rt_rule);
+							return IPACM_FAILURE;
+		            }
+
+		            get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl;
+					IPACMDBG("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, 
+		            				 get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[v6_num], iptype);			  
+			    }
+			}
+		   
+  	    } /* end of for loop */
+
+		free(rt_rule);
+
+		if (iptype == IPA_IP_v4)
+		{
+			get_client_memptr(eth_client, eth_index)->route_rule_set_v4 = true;
+		}
+		else
+		{
+			get_client_memptr(eth_client, eth_index)->route_rule_set_v6 = get_client_memptr(eth_client, eth_index)->ipv6_set;
+		}
+	}
+
+	return IPACM_SUCCESS;
+}
+
+/*handle eth client del mode*/
+int IPACM_Lan::handle_eth_client_down_evt(uint8_t *mac_addr)
+{
+	int clt_indx;
+	uint32_t tx_index;
+	int num_eth_client_tmp = num_eth_client;
+	int num_v6;
+
+	IPACMDBG("total client: %d\n", num_eth_client_tmp);
+
+	clt_indx = get_eth_client_index(mac_addr);
+	if (clt_indx == IPACM_INVALID_INDEX)
+	{
+		IPACMDBG("eth client not attached\n");
+		return IPACM_SUCCESS;
+	}
+
+	/* First reset nat rules and then route rules */
+	if(get_client_memptr(eth_client, clt_indx)->ipv4_set == true)
+	{
+	        IPACMDBG("Deleting Nat Rules\n");
+	        Nat_App->UpdatePwrSaveIf(get_client_memptr(eth_client, clt_indx)->v4_addr);
+ 	}	
+	
+	if (delete_eth_rtrules(clt_indx, IPA_IP_v4))
+	{
+		IPACMERR("unbale to delete ecm-client v4 route rules\n");
+		return IPACM_FAILURE;
+	}
+
+	if (delete_eth_rtrules(clt_indx, IPA_IP_v6))
+	{
+		IPACMERR("unbale to delete ecm-client v6 route rules\n");
+		return IPACM_FAILURE;
+	}
+
+	/* Delete eth client header */
+	if(get_client_memptr(eth_client, clt_indx)->ipv4_header_set == true)
+	{
+		if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, clt_indx)->hdr_hdl_v4)
+				== false)
+		{
+			return IPACM_FAILURE;
+		}
+		get_client_memptr(eth_client, clt_indx)->ipv4_header_set = false;
+	}
+
+	if(get_client_memptr(eth_client, clt_indx)->ipv6_header_set == true)
+	{
+		if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, clt_indx)->hdr_hdl_v6)
+				== false)
+		{
+			return IPACM_FAILURE;
+		}
+		get_client_memptr(eth_client, clt_indx)->ipv6_header_set = false;
+	}
+
+	/* Reset ip_set to 0*/
+	get_client_memptr(eth_client, clt_indx)->ipv4_set = false;
+	get_client_memptr(eth_client, clt_indx)->ipv6_set = 0;
+	get_client_memptr(eth_client, clt_indx)->ipv4_header_set = false;
+	get_client_memptr(eth_client, clt_indx)->ipv6_header_set = false;
+	get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = false;
+	get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = 0;
+
+	for (; clt_indx < num_eth_client_tmp - 1; clt_indx++)
+	{
+		memcpy(get_client_memptr(eth_client, clt_indx)->mac,
+					 get_client_memptr(eth_client, (clt_indx + 1))->mac,
+					 sizeof(get_client_memptr(eth_client, clt_indx)->mac));
+
+		get_client_memptr(eth_client, clt_indx)->hdr_hdl_v4 = get_client_memptr(eth_client, (clt_indx + 1))->hdr_hdl_v4;
+		get_client_memptr(eth_client, clt_indx)->hdr_hdl_v6 = get_client_memptr(eth_client, (clt_indx + 1))->hdr_hdl_v6;
+		get_client_memptr(eth_client, clt_indx)->v4_addr = get_client_memptr(eth_client, (clt_indx + 1))->v4_addr;
+
+		get_client_memptr(eth_client, clt_indx)->ipv4_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv4_set;
+		get_client_memptr(eth_client, clt_indx)->ipv6_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv6_set;
+		get_client_memptr(eth_client, clt_indx)->ipv4_header_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv4_header_set;
+		get_client_memptr(eth_client, clt_indx)->ipv6_header_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv6_header_set;
+
+		get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = get_client_memptr(eth_client, (clt_indx + 1))->route_rule_set_v4;
+		get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = get_client_memptr(eth_client, (clt_indx + 1))->route_rule_set_v6;
+
+        for (num_v6=0;num_v6< get_client_memptr(eth_client, clt_indx)->ipv6_set;num_v6++)	 
+	    {					
+		    get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][0] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][0];
+		    get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][1] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][1];
+		    get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][2] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][2];
+		    get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6][3] = get_client_memptr(eth_client, (clt_indx + 1))->v6_addr[num_v6][3]; 
+        }
+
+		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+		{
+			get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4 =
+				 get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4;
+
+			for(num_v6=0;num_v6< get_client_memptr(eth_client, clt_indx)->route_rule_set_v6;num_v6++)	 
+			{
+			  get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6] =
+			   	 get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6];
+			  get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6] =
+			   	 get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6];
+		    }
+		}
+	}
+
+	IPACMDBG(" %d eth client deleted successfully \n", num_eth_client);
+	num_eth_client = num_eth_client - 1;
+	IPACMDBG(" Number of eth client: %d\n", num_eth_client);
+
+	/* Del RM dependency */
+	if(num_eth_client == 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;
+}
+
+/*handle LAN iface down event*/
 int IPACM_Lan::handle_down_evt()
 {
 	int i;
 	uint32_t tx_index;
 	int res = IPACM_SUCCESS;
 
-	
-	if (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat == ETH_IF)
-	{
-		
-		/* delete full header */
-		if (ipv4_header_set)
-		{
-			if (m_header.DeleteHeaderHdl(ETH_hdr_hdl_v4)
-					== false)
-			{
-					IPACMDBG("ETH ipv4 header delete fail\n");
-					res = IPACM_FAILURE;
-					goto fail;
-			}
-			IPACMDBG("ETH ipv4 header delete success\n");
-		}
-
-		if (ipv6_header_set)
-		{
-			if (m_header.DeleteHeaderHdl(ETH_hdr_hdl_v6)
-					== false)
-			{
-				IPACMDBG("ETH ipv6 header delete fail\n");
-				res = IPACM_FAILURE;
-				goto fail;
-			}
-			IPACMDBG("ETH ipv6 header delete success\n");
-		}
-	}
-	
-	
 	/* no iface address up, directly close iface*/
 	if (ip_type == IPACM_IP_NULL)
 	{
@@ -1620,39 +1491,43 @@
 		}
 	}
 
-        IPACMDBG("Finished delete default iface ipv6 rules \n ");	
-
-	/* free unicast routing rule	*/
-	if (tx_prop != NULL)
+	IPACMDBG("Finished delete default iface ipv6 rules \n ");	
+	/* clean eth-client header, routing rules */
+	IPACMDBG("left %d eth clients need to be deleted \n ", num_eth_client);
+	for (i = 0; i < num_eth_client; i++)
 	{
-		for (i = 0; i < num_uni_rt; i++)
-		{
-			for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
+			delete_eth_rtrules(i, IPA_IP_v4);
+			delete_eth_rtrules(i, IPA_IP_v6);
+	
+			IPACMDBG("Delete %d client header\n", num_eth_client);
+	
+	
+			if(get_client_memptr(eth_client, i)->ipv4_header_set == true)
 			{
-							if(get_rt_ruleptr(route_rule, i)->ip != tx_prop->tx[tx_index].ip)
-							{
-	    	            	                            IPACMDBG("Tx:%d, ip-type: %d conflict ip-type: %d no unicast LAN RT-rule deleted, index: %d\n", 
-	    	            					    tx_index, tx_prop->tx[tx_index].ip,get_rt_ruleptr(route_rule, i)->ip,i);		
-										continue;
-							}		
-
-				IPACMDBG("Tx:%d, ip-type: %d - ip-type: %d Delete unicast LAN RT-rule deleted index: %d\n", 
-         					    tx_index, tx_prop->tx[tx_index].ip,get_rt_ruleptr(route_rule, i)->ip,i);		
-
-				if (m_routing.DeleteRoutingHdl(get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index],
-																			 get_rt_ruleptr(route_rule, i)->ip) == false)
+			if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v4)
+					== false)
 				{
-					IPACMERR("Routing rule 0x%x deletion failed!\n",get_rt_ruleptr(route_rule, i)->rt_rule_hdl[tx_index]);
 					res = IPACM_FAILURE;
 					goto fail;
 				}
 			}
+	
+			if(get_client_memptr(eth_client, i)->ipv6_header_set == true)
+			{
+			if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v6)
+					== false)
+			{
+				res = IPACM_FAILURE;
+				goto fail;
+			}
+			}		
+	} /* end of for loop */
+	
+	/* free the edm clients cache */
+	IPACMDBG("Free ecm clients cache\n");
 
-		}
-	}
-
-        /* 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]);				
+	/* 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)
@@ -1713,16 +1588,13 @@
 		IPACMDBG("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode);
 		handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode);
 	}
-
+	
 fail:
 	/* 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]);	
 	IPACMDBG("Finished delete dependency \n ");
 
-	if (route_rule != NULL)
-	{
-		free(route_rule);
-	}
+	free(eth_client);
 
 	if (tx_prop != NULL)
 	{