Merge "ipacm: offload 11AD clients" into data.lnx.5.1
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h
index 524f4ac..af1b616 100644
--- a/ipacm/inc/IPACM_Config.h
+++ b/ipacm/inc/IPACM_Config.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -99,7 +99,7 @@
 	/* Store the non nat iface names */
 	NatIfaces *pNatIfaces;
 
-	/* Store the bridge iface names */
+	/* Store the bridge iface name */
 	char ipa_virtual_iface_name[IPA_IFACE_NAME_LEN];
 
 	/* Store the number of interface IPACM read from XML file */
diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h
index 051184d..59a8bb2 100644
--- a/ipacm/inc/IPACM_Defs.h
+++ b/ipacm/inc/IPACM_Defs.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -197,6 +197,8 @@
 #endif
 	IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE,
 	IPA_LAN_DELETE_SELF,                      /* ipacm_event_data_fid */
+	IPA_WIGIG_CLIENT_ADD_EVENT,               /* ipacm_event_data_mac_ep */
+	IPA_WIGIG_FST_SWITCH,                     /* ipacm_event_data_fst */
 	IPACM_EVENT_MAX
 } ipa_cm_event_id;
 
@@ -275,6 +277,7 @@
 	ipa_ip_type iptype;
 	uint8_t mac_addr[6];
 	char iface_name[IPA_IFACE_NAME_LEN];
+	int ep;
 } ipacm_event_eth_bridge;
 
 typedef struct
@@ -328,6 +331,20 @@
 	uint8_t mac_addr[IPA_MAC_ADDR_SIZE];
 } ipacm_event_data_mac;
 
+typedef struct _ipacm_event_data_mac_ep
+{
+	int if_index;
+	enum ipa_client_type client;
+	uint8_t mac_addr[IPA_MAC_ADDR_SIZE];
+} ipacm_event_data_mac_ep;
+
+typedef struct _ipacm_event_data_fst
+{
+	int if_index;
+	bool to_wigig;
+	uint8_t mac_addr[IPA_MAC_ADDR_SIZE];
+} ipacm_event_data_fst;
+
 typedef struct
 {
 	int if_index;
diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h
index 03219c5..700dfbc 100644
--- a/ipacm/inc/IPACM_Lan.h
+++ b/ipacm/inc/IPACM_Lan.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -151,7 +151,7 @@
 
 	/* add routing rule and return handle to lan2lan controller */
 	int eth_bridge_add_rt_rule(uint8_t *mac, char *rt_tbl_name, uint32_t hdr_proc_ctx_hdl,
-		ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int *rt_rule_count);
+		ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int *rt_rule_count, int ep);
 
 	/* modify routing rule*/
 	int eth_bridge_modify_rt_rule(uint8_t *mac, uint32_t hdr_proc_ctx_hdl,
@@ -209,7 +209,7 @@
 
 	/* mac address has to be provided for client related events */
 	void eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac,
-		uint32_t *ipv6_addr, char *iface_name);
+		uint32_t *ipv6_addr, char *iface_name, int ep);
 
 #ifdef FEATURE_L2TP
 	/* check if the event is associated with vlan interface */
@@ -282,6 +282,10 @@
 
 private:
 
+	int set_client_pipe(enum ipa_client_type client, uint32_t *pipe);
+	int set_tether_client(wan_ioctl_set_tether_client_pipe *tether_client);
+	int set_tether_client_wigig(wan_ioctl_set_tether_client_pipe *tether_client);
+
 	/* get hdr proc ctx type given source and destination l2 hdr type */
 	ipa_hdr_proc_type eth_bridge_get_hdr_proc_type(ipa_hdr_l2_type t1, ipa_hdr_l2_type t2);
 
diff --git a/ipacm/inc/IPACM_LanToLan.h b/ipacm/inc/IPACM_LanToLan.h
index e517e97..66a1835 100644
--- a/ipacm/inc/IPACM_LanToLan.h
+++ b/ipacm/inc/IPACM_LanToLan.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2014-2019, 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
@@ -102,6 +102,7 @@
 	bool is_l2tp_client;
 	l2tp_vlan_mapping_info *mapping_info;
 	l2tp_rt_rule_info l2tp_rt_rule_hdl[IPA_HDR_L2_MAX];
+	int ep;
 };
 
 struct flt_rule_info
@@ -141,7 +142,7 @@
 	void handle_new_iface_up(char rt_tbl_name_for_flt[][IPA_RESOURCE_NAME_MAX], char rt_tbl_name_for_rt[][IPA_RESOURCE_NAME_MAX],
 		IPACM_LanToLan_Iface *peer_iface);
 
-	void handle_client_add(uint8_t *mac, bool is_l2tp_client, l2tp_vlan_mapping_info *mapping_info);
+	void handle_client_add(uint8_t *mac, bool is_l2tp_client, l2tp_vlan_mapping_info *mapping_info, int ep);
 
 	void handle_client_del(uint8_t *mac);
 
diff --git a/ipacm/inc/IPACM_Wlan.h b/ipacm/inc/IPACM_Wlan.h
index 94623f9..f3c6d65 100644
--- a/ipacm/inc/IPACM_Wlan.h
+++ b/ipacm/inc/IPACM_Wlan.h
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -71,6 +71,7 @@
 	bool ipv4_header_set;
 	bool ipv6_header_set;
 	bool power_save_set;
+	enum ipa_client_type wigig_ipa_client;
 	wlan_client_rt_hdl wifi_rt_hdl[0]; /* depends on number of tx properties */
 }ipa_wlan_client;
 
@@ -211,6 +212,8 @@
 		return IPACM_SUCCESS;
 	}
 
+	int handle_wigig_client_add(ipacm_event_data_mac_ep *data);
+
 	/* for handle wifi client initial,copy all partial headers (tx property) */
 	int handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data);
 
diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp
index 90d3647..bfacd7c 100644
--- a/ipacm/src/IPACM_Config.cpp
+++ b/ipacm/src/IPACM_Config.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -106,8 +106,7 @@
 	__stringify(IPA_ETH_BRIDGE_CLIENT_ADD),                /* ipacm_event_eth_bridge*/
 	__stringify(IPA_ETH_BRIDGE_CLIENT_DEL),                /* ipacm_event_eth_bridge*/
 	__stringify(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH),       /* ipacm_event_eth_bridge*/
-	__stringify(IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE),       /* ipacm_event_iface*/
-	__stringify(IPA_LAN_DELETE_SELF),                      /* ipacm_event_data_fid */
+	__stringify(IPA_SSR_NOTICE)			       /* NULL*/
 #ifdef FEATURE_L2TP
 	__stringify(IPA_ADD_VLAN_IFACE),                       /* ipa_ioc_vlan_iface_info */
 	__stringify(IPA_DEL_VLAN_IFACE),                       /* ipa_ioc_vlan_iface_info */
@@ -116,6 +115,10 @@
 	__stringify(IPA_VLAN_CLIENT_INFO),                     /* ipacm_event_data_all */
 	__stringify(IPA_VLAN_IFACE_INFO),                      /* ipacm_event_data_all */
 #endif
+	__stringify(IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE),       /* ipacm_event_iface*/
+	__stringify(IPA_LAN_DELETE_SELF),                      /* ipacm_event_data_fid */
+	__stringify(IPA_WIGIG_CLIENT_ADD_EVENT),               /* ipacm_event_data_mac_ep */
+	__stringify(IPA_WIGIG_FST_SWITCH),                     /* ipacm_event_data_fst */
 	__stringify(IPACM_EVENT_MAX),
 };
 
diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp
index 248bb78..1c7dfc4 100644
--- a/ipacm/src/IPACM_IfaceManager.cpp
+++ b/ipacm/src/IPACM_IfaceManager.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -420,6 +420,7 @@
 #ifdef FEATURE_IPACM_HAL
 				IPACM_EvtDispatcher::registr(IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE, wl);
 #endif
+				IPACM_EvtDispatcher::registr(IPA_WIGIG_CLIENT_ADD_EVENT, wl);
 				/* IPA_LAN_DELETE_SELF should be always last */
 				IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, wl);
 				IPACMDBG_H("ipa_WLAN (%s):ipa_index (%d) instance open/registr ok\n", wl->dev_name, wl->ipa_if_num);
diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp
index ac80a90..fd45856 100644
--- a/ipacm/src/IPACM_Lan.cpp
+++ b/ipacm/src/IPACM_Lan.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -379,7 +379,7 @@
 			{
 				IPACMDBG_H("Got IPv6 new addr event for a vlan iface %s.\n", data->iface_name);
 				eth_bridge_post_event(IPA_HANDLE_VLAN_IFACE_INFO, data->iptype, NULL,
-					data->ipv6_addr, data->iface_name);
+					data->ipv6_addr, data->iface_name, IPA_CLIENT_MAX);
 			}
 #endif
 			if (ipa_interface_index == ipa_if_num)
@@ -973,7 +973,8 @@
 						/* Add NAT rules after ipv4 RT rules are set */
 						CtList->HandleNeighIpAddrAddEvt(data);
 					}
-					eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name);
+					eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name,
+						IPA_CLIENT_MAX);
 				}
 #ifdef FEATURE_L2TP
 				else if(is_l2tp_event(data->iface_name) && ipa_if_cate == ODU_IF)
@@ -989,13 +990,14 @@
 							IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
 						}
 					}
-					eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name);
+					eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name,
+						IPA_CLIENT_MAX);
 				}
 				else
 				{
 					if(data->iptype == IPA_IP_v6 && is_unique_local_ipv6_addr(data->ipv6_addr))
 					{
-						eth_bridge_post_event(IPA_HANDLE_VLAN_CLIENT_INFO, IPA_IP_MAX, data->mac_addr, data->ipv6_addr, data->iface_name);
+						eth_bridge_post_event(IPA_HANDLE_VLAN_CLIENT_INFO, IPA_IP_MAX, data->mac_addr, data->ipv6_addr, data->iface_name, IPA_CLIENT_MAX);
 					}
 				}
 #endif
@@ -1036,7 +1038,8 @@
 				}
 				else
 				{
-					eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name);
+					eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr, NULL, data->iface_name,
+						IPA_CLIENT_MAX);
 				}
 				return;
 			}
@@ -1361,7 +1364,7 @@
 
 		/* populate the flt rule offset for eth bridge */
 		eth_bridge_flt_rule_offset[data->iptype] = ipv4_icmp_flt_rule_hdl[0];
-		eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL, NULL, NULL);
+		eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL, NULL, NULL, IPA_CLIENT_MAX);
 	}
 	else
 	{
@@ -1463,7 +1466,7 @@
 
 			/* populate the flt rule offset for eth bridge */
 			eth_bridge_flt_rule_offset[data->iptype] = ipv6_icmp_flt_rule_hdl[0];
-			eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL, NULL, NULL);
+			eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL, NULL, NULL, IPA_CLIENT_MAX);
 
 			init_fl_rule(data->iptype);
 		}
@@ -3071,7 +3074,7 @@
 			IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
 		}
 	}
-	eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL);
+	eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL, IPA_CLIENT_MAX);
 
 /* Delete private subnet*/
 #ifdef FEATURE_IPA_ANDROID
@@ -4419,69 +4422,191 @@
 	return IPACM_SUCCESS;
 }
 
-/*handle tether client */
-int IPACM_Lan::handle_tethering_client(bool reset, ipacm_client_enum ipa_client)
+int IPACM_Lan::set_client_pipe(enum ipa_client_type client, uint32_t *pipe)
 {
-	int fd, ret = IPACM_SUCCESS;
-	uint32_t cnt;
-	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
-	wan_ioctl_set_tether_client_pipe tether_client;
+	int fd;
 
-	if(fd_wwan_ioctl < 0)
+	fd = open(IPA_DEVICE_NAME, O_RDWR);
+	if(fd < 0)
 	{
-		IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
+		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
 		return IPACM_FAILURE;
 	}
 
-	fd = open(IPA_DEVICE_NAME, O_RDWR);
-	if (fd < 0)
+	*pipe = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, client);
+
+	close(fd);
+	return IPACM_SUCCESS;
+}
+
+int IPACM_Lan::set_tether_client_wigig(wan_ioctl_set_tether_client_pipe *tether_client)
+{
+#define NUM_WIGIG_TX_PIPES 4
+
+	uint32_t cnt;
+	int ret;
+	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
+
+	if(fd_wwan_ioctl < 0)
 	{
-		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
+		IPACMERR("Failed to open %s.\n", WWAN_QMI_IOCTL_DEVICE_NAME);
+		return IPACM_FAILURE;
+	}
+
+	if(!tx_prop || !rx_prop)
+	{
+		IPACMERR("no props, can't set client %p, %p\n", rx_prop, tx_prop);
 		close(fd_wwan_ioctl);
 		return IPACM_FAILURE;
 	}
 
-	memset(&tether_client, 0, sizeof(tether_client));
-	tether_client.reset_client = reset;
-	tether_client.ipa_client = ipa_client;
+	/* only one rx pipe for wigig */
+	tether_client->ul_src_pipe_len = rx_prop->num_rx_props;
+	for(cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
+	{
+		ret = set_client_pipe(rx_prop->rx[cnt].src_pipe, &tether_client->ul_src_pipe_list[cnt]);
+		if(ret)
+		{
+			close(fd_wwan_ioctl);
+			return ret;
+		}
+		IPACMDBG_H("Rx(%d), src_pipe: %d, ipa_pipe: %d\n",
+			cnt, rx_prop->rx[cnt].src_pipe,
+			tether_client->ul_src_pipe_list[cnt]);
+	}
+
+	for(int i = 0; i < NUM_WIGIG_TX_PIPES; i++)
+	{
+		/* 4 tx pipes for wigig */
+		tether_client->dl_dst_pipe_len = tx_prop->num_tx_props;
+		for(cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
+		{
+			enum ipa_client_type client;
+
+			switch(i) {
+				case 0:
+					client = IPA_CLIENT_WIGIG1_CONS;
+					break;
+				case 1:
+					client = IPA_CLIENT_WIGIG2_CONS;
+					break;
+				case 2:
+					client = IPA_CLIENT_WIGIG3_CONS;
+					break;
+				case 3:
+					client = IPA_CLIENT_WIGIG4_CONS;
+					break;
+				default:
+					IPACMERR("shouldn't get here\n");
+					close(fd_wwan_ioctl);
+					return IPACM_FAILURE;
+			}
+			ret = set_client_pipe(client, &tether_client->dl_dst_pipe_list[cnt]);
+			if(ret)
+			{
+				close(fd_wwan_ioctl);
+				return ret;
+			}
+			IPACMDBG_H("Tx(%d), IPA_CLIENT_WIGIG%d_CONS, ipa_pipe: %d\n",
+				cnt, i + 1,
+				tether_client->dl_dst_pipe_list[cnt]);
+		}
+
+		ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, tether_client);
+		if(ret != 0)
+		{
+			IPACMERR("Failed set tether-client-pipe %p with ret %d\n ", tether_client, ret);
+		}
+		IPACMDBG("Set wigig tether-client-pipe (%d) %p\n", i, tether_client);
+	}
+
+	close(fd_wwan_ioctl);
+	return ret;
+}
+
+int IPACM_Lan::set_tether_client(wan_ioctl_set_tether_client_pipe *tether_client)
+{
+	uint32_t cnt;
+	int ret;
+	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
+
+	if(fd_wwan_ioctl < 0)
+	{
+		IPACMERR("Failed to open %s.\n", WWAN_QMI_IOCTL_DEVICE_NAME);
+		return IPACM_FAILURE;
+	}
 
 	if(tx_prop != NULL)
 	{
-		tether_client.dl_dst_pipe_len = tx_prop->num_tx_props;
-		for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
+		tether_client->dl_dst_pipe_len = tx_prop->num_tx_props;
+		for(cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
 		{
+			ret = set_client_pipe(tx_prop->tx[cnt].dst_pipe, &tether_client->dl_dst_pipe_list[cnt]);
+			if(ret)
+			{
+				close(fd_wwan_ioctl);
+				return ret;
+			}
 			IPACMDBG_H("Tx(%d), dst_pipe: %d, ipa_pipe: %d\n",
-					cnt, tx_prop->tx[cnt].dst_pipe,
-						ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe));
-			tether_client.dl_dst_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe);
+				cnt, tx_prop->tx[cnt].dst_pipe,
+				tether_client->dl_dst_pipe_list[cnt]);
 		}
 	}
 
 	if(rx_prop != NULL)
 	{
-		tether_client.ul_src_pipe_len = rx_prop->num_rx_props;
-		for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
+		tether_client->ul_src_pipe_len = rx_prop->num_rx_props;
+		for(cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
 		{
+			ret = set_client_pipe(rx_prop->rx[cnt].src_pipe, &tether_client->ul_src_pipe_list[cnt]);
+			if(ret)
+			{
+				close(fd_wwan_ioctl);
+				return ret;
+			}
 			IPACMDBG_H("Rx(%d), src_pipe: %d, ipa_pipe: %d\n",
-					cnt, rx_prop->rx[cnt].src_pipe,
-						ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe));
-			tether_client.ul_src_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe);
+				cnt, rx_prop->rx[cnt].src_pipe,
+				tether_client->ul_src_pipe_list[cnt]);
 		}
 	}
 
 	ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, &tether_client);
-	if (ret != 0)
+	if(ret != 0)
 	{
 		IPACMERR("Failed set tether-client-pipe %p with ret %d\n ", &tether_client, ret);
 	}
 	IPACMDBG("Set tether-client-pipe %p\n", &tether_client);
-	close(fd);
+
 	close(fd_wwan_ioctl);
 	return ret;
 }
 
+/*handle tether client */
+int IPACM_Lan::handle_tethering_client(bool reset, ipacm_client_enum ipa_client)
+{
+	int ret = IPACM_SUCCESS;
+	wan_ioctl_set_tether_client_pipe tether_client;
+
+	memset(&tether_client, 0, sizeof(tether_client));
+	tether_client.reset_client = reset;
+	tether_client.ipa_client = ipa_client;
+
+	/* special case for wigig (11ad) who has 4 Tx and 1 RX pipe */
+	if(!strcmp(dev_name, "wigig0"))
+	{
+		set_tether_client_wigig(&tether_client);
+	}
+	else
+	{
+		set_tether_client(&tether_client);
+	}
+
+	return ret;
+}
+
 /* mac address has to be provided for client related events */
-void IPACM_Lan::eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac, uint32_t *ipv6_addr, char *iface_name)
+void IPACM_Lan::eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac, uint32_t *ipv6_addr, char *iface_name,
+	int ep)
 {
 	ipacm_cmd_q_data eth_bridge_evt;
 	ipacm_event_eth_bridge *evt_data_eth_bridge;
@@ -4540,6 +4665,7 @@
 
 		evt_data_eth_bridge->p_iface = this;
 		evt_data_eth_bridge->iptype = iptype;
+		evt_data_eth_bridge->ep = ep;
 		if(mac)
 		{
 			IPACMDBG_H("Mac: 0x%02x%02x%02x%02x%02x%02x \n",
@@ -4605,7 +4731,8 @@
 
 /* add routing rule and return handle to lan2lan controller */
 int IPACM_Lan::eth_bridge_add_rt_rule(uint8_t *mac, char *rt_tbl_name, uint32_t hdr_proc_ctx_hdl,
-		ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int *rt_rule_count)
+		ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int *rt_rule_count,
+		int ep)
 {
 	int len, res = IPACM_SUCCESS;
 	uint32_t i, position, num_rt_rule;
@@ -4654,7 +4781,12 @@
 				goto end;
 			}
 
-			if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->isMCC_Mode)
+			if ((ep >= IPA_CLIENT_WIGIG1_CONS) && (ep <= IPA_CLIENT_WIGIG4_CONS))
+			{
+				IPACMDBG_H("wigig DL pipe %d\n", ep);
+				rt_rule.rule.dst = (enum ipa_client_type)ep;
+			}
+			else if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->isMCC_Mode)
 			{
 				IPACMDBG_H("In WLAN MCC mode, use alt dst pipe: %d\n",
 						tx_prop->tx[i].alt_dst_pipe);
diff --git a/ipacm/src/IPACM_LanToLan.cpp b/ipacm/src/IPACM_LanToLan.cpp
index 2902268..ca39327 100644
--- a/ipacm/src/IPACM_LanToLan.cpp
+++ b/ipacm/src/IPACM_LanToLan.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2014-2019, 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
@@ -466,7 +466,7 @@
 		if(it_iface->get_iface_pointer() == data->p_iface)	//find the interface
 		{
 			IPACMDBG_H("Found the interface.\n");
-			it_iface->handle_client_add(data->mac_addr, is_l2tp_client, mapping_info);
+			it_iface->handle_client_add(data->mac_addr, is_l2tp_client, mapping_info, data->ep);
 			break;
 		}
 	}
@@ -911,7 +911,7 @@
 		IPACMDBG_H("This is for inter interface communication.\n");
 
 		m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v4], hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type],
-			peer_l2_hdr_type, IPA_IP_v4, rt_rule_hdl, &num_rt_rule);
+			peer_l2_hdr_type, IPA_IP_v4, rt_rule_hdl, &num_rt_rule, client->ep);
 
 		client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4] = num_rt_rule;
 		IPACMDBG_H("Number of IPv4 routing rule is %d.\n", num_rt_rule);
@@ -922,7 +922,7 @@
 		}
 
 		m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v6], hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type],
-			peer_l2_hdr_type, IPA_IP_v6, rt_rule_hdl, &num_rt_rule);
+			peer_l2_hdr_type, IPA_IP_v6, rt_rule_hdl, &num_rt_rule, client->ep);
 
 		client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6] = num_rt_rule;
 		IPACMDBG_H("Number of IPv6 routing rule is %d.\n", num_rt_rule);
@@ -936,7 +936,7 @@
 	{
 		IPACMDBG_H("This is for intra interface communication.\n");
 		m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v4], hdr_proc_ctx_for_intra_interface,
-			peer_l2_hdr_type, IPA_IP_v4, rt_rule_hdl, &num_rt_rule);
+			peer_l2_hdr_type, IPA_IP_v4, rt_rule_hdl, &num_rt_rule, client->ep);
 
 		client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4] = num_rt_rule;
 		IPACMDBG_H("Number of IPv4 routing rule is %d.\n", num_rt_rule);
@@ -947,7 +947,7 @@
 		}
 
 		m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v6], hdr_proc_ctx_for_intra_interface,
-			peer_l2_hdr_type, IPA_IP_v6, rt_rule_hdl, &num_rt_rule);
+			peer_l2_hdr_type, IPA_IP_v6, rt_rule_hdl, &num_rt_rule, client->ep);
 
 		client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6] = num_rt_rule;
 		IPACMDBG_H("Number of IPv6 routing rule is %d.\n", num_rt_rule);
@@ -1569,7 +1569,10 @@
 	return;
 }
 
-void IPACM_LanToLan_Iface::handle_client_add(uint8_t *mac, bool is_l2tp_client, l2tp_vlan_mapping_info *mapping_info)
+void IPACM_LanToLan_Iface::handle_client_add(uint8_t *mac,
+	bool is_l2tp_client,
+	l2tp_vlan_mapping_info *mapping_info,
+	int ep)
 {
 	list<client_info>::iterator it_client;
 	list<peer_iface_info>::iterator it_peer_info;
@@ -1578,7 +1581,7 @@
 
 	for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
 	{
-		if(memcmp(it_client->mac_addr, mac, sizeof(it_client->mac_addr)) == 0)
+		if((memcmp(it_client->mac_addr, mac, sizeof(it_client->mac_addr)) == 0))
 		{
 			IPACMDBG_H("This client has been added before.\n");
 			return;
@@ -1596,6 +1599,7 @@
 	memcpy(new_client.mac_addr, mac, sizeof(new_client.mac_addr));
 	new_client.is_l2tp_client = is_l2tp_client;
 	new_client.mapping_info = mapping_info;
+	new_client.ep = ep;
 	m_client_info.push_front(new_client);
 
 	client_info &front_client = m_client_info.front();
diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp
index 327982e..0c9be6b 100644
--- a/ipacm/src/IPACM_Main.cpp
+++ b/ipacm/src/IPACM_Main.cpp
@@ -236,8 +236,9 @@
 	struct ipa_ecm_msg event_ecm;
 	struct ipa_wan_msg event_wan;
 	struct ipa_wlan_msg_ex event_ex_o;
-	struct ipa_wlan_msg *event_wlan=NULL;
-	struct ipa_wlan_msg_ex *event_ex= NULL;
+	struct ipa_wlan_msg *event_wlan = NULL;
+	struct ipa_wlan_msg_ex *event_ex = NULL;
+	struct ipa_wigig_msg *event_wigig = NULL;
 	struct ipa_get_data_stats_resp_msg_v01 event_data_stats;
 	struct ipa_get_apn_data_stats_resp_msg_v01 event_network_stats;
 #ifdef FEATURE_IPACM_HAL
@@ -246,6 +247,7 @@
 
 	ipacm_cmd_q_data evt_data;
 	ipacm_event_data_mac *data = NULL;
+	ipacm_event_data_mac_ep *data_wigig = NULL;
 	ipacm_event_data_fid *data_fid = NULL;
 	ipacm_event_data_iptype *data_iptype = NULL;
 	ipacm_event_data_wlan_ex *data_ex;
@@ -394,7 +396,28 @@
 		        evt_data.event = IPA_WLAN_CLIENT_ADD_EVENT;
 			evt_data.evt_data = data;
 			break;
+		case WIGIG_CLIENT_CONNECT:
+			event_wigig = (struct ipa_wigig_msg *)(buffer + sizeof(struct ipa_msg_meta));
+			IPACMDBG_H("Received WIGIG_CLIENT_CONNECT\n");
+			IPACMDBG_H("Mac Address %02x:%02x:%02x:%02x:%02x:%02x, ep %d\n",
+				event_wigig->client_mac_addr[0], event_wigig->client_mac_addr[1], event_wigig->client_mac_addr[2],
+				event_wigig->client_mac_addr[3], event_wigig->client_mac_addr[4], event_wigig->client_mac_addr[5],
+				event_wigig->u.ipa_client);
 
+			data_wigig = (ipacm_event_data_mac_ep *)malloc(sizeof(ipacm_event_data_mac_ep));
+			if(data_wigig == NULL)
+			{
+				IPACMERR("unable to allocate memory for event_wigig data\n");
+				return NULL;
+			}
+			memcpy(data_wigig->mac_addr,
+				event_wigig->client_mac_addr,
+				sizeof(data_wigig->mac_addr));
+			ipa_get_if_index(event_wigig->name, &(data_wigig->if_index));
+			data_wigig->client = event_wigig->u.ipa_client;
+			evt_data.event = IPA_WIGIG_CLIENT_ADD_EVENT;
+			evt_data.evt_data = data_wigig;
+			break;
 		case WLAN_CLIENT_CONNECT_EX:
 			IPACMDBG_H("Received WLAN_CLIENT_CONNECT_EX\n");
 
diff --git a/ipacm/src/IPACM_Neighbor.cpp b/ipacm/src/IPACM_Neighbor.cpp
index 5ed5453..1fd45df 100644
--- a/ipacm/src/IPACM_Neighbor.cpp
+++ b/ipacm/src/IPACM_Neighbor.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -187,10 +187,10 @@
 						IPACMDBG_H("This is link local ipv4 address: 0x%x : ignore this NEIGH_EVENT\n", data->ipv4_addr);
 						return;
 					}
-					/* check if iface is bridge interface*/
+					/* check if iface is bridge interface */
 					if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) == 0)
 					{
-						/* searh if seen this client or not*/
+						/* search if seen this client or not */
 						for (i = 0; i < num_neighbor_client_temp; i++)
 						{
 							if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
@@ -243,10 +243,10 @@
 								if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
 								{
 									/* update the network interface client associated */
-									neighbor_client[i].iface_index = data->if_index;
 									neighbor_client[i].ipa_if_num = ipa_interface_index;
 									neighbor_client[i].v4_addr = data->ipv4_addr; // cache client's previous ipv4 address
 									strlcpy(neighbor_client[i].iface_name, data->iface_name, sizeof(neighbor_client[i].iface_name));
+									neighbor_client[i].iface_index = data->if_index;
 									IPACMDBG_H("update cache %d-entry, with %s iface, ipv4 address: 0x%x\n",
 										i, data->iface_name, data->ipv4_addr);
 									break;
@@ -305,7 +305,7 @@
 						else
 						{
 							evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
-							/*searh if seen this client or not*/
+							/*search if seen this client or not*/
 							for (i = 0; i < num_neighbor_client_temp; i++)
 							{
 								/* find the client */
@@ -329,12 +329,12 @@
 									for (; i < num_neighbor_client_temp - 1; i++)
 									{
 										memcpy(neighbor_client[i].mac_addr,
-													neighbor_client[i+1].mac_addr,
+													neighbor_client[i + 1].mac_addr,
 													sizeof(neighbor_client[i].mac_addr));
-										neighbor_client[i].iface_index = neighbor_client[i+1].iface_index;
-										neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr;
-										neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num;
-										strlcpy(neighbor_client[i].iface_name, neighbor_client[i+1].iface_name,
+										neighbor_client[i].iface_index = neighbor_client[i + 1].iface_index;
+										neighbor_client[i].v4_addr = neighbor_client[i + 1].v4_addr;
+										neighbor_client[i].ipa_if_num = neighbor_client[i + 1].ipa_if_num;
+										strlcpy(neighbor_client[i].iface_name, neighbor_client[i + 1].iface_name,
 											sizeof(neighbor_client[i].iface_name));
 									}
 									num_neighbor_client--;
@@ -365,10 +365,10 @@
 				if ((data->ipv6_addr[0]) || (data->ipv6_addr[1]) || (data->ipv6_addr[2]) || (data->ipv6_addr[3]))
 				{
 					IPACMDBG("Got New_Neighbor event with ipv6 address \n");
-					/* check if iface is bridge interface*/
+					/* check if iface is bridge  interface */
 					if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, data->iface_name) == 0)
 					{
-						/* searh if seen this client or not*/
+						/* search if seen this client or not*/
 						for (i = 0; i < num_neighbor_client_temp; i++)
 						{
 							if (memcmp(neighbor_client[i].mac_addr, data->mac_addr, sizeof(neighbor_client[i].mac_addr)) == 0)
@@ -376,8 +376,10 @@
 								data->if_index = neighbor_client[i].iface_index;
 								strlcpy(data->iface_name, neighbor_client[i].iface_name, sizeof(data->iface_name));
 								/* construct IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT command and insert to command-queue */
-								if (event == IPA_NEW_NEIGH_EVENT) evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
-								else evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
+								if (event == IPA_NEW_NEIGH_EVENT)
+									evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT;
+								else
+									evt_data.event = IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT;
 								data_all = (ipacm_event_data_all *)malloc(sizeof(ipacm_event_data_all));
 								if (data_all == NULL)
 								{
@@ -486,29 +488,29 @@
 							if (event == IPA_DEL_NEIGH_EVENT)
 							{
 								IPACMDBG_H("Clean %d-st Cached client-MAC %02x:%02x:%02x:%02x:%02x:%02x\n, total client: %d\n",
-										i,
-										neighbor_client[i].mac_addr[0],
-										neighbor_client[i].mac_addr[1],
-										neighbor_client[i].mac_addr[2],
-										neighbor_client[i].mac_addr[3],
-										neighbor_client[i].mac_addr[4],
-										neighbor_client[i].mac_addr[5],
-										num_neighbor_client);
+									i,
+									neighbor_client[i].mac_addr[0],
+									neighbor_client[i].mac_addr[1],
+									neighbor_client[i].mac_addr[2],
+									neighbor_client[i].mac_addr[3],
+									neighbor_client[i].mac_addr[4],
+									neighbor_client[i].mac_addr[5],
+									num_neighbor_client);
 
 								memset(neighbor_client[i].mac_addr, 0, sizeof(neighbor_client[i].mac_addr));
 								neighbor_client[i].iface_index = 0;
 								neighbor_client[i].v4_addr = 0;
 								neighbor_client[i].ipa_if_num = 0;
 								memset(neighbor_client[i].iface_name, 0, sizeof(neighbor_client[i].iface_name));
-								for (; i < num_neighbor_client_temp - 1; i++)
+								for(; i < num_neighbor_client_temp - 1; i++)
 								{
 									memcpy(neighbor_client[i].mac_addr,
-												neighbor_client[i+1].mac_addr,
-												sizeof(neighbor_client[i].mac_addr));
-									neighbor_client[i].iface_index = neighbor_client[i+1].iface_index;
-									neighbor_client[i].v4_addr = neighbor_client[i+1].v4_addr;
-									neighbor_client[i].ipa_if_num = neighbor_client[i+1].ipa_if_num;
-									strlcpy(neighbor_client[i].iface_name, neighbor_client[i+1].iface_name,
+										neighbor_client[i + 1].mac_addr,
+										sizeof(neighbor_client[i].mac_addr));
+									neighbor_client[i].iface_index = neighbor_client[i + 1].iface_index;
+									neighbor_client[i].v4_addr = neighbor_client[i + 1].v4_addr;
+									neighbor_client[i].ipa_if_num = neighbor_client[i + 1].ipa_if_num;
+									strlcpy(neighbor_client[i].iface_name, neighbor_client[i + 1].iface_name,
 										sizeof(neighbor_client[i].iface_name));
 								}
 								num_neighbor_client--;
diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp
index d8a370c..f17c0e9 100644
--- a/ipacm/src/IPACM_Wlan.cpp
+++ b/ipacm/src/IPACM_Wlan.cpp
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+Copyright (c) 2013-2019, 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
@@ -733,7 +733,8 @@
 				{
 					if(data->attribs[i].attrib_type == WLAN_HDR_ATTRIB_MAC_ADDR)
 					{
-						eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->attribs[i].u.mac_addr, NULL, NULL);
+						eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->attribs[i].u.mac_addr, NULL, NULL,
+							IPA_CLIENT_MAX);
 						break;
 					}
 				}
@@ -743,6 +744,18 @@
 		}
 		break;
 
+	case IPA_WIGIG_CLIENT_ADD_EVENT:
+	{
+		ipacm_event_data_mac_ep *data = (ipacm_event_data_mac_ep *)param;
+		ipa_interface_index = iface_ipa_index_query(data->if_index);
+		if(ipa_interface_index == ipa_if_num)
+		{
+			IPACMDBG_H("Received IPA_WIGIG_CLIENT_ADD_EVENT\n");
+			handle_wigig_client_add(data);
+		}
+	}
+	break;
+
 	case IPA_WLAN_CLIENT_DEL_EVENT:
 		{
 			ipacm_event_data_mac *data = (ipacm_event_data_mac *)param;
@@ -750,7 +763,7 @@
 			if (ipa_interface_index == ipa_if_num)
 			{
 				IPACMDBG_H("Received IPA_WLAN_CLIENT_DEL_EVENT\n");
-				eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr, NULL, NULL);
+				eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr, NULL, NULL, IPA_CLIENT_MAX);
 				handle_wlan_client_down_evt(data->mac_addr);
 			}
 		}
@@ -819,7 +832,7 @@
 				}
 
 				handle_wlan_client_route_rule(data->mac_addr, data->iptype);
-				if (data->iptype == IPA_IP_v4)
+				if(data->iptype == IPA_IP_v4)
 				{
 					/* Add NAT rules after ipv4 RT rules are set */
 					CtList->HandleNeighIpAddrAddEvt(data);
@@ -828,7 +841,6 @@
 			}
 		}
 		break;
-
 		/* handle software routing enable event, iface will update softwarerouting_act to true*/
 	case IPA_SW_ROUTING_ENABLE:
 		IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n");
@@ -852,7 +864,7 @@
 		{
 			handle_SCC_MCC_switch(ip_type);
 		}
-		eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL, NULL, NULL);
+		eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL, NULL, NULL, IPA_CLIENT_MAX);
 		break;
 
 	case IPA_WLAN_SWITCH_TO_MCC:
@@ -866,7 +878,7 @@
 		{
 			handle_SCC_MCC_switch(ip_type);
 		}
-		eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL, NULL, NULL);
+		eth_bridge_post_event(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, IPA_IP_MAX, NULL, NULL, NULL, IPA_CLIENT_MAX);
 		break;
 
 	case IPA_CRADLE_WAN_MODE_SWITCH:
@@ -976,6 +988,44 @@
 	return;
 }
 
+
+int IPACM_Wlan::handle_wigig_client_add(ipacm_event_data_mac_ep *data)
+{
+	ipacm_event_data_wlan_ex *wlan_data;
+	int ret = IPACM_SUCCESS;
+
+	wlan_data = (ipacm_event_data_wlan_ex *)malloc(sizeof(ipa_wlan_msg_ex) + sizeof(ipa_wlan_hdr_attrib_val));
+	if(wlan_data == NULL)
+	{
+		IPACMERR("Unable to allocate memory\n");
+		return IPACM_FAILURE;
+	}
+
+	wlan_data->num_of_attribs = 1;
+	wlan_data->if_index = data->if_index;
+	wlan_data->attribs[0].attrib_type = WLAN_HDR_ATTRIB_MAC_ADDR;
+	wlan_data->attribs[0].offset = 0;
+	memcpy(wlan_data->attribs[0].u.mac_addr, data->mac_addr, sizeof(wlan_data->attribs[0].u.mac_addr));
+
+	eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr, NULL, NULL, data->client);
+	handle_wlan_client_init_ex(wlan_data);
+
+	int idx = get_wlan_client_index(data->mac_addr);
+
+	if(idx == IPACM_INVALID_INDEX)
+	{
+		IPACMERR("wlan client not attached\n");
+		ret = IPACM_FAILURE;
+		goto fail;
+	}
+
+	/* store client pipe hdl for the time we add the DL header */
+	get_client_memptr(wlan_client, idx)->wigig_ipa_client = data->client;
+fail:
+	free(wlan_data);
+	return ret;
+}
+
 /* handle wifi client initial,copy all partial headers (tx property) */
 int IPACM_Wlan::handle_wlan_client_init_ex(ipacm_event_data_wlan_ex *data)
 {
@@ -1306,27 +1356,27 @@
 			}
 			else
 			{
-			   /* check if client got new IPv4 address*/
-			   if(data->ipv4_addr == get_client_memptr(wlan_client, clnt_indx)->v4_addr)
-			   {
-			     IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx);
-				 return IPACM_FAILURE;
-			   }
-			   else
-			   {
-			     IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
-				 /* delete NAT rules first */
-				 CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clnt_indx)->v4_addr);
-			     delete_default_qos_rtrules(clnt_indx,IPA_IP_v4);
-		         get_client_memptr(wlan_client, clnt_indx)->route_rule_set_v4 = false;
-			     get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr;
+				/* check if client got new IPv4 address*/
+				if(data->ipv4_addr == get_client_memptr(wlan_client, clnt_indx)->v4_addr)
+				{
+					IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx);
+					return IPACM_FAILURE;
+				}
+				else
+				{
+					IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
+					/* delete NAT rules first */
+					CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clnt_indx)->v4_addr);
+					delete_default_qos_rtrules(clnt_indx, IPA_IP_v4);
+					get_client_memptr(wlan_client, clnt_indx)->route_rule_set_v4 = false;
+					get_client_memptr(wlan_client, clnt_indx)->v4_addr = data->ipv4_addr;
+				}
 			}
 		}
-	}
-	else
-	{
-		    IPACMDBG_H("Invalid client IPv4 address \n");
-		    return IPACM_FAILURE;
+		else
+		{
+			IPACMDBG_H("Invalid client IPv4 address \n");
+			return IPACM_FAILURE;
 		}
 	}
 	else
@@ -1478,15 +1528,24 @@
 						sizeof(rt_rule->rt_tbl_name));
 				rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
 
-				if(IPACM_Iface::ipacmcfg->isMCC_Mode)
+				if(!strcmp("wigig0", dev_name))
 				{
-					IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
-							tx_prop->tx[tx_index].alt_dst_pipe);
-					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
+					IPACMDBG_H("for WIGIG client use relevant pipe %d\n",
+						get_client_memptr(wlan_client, wlan_index)->wigig_ipa_client);
+					rt_rule_entry->rule.dst = get_client_memptr(wlan_client, wlan_index)->wigig_ipa_client;
 				}
 				else
 				{
-					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+					if(IPACM_Iface::ipacmcfg->isMCC_Mode)
+					{
+						IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
+							tx_prop->tx[tx_index].alt_dst_pipe);
+						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
+					}
+					else
+					{
+						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+					}
 				}
 
 				memcpy(&rt_rule_entry->rule.attrib,
@@ -1561,15 +1620,24 @@
 							sizeof(rt_rule->rt_tbl_name));
 					rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
 					/* Downlink traffic from Wan iface, directly through IPA */
-					if(IPACM_Iface::ipacmcfg->isMCC_Mode)
+					if(!strcmp("wigig0", dev_name))
 					{
-						IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
-								tx_prop->tx[tx_index].alt_dst_pipe);
-						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
+						IPACMDBG_H("for WIGIG client use relevant pipe %d\n",
+							get_client_memptr(wlan_client, wlan_index)->wigig_ipa_client);
+						rt_rule_entry->rule.dst = get_client_memptr(wlan_client, wlan_index)->wigig_ipa_client;
 					}
 					else
 					{
-						rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+						if(IPACM_Iface::ipacmcfg->isMCC_Mode)
+						{
+							IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n",
+								tx_prop->tx[tx_index].alt_dst_pipe);
+							rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe;
+						}
+						else
+						{
+							rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
+						}
 					}
 					memcpy(&rt_rule_entry->rule.attrib,
 							&tx_prop->tx[tx_index].attrib,
@@ -1672,17 +1740,17 @@
 	/* First reset nat rules and then route rules */
 	if(get_client_memptr(wlan_client, clt_indx)->ipv4_set == true)
 	{
-	        IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, clt_indx)->v4_addr);
-			CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clt_indx)->v4_addr);
- 	}
+		IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wlan_client, clt_indx)->v4_addr);
+		CtList->HandleNeighIpAddrDelEvt(get_client_memptr(wlan_client, clt_indx)->v4_addr);
+	}
 
-	if (delete_default_qos_rtrules(clt_indx, IPA_IP_v4))
+	if(delete_default_qos_rtrules(clt_indx, IPA_IP_v4))
 	{
 		IPACMERR("unbale to delete v4 default qos route rules for index: %d\n", clt_indx);
 		return IPACM_FAILURE;
 	}
 
-	if (delete_default_qos_rtrules(clt_indx, IPA_IP_v6))
+	if(delete_default_qos_rtrules(clt_indx, IPA_IP_v6))
 	{
 		IPACMERR("unbale to delete v6 default qos route rules for indexn: %d\n", clt_indx);
 		return IPACM_FAILURE;
@@ -1927,7 +1995,7 @@
 	}
 	IPACMDBG_H("finished deleting default RT rules\n ");
 
-	eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL);
+	eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL, IPA_CLIENT_MAX);
 
 	/* free the wlan clients cache */
 	IPACMDBG_H("Free wlan clients cache\n");
@@ -2316,23 +2384,23 @@
 	/* ====== post events to mimic WLAN interface goes down/up when AP mode is changing ====== */
 
 	/* first post IFACE_DOWN event */
-	eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL);
+	eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL, NULL, NULL, IPA_CLIENT_MAX);
 
 	/* then post IFACE_UP event */
 	if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
 	{
-		eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL, NULL, NULL);
+		eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL, NULL, NULL, IPA_CLIENT_MAX);
 	}
 	if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
 	{
-		eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL, NULL, NULL);
+		eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL, NULL, NULL, IPA_CLIENT_MAX);
 	}
 
 	/* at last post CLIENT_ADD event */
 	for(i = 0; i < num_wifi_client; i++)
 	{
 		eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX,
-			get_client_memptr(wlan_client, i)->mac, NULL, NULL);
+			get_client_memptr(wlan_client, i)->mac, NULL, NULL, IPA_CLIENT_MAX);
 	}
 
 	return;
diff --git a/ipacm/src/IPACM_cfg.xml b/ipacm/src/IPACM_cfg.xml
index 9bac7a4..0c125e5 100644
--- a/ipacm/src/IPACM_cfg.xml
+++ b/ipacm/src/IPACM_cfg.xml
@@ -54,6 +54,11 @@
 			   <WlanMode>full</WlanMode>
 			</Iface>
 			<Iface>
+			   <Name>wigig0</Name>
+			   <Category>UNKNOWN</Category>
+			   <WlanMode>full</WlanMode>
+			</Iface>
+			<Iface>
 			   <Name>wlan0</Name>
 			   <Category>UNKNOWN</Category>
 			   <WlanMode>full</WlanMode>
@@ -80,7 +85,7 @@
 			<Iface>
 			   <Name>bridge0</Name>
 			   <Category>VIRTUAL</Category>
-		    </Iface>
+			</Iface>
 		</IPACMIface>
 		<IPPassthroughFlag>
 			<IPPassthroughMode>0</IPPassthroughMode>