Home | History | Annotate | Download | only in src
      1 /*
      2 Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7 * Redistributions of source code must retain the above copyright
      8 notice, this list of conditions and the following disclaimer.
      9 
     10 * Redistributions in binary form must reproduce the above
     11 copyright notice, this list of conditions and the following
     12 disclaimer in the documentation and/or other materials provided
     13 with the distribution.
     14 
     15 * Neither the name of The Linux Foundation nor the names of its
     16 contributors may be used to endorse or promote products derived
     17 from this software without specific prior written permission.
     18 
     19 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     20 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     22 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     23 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     26 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     27 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     28 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     29 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 */
     31 /*!
     32 	@file
     33 	IPACM_Lan.cpp
     34 
     35 	@brief
     36 	This file implements the LAN iface functionality.
     37 
     38 	@Author
     39 	Skylar Chang
     40 
     41 */
     42 #include <string.h>
     43 #include <fcntl.h>
     44 #include <sys/ioctl.h>
     45 #include "IPACM_Netlink.h"
     46 #include "IPACM_Lan.h"
     47 #include "IPACM_Wan.h"
     48 #include "IPACM_IfaceManager.h"
     49 #include "linux/rmnet_ipa_fd_ioctl.h"
     50 #include "linux/ipa_qmi_service_v01.h"
     51 #include "linux/msm_ipa.h"
     52 #include "IPACM_ConntrackListener.h"
     53 #include <sys/ioctl.h>
     54 #include <fcntl.h>
     55 #ifdef FEATURE_IPACM_HAL
     56 #include "IPACM_OffloadManager.h"
     57 #endif
     58 bool IPACM_Lan::odu_up = false;
     59 
     60 IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index)
     61 {
     62 	num_eth_client = 0;
     63 	header_name_count = 0;
     64 	ipv6_set = 0;
     65 	ipv4_header_set = false;
     66 	ipv6_header_set = false;
     67 	odu_route_rule_v4_hdl = NULL;
     68 	odu_route_rule_v6_hdl = NULL;
     69 	eth_client = NULL;
     70 	int m_fd_odu, ret = IPACM_SUCCESS;
     71 	uint32_t i;
     72 
     73 	Nat_App = NatApp::GetInstance();
     74 	if (Nat_App == NULL)
     75 	{
     76 		IPACMERR("unable to get Nat App instance \n");
     77 		return;
     78 	}
     79 
     80 	num_wan_ul_fl_rule_v4 = 0;
     81 	num_wan_ul_fl_rule_v6 = 0;
     82 	is_active = true;
     83 	modem_ul_v4_set = false;
     84 	modem_ul_v6_set = false;
     85 	is_mode_switch = false;
     86 	if_ipv4_subnet =0;
     87 	each_client_rt_rule_count[IPA_IP_v4] = 0;
     88 	each_client_rt_rule_count[IPA_IP_v6] = 0;
     89 	eth_client_len = 0;
     90 
     91 	/* support eth multiple clients */
     92 	if(iface_query != NULL)
     93 	{
     94 		if(ipa_if_cate != WLAN_IF)
     95 		{
     96 			eth_client_len = (sizeof(ipa_eth_client)) + (iface_query->num_tx_props * sizeof(eth_client_rt_hdl));
     97 			eth_client = (ipa_eth_client *)calloc(IPA_MAX_NUM_ETH_CLIENTS, eth_client_len);
     98 			if (eth_client == NULL)
     99 			{
    100 				IPACMERR("unable to allocate memory\n");
    101 				return;
    102 			}
    103 		}
    104 
    105 		IPACMDBG_H(" IPACM->IPACM_Lan(%d) constructor: Tx:%d Rx:%d \n", ipa_if_num,
    106 					 iface_query->num_tx_props, iface_query->num_rx_props);
    107 
    108 		/* ODU routing table initilization */
    109 		if(ipa_if_cate == ODU_IF)
    110 		{
    111 			odu_route_rule_v4_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
    112 			odu_route_rule_v6_hdl = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t));
    113 			if ((odu_route_rule_v4_hdl == NULL) || (odu_route_rule_v6_hdl == NULL))
    114 			{
    115 				IPACMERR("unable to allocate memory\n");
    116 				return;
    117 			}
    118 		}
    119 	}
    120 
    121 	memset(wan_ul_fl_rule_hdl_v4, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t));
    122 	memset(wan_ul_fl_rule_hdl_v6, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t));
    123 
    124 	memset(ipv4_icmp_flt_rule_hdl, 0, NUM_IPV4_ICMP_FLT_RULE * sizeof(uint32_t));
    125 
    126 	memset(private_fl_rule_hdl, 0, IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(uint32_t));
    127 	memset(ipv6_prefix_flt_rule_hdl, 0, NUM_IPV6_PREFIX_FLT_RULE * sizeof(uint32_t));
    128 	memset(ipv6_icmp_flt_rule_hdl, 0, NUM_IPV6_ICMP_FLT_RULE * sizeof(uint32_t));
    129 	memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
    130 
    131 	/* ODU routing table initilization */
    132 	if(ipa_if_cate == ODU_IF)
    133 	{
    134 		/* only do one time ioctl to odu-driver to infrom in router or bridge mode*/
    135 		if (IPACM_Lan::odu_up != true)
    136 		{
    137 				m_fd_odu = open(IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU, O_RDWR);
    138 				if (0 == m_fd_odu)
    139 				{
    140 					IPACMERR("Failed opening %s.\n", IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU);
    141 					return ;
    142 				}
    143 
    144 				if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true)
    145 				{
    146 					ret = ioctl(m_fd_odu, ODU_BRIDGE_IOC_SET_MODE, ODU_BRIDGE_MODE_ROUTER);
    147 					IPACM_Iface::ipacmcfg->ipacm_odu_enable = true;
    148 				}
    149 				else
    150 				{
    151 					ret = ioctl(m_fd_odu, ODU_BRIDGE_IOC_SET_MODE, ODU_BRIDGE_MODE_BRIDGE);
    152 					IPACM_Iface::ipacmcfg->ipacm_odu_enable = true;
    153 				}
    154 
    155 				if (ret)
    156 				{
    157 					IPACMERR("Failed tell odu-driver the mode\n");
    158 				}
    159 				IPACMDBG("Tell odu-driver in router-mode(%d)\n", IPACM_Iface::ipacmcfg->ipacm_odu_router_mode);
    160 				IPACMDBG_H("odu is up: odu-driver in router-mode(%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_router_mode);
    161 				close(m_fd_odu);
    162 				IPACM_Lan::odu_up = true;
    163 		}
    164 	}
    165 
    166 	if(iface_query != NULL && tx_prop != NULL)
    167 	{
    168 		for(i=0; i<iface_query->num_tx_props; i++)
    169 			each_client_rt_rule_count[tx_prop->tx[i].ip]++;
    170 	}
    171 	IPACMDBG_H("Need to add %d IPv4 and %d IPv6 routing rules for eth bridge for each client.\n", each_client_rt_rule_count[IPA_IP_v4], each_client_rt_rule_count[IPA_IP_v6]);
    172 
    173 #ifdef FEATURE_IPA_ANDROID
    174 	/* set the IPA-client pipe enum */
    175 	if(ipa_if_cate == LAN_IF)
    176 	{
    177 #ifdef FEATURE_IPACM_HAL
    178 		handle_tethering_client(false, IPACM_CLIENT_MAX);
    179 #else
    180 		handle_tethering_client(false, IPACM_CLIENT_USB);
    181 #endif
    182 	}
    183 #endif
    184 
    185 	memset(is_downstream_set, 0, sizeof(is_downstream_set));
    186 	memset(is_upstream_set, 0, sizeof(is_upstream_set));
    187 	memset(&prefix, 0, sizeof(prefix));
    188 
    189 #ifdef FEATURE_IPACM_HAL
    190 		/* check if Upstream was set before */
    191 		if (IPACM_Wan::isWanUP(ipa_if_num))
    192 		{
    193 				IPACMDBG_H("Upstream was set previously for ipv4, change is_upstream_set flag\n");
    194 				is_upstream_set[IPA_IP_v4] = true;
    195 		}
    196 
    197 		if (IPACM_Wan::isWanUP_V6(ipa_if_num))
    198 		{
    199 				IPACMDBG_H("Upstream was set previously for ipv6, change is_upstream_set flag\n");
    200 				is_upstream_set[IPA_IP_v6] = true;
    201 		}
    202 #endif
    203 	return;
    204 }
    205 
    206 IPACM_Lan::~IPACM_Lan()
    207 {
    208 	IPACM_EvtDispatcher::deregistr(this);
    209 	IPACM_IfaceManager::deregistr(this);
    210 	return;
    211 }
    212 
    213 
    214 /* LAN-iface's callback function */
    215 void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
    216 {
    217 	if(is_active == false && event != IPA_LAN_DELETE_SELF)
    218 	{
    219 		IPACMDBG_H("The interface is no longer active, return.\n");
    220 		return;
    221 	}
    222 
    223 	int ipa_interface_index;
    224 	ipacm_ext_prop* ext_prop;
    225 	ipacm_event_iface_up_tehter* data_wan_tether;
    226 
    227 	switch (event)
    228 	{
    229 	case IPA_LINK_DOWN_EVENT:
    230 		{
    231 			ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
    232 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    233 			if (ipa_interface_index == ipa_if_num)
    234 			{
    235 				IPACMDBG_H("Received IPA_LINK_DOWN_EVENT\n");
    236 				handle_down_evt();
    237 				IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
    238 				return;
    239 			}
    240 		}
    241 		break;
    242 
    243 	case IPA_CFG_CHANGE_EVENT:
    244 		{
    245 			if ( IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat != ipa_if_cate)
    246 			{
    247 				IPACMDBG_H("Received IPA_CFG_CHANGE_EVENT and category changed\n");
    248 				/* delete previous instance */
    249 				handle_down_evt();
    250 				IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface
    251 				is_mode_switch = true; // need post internal usb-link up event
    252 				return;
    253 			}
    254 			/* Add Natting iface to IPACM_Config if there is  Rx/Tx property */
    255 			if (rx_prop != NULL || tx_prop != NULL)
    256 			{
    257 				IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name);
    258 				IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name);
    259 			}
    260 		}
    261 		break;
    262 
    263 	case IPA_PRIVATE_SUBNET_CHANGE_EVENT:
    264 		{
    265 			ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
    266 			/* internel event: data->if_index is ipa_if_index */
    267 			if (data->if_index == ipa_if_num)
    268 			{
    269 				IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from itself posting, ignore\n");
    270 				return;
    271 			}
    272 			else
    273 			{
    274 				IPACMDBG_H("Received IPA_PRIVATE_SUBNET_CHANGE_EVENT from other LAN iface \n");
    275 #ifdef FEATURE_IPA_ANDROID
    276 				handle_private_subnet_android(IPA_IP_v4);
    277 #endif
    278 				IPACMDBG_H(" delete old private subnet rules, use new sets \n");
    279 				return;
    280 			}
    281 		}
    282 		break;
    283 
    284 	case IPA_LAN_DELETE_SELF:
    285 	{
    286 		ipacm_event_data_fid *data = (ipacm_event_data_fid *)param;
    287 		if(data->if_index == ipa_if_num)
    288 		{
    289 			IPACMDBG_H("Received IPA_LAN_DELETE_SELF event.\n");
    290 			IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance close \n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
    291 			/* posting link-up event for cradle use-case */
    292 			if(is_mode_switch)
    293 			{
    294 				IPACMDBG_H("Posting IPA_USB_LINK_UP_EVENT event for (%s)\n", dev_name);
    295 				ipacm_cmd_q_data evt_data;
    296 				memset(&evt_data, 0, sizeof(evt_data));
    297 
    298 				ipacm_event_data_fid *data_fid = NULL;
    299 				data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
    300 				if(data_fid == NULL)
    301 				{
    302 					IPACMERR("unable to allocate memory for IPA_USB_LINK_UP_EVENT data_fid\n");
    303 					return;
    304 				}
    305 				if(IPACM_Iface::ipa_get_if_index(dev_name, &(data_fid->if_index)))
    306 				{
    307 					IPACMERR("Error while getting interface index for %s device", dev_name);
    308 				}
    309 				evt_data.event = IPA_USB_LINK_UP_EVENT;
    310 				evt_data.evt_data = data_fid;
    311 				//IPACMDBG_H("Posting event:%d\n", evt_data.event);
    312 				IPACM_EvtDispatcher::PostEvt(&evt_data);
    313 			}
    314 #ifndef FEATURE_IPA_ANDROID
    315 			if(rx_prop != NULL)
    316 			{
    317 				if(IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4) != 0)
    318 				{
    319 					IPACMDBG_DMESG("### WARNING ### num ipv4 flt rules on client %d is not expected: %d expected value: 0",
    320 						rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4));
    321 				}
    322 				if(IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6) != 0)
    323 				{
    324 					IPACMDBG_DMESG("### WARNING ### num ipv6 flt rules on client %d is not expected: %d expected value: 0",
    325 						rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6));
    326 				}
    327 			}
    328 #endif
    329 			delete this;
    330 		}
    331 		break;
    332 	}
    333 
    334 	case IPA_ADDR_ADD_EVENT:
    335 		{
    336 			ipacm_event_data_addr *data = (ipacm_event_data_addr *)param;
    337 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    338 
    339 			if ( (data->iptype == IPA_IP_v4 && data->ipv4_addr == 0) ||
    340 					 (data->iptype == IPA_IP_v6 &&
    341 						data->ipv6_addr[0] == 0 && data->ipv6_addr[1] == 0 &&
    342 					  data->ipv6_addr[2] == 0 && data->ipv6_addr[3] == 0) )
    343 			{
    344 				IPACMDBG_H("Invalid address, ignore IPA_ADDR_ADD_EVENT event\n");
    345 				return;
    346 			}
    347 
    348 
    349 			if (ipa_interface_index == ipa_if_num)
    350 			{
    351 				IPACMDBG_H("Received IPA_ADDR_ADD_EVENT\n");
    352 
    353 				/* only call ioctl for ODU iface with bridge mode */
    354 				if(IPACM_Iface::ipacmcfg->ipacm_odu_enable == true && IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false
    355 						&& ipa_if_cate == ODU_IF)
    356 				{
    357 					if((data->iptype == IPA_IP_v6) && (num_dft_rt_v6 == 0))
    358 					{
    359 						handle_addr_evt_odu_bridge(data);
    360 					}
    361 #ifdef FEATURE_IPA_ANDROID
    362 					add_dummy_private_subnet_flt_rule(data->iptype);
    363 					handle_private_subnet_android(data->iptype);
    364 #else
    365 					handle_private_subnet(data->iptype);
    366 #endif
    367 				}
    368 				else
    369 				{
    370 
    371 					/* check v4 not setup before, v6 can have 2 iface ip */
    372 					if( ((data->iptype != ip_type) && (ip_type != IPA_IP_MAX))
    373 						|| ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES)))
    374 					{
    375 						IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6);
    376 						if(handle_addr_evt(data) == IPACM_FAILURE)
    377 						{
    378 							return;
    379 						}
    380 
    381 #ifdef FEATURE_IPA_ANDROID
    382 						add_dummy_private_subnet_flt_rule(data->iptype);
    383 						handle_private_subnet_android(data->iptype);
    384 #else
    385 						handle_private_subnet(data->iptype);
    386 #endif
    387 
    388 #ifndef FEATURE_IPACM_HAL
    389 						if (IPACM_Wan::isWanUP(ipa_if_num))
    390 						{
    391 							if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX)
    392 							{
    393 								if(IPACM_Wan::backhaul_is_sta_mode == false)
    394 								{
    395 									ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
    396 									handle_wan_up_ex(ext_prop, IPA_IP_v4,
    397 												IPACM_Wan::getXlat_Mux_Id());
    398 								}
    399 								else
    400 								{
    401 									handle_wan_up(IPA_IP_v4);
    402 								}
    403 							}
    404 							IPACMDBG_H("Finished checking wan_up\n");
    405 						} else {
    406 							IPACMDBG_H("Wan_V4 haven't up yet\n");
    407 						}
    408 
    409 						if(IPACM_Wan::isWanUP_V6(ipa_if_num))
    410 						{
    411 							if((data->iptype == IPA_IP_v6 || data->iptype == IPA_IP_MAX) && num_dft_rt_v6 == 1)
    412 							{
    413 								memcpy(ipv6_prefix, IPACM_Wan::backhaul_ipv6_prefix, sizeof(ipv6_prefix));
    414 								install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
    415 								if(IPACM_Wan::backhaul_is_sta_mode == false)
    416 								{
    417 									ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
    418 									handle_wan_up_ex(ext_prop, IPA_IP_v6, 0);
    419 								}
    420 								else
    421 								{
    422 									handle_wan_up(IPA_IP_v6);
    423 								}
    424 							}
    425 							IPACMDBG_H("Finished checking wan_up_v6\n");
    426 						} else {
    427 							IPACMDBG_H("Wan_V6 haven't up yet\n");
    428 						}
    429 #endif
    430 						/* Post event to NAT */
    431 						if (data->iptype == IPA_IP_v4)
    432 						{
    433 							ipacm_cmd_q_data evt_data;
    434 							ipacm_event_iface_up *info;
    435 
    436 							info = (ipacm_event_iface_up *)
    437 								malloc(sizeof(ipacm_event_iface_up));
    438 							if (info == NULL)
    439 							{
    440 								IPACMERR("Unable to allocate memory\n");
    441 								return;
    442 							}
    443 
    444 							memcpy(info->ifname, dev_name, IF_NAME_LEN);
    445 							info->ipv4_addr = data->ipv4_addr;
    446 							info->addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[0].subnet_mask;
    447 
    448 							evt_data.event = IPA_HANDLE_LAN_UP;
    449 							evt_data.evt_data = (void *)info;
    450 
    451 							/* Insert IPA_HANDLE_LAN_UP to command queue */
    452 							IPACMDBG_H("posting IPA_HANDLE_LAN_UP for IPv4 with below information\n");
    453 							IPACMDBG_H("IPv4 address:0x%x, IPv4 address mask:0x%x\n",
    454 											info->ipv4_addr, info->addr_mask);
    455 							IPACM_EvtDispatcher::PostEvt(&evt_data);
    456 						}
    457 						IPACMDBG_H("Finish handling IPA_ADDR_ADD_EVENT for ip-family(%d)\n", data->iptype);
    458 					}
    459 
    460 					IPACMDBG_H("Finish handling IPA_ADDR_ADD_EVENT for ip-family(%d)\n", data->iptype);
    461 					/* checking if SW-RT_enable */
    462 					if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true)
    463 					{
    464 						/* handle software routing enable event*/
    465 						IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name);
    466 						handle_software_routing_enable();
    467 					}
    468 
    469 				}
    470 			}
    471 		}
    472 		break;
    473 #ifdef FEATURE_IPA_ANDROID
    474 	case IPA_HANDLE_WAN_UP_TETHER:
    475 		IPACMDBG_H("Received IPA_HANDLE_WAN_UP_TETHER event\n");
    476 
    477 		data_wan_tether = (ipacm_event_iface_up_tehter*)param;
    478 		if(data_wan_tether == NULL)
    479 		{
    480 			IPACMERR("No event data is found.\n");
    481 			return;
    482 		}
    483 		IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
    484 					data_wan_tether->if_index_tether,
    485 					IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
    486 #ifndef FEATURE_IPACM_HAL
    487 		if (data_wan_tether->if_index_tether != ipa_if_num)
    488 		{
    489 			IPACMERR("IPA_HANDLE_WAN_UP_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num);
    490 			return;
    491 		}
    492 #endif
    493 		if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
    494 		{
    495 #ifdef FEATURE_IPACM_HAL
    496 			if (is_upstream_set[IPA_IP_v4] == false)
    497 			{
    498 				IPACMDBG_H("Add upstream for IPv4.\n");
    499 				is_upstream_set[IPA_IP_v4] = true;
    500 				if (is_downstream_set[IPA_IP_v4] == true)
    501 				{
    502 					IPACMDBG_H("Downstream was set before, adding UL rules.\n");
    503 					if (data_wan_tether->is_sta == false)
    504 					{
    505 							ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
    506 							handle_wan_up_ex(ext_prop, IPA_IP_v4, 0);
    507 					} else {
    508 							handle_wan_up(IPA_IP_v4);
    509 					}
    510 				}
    511 			}
    512 #else
    513 			if (data_wan_tether->is_sta == false)
    514 			{
    515 					ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
    516 					handle_wan_up_ex(ext_prop, IPA_IP_v4, 0);
    517 			} else {
    518 					handle_wan_up(IPA_IP_v4);
    519 			}
    520 #endif
    521 		}
    522 		break;
    523 
    524 	case IPA_HANDLE_WAN_UP_V6_TETHER:
    525 		IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6_TETHER event\n");
    526 
    527 		data_wan_tether = (ipacm_event_iface_up_tehter*)param;
    528 		if (data_wan_tether == NULL)
    529 		{
    530 			IPACMERR("No event data is found.\n");
    531 			return;
    532 		}
    533 		IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
    534 					data_wan_tether->if_index_tether,
    535 					IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
    536 #ifndef FEATURE_IPACM_HAL
    537 		if (data_wan_tether->if_index_tether != ipa_if_num)
    538 		{
    539 			IPACMERR("IPA_HANDLE_WAN_UP_V6_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num);
    540 			return;
    541 		}
    542 #endif
    543 		if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
    544 		{
    545 #ifdef FEATURE_IPACM_HAL
    546 			if (is_upstream_set[IPA_IP_v6] == false)
    547 			{
    548 				IPACMDBG_H("Add upstream for IPv6.\n");
    549 				is_upstream_set[IPA_IP_v6] = true;
    550 
    551 				if (is_downstream_set[IPA_IP_v6] == true)
    552 				{
    553 					IPACMDBG_H("Downstream was set before, adding UL rules.\n");
    554 					memcpy(ipv6_prefix, data_wan_tether->ipv6_prefix, sizeof(ipv6_prefix));
    555 					install_ipv6_prefix_flt_rule(data_wan_tether->ipv6_prefix);
    556 					if (data_wan_tether->is_sta == false)
    557 					{
    558 						ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
    559 						handle_wan_up_ex(ext_prop, IPA_IP_v6, 0);
    560 					}
    561 					else
    562 					{
    563 						handle_wan_up(IPA_IP_v6);
    564 					}
    565 				}
    566 			}
    567 #else
    568 			if (data_wan_tether->is_sta == false)
    569 			{
    570 				ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
    571 				handle_wan_up_ex(ext_prop, IPA_IP_v6, 0);
    572 			} else {
    573 				handle_wan_up(IPA_IP_v6);
    574 			}
    575 #endif
    576 		}
    577 		break;
    578 
    579 	case IPA_HANDLE_WAN_DOWN_TETHER:
    580 		IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_TETHER event\n");
    581 		data_wan_tether = (ipacm_event_iface_up_tehter*)param;
    582 		if (data_wan_tether == NULL)
    583 		{
    584 			IPACMERR("No event data is found.\n");
    585 			return;
    586 		}
    587 		IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
    588 					data_wan_tether->if_index_tether,
    589 					IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
    590 #ifndef FEATURE_IPACM_HAL
    591 		if (data_wan_tether->if_index_tether != ipa_if_num)
    592 		{
    593 			IPACMERR("IPA_HANDLE_WAN_DOWN_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num);
    594 			return;
    595 		}
    596 #endif
    597 		if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
    598 		{
    599 #ifdef FEATURE_IPACM_HAL
    600 			if(is_upstream_set[IPA_IP_v4] == true)
    601 			{
    602 				IPACMDBG_H("Del upstream for IPv4.\n");
    603 				is_upstream_set[IPA_IP_v4] = false;
    604 				if(is_downstream_set[IPA_IP_v4] == true)
    605 				{
    606 					IPACMDBG_H("Downstream was set before, deleting UL rules.\n");
    607 					handle_wan_down(data_wan_tether->is_sta);
    608 				}
    609 			}
    610 #else
    611 			handle_wan_down(data_wan_tether->is_sta);
    612 #endif
    613 		}
    614 		break;
    615 
    616 	case IPA_HANDLE_WAN_DOWN_V6_TETHER:
    617 		IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6_TETHER event\n");
    618 		data_wan_tether = (ipacm_event_iface_up_tehter*)param;
    619 		if(data_wan_tether == NULL)
    620 		{
    621 			IPACMERR("No event data is found.\n");
    622 			return;
    623 		}
    624 		IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
    625 					data_wan_tether->if_index_tether,
    626 					IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
    627 #ifndef FEATURE_IPACM_HAL
    628 		if (data_wan_tether->if_index_tether != ipa_if_num)
    629 		{
    630 			IPACMERR("IPA_HANDLE_WAN_DOWN_V6_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num);
    631 			return;
    632 		}
    633 #endif
    634 		if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
    635 		{
    636 #ifdef FEATURE_IPACM_HAL
    637 			if (is_upstream_set[IPA_IP_v6] == true)
    638 			{
    639 				IPACMDBG_H("Del upstream for IPv6.\n");
    640 				is_upstream_set[IPA_IP_v6] = false;
    641 				if(is_downstream_set[IPA_IP_v6] == true)
    642 				{
    643 					IPACMDBG_H("Downstream was set before, deleting UL rules.\n");
    644 					/* reset usb-client ipv6 rt-rules */
    645 					handle_lan_client_reset_rt(IPA_IP_v6);
    646 					handle_wan_down_v6(data_wan_tether->is_sta);
    647 				}
    648 			}
    649 #else
    650 			/* reset usb-client ipv6 rt-rules */
    651 			handle_lan_client_reset_rt(IPA_IP_v6);
    652 			handle_wan_down_v6(data_wan_tether->is_sta);
    653 #endif
    654 		}
    655 		break;
    656 
    657 	case IPA_DOWNSTREAM_ADD:
    658 	{
    659 		ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param;
    660 		ipa_interface_index = iface_ipa_index_query(data->if_index);
    661 		if (ipa_interface_index == ipa_if_num)
    662 		{
    663 			IPACMDBG_H("Received IPA_DOWNSTREAM_ADD event.\n");
    664 			if (is_downstream_set[data->prefix.iptype] == false)
    665 			{
    666 				IPACMDBG_H("Add downstream for IP iptype %d\n", data->prefix.iptype);
    667 				is_downstream_set[data->prefix.iptype] = true;
    668 				memcpy(&prefix[data->prefix.iptype], &data->prefix,
    669 					sizeof(prefix[data->prefix.iptype]));
    670 
    671 				if (is_upstream_set[data->prefix.iptype] == true)
    672 				{
    673 					IPACMDBG_H("Upstream was set before, adding UL rules.\n");
    674 					if (ip_type == IPA_IP_MAX || ip_type == data->prefix.iptype)
    675 					{
    676 						if (data->prefix.iptype == IPA_IP_v6) /* ipv6 only */
    677 						{
    678 							/* Only offload clients has same prefix as Android gave */
    679 							ipv6_prefix[0] = data->prefix.v6Addr[0];
    680 							ipv6_prefix[1] = data->prefix.v6Addr[1];
    681 							IPACMDBG_H("ipv6_prefix0x%x:%x\n", ipv6_prefix[0], ipv6_prefix[1]);
    682 							install_ipv6_prefix_flt_rule(ipv6_prefix);
    683 						}
    684 
    685 						if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */
    686 						{
    687 							ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(data->prefix.iptype);
    688 							handle_wan_up_ex(ext_prop, data->prefix.iptype, 0);
    689 						} else {
    690 							handle_wan_up(data->prefix.iptype); /* STA */
    691 						}
    692 					}
    693 				}
    694 			} else {
    695 				IPACMDBG_H("downstream for IP iptype %d already set \n", data->prefix.iptype);
    696 			}
    697 		}
    698 		break;
    699 	}
    700 
    701 	case IPA_DOWNSTREAM_DEL:
    702 	{
    703 		ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param;
    704 		ipa_interface_index = iface_ipa_index_query(data->if_index);
    705 		if (ipa_interface_index == ipa_if_num)
    706 		{
    707 			IPACMDBG_H("Received IPA_DOWNSTREAM_DEL event.\n");
    708 			if (is_downstream_set[data->prefix.iptype] == true)
    709 			{
    710 				IPACMDBG_H("Del downstream for IP iptype %d.\n", data->prefix.iptype);
    711 				is_downstream_set[data->prefix.iptype] = false;
    712 
    713 				if (is_upstream_set[data->prefix.iptype] == true)
    714 				{
    715 					IPACMDBG_H("Upstream was set before, deleting UL rules.\n");
    716 					if (data->prefix.iptype == IPA_IP_v4)
    717 					{
    718 						handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */
    719 					} else {
    720 						handle_lan_client_reset_rt(IPA_IP_v6);
    721 						handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */
    722 					}
    723 				}
    724 			}
    725 		}
    726 		break;
    727 	}
    728 
    729 #else
    730 	case IPA_HANDLE_WAN_UP:
    731 		IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n");
    732 
    733 		ipacm_event_iface_up* data_wan = (ipacm_event_iface_up*)param;
    734 		if (data_wan == NULL)
    735 		{
    736 			IPACMERR("No event data is found.\n");
    737 			return;
    738 		}
    739 		IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta);
    740 		if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
    741 		{
    742 		if (data_wan->is_sta == false)
    743 		{
    744 				ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
    745 				handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id);
    746 		}
    747 		else
    748 		{
    749 			handle_wan_up(IPA_IP_v4);
    750 		}
    751 		}
    752 		break;
    753 
    754 	case IPA_HANDLE_WAN_UP_V6:
    755 		IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6 event\n");
    756 
    757 		data_wan = (ipacm_event_iface_up*)param;
    758 		if (data_wan == NULL)
    759 		{
    760 			IPACMERR("No event data is found.\n");
    761 			return;
    762 		}
    763 		IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta);
    764 		if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
    765 		{
    766 			memcpy(ipv6_prefix, data_wan->ipv6_prefix, sizeof(ipv6_prefix));
    767 			install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix);
    768 			if (data_wan->is_sta == false)
    769 			{
    770 				ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
    771 				handle_wan_up_ex(ext_prop, IPA_IP_v6, 0);
    772 			}
    773 			else
    774 			{
    775 				handle_wan_up(IPA_IP_v6);
    776 			}
    777 		}
    778 		break;
    779 
    780 	case IPA_HANDLE_WAN_DOWN:
    781 		IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n");
    782 		data_wan = (ipacm_event_iface_up*)param;
    783 		if (data_wan == NULL)
    784 		{
    785 			IPACMERR("No event data is found.\n");
    786 			return;
    787 		}
    788 		IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta);
    789 		if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
    790 		{
    791 			handle_wan_down(data_wan->is_sta);
    792 		}
    793 		break;
    794 
    795 	case IPA_HANDLE_WAN_DOWN_V6:
    796 		IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6 event\n");
    797 		data_wan = (ipacm_event_iface_up*)param;
    798 		if (data_wan == NULL)
    799 		{
    800 			IPACMERR("No event data is found.\n");
    801 			return;
    802 		}
    803 		/* clean up v6 RT rules*/
    804 		IPACMDBG_H("Received IPA_WAN_V6_DOWN in LAN-instance and need clean up client IPv6 address \n");
    805 		/* reset usb-client ipv6 rt-rules */
    806 		handle_lan_client_reset_rt(IPA_IP_v6);
    807 
    808 		IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta);
    809 		if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
    810 		{
    811 			handle_wan_down_v6(data_wan->is_sta);
    812 		}
    813 		break;
    814 #endif
    815 
    816 	case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
    817 		{
    818 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;
    819 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    820 			IPACMDBG_H("Recieved IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event \n");
    821 			IPACMDBG_H("check iface %s category: %d\n", dev_name, ipa_if_cate);
    822 
    823 			if (ipa_interface_index == ipa_if_num && ipa_if_cate == ODU_IF)
    824 			{
    825 				IPACMDBG_H("ODU iface got v4-ip \n");
    826 				/* first construc ODU full header */
    827 				if ((ipv4_header_set == false) && (ipv6_header_set == false))
    828 				{
    829 					/* construct ODU RT tbl */
    830 					handle_odu_hdr_init(data->mac_addr);
    831 					if (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true)
    832 					{
    833 						handle_odu_route_add();
    834 						IPACMDBG_H("construct ODU header and route rules, embms_flag (%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable);
    835 					}
    836 					else
    837 					{
    838 						IPACMDBG_H("construct ODU header only, embms_flag (%d) \n", IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable);
    839 					}
    840 				}
    841 				/* if ODU in bridge mode, directly return */
    842 				if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false)
    843 				{
    844 					IPACMDBG_H("ODU is in bridge mode, no action \n");
    845 					return;
    846 				}
    847 			}
    848 
    849 			if (ipa_interface_index == ipa_if_num)
    850 			{
    851 				IPACMDBG_H("ETH iface got client \n");
    852 				/* first construc ETH full header */
    853 				handle_eth_hdr_init(data->mac_addr);
    854 				IPACMDBG_H("construct ETH header and route rules \n");
    855 				/* Associate with IP and construct RT-rule */
    856 				if (handle_eth_client_ipaddr(data) == IPACM_FAILURE)
    857 				{
    858 					return;
    859 				}
    860 				handle_eth_client_route_rule(data->mac_addr, data->iptype);
    861 				if (data->iptype == IPA_IP_v4)
    862 				{
    863 					/* Add NAT rules after ipv4 RT rules are set */
    864 					CtList->HandleNeighIpAddrAddEvt(data);
    865 				}
    866 				eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_ADD, IPA_IP_MAX, data->mac_addr);
    867 				return;
    868 			}
    869 		}
    870 		break;
    871 
    872 	case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT:
    873 		{
    874 			ipacm_event_data_all *data = (ipacm_event_data_all *)param;
    875 			ipa_interface_index = iface_ipa_index_query(data->if_index);
    876 
    877 			IPACMDBG_H("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event. \n");
    878 			IPACMDBG_H("check iface %s category: %d\n", dev_name, ipa_if_cate);
    879 			/* if ODU in bridge mode, directly return */
    880 			if (ipa_if_cate == ODU_IF && IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == false)
    881 			{
    882 				IPACMDBG_H("ODU is in bridge mode, no action \n");
    883 				return;
    884 			}
    885 
    886 			if (ipa_interface_index == ipa_if_num)
    887 			{
    888 				if (data->iptype == IPA_IP_v6)
    889 				{
    890 					handle_del_ipv6_addr(data);
    891 					return;
    892 				}
    893 
    894 				eth_bridge_post_event(IPA_ETH_BRIDGE_CLIENT_DEL, IPA_IP_MAX, data->mac_addr);
    895 
    896 				IPACMDBG_H("LAN iface delete client \n");
    897 				handle_eth_client_down_evt(data->mac_addr);
    898 				return;
    899 			}
    900 		}
    901 		break;
    902 
    903 	case IPA_SW_ROUTING_ENABLE:
    904 		IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n");
    905 		/* handle software routing enable event*/
    906 		handle_software_routing_enable();
    907 		break;
    908 
    909 	case IPA_SW_ROUTING_DISABLE:
    910 		IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n");
    911 		/* handle software routing disable event*/
    912 		handle_software_routing_disable();
    913 		break;
    914 
    915 	case IPA_CRADLE_WAN_MODE_SWITCH:
    916 	{
    917 		IPACMDBG_H("Received IPA_CRADLE_WAN_MODE_SWITCH event.\n");
    918 		ipacm_event_cradle_wan_mode* wan_mode = (ipacm_event_cradle_wan_mode*)param;
    919 		if(wan_mode == NULL)
    920 		{
    921 			IPACMERR("Event data is empty.\n");
    922 			return;
    923 		}
    924 
    925 		if(wan_mode->cradle_wan_mode == BRIDGE)
    926 		{
    927 			handle_cradle_wan_mode_switch(true);
    928 		}
    929 		else
    930 		{
    931 			handle_cradle_wan_mode_switch(false);
    932 		}
    933 	}
    934 	break;
    935 
    936 	case IPA_TETHERING_STATS_UPDATE_EVENT:
    937 	{
    938 		IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_EVENT event.\n");
    939 		if (IPACM_Wan::isWanUP(ipa_if_num) || IPACM_Wan::isWanUP_V6(ipa_if_num))
    940 		{
    941 			if(IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */
    942 			{
    943 				ipa_get_data_stats_resp_msg_v01 *data = (ipa_get_data_stats_resp_msg_v01 *)param;
    944 				IPACMDBG("Received IPA_TETHERING_STATS_UPDATE_STATS ipa_stats_type: %d\n",data->ipa_stats_type);
    945 				IPACMDBG("Received %d UL, %d DL pipe stats\n",data->ul_src_pipe_stats_list_len,
    946 					data->dl_dst_pipe_stats_list_len);
    947 				if (data->ipa_stats_type != QMI_IPA_STATS_TYPE_PIPE_V01)
    948 				{
    949 					IPACMERR("not valid pipe stats enum(%d)\n", data->ipa_stats_type);
    950 					return;
    951 				}
    952 				handle_tethering_stats_event(data);
    953 			}
    954 		}
    955 	}
    956 	break;
    957 
    958 	default:
    959 		break;
    960 	}
    961 
    962 	return;
    963 }
    964 
    965 
    966 int IPACM_Lan::handle_del_ipv6_addr(ipacm_event_data_all *data)
    967 {
    968 	uint32_t tx_index;
    969 	uint32_t rt_hdl;
    970 	int num_v6 =0, clnt_indx;
    971 
    972 	clnt_indx = get_eth_client_index(data->mac_addr);
    973 	if (clnt_indx == IPACM_INVALID_INDEX)
    974 	{
    975 		IPACMERR("eth client not found/attached \n");
    976 		return IPACM_FAILURE;
    977 	}
    978 
    979 	if(data->iptype == IPA_IP_v6)
    980 	{
    981 		if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) ||
    982 				(data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] != 0))
    983 		{
    984 			IPACMDBG_H("ipv6 address got: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
    985 			for(num_v6=0;num_v6 < get_client_memptr(eth_client, clnt_indx)->ipv6_set;num_v6++)
    986 			{
    987 				if( data->ipv6_addr[0] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][0] &&
    988 					data->ipv6_addr[1] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][1] &&
    989 					data->ipv6_addr[2]== get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][2] &&
    990 					data->ipv6_addr[3] == get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][3])
    991 				{
    992 					IPACMDBG_H("ipv6 addr is found at position:%d for client:%d\n", num_v6, clnt_indx);
    993 					break;
    994 				}
    995 			}
    996 		}
    997 		else
    998 		{
    999 			IPACMDBG_H("Invalid ipv6 address\n");
   1000 			return IPACM_FAILURE;
   1001 		}
   1002 		if (num_v6 == IPV6_NUM_ADDR)
   1003 		{
   1004 			IPACMDBG_H("ipv6 addr is not found. \n");
   1005 			return IPACM_FAILURE;
   1006 		}
   1007 
   1008 		for(tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   1009 		{
   1010 			if((tx_prop->tx[tx_index].ip == IPA_IP_v6) && (get_client_memptr(eth_client, clnt_indx)->route_rule_set_v6 != 0))
   1011 			{
   1012 				IPACMDBG_H("Delete client index %d ipv6 RT-rules for %d-st ipv6 for tx:%d\n", clnt_indx, num_v6, tx_index);
   1013 				rt_hdl = get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6];
   1014 				if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false)
   1015 				{
   1016 					return IPACM_FAILURE;
   1017 				}
   1018 				rt_hdl = get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6];
   1019 				if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false)
   1020 				{
   1021 					return IPACM_FAILURE;
   1022 				}
   1023 				get_client_memptr(eth_client, clnt_indx)->ipv6_set--;
   1024 				get_client_memptr(eth_client, clnt_indx)->route_rule_set_v6--;
   1025 
   1026 				for(;num_v6< get_client_memptr(eth_client, clnt_indx)->ipv6_set;num_v6++)
   1027 				{
   1028 					get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][0] =
   1029 						get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][0];
   1030 					get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][1] =
   1031 						get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][1];
   1032 					get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][2] =
   1033 						get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][2];
   1034 					get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6][3] =
   1035 						get_client_memptr(eth_client, clnt_indx)->v6_addr[num_v6+1][3];
   1036 					get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6] =
   1037 						get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6+1];
   1038 					get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6] =
   1039 						get_client_memptr(eth_client, clnt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6+1];
   1040 				}
   1041 			}
   1042 		}
   1043 	}
   1044 	return IPACM_SUCCESS;
   1045 }
   1046 
   1047 /* delete filter rule for wan_down event for IPv4*/
   1048 int IPACM_Lan::handle_wan_down(bool is_sta_mode)
   1049 {
   1050 	ipa_fltr_installed_notif_req_msg_v01 flt_index;
   1051 	int fd;
   1052 
   1053 	fd = open(IPA_DEVICE_NAME, O_RDWR);
   1054 	if (0 == fd)
   1055 	{
   1056 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
   1057 		return IPACM_FAILURE;
   1058 	}
   1059 
   1060 	if(is_sta_mode == false && modem_ul_v4_set == true)
   1061 	{
   1062 		if (num_wan_ul_fl_rule_v4 > MAX_WAN_UL_FILTER_RULES)
   1063 		{
   1064 			IPACMERR("number of wan_ul_fl_rule_v4 (%d) > MAX_WAN_UL_FILTER_RULES (%d), aborting...\n", num_wan_ul_fl_rule_v4, MAX_WAN_UL_FILTER_RULES);
   1065 			close(fd);
   1066 			return IPACM_FAILURE;
   1067 		}
   1068 		if (m_filtering.DeleteFilteringHdls(wan_ul_fl_rule_hdl_v4,
   1069 			IPA_IP_v4, num_wan_ul_fl_rule_v4) == false)
   1070 		{
   1071 			IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n");
   1072 			close(fd);
   1073 			return IPACM_FAILURE;
   1074 		}
   1075 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, num_wan_ul_fl_rule_v4);
   1076 
   1077 		memset(wan_ul_fl_rule_hdl_v4, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t));
   1078 		num_wan_ul_fl_rule_v4 = 0;
   1079 		modem_ul_v4_set = false;
   1080 
   1081 		memset(&flt_index, 0, sizeof(flt_index));
   1082 		flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe);
   1083 		flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01;
   1084 #ifndef FEATURE_IPA_V3
   1085 		flt_index.filter_index_list_len = 0;
   1086 #else /* defined (FEATURE_IPA_V3) */
   1087 		flt_index.rule_id_valid = 1;
   1088 		flt_index.rule_id_len = 0;
   1089 #endif
   1090 		flt_index.embedded_pipe_index_valid = 1;
   1091 		flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD);
   1092 		flt_index.retain_header_valid = 1;
   1093 		flt_index.retain_header = 0;
   1094 		flt_index.embedded_call_mux_id_valid = 1;
   1095 		flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId();
   1096 
   1097 		if(false == m_filtering.SendFilteringRuleIndex(&flt_index))
   1098 		{
   1099 			IPACMERR("Error sending filtering rule index, aborting...\n");
   1100 			close(fd);
   1101 			return IPACM_FAILURE;
   1102 		}
   1103 	}
   1104 	else
   1105 	{
   1106 		if (m_filtering.DeleteFilteringHdls(&lan_wan_fl_rule_hdl[0], IPA_IP_v4, 1) == false)
   1107 		{
   1108 			IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n");
   1109 			close(fd);
   1110 			return IPACM_FAILURE;
   1111 		}
   1112 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   1113 	}
   1114 
   1115 	close(fd);
   1116 	return IPACM_SUCCESS;
   1117 }
   1118 
   1119 /* handle new_address event*/
   1120 int IPACM_Lan::handle_addr_evt(ipacm_event_data_addr *data)
   1121 {
   1122 	struct ipa_ioc_add_rt_rule *rt_rule;
   1123 	struct ipa_rt_rule_add *rt_rule_entry;
   1124 	const int NUM_RULES = 1;
   1125 	uint32_t num_ipv6_addr;
   1126 	int res = IPACM_SUCCESS;
   1127 #ifdef FEATURE_IPACM_HAL
   1128 	IPACM_OffloadManager* OffloadMng;
   1129 #endif
   1130 
   1131 	IPACMDBG_H("set route/filter rule ip-type: %d \n", data->iptype);
   1132 
   1133 /* Add private subnet*/
   1134 #ifdef FEATURE_IPA_ANDROID
   1135 	if (data->iptype == IPA_IP_v4)
   1136 	{
   1137 		IPACMDBG_H("current IPACM private subnet_addr number(%d)\n", IPACM_Iface::ipacmcfg->ipa_num_private_subnet);
   1138 		if_ipv4_subnet = (data->ipv4_addr >> 8) << 8;
   1139 		IPACMDBG_H(" Add IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet);
   1140 		if(IPACM_Iface::ipacmcfg->AddPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false)
   1141 		{
   1142 			IPACMERR(" can't Add IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet);
   1143 		}
   1144 	}
   1145 #endif /* defined(FEATURE_IPA_ANDROID)*/
   1146 
   1147 	/* Update the IP Type. */
   1148 	config_ip_type(data->iptype);
   1149 
   1150 	if (data->iptype == IPA_IP_v4)
   1151 	{
   1152 		rt_rule = (struct ipa_ioc_add_rt_rule *)
   1153 			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
   1154 							NUM_RULES * sizeof(struct ipa_rt_rule_add));
   1155 
   1156 		if (!rt_rule)
   1157 		{
   1158 			IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
   1159 			return IPACM_FAILURE;
   1160 		}
   1161 
   1162 		rt_rule->commit = 1;
   1163 		rt_rule->num_rules = NUM_RULES;
   1164 		rt_rule->ip = data->iptype;
   1165 		rt_rule_entry = &rt_rule->rules[0];
   1166 		rt_rule_entry->at_rear = false;
   1167 		rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;  //go to A5
   1168 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
   1169 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name));
   1170 		rt_rule_entry->rule.attrib.u.v4.dst_addr      = data->ipv4_addr;
   1171 		rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
   1172 #ifdef FEATURE_IPA_V3
   1173 		rt_rule_entry->rule.hashable = true;
   1174 #endif
   1175 		if (false == m_routing.AddRoutingRule(rt_rule))
   1176 		{
   1177 			IPACMERR("Routing rule addition failed!\n");
   1178 			res = IPACM_FAILURE;
   1179 			goto fail;
   1180 		}
   1181 		else if (rt_rule_entry->status)
   1182 		{
   1183 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
   1184 			res = rt_rule_entry->status;
   1185 			goto fail;
   1186 		}
   1187 		dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl;
   1188 		IPACMDBG_H("ipv4 iface rt-rule hdl1=0x%x\n", dft_rt_rule_hdl[0]);
   1189 		/* initial multicast/broadcast/fragment filter rule */
   1190 
   1191 		init_fl_rule(data->iptype);
   1192 		install_ipv4_icmp_flt_rule();
   1193 
   1194 		/* populate the flt rule offset for eth bridge */
   1195 		eth_bridge_flt_rule_offset[data->iptype] = ipv4_icmp_flt_rule_hdl[0];
   1196 		eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v4, NULL);
   1197 	}
   1198 	else
   1199 	{
   1200 	    /* check if see that v6-addr already or not*/
   1201 	    for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++)
   1202 	    {
   1203             if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) &&
   1204 	           (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) &&
   1205 	           (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) &&
   1206 	           (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3]))
   1207             {
   1208 				return IPACM_FAILURE;
   1209 				break;
   1210 	        }
   1211 	    }
   1212 
   1213 		rt_rule = (struct ipa_ioc_add_rt_rule *)
   1214 			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
   1215 							NUM_RULES * sizeof(struct ipa_rt_rule_add));
   1216 
   1217 		if (!rt_rule)
   1218 		{
   1219 			IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
   1220 			return IPACM_FAILURE;
   1221 		}
   1222 
   1223 		rt_rule->commit = 1;
   1224 		rt_rule->num_rules = NUM_RULES;
   1225 		rt_rule->ip = data->iptype;
   1226 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name));
   1227 
   1228 		rt_rule_entry = &rt_rule->rules[0];
   1229 		rt_rule_entry->at_rear = false;
   1230 		rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;  //go to A5
   1231 		rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR;
   1232 		rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0];
   1233 		rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1];
   1234 		rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2];
   1235 		rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[3];
   1236 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
   1237 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
   1238 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
   1239 		rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
   1240 		ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0];
   1241 		ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1];
   1242 		ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2];
   1243 		ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3];
   1244 #ifdef FEATURE_IPA_V3
   1245 		rt_rule_entry->rule.hashable = true;
   1246 #endif
   1247 		if (false == m_routing.AddRoutingRule(rt_rule))
   1248 		{
   1249 			IPACMERR("Routing rule addition failed!\n");
   1250 			res = IPACM_FAILURE;
   1251 			goto fail;
   1252 		}
   1253 		else if (rt_rule_entry->status)
   1254 		{
   1255 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
   1256 			res = rt_rule_entry->status;
   1257 			goto fail;
   1258 		}
   1259 		dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl;
   1260 
   1261 		/* setup same rule for v6_wan table*/
   1262 		strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
   1263 		if (false == m_routing.AddRoutingRule(rt_rule))
   1264 		{
   1265 			IPACMERR("Routing rule addition failed!\n");
   1266 			res = IPACM_FAILURE;
   1267 			goto fail;
   1268 		}
   1269 		else if (rt_rule_entry->status)
   1270 		{
   1271 			IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status);
   1272 			res = rt_rule_entry->status;
   1273 			goto fail;
   1274 		}
   1275 		dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl;
   1276 
   1277 		IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n",
   1278 		          dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6],
   1279 		          dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],num_dft_rt_v6);
   1280 
   1281 		if (num_dft_rt_v6 == 0)
   1282 		{
   1283 			install_ipv6_icmp_flt_rule();
   1284 
   1285 			/* populate the flt rule offset for eth bridge */
   1286 			eth_bridge_flt_rule_offset[data->iptype] = ipv6_icmp_flt_rule_hdl[0];
   1287 			eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_UP, IPA_IP_v6, NULL);
   1288 
   1289 			init_fl_rule(data->iptype);
   1290 		}
   1291 		num_dft_rt_v6++;
   1292 		IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6);
   1293 	}
   1294 
   1295 #ifdef FEATURE_IPACM_HAL
   1296 	/* check if having pending add_downstream cache*/
   1297 	OffloadMng = IPACM_OffloadManager::GetInstance();
   1298 	if (OffloadMng == NULL) {
   1299 		IPACMERR("failed to get IPACM_OffloadManager instance !\n");
   1300 	} else {
   1301 		IPACMDBG_H(" check iface %s if having add_downstream cache events\n", dev_name);
   1302 		OffloadMng->search_framwork_cache(dev_name);
   1303 	}
   1304 #endif
   1305 
   1306 	IPACMDBG_H("finish route/filter rule ip-type: %d, res(%d)\n", data->iptype, res);
   1307 
   1308 fail:
   1309 	free(rt_rule);
   1310 	return res;
   1311 }
   1312 
   1313 /* configure private subnet filter rules*/
   1314 int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype)
   1315 {
   1316 	struct ipa_flt_rule_add flt_rule_entry;
   1317 	int i;
   1318 
   1319 	ipa_ioc_add_flt_rule *m_pFilteringTable;
   1320 
   1321 	IPACMDBG_H("lan->handle_private_subnet(); set route/filter rule \n");
   1322 
   1323 	if (rx_prop == NULL)
   1324 	{
   1325 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   1326 		return IPACM_SUCCESS;
   1327 	}
   1328 
   1329 	if (iptype == IPA_IP_v4)
   1330 	{
   1331 
   1332 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
   1333 			 calloc(1,
   1334 							sizeof(struct ipa_ioc_add_flt_rule) +
   1335 							(IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_add)
   1336 							);
   1337 		if (!m_pFilteringTable)
   1338 		{
   1339 			PERROR("Error Locate ipa_flt_rule_add memory...\n");
   1340 			return IPACM_FAILURE;
   1341 		}
   1342 		m_pFilteringTable->commit = 1;
   1343 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   1344 		m_pFilteringTable->global = false;
   1345 		m_pFilteringTable->ip = IPA_IP_v4;
   1346 		m_pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
   1347 
   1348 		/* Make LAN-traffic always go A5, use default IPA-RT table */
   1349 		if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4))
   1350 		{
   1351 			IPACMERR("LAN m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_default_v4);
   1352 			free(m_pFilteringTable);
   1353 			return IPACM_FAILURE;
   1354 		}
   1355 
   1356 		for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++)
   1357 		{
   1358 			memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   1359 			flt_rule_entry.at_rear = true;
   1360 			flt_rule_entry.rule.retain_hdr = 1;
   1361 			flt_rule_entry.flt_rule_hdl = -1;
   1362 			flt_rule_entry.status = -1;
   1363 			flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   1364 #ifdef FEATURE_IPA_V3
   1365 			flt_rule_entry.rule.hashable = true;
   1366 #endif
   1367                         /* Support private subnet feature including guest-AP can't talk to primary AP etc */
   1368 			flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl;
   1369 			IPACMDBG_H(" private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name);
   1370 
   1371 			memcpy(&flt_rule_entry.rule.attrib,
   1372 						 &rx_prop->rx[0].attrib,
   1373 						 sizeof(flt_rule_entry.rule.attrib));
   1374 			flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   1375 			flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask;
   1376 			flt_rule_entry.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr;
   1377 			memcpy(&(m_pFilteringTable->rules[i]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   1378 			IPACMDBG_H("Loop %d  5\n", i);
   1379 		}
   1380 
   1381 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   1382 		{
   1383 			IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
   1384 			free(m_pFilteringTable);
   1385 			return IPACM_FAILURE;
   1386 		}
   1387 		IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet);
   1388 
   1389 		/* copy filter rule hdls */
   1390 		for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_private_subnet; i++)
   1391 		{
   1392 			private_fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
   1393 		}
   1394 		free(m_pFilteringTable);
   1395 	}
   1396 	else
   1397 	{
   1398 		IPACMDBG_H("No private subnet rules for ipv6 iface %s\n", dev_name);
   1399 	}
   1400 	return IPACM_SUCCESS;
   1401 }
   1402 
   1403 
   1404 /* for STA mode wan up:  configure filter rule for wan_up event*/
   1405 int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type)
   1406 {
   1407 	struct ipa_flt_rule_add flt_rule_entry;
   1408 	int len = 0;
   1409 	ipa_ioc_add_flt_rule *m_pFilteringTable;
   1410 
   1411 	IPACMDBG_H("set WAN interface as default filter rule\n");
   1412 
   1413 	if (rx_prop == NULL)
   1414 	{
   1415 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   1416 		return IPACM_SUCCESS;
   1417 	}
   1418 
   1419 	if(ip_type == IPA_IP_v4)
   1420 	{
   1421 		len = sizeof(struct ipa_ioc_add_flt_rule) + (1 * sizeof(struct ipa_flt_rule_add));
   1422 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
   1423 		if (m_pFilteringTable == NULL)
   1424 		{
   1425 			PERROR("Error Locate ipa_flt_rule_add memory...\n");
   1426 			return IPACM_FAILURE;
   1427 		}
   1428 
   1429 		m_pFilteringTable->commit = 1;
   1430 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   1431 		m_pFilteringTable->global = false;
   1432 		m_pFilteringTable->ip = IPA_IP_v4;
   1433 		m_pFilteringTable->num_rules = (uint8_t)1;
   1434 
   1435 		IPACMDBG_H("Retrieving routing hanle for table: %s\n",
   1436 						 IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name);
   1437 		if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4))
   1438 		{
   1439 			IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4=0x%p) Failed.\n",
   1440 							 &IPACM_Iface::ipacmcfg->rt_tbl_wan_v4);
   1441 			free(m_pFilteringTable);
   1442 			return IPACM_FAILURE;
   1443 		}
   1444 		IPACMDBG_H("Routing hanle for table: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl);
   1445 
   1446 
   1447 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields
   1448 		flt_rule_entry.at_rear = true;
   1449 		flt_rule_entry.flt_rule_hdl = -1;
   1450 		flt_rule_entry.status = -1;
   1451 		if(IPACM_Wan::isWan_Bridge_Mode())
   1452 		{
   1453 			flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   1454 		}
   1455 		else
   1456 		{
   1457 			flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT; //IPA_PASS_TO_ROUTING
   1458 		}
   1459 #ifdef FEATURE_IPA_V3
   1460 		flt_rule_entry.rule.hashable = true;
   1461 #endif
   1462 		flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl;
   1463 
   1464 		memcpy(&flt_rule_entry.rule.attrib,
   1465 					 &rx_prop->rx[0].attrib,
   1466 					 sizeof(flt_rule_entry.rule.attrib));
   1467 
   1468 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   1469 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0;
   1470 		flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0;
   1471 
   1472 /* only offload UL traffic of certain clients */
   1473 #ifdef FEATURE_IPACM_HAL
   1474 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
   1475 		flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = prefix[IPA_IP_v4].v4Mask;
   1476 		flt_rule_entry.rule.attrib.u.v4.dst_addr = prefix[IPA_IP_v4].v4Addr;
   1477 #endif
   1478 		memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry));
   1479 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   1480 		{
   1481 			IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n");
   1482 			free(m_pFilteringTable);
   1483 			return IPACM_FAILURE;
   1484 		}
   1485 		else
   1486 		{
   1487 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   1488 			IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n",
   1489 							 m_pFilteringTable->rules[0].flt_rule_hdl,
   1490 							 m_pFilteringTable->rules[0].status);
   1491 		}
   1492 
   1493 
   1494 		/* copy filter hdls  */
   1495 		lan_wan_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
   1496 		free(m_pFilteringTable);
   1497 	}
   1498 	else if(ip_type == IPA_IP_v6)
   1499 	{
   1500 		/* add default v6 filter rule */
   1501 		m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
   1502 			 calloc(1, sizeof(struct ipa_ioc_add_flt_rule) +
   1503 					1 * sizeof(struct ipa_flt_rule_add));
   1504 
   1505 		if (!m_pFilteringTable)
   1506 		{
   1507 			PERROR("Error Locate ipa_flt_rule_add memory...\n");
   1508 			return IPACM_FAILURE;
   1509 		}
   1510 
   1511 		m_pFilteringTable->commit = 1;
   1512 		m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   1513 		m_pFilteringTable->global = false;
   1514 		m_pFilteringTable->ip = IPA_IP_v6;
   1515 		m_pFilteringTable->num_rules = (uint8_t)1;
   1516 
   1517 		if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_v6))
   1518 		{
   1519 			IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_v6=0x%p) Failed.\n", &IPACM_Iface::ipacmcfg->rt_tbl_v6);
   1520 			free(m_pFilteringTable);
   1521 			return IPACM_FAILURE;
   1522 		}
   1523 
   1524 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   1525 
   1526 		flt_rule_entry.at_rear = true;
   1527 		flt_rule_entry.flt_rule_hdl = -1;
   1528 		flt_rule_entry.status = -1;
   1529 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   1530 #ifdef FEATURE_IPA_V3
   1531 		flt_rule_entry.rule.hashable = true;
   1532 #endif
   1533 		flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_v6.hdl;
   1534 
   1535 		memcpy(&flt_rule_entry.rule.attrib,
   1536 					 &rx_prop->rx[0].attrib,
   1537 					 sizeof(flt_rule_entry.rule.attrib));
   1538 
   1539 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   1540 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0x00000000;
   1541 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
   1542 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
   1543 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
   1544 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0X00000000;
   1545 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
   1546 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
   1547 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
   1548 
   1549 /* only offload UL traffic of certain clients */
   1550 #ifdef FEATURE_IPACM_HAL
   1551 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
   1552 		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[0] = ntohl(prefix[IPA_IP_v6].v6Mask[0]);
   1553 		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[1] = ntohl(prefix[IPA_IP_v6].v6Mask[1]);
   1554 		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[2] = ntohl(prefix[IPA_IP_v6].v6Mask[2]);
   1555 		flt_rule_entry.rule.attrib.u.v6.src_addr_mask[3] = ntohl(prefix[IPA_IP_v6].v6Mask[3]);
   1556 		flt_rule_entry.rule.attrib.u.v6.src_addr[0] = ntohl(prefix[IPA_IP_v6].v6Addr[0]);
   1557 		flt_rule_entry.rule.attrib.u.v6.src_addr[1] = ntohl(prefix[IPA_IP_v6].v6Addr[1]);
   1558 		flt_rule_entry.rule.attrib.u.v6.src_addr[2] = ntohl(prefix[IPA_IP_v6].v6Addr[2]);
   1559 		flt_rule_entry.rule.attrib.u.v6.src_addr[3] = ntohl(prefix[IPA_IP_v6].v6Addr[3]);
   1560 
   1561 #endif
   1562 		memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   1563 		if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
   1564 		{
   1565 			IPACMERR("Error Adding Filtering rule, aborting...\n");
   1566 			free(m_pFilteringTable);
   1567 			return IPACM_FAILURE;
   1568 		}
   1569 		else
   1570 		{
   1571 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   1572 			IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status);
   1573 		}
   1574 
   1575 		/* copy filter hdls */
   1576 		dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES] = m_pFilteringTable->rules[0].flt_rule_hdl;
   1577 		free(m_pFilteringTable);
   1578 	}
   1579 
   1580 	return IPACM_SUCCESS;
   1581 }
   1582 
   1583 int IPACM_Lan::handle_wan_up_ex(ipacm_ext_prop *ext_prop, ipa_ip_type iptype, uint8_t xlat_mux_id)
   1584 {
   1585 	int fd, ret = IPACM_SUCCESS;
   1586 	uint32_t cnt;
   1587 	IPACM_Config* ipacm_config = IPACM_Iface::ipacmcfg;
   1588 	struct ipa_ioc_write_qmapid mux;
   1589 
   1590 	if(rx_prop != NULL)
   1591 	{
   1592 		/* give mud ID to IPA-driver for WLAN/LAN pkts */
   1593 		fd = open(IPA_DEVICE_NAME, O_RDWR);
   1594 		if (0 == fd)
   1595 		{
   1596 			IPACMDBG_H("Failed opening %s.\n", IPA_DEVICE_NAME);
   1597 			return IPACM_FAILURE;
   1598 		}
   1599 
   1600 		mux.qmap_id = ipacm_config->GetQmapId();
   1601 		for(cnt=0; cnt<rx_prop->num_rx_props; cnt++)
   1602 		{
   1603 			mux.client = rx_prop->rx[cnt].src_pipe;
   1604 			ret = ioctl(fd, IPA_IOC_WRITE_QMAPID, &mux);
   1605 			if (ret)
   1606 			{
   1607 				IPACMERR("Failed to write mux id %d\n", mux.qmap_id);
   1608 				close(fd);
   1609 				return IPACM_FAILURE;
   1610 			}
   1611 		}
   1612 		close(fd);
   1613 	}
   1614 
   1615 	/* check only add static UL filter rule once */
   1616 	if (iptype ==IPA_IP_v6 && modem_ul_v6_set == false)
   1617 	{
   1618 		IPACMDBG_H("IPA_IP_v6 num_dft_rt_v6 %d xlat_mux_id: %d modem_ul_v6_set: %d\n", num_dft_rt_v6, xlat_mux_id, modem_ul_v6_set);
   1619 		ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id);
   1620 		modem_ul_v6_set = true;
   1621 	} else if (iptype ==IPA_IP_v4 && modem_ul_v4_set == false) {
   1622 		IPACMDBG_H("IPA_IP_v4 xlat_mux_id: %d, modem_ul_v4_set %d\n", xlat_mux_id, modem_ul_v4_set);
   1623 		ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id);
   1624 		modem_ul_v4_set = true;
   1625 	} else {
   1626 		IPACMDBG_H("ip-type: %d modem_ul_v4_set: %d, modem_ul_v6_set %d\n", iptype, modem_ul_v4_set, modem_ul_v6_set);
   1627 	}
   1628 	return ret;
   1629 }
   1630 
   1631 /* handle ETH client initial, construct full headers (tx property) */
   1632 int IPACM_Lan::handle_eth_hdr_init(uint8_t *mac_addr)
   1633 {
   1634 
   1635 #define ETH_IFACE_INDEX_LEN 2
   1636 
   1637 	int res = IPACM_SUCCESS, len = 0;
   1638 	char index[ETH_IFACE_INDEX_LEN];
   1639 	struct ipa_ioc_copy_hdr sCopyHeader;
   1640 	struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
   1641 	uint32_t cnt;
   1642 	int clnt_indx;
   1643 
   1644 	clnt_indx = get_eth_client_index(mac_addr);
   1645 
   1646 	if (clnt_indx != IPACM_INVALID_INDEX)
   1647 	{
   1648 		IPACMERR("eth client is found/attached already with index %d \n", clnt_indx);
   1649 		return IPACM_FAILURE;
   1650 	}
   1651 
   1652 	/* add header to IPA */
   1653 	if (num_eth_client >= IPA_MAX_NUM_ETH_CLIENTS)
   1654 	{
   1655 		IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_ETH_CLIENTS);
   1656 		return IPACM_FAILURE;
   1657 	}
   1658 
   1659 	IPACMDBG_H("ETH client number: %d\n", num_eth_client);
   1660 
   1661 	memcpy(get_client_memptr(eth_client, num_eth_client)->mac,
   1662 				 mac_addr,
   1663 				 sizeof(get_client_memptr(eth_client, num_eth_client)->mac));
   1664 
   1665 
   1666 	IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   1667 					 mac_addr[0], mac_addr[1], mac_addr[2],
   1668 					 mac_addr[3], mac_addr[4], mac_addr[5]);
   1669 
   1670 	IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   1671 					 get_client_memptr(eth_client, num_eth_client)->mac[0],
   1672 					 get_client_memptr(eth_client, num_eth_client)->mac[1],
   1673 					 get_client_memptr(eth_client, num_eth_client)->mac[2],
   1674 					 get_client_memptr(eth_client, num_eth_client)->mac[3],
   1675 					 get_client_memptr(eth_client, num_eth_client)->mac[4],
   1676 					 get_client_memptr(eth_client, num_eth_client)->mac[5]);
   1677 
   1678 	/* add header to IPA */
   1679 	if(tx_prop != NULL)
   1680 	{
   1681 		len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
   1682 		pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len);
   1683 		if (pHeaderDescriptor == NULL)
   1684 		{
   1685 			IPACMERR("calloc failed to allocate pHeaderDescriptor\n");
   1686 			return IPACM_FAILURE;
   1687 		}
   1688 
   1689 		/* copy partial header for v4*/
   1690 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   1691 		{
   1692 				 if(tx_prop->tx[cnt].ip==IPA_IP_v4)
   1693 				 {
   1694 								IPACMDBG_H("Got partial v4-header name from %d tx props\n", cnt);
   1695 								memset(&sCopyHeader, 0, sizeof(sCopyHeader));
   1696 								memcpy(sCopyHeader.name,
   1697 											 tx_prop->tx[cnt].hdr_name,
   1698 											 sizeof(sCopyHeader.name));
   1699 
   1700 								IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
   1701 								if (m_header.CopyHeader(&sCopyHeader) == false)
   1702 								{
   1703 									PERROR("ioctl copy header failed");
   1704 									res = IPACM_FAILURE;
   1705 									goto fail;
   1706 								}
   1707 
   1708 								IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
   1709 								IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
   1710 								if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
   1711 								{
   1712 									IPACMERR("header oversize\n");
   1713 									res = IPACM_FAILURE;
   1714 									goto fail;
   1715 								}
   1716 								else
   1717 								{
   1718 									memcpy(pHeaderDescriptor->hdr[0].hdr,
   1719 												 sCopyHeader.hdr,
   1720 												 sCopyHeader.hdr_len);
   1721 								}
   1722 
   1723 								/* copy client mac_addr to partial header */
   1724 								if (sCopyHeader.is_eth2_ofst_valid)
   1725 								{
   1726 									memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst],
   1727 											 mac_addr,
   1728 											 IPA_MAC_ADDR_SIZE);
   1729 								}
   1730 								/* replace src mac to bridge mac_addr if any  */
   1731 								if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
   1732 								{
   1733 									memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
   1734 											IPACM_Iface::ipacmcfg->bridge_mac,
   1735 											IPA_MAC_ADDR_SIZE);
   1736 									IPACMDBG_H("device is in bridge mode \n");
   1737 								}
   1738 
   1739 								pHeaderDescriptor->commit = true;
   1740 								pHeaderDescriptor->num_hdrs = 1;
   1741 
   1742 								memset(pHeaderDescriptor->hdr[0].name, 0,
   1743 											 sizeof(pHeaderDescriptor->hdr[0].name));
   1744 
   1745 								snprintf(index,sizeof(index), "%d", ipa_if_num);
   1746 								strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name));
   1747 								pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   1748 								if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_ETH_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
   1749 								{
   1750 									IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
   1751 									res = IPACM_FAILURE;
   1752 									goto fail;
   1753 								}
   1754 
   1755 								snprintf(index,sizeof(index), "%d", header_name_count);
   1756 								if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
   1757 								{
   1758 									IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
   1759 									res = IPACM_FAILURE;
   1760 									goto fail;
   1761 								}
   1762 
   1763 								pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
   1764 								pHeaderDescriptor->hdr[0].hdr_hdl = -1;
   1765 								pHeaderDescriptor->hdr[0].is_partial = 0;
   1766 								pHeaderDescriptor->hdr[0].status = -1;
   1767 
   1768 					 if (m_header.AddHeader(pHeaderDescriptor) == false ||
   1769 							pHeaderDescriptor->hdr[0].status != 0)
   1770 					 {
   1771 						IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
   1772 						res = IPACM_FAILURE;
   1773 						goto fail;
   1774 					 }
   1775 
   1776 					get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
   1777 					IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n",
   1778 												 num_eth_client,
   1779 												 pHeaderDescriptor->hdr[0].name,
   1780 												 get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v4);
   1781 									get_client_memptr(eth_client, num_eth_client)->ipv4_header_set=true;
   1782 
   1783 					break;
   1784 				 }
   1785 		}
   1786 
   1787 
   1788 		/* copy partial header for v6*/
   1789 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   1790 		{
   1791 			if(tx_prop->tx[cnt].ip==IPA_IP_v6)
   1792 			{
   1793 
   1794 				IPACMDBG_H("Got partial v6-header name from %d tx props\n", cnt);
   1795 				memset(&sCopyHeader, 0, sizeof(sCopyHeader));
   1796 				memcpy(sCopyHeader.name,
   1797 						tx_prop->tx[cnt].hdr_name,
   1798 							sizeof(sCopyHeader.name));
   1799 
   1800 				IPACMDBG_H("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
   1801 				if (m_header.CopyHeader(&sCopyHeader) == false)
   1802 				{
   1803 					PERROR("ioctl copy header failed");
   1804 					res = IPACM_FAILURE;
   1805 					goto fail;
   1806 				}
   1807 
   1808 				IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
   1809 				IPACMDBG_H("header eth2_ofst_valid: %d, eth2_ofst: %d\n", sCopyHeader.is_eth2_ofst_valid, sCopyHeader.eth2_ofst);
   1810 				if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
   1811 				{
   1812 					IPACMERR("header oversize\n");
   1813 					res = IPACM_FAILURE;
   1814 					goto fail;
   1815 				}
   1816 				else
   1817 				{
   1818 					memcpy(pHeaderDescriptor->hdr[0].hdr,
   1819 							sCopyHeader.hdr,
   1820 								sCopyHeader.hdr_len);
   1821 				}
   1822 
   1823 				/* copy client mac_addr to partial header */
   1824 				if (sCopyHeader.is_eth2_ofst_valid)
   1825 				{
   1826 					memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst],
   1827 						mac_addr,
   1828 						IPA_MAC_ADDR_SIZE);
   1829 				}
   1830 				/* replace src mac to bridge mac_addr if any  */
   1831 				if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
   1832 				{
   1833 					memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
   1834 							IPACM_Iface::ipacmcfg->bridge_mac,
   1835 							IPA_MAC_ADDR_SIZE);
   1836 					IPACMDBG_H("device is in bridge mode \n");
   1837 				}
   1838 
   1839 				pHeaderDescriptor->commit = true;
   1840 				pHeaderDescriptor->num_hdrs = 1;
   1841 
   1842 				memset(pHeaderDescriptor->hdr[0].name, 0,
   1843 					 sizeof(pHeaderDescriptor->hdr[0].name));
   1844 
   1845 				snprintf(index,sizeof(index), "%d", ipa_if_num);
   1846 				strlcpy(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name));
   1847 				pHeaderDescriptor->hdr[0].name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   1848 				if (strlcat(pHeaderDescriptor->hdr[0].name, IPA_ETH_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
   1849 				{
   1850 					IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
   1851 					res = IPACM_FAILURE;
   1852 					goto fail;
   1853 				}
   1854 				snprintf(index,sizeof(index), "%d", header_name_count);
   1855 				if (strlcat(pHeaderDescriptor->hdr[0].name, index, sizeof(pHeaderDescriptor->hdr[0].name)) > IPA_RESOURCE_NAME_MAX)
   1856 				{
   1857 					IPACMERR(" header name construction failed exceed length (%zu)\n", strlen(pHeaderDescriptor->hdr[0].name));
   1858 					res = IPACM_FAILURE;
   1859 					goto fail;
   1860 				}
   1861 
   1862 				pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
   1863 				pHeaderDescriptor->hdr[0].hdr_hdl = -1;
   1864 				pHeaderDescriptor->hdr[0].is_partial = 0;
   1865 				pHeaderDescriptor->hdr[0].status = -1;
   1866 
   1867 				if (m_header.AddHeader(pHeaderDescriptor) == false ||
   1868 						pHeaderDescriptor->hdr[0].status != 0)
   1869 				{
   1870 					IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
   1871 					res = IPACM_FAILURE;
   1872 					goto fail;
   1873 				}
   1874 
   1875 				get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
   1876 				IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n",
   1877 						 num_eth_client,
   1878 						 pHeaderDescriptor->hdr[0].name,
   1879 									 get_client_memptr(eth_client, num_eth_client)->hdr_hdl_v6);
   1880 
   1881 									get_client_memptr(eth_client, num_eth_client)->ipv6_header_set=true;
   1882 
   1883 				break;
   1884 
   1885 			}
   1886 		}
   1887 		/* initialize wifi client*/
   1888 		get_client_memptr(eth_client, num_eth_client)->route_rule_set_v4 = false;
   1889 		get_client_memptr(eth_client, num_eth_client)->route_rule_set_v6 = 0;
   1890 		get_client_memptr(eth_client, num_eth_client)->ipv4_set = false;
   1891 		get_client_memptr(eth_client, num_eth_client)->ipv6_set = 0;
   1892 		num_eth_client++;
   1893 		header_name_count++; //keep increasing header_name_count
   1894 		res = IPACM_SUCCESS;
   1895 		IPACMDBG_H("eth client number: %d\n", num_eth_client);
   1896 	}
   1897 	else
   1898 	{
   1899 		return res;
   1900 	}
   1901 fail:
   1902 	free(pHeaderDescriptor);
   1903 	return res;
   1904 }
   1905 
   1906 /*handle eth client */
   1907 int IPACM_Lan::handle_eth_client_ipaddr(ipacm_event_data_all *data)
   1908 {
   1909 	int clnt_indx;
   1910 	int v6_num;
   1911 	uint32_t ipv6_link_local_prefix = 0xFE800000;
   1912 	uint32_t ipv6_link_local_prefix_mask = 0xFFC00000;
   1913 
   1914 	IPACMDBG_H("number of eth clients: %d\n", num_eth_client);
   1915 	IPACMDBG_H("event MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   1916 					 data->mac_addr[0],
   1917 					 data->mac_addr[1],
   1918 					 data->mac_addr[2],
   1919 					 data->mac_addr[3],
   1920 					 data->mac_addr[4],
   1921 					 data->mac_addr[5]);
   1922 
   1923 	clnt_indx = get_eth_client_index(data->mac_addr);
   1924 
   1925 		if (clnt_indx == IPACM_INVALID_INDEX)
   1926 		{
   1927 			IPACMERR("eth client not found/attached \n");
   1928 			return IPACM_FAILURE;
   1929 		}
   1930 
   1931 	IPACMDBG_H("Ip-type received %d\n", data->iptype);
   1932 	if (data->iptype == IPA_IP_v4)
   1933 	{
   1934 		IPACMDBG_H("ipv4 address: 0x%x\n", data->ipv4_addr);
   1935 		if (data->ipv4_addr != 0) /* not 0.0.0.0 */
   1936 		{
   1937 			if (get_client_memptr(eth_client, clnt_indx)->ipv4_set == false)
   1938 			{
   1939 				get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr;
   1940 				get_client_memptr(eth_client, clnt_indx)->ipv4_set = true;
   1941 			}
   1942 			else
   1943 			{
   1944 			   /* check if client got new IPv4 address*/
   1945 			   if(data->ipv4_addr == get_client_memptr(eth_client, clnt_indx)->v4_addr)
   1946 			   {
   1947 				IPACMDBG_H("Already setup ipv4 addr for client:%d, ipv4 address didn't change\n", clnt_indx);
   1948 				 return IPACM_FAILURE;
   1949 			   }
   1950 			   else
   1951 			   {
   1952 					IPACMDBG_H("ipv4 addr for client:%d is changed \n", clnt_indx);
   1953 					/* delete NAT rules first */
   1954 					CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, clnt_indx)->v4_addr);
   1955 					delete_eth_rtrules(clnt_indx,IPA_IP_v4);
   1956 					get_client_memptr(eth_client, clnt_indx)->route_rule_set_v4 = false;
   1957 					get_client_memptr(eth_client, clnt_indx)->v4_addr = data->ipv4_addr;
   1958 				}
   1959 			}
   1960 		}
   1961 		else
   1962 		{
   1963 		    IPACMDBG_H("Invalid client IPv4 address \n");
   1964 		    return IPACM_FAILURE;
   1965 		}
   1966 	}
   1967 	else
   1968 	{
   1969 		if ((data->ipv6_addr[0] != 0) || (data->ipv6_addr[1] != 0) ||
   1970 				(data->ipv6_addr[2] != 0) || (data->ipv6_addr[3] != 0)) /* check if all 0 not valid ipv6 address */
   1971 		{
   1972 			IPACMDBG_H("ipv6 address: 0x%x:%x:%x:%x\n", data->ipv6_addr[0], data->ipv6_addr[1], data->ipv6_addr[2], data->ipv6_addr[3]);
   1973 			if( (data->ipv6_addr[0] & ipv6_link_local_prefix_mask) != (ipv6_link_local_prefix & ipv6_link_local_prefix_mask) &&
   1974 				memcmp(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix)) != 0)
   1975 			{
   1976 				IPACMDBG_H("This IPv6 address is not global IPv6 address with correct prefix, ignore.\n");
   1977 				return IPACM_FAILURE;
   1978 			}
   1979 
   1980             if(get_client_memptr(eth_client, clnt_indx)->ipv6_set < IPV6_NUM_ADDR)
   1981 			{
   1982 
   1983 		       for(v6_num=0;v6_num < get_client_memptr(eth_client, clnt_indx)->ipv6_set;v6_num++)
   1984 				{
   1985 					if( data->ipv6_addr[0] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][0] &&
   1986 			           data->ipv6_addr[1] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][1] &&
   1987 			  	        data->ipv6_addr[2]== get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][2] &&
   1988 			  	         data->ipv6_addr[3] == get_client_memptr(eth_client, clnt_indx)->v6_addr[v6_num][3])
   1989 					{
   1990 						IPACMDBG_H("Already see this ipv6 addr at position: %d for client:%d\n", v6_num, clnt_indx);
   1991 						return IPACM_FAILURE; /* not setup the RT rules*/
   1992 					}
   1993 				}
   1994 
   1995 		       /* not see this ipv6 before for wifi client*/
   1996 			   get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][0] = data->ipv6_addr[0];
   1997 			   get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][1] = data->ipv6_addr[1];
   1998 			   get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][2] = data->ipv6_addr[2];
   1999 			   get_client_memptr(eth_client, clnt_indx)->v6_addr[get_client_memptr(eth_client, clnt_indx)->ipv6_set][3] = data->ipv6_addr[3];
   2000 			   get_client_memptr(eth_client, clnt_indx)->ipv6_set++;
   2001 		    }
   2002 		    else
   2003 		    {
   2004 		        IPACMDBG_H("Already got %d ipv6 addr for client:%d\n", IPV6_NUM_ADDR, clnt_indx);
   2005 				return IPACM_FAILURE; /* not setup the RT rules*/
   2006 		    }
   2007 		}
   2008 		else
   2009 		{
   2010 			IPACMDBG_H("Invalid IPV6 address\n");
   2011 			return IPACM_FAILURE;
   2012 		}
   2013 	}
   2014 
   2015 	return IPACM_SUCCESS;
   2016 }
   2017 
   2018 /*handle eth client routing rule*/
   2019 int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype)
   2020 {
   2021 	struct ipa_ioc_add_rt_rule *rt_rule;
   2022 	struct ipa_rt_rule_add *rt_rule_entry;
   2023 	uint32_t tx_index;
   2024 	int eth_index,v6_num;
   2025 	const int NUM = 1;
   2026 
   2027 	if(tx_prop == NULL)
   2028 	{
   2029 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   2030 		return IPACM_SUCCESS;
   2031 	}
   2032 
   2033 	IPACMDBG_H("Received mac_addr MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   2034 					 mac_addr[0], mac_addr[1], mac_addr[2],
   2035 					 mac_addr[3], mac_addr[4], mac_addr[5]);
   2036 
   2037 	eth_index = get_eth_client_index(mac_addr);
   2038 	if (eth_index == IPACM_INVALID_INDEX)
   2039 	{
   2040 		IPACMDBG_H("eth client not found/attached \n");
   2041 		return IPACM_SUCCESS;
   2042 	}
   2043 
   2044 	if (iptype==IPA_IP_v4) {
   2045 		IPACMDBG_H("eth client index: %d, ip-type: %d, ipv4_set:%d, ipv4_rule_set:%d \n", eth_index, iptype,
   2046 					 get_client_memptr(eth_client, eth_index)->ipv4_set,
   2047 					 get_client_memptr(eth_client, eth_index)->route_rule_set_v4);
   2048 	} else {
   2049 		IPACMDBG_H("eth client index: %d, ip-type: %d, ipv6_set:%d, ipv6_rule_num:%d \n", eth_index, iptype,
   2050 					 get_client_memptr(eth_client, eth_index)->ipv6_set,
   2051 					 get_client_memptr(eth_client, eth_index)->route_rule_set_v6);
   2052 	}
   2053 	/* Add default routing rules if not set yet */
   2054 	if ((iptype == IPA_IP_v4
   2055 			 && get_client_memptr(eth_client, eth_index)->route_rule_set_v4 == false
   2056 			 && get_client_memptr(eth_client, eth_index)->ipv4_set == true)
   2057 			|| (iptype == IPA_IP_v6
   2058 		            && get_client_memptr(eth_client, eth_index)->route_rule_set_v6 < get_client_memptr(eth_client, eth_index)->ipv6_set
   2059 					))
   2060 	{
   2061 
   2062         /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */
   2063 		IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   2064 		if (tx_prop != NULL)
   2065 		{
   2066 			IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   2067 			IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false);
   2068 		}
   2069 		rt_rule = (struct ipa_ioc_add_rt_rule *)
   2070 			 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
   2071 						NUM * sizeof(struct ipa_rt_rule_add));
   2072 
   2073 		if (rt_rule == NULL)
   2074 		{
   2075 			PERROR("Error Locate ipa_ioc_add_rt_rule memory...\n");
   2076 			return IPACM_FAILURE;
   2077 		}
   2078 
   2079 		rt_rule->commit = 1;
   2080 		rt_rule->num_rules = (uint8_t)NUM;
   2081 		rt_rule->ip = iptype;
   2082 
   2083 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   2084 		{
   2085 			if(iptype != tx_prop->tx[tx_index].ip)
   2086 		    {
   2087 				IPACMDBG_H("Tx:%d, ip-type: %d conflict ip-type: %d no RT-rule added\n",
   2088 						tx_index, tx_prop->tx[tx_index].ip,iptype);
   2089 		   	        continue;
   2090 		    }
   2091 
   2092   	   	    rt_rule_entry = &rt_rule->rules[0];
   2093 			rt_rule_entry->at_rear = 0;
   2094 
   2095 			if (iptype == IPA_IP_v4)
   2096 			{
   2097 		        IPACMDBG_H("client index(%d):ipv4 address: 0x%x\n", eth_index,
   2098 		  		        get_client_memptr(eth_client, eth_index)->v4_addr);
   2099 
   2100                 IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n",
   2101 		  				 eth_index,
   2102 		  				 get_client_memptr(eth_client, eth_index)->hdr_hdl_v4);
   2103 				strlcpy(rt_rule->rt_tbl_name,
   2104 								IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name,
   2105 								sizeof(rt_rule->rt_tbl_name));
   2106 				rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   2107 			    rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   2108 			    memcpy(&rt_rule_entry->rule.attrib,
   2109 						 &tx_prop->tx[tx_index].attrib,
   2110 						 sizeof(rt_rule_entry->rule.attrib));
   2111 			    rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2112 		   	    rt_rule_entry->rule.hdr_hdl = get_client_memptr(eth_client, eth_index)->hdr_hdl_v4;
   2113 				rt_rule_entry->rule.attrib.u.v4.dst_addr = get_client_memptr(eth_client, eth_index)->v4_addr;
   2114 				rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
   2115 #ifdef FEATURE_IPA_V3
   2116 				rt_rule_entry->rule.hashable = false;
   2117 #endif
   2118 			    if (false == m_routing.AddRoutingRule(rt_rule))
   2119   	            {
   2120   	          	            IPACMERR("Routing rule addition failed!\n");
   2121   	          	            free(rt_rule);
   2122   	          	            return IPACM_FAILURE;
   2123 			    }
   2124 
   2125 			    /* copy ipv4 RT hdl */
   2126 		        get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4 =
   2127   	   	        rt_rule->rules[0].rt_rule_hdl;
   2128 		        IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
   2129 		      	get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4, iptype);
   2130 
   2131   	   	    } else {
   2132 
   2133 		        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++)
   2134 			    {
   2135                     IPACMDBG_H("client(%d): v6 header handle:(0x%x)\n",
   2136 		  	    			 eth_index,
   2137 		  	    			 get_client_memptr(eth_client, eth_index)->hdr_hdl_v6);
   2138 
   2139 		            /* v6 LAN_RT_TBL */
   2140 				strlcpy(rt_rule->rt_tbl_name,
   2141 			    					IPACM_Iface::ipacmcfg->rt_tbl_v6.name,
   2142 			    					sizeof(rt_rule->rt_tbl_name));
   2143 				rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   2144 		            /* Support QCMAP LAN traffic feature, send to A5 */
   2145 					rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS;
   2146 			        memset(&rt_rule_entry->rule.attrib, 0, sizeof(rt_rule_entry->rule.attrib));
   2147 		   	        rt_rule_entry->rule.hdr_hdl = 0;
   2148 			        rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2149 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][0];
   2150 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][1];
   2151 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][2];
   2152 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][3];
   2153 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
   2154 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
   2155 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
   2156 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
   2157 #ifdef FEATURE_IPA_V3
   2158 					rt_rule_entry->rule.hashable = true;
   2159 #endif
   2160    	                if (false == m_routing.AddRoutingRule(rt_rule))
   2161   	                {
   2162   	                	    IPACMERR("Routing rule addition failed!\n");
   2163   	                	    free(rt_rule);
   2164   	                	    return IPACM_FAILURE;
   2165 			        }
   2166 
   2167 		            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;
   2168 		            IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
   2169 		            				 get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[v6_num], iptype);
   2170 
   2171 			        /*Copy same rule to v6 WAN RT TBL*/
   2172 				strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name));
   2173 				rt_rule->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = '\0';
   2174 				/* Downlink traffic from Wan iface, directly through IPA */
   2175 					rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   2176 			        memcpy(&rt_rule_entry->rule.attrib,
   2177 						 &tx_prop->tx[tx_index].attrib,
   2178 						 sizeof(rt_rule_entry->rule.attrib));
   2179 		   	        rt_rule_entry->rule.hdr_hdl = get_client_memptr(eth_client, eth_index)->hdr_hdl_v6;
   2180 			        rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2181 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][0];
   2182 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][1];
   2183 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][2];
   2184 		   	        rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, eth_index)->v6_addr[v6_num][3];
   2185 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
   2186 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
   2187 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF;
   2188 					rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF;
   2189 #ifdef FEATURE_IPA_V3
   2190 					rt_rule_entry->rule.hashable = true;
   2191 #endif
   2192 		            if (false == m_routing.AddRoutingRule(rt_rule))
   2193 		            {
   2194 							IPACMERR("Routing rule addition failed!\n");
   2195 							free(rt_rule);
   2196 							return IPACM_FAILURE;
   2197 		            }
   2198 
   2199 		            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;
   2200 					IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index,
   2201 		            				 get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[v6_num], iptype);
   2202 			    }
   2203 			}
   2204 
   2205   	    } /* end of for loop */
   2206 
   2207 		free(rt_rule);
   2208 
   2209 		if (iptype == IPA_IP_v4)
   2210 		{
   2211 			get_client_memptr(eth_client, eth_index)->route_rule_set_v4 = true;
   2212 		}
   2213 		else
   2214 		{
   2215 			get_client_memptr(eth_client, eth_index)->route_rule_set_v6 = get_client_memptr(eth_client, eth_index)->ipv6_set;
   2216 		}
   2217 	}
   2218 	return IPACM_SUCCESS;
   2219 }
   2220 
   2221 /* handle odu client initial, construct full headers (tx property) */
   2222 int IPACM_Lan::handle_odu_hdr_init(uint8_t *mac_addr)
   2223 {
   2224 	int res = IPACM_SUCCESS, len = 0;
   2225 	struct ipa_ioc_copy_hdr sCopyHeader;
   2226 	struct ipa_ioc_add_hdr *pHeaderDescriptor = NULL;
   2227 	uint32_t cnt;
   2228 
   2229 	IPACMDBG("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
   2230 					 mac_addr[0], mac_addr[1], mac_addr[2],
   2231 					 mac_addr[3], mac_addr[4], mac_addr[5]);
   2232 
   2233 	/* add header to IPA */
   2234 	if(tx_prop != NULL)
   2235 	{
   2236 		len = sizeof(struct ipa_ioc_add_hdr) + (1 * sizeof(struct ipa_hdr_add));
   2237 		pHeaderDescriptor = (struct ipa_ioc_add_hdr *)calloc(1, len);
   2238 		if (pHeaderDescriptor == NULL)
   2239 		{
   2240 			IPACMERR("calloc failed to allocate pHeaderDescriptor\n");
   2241 			return IPACM_FAILURE;
   2242 		}
   2243 
   2244 		/* copy partial header for v4*/
   2245 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   2246 		{
   2247 				 if(tx_prop->tx[cnt].ip==IPA_IP_v4)
   2248 				 {
   2249 								IPACMDBG("Got partial v4-header name from %d tx props\n", cnt);
   2250 								memset(&sCopyHeader, 0, sizeof(sCopyHeader));
   2251 								memcpy(sCopyHeader.name,
   2252 											tx_prop->tx[cnt].hdr_name,
   2253 											 sizeof(sCopyHeader.name));
   2254 								IPACMDBG("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
   2255 								if (m_header.CopyHeader(&sCopyHeader) == false)
   2256 								{
   2257 									PERROR("ioctl copy header failed");
   2258 									res = IPACM_FAILURE;
   2259 									goto fail;
   2260 								}
   2261 								IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
   2262 								if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
   2263 								{
   2264 									IPACMERR("header oversize\n");
   2265 									res = IPACM_FAILURE;
   2266 									goto fail;
   2267 								}
   2268 								else
   2269 								{
   2270 									memcpy(pHeaderDescriptor->hdr[0].hdr,
   2271 												 sCopyHeader.hdr,
   2272 												 sCopyHeader.hdr_len);
   2273 								}
   2274 								/* copy client mac_addr to partial header */
   2275 								if (sCopyHeader.is_eth2_ofst_valid)
   2276 								{
   2277 									memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst],
   2278 											 mac_addr,
   2279 											 IPA_MAC_ADDR_SIZE);
   2280 								}
   2281 								/* replace src mac to bridge mac_addr if any  */
   2282 								if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
   2283 								{
   2284 									memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
   2285 											IPACM_Iface::ipacmcfg->bridge_mac,
   2286 											IPA_MAC_ADDR_SIZE);
   2287 									IPACMDBG_H("device is in bridge mode \n");
   2288 								}
   2289 
   2290 								pHeaderDescriptor->commit = true;
   2291 								pHeaderDescriptor->num_hdrs = 1;
   2292 
   2293 								memset(pHeaderDescriptor->hdr[0].name, 0,
   2294 											 sizeof(pHeaderDescriptor->hdr[0].name));
   2295 								strlcpy(pHeaderDescriptor->hdr[0].name, IPA_ODU_HDR_NAME_v4, sizeof(pHeaderDescriptor->hdr[0].name));
   2296 								pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
   2297 								pHeaderDescriptor->hdr[0].hdr_hdl = -1;
   2298 								pHeaderDescriptor->hdr[0].is_partial = 0;
   2299 								pHeaderDescriptor->hdr[0].status = -1;
   2300 
   2301 					 if (m_header.AddHeader(pHeaderDescriptor) == false ||
   2302 							pHeaderDescriptor->hdr[0].status != 0)
   2303 					 {
   2304 						IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
   2305 						res = IPACM_FAILURE;
   2306 						goto fail;
   2307 					 }
   2308 
   2309 					ODU_hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl;
   2310 					ipv4_header_set = true ;
   2311 					IPACMDBG(" ODU v4 full header name:%s header handle:(0x%x)\n",
   2312 										 pHeaderDescriptor->hdr[0].name,
   2313 												 ODU_hdr_hdl_v4);
   2314 					break;
   2315 				 }
   2316 		}
   2317 
   2318 
   2319 		/* copy partial header for v6*/
   2320 		for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   2321 		{
   2322 			if(tx_prop->tx[cnt].ip==IPA_IP_v6)
   2323 			{
   2324 
   2325 				IPACMDBG("Got partial v6-header name from %d tx props\n", cnt);
   2326 				memset(&sCopyHeader, 0, sizeof(sCopyHeader));
   2327 				memcpy(sCopyHeader.name,
   2328 						tx_prop->tx[cnt].hdr_name,
   2329 							sizeof(sCopyHeader.name));
   2330 
   2331 				IPACMDBG("header name: %s in tx:%d\n", sCopyHeader.name,cnt);
   2332 				if (m_header.CopyHeader(&sCopyHeader) == false)
   2333 				{
   2334 					PERROR("ioctl copy header failed");
   2335 					res = IPACM_FAILURE;
   2336 					goto fail;
   2337 				}
   2338 
   2339 				IPACMDBG("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial);
   2340 				if (sCopyHeader.hdr_len > IPA_HDR_MAX_SIZE)
   2341 				{
   2342 					IPACMERR("header oversize\n");
   2343 					res = IPACM_FAILURE;
   2344 					goto fail;
   2345 				}
   2346 				else
   2347 				{
   2348 					memcpy(pHeaderDescriptor->hdr[0].hdr,
   2349 							sCopyHeader.hdr,
   2350 								sCopyHeader.hdr_len);
   2351 				}
   2352 
   2353 				/* copy client mac_addr to partial header */
   2354 				if (sCopyHeader.is_eth2_ofst_valid)
   2355 				{
   2356 					memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst],
   2357 					 mac_addr,
   2358 					 IPA_MAC_ADDR_SIZE);
   2359 				}
   2360 				/* replace src mac to bridge mac_addr if any  */
   2361 				if (IPACM_Iface::ipacmcfg->ipa_bridge_enable)
   2362 				{
   2363 					memcpy(&pHeaderDescriptor->hdr[0].hdr[sCopyHeader.eth2_ofst+IPA_MAC_ADDR_SIZE],
   2364 							IPACM_Iface::ipacmcfg->bridge_mac,
   2365 							IPA_MAC_ADDR_SIZE);
   2366 					IPACMDBG_H("device is in bridge mode \n");
   2367 				}
   2368 
   2369 				pHeaderDescriptor->commit = true;
   2370 				pHeaderDescriptor->num_hdrs = 1;
   2371 
   2372 				memset(pHeaderDescriptor->hdr[0].name, 0,
   2373 					 sizeof(pHeaderDescriptor->hdr[0].name));
   2374 
   2375 				strlcpy(pHeaderDescriptor->hdr[0].name, IPA_ODU_HDR_NAME_v6, sizeof(pHeaderDescriptor->hdr[0].name));
   2376 				pHeaderDescriptor->hdr[0].hdr_len = sCopyHeader.hdr_len;
   2377 				pHeaderDescriptor->hdr[0].hdr_hdl = -1;
   2378 				pHeaderDescriptor->hdr[0].is_partial = 0;
   2379 				pHeaderDescriptor->hdr[0].status = -1;
   2380 
   2381 				if (m_header.AddHeader(pHeaderDescriptor) == false ||
   2382 						pHeaderDescriptor->hdr[0].status != 0)
   2383 				{
   2384 					IPACMERR("ioctl IPA_IOC_ADD_HDR failed: %d\n", pHeaderDescriptor->hdr[0].status);
   2385 					res = IPACM_FAILURE;
   2386 					goto fail;
   2387 				}
   2388 
   2389 				ODU_hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl;
   2390 				ipv6_header_set = true ;
   2391 				IPACMDBG(" ODU v4 full header name:%s header handle:(0x%x)\n",
   2392 									 pHeaderDescriptor->hdr[0].name,
   2393 											 ODU_hdr_hdl_v6);
   2394 				break;
   2395 			}
   2396 		}
   2397 	}
   2398 fail:
   2399 	free(pHeaderDescriptor);
   2400 	return res;
   2401 }
   2402 
   2403 
   2404 /* handle odu default route rule configuration */
   2405 int IPACM_Lan::handle_odu_route_add()
   2406 {
   2407 	/* add default WAN route */
   2408 	struct ipa_ioc_add_rt_rule *rt_rule;
   2409 	struct ipa_rt_rule_add *rt_rule_entry;
   2410 	uint32_t tx_index;
   2411 	const int NUM = 1;
   2412 
   2413 	if(tx_prop == NULL)
   2414 	{
   2415 	  IPACMDBG_H("No tx properties, ignore default route setting\n");
   2416 	  return IPACM_SUCCESS;
   2417 	}
   2418 
   2419 	rt_rule = (struct ipa_ioc_add_rt_rule *)
   2420 		 calloc(1, sizeof(struct ipa_ioc_add_rt_rule) +
   2421 						NUM * sizeof(struct ipa_rt_rule_add));
   2422 
   2423 	if (!rt_rule)
   2424 	{
   2425 		IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n");
   2426 		return IPACM_FAILURE;
   2427 	}
   2428 
   2429 	rt_rule->commit = 1;
   2430 	rt_rule->num_rules = (uint8_t)NUM;
   2431 
   2432 
   2433 	IPACMDBG_H("WAN table created %s \n", rt_rule->rt_tbl_name);
   2434 	rt_rule_entry = &rt_rule->rules[0];
   2435 	rt_rule_entry->at_rear = true;
   2436 
   2437 	for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   2438 	{
   2439 
   2440 		if (IPA_IP_v4 == tx_prop->tx[tx_index].ip)
   2441 		{
   2442 			strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v4.name, sizeof(rt_rule->rt_tbl_name));
   2443 			rt_rule_entry->rule.hdr_hdl = ODU_hdr_hdl_v4;
   2444 			rt_rule->ip = IPA_IP_v4;
   2445 		}
   2446 		else
   2447 		{
   2448 			strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_odu_v6.name, sizeof(rt_rule->rt_tbl_name));
   2449 			rt_rule_entry->rule.hdr_hdl = ODU_hdr_hdl_v6;
   2450 			rt_rule->ip = IPA_IP_v6;
   2451 		}
   2452 
   2453 		rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe;
   2454 		memcpy(&rt_rule_entry->rule.attrib,
   2455 					 &tx_prop->tx[tx_index].attrib,
   2456 					 sizeof(rt_rule_entry->rule.attrib));
   2457 
   2458 		rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   2459 		if (IPA_IP_v4 == tx_prop->tx[tx_index].ip)
   2460 		{
   2461 			rt_rule_entry->rule.attrib.u.v4.dst_addr      = 0;
   2462 			rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0;
   2463 #ifdef FEATURE_IPA_V3
   2464 			rt_rule_entry->rule.hashable = true;
   2465 #endif
   2466 			if (false == m_routing.AddRoutingRule(rt_rule))
   2467 			{
   2468 				IPACMERR("Routing rule addition failed!\n");
   2469 				free(rt_rule);
   2470 				return IPACM_FAILURE;
   2471 			}
   2472 			odu_route_rule_v4_hdl[tx_index] = rt_rule_entry->rt_rule_hdl;
   2473 			IPACMDBG_H("Got ipv4 ODU-route rule hdl:0x%x,tx:%d,ip-type: %d \n",
   2474 						 odu_route_rule_v4_hdl[tx_index],
   2475 						 tx_index,
   2476 						 IPA_IP_v4);
   2477 		}
   2478 		else
   2479 		{
   2480 			rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = 0;
   2481 			rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = 0;
   2482 			rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = 0;
   2483 			rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = 0;
   2484 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0;
   2485 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0;
   2486 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0;
   2487 			rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0;
   2488 #ifdef FEATURE_IPA_V3
   2489 			rt_rule_entry->rule.hashable = true;
   2490 #endif
   2491 			if (false == m_routing.AddRoutingRule(rt_rule))
   2492 			{
   2493 				IPACMERR("Routing rule addition failed!\n");
   2494 				free(rt_rule);
   2495 				return IPACM_FAILURE;
   2496 			}
   2497 			odu_route_rule_v6_hdl[tx_index] = rt_rule_entry->rt_rule_hdl;
   2498 			IPACMDBG_H("Set ipv6 ODU-route rule hdl for v6_lan_table:0x%x,tx:%d,ip-type: %d \n",
   2499 					odu_route_rule_v6_hdl[tx_index],
   2500 					tx_index,
   2501 					IPA_IP_v6);
   2502 		}
   2503 	}
   2504 	free(rt_rule);
   2505 	return IPACM_SUCCESS;
   2506 }
   2507 
   2508 /* handle odu default route rule deletion */
   2509 int IPACM_Lan::handle_odu_route_del()
   2510 {
   2511 	uint32_t tx_index;
   2512 
   2513 	if(tx_prop == NULL)
   2514 	{
   2515 		IPACMDBG_H("No tx properties, ignore delete default route setting\n");
   2516 		return IPACM_SUCCESS;
   2517 	}
   2518 
   2519 	for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   2520 	{
   2521 		if (tx_prop->tx[tx_index].ip == IPA_IP_v4)
   2522 		{
   2523 			IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n",
   2524 					tx_index, tx_prop->tx[tx_index].ip,IPA_IP_v4);
   2525 
   2526 			if (m_routing.DeleteRoutingHdl(odu_route_rule_v4_hdl[tx_index], IPA_IP_v4)
   2527 					== false)
   2528 			{
   2529 				IPACMERR("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v4, odu_route_rule_v4_hdl[tx_index], tx_index);
   2530 				return IPACM_FAILURE;
   2531 			}
   2532 		}
   2533 		else
   2534 		{
   2535 			IPACMDBG_H("Tx:%d, ip-type: %d match ip-type: %d, RT-rule deleted\n",
   2536 					tx_index, tx_prop->tx[tx_index].ip,IPA_IP_v6);
   2537 
   2538 			if (m_routing.DeleteRoutingHdl(odu_route_rule_v6_hdl[tx_index], IPA_IP_v6)
   2539 					== false)
   2540 			{
   2541 				IPACMERR("IP-family:%d, Routing rule(hdl:0x%x) deletion failed with tx_index %d!\n", IPA_IP_v6, odu_route_rule_v6_hdl[tx_index], tx_index);
   2542 				return IPACM_FAILURE;
   2543 			}
   2544 		}
   2545 	}
   2546 
   2547 	return IPACM_SUCCESS;
   2548 }
   2549 
   2550 /*handle eth client del mode*/
   2551 int IPACM_Lan::handle_eth_client_down_evt(uint8_t *mac_addr)
   2552 {
   2553 	int clt_indx;
   2554 	uint32_t tx_index;
   2555 	int num_eth_client_tmp = num_eth_client;
   2556 	int num_v6;
   2557 
   2558 	IPACMDBG_H("total client: %d\n", num_eth_client_tmp);
   2559 
   2560 	clt_indx = get_eth_client_index(mac_addr);
   2561 	if (clt_indx == IPACM_INVALID_INDEX)
   2562 	{
   2563 		IPACMDBG_H("eth client not attached\n");
   2564 		return IPACM_SUCCESS;
   2565 	}
   2566 
   2567 	/* First reset nat rules and then route rules */
   2568 	if(get_client_memptr(eth_client, clt_indx)->ipv4_set == true)
   2569 	{
   2570 			IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, clt_indx)->v4_addr);
   2571 			CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, clt_indx)->v4_addr);
   2572  	}
   2573 
   2574 	if (delete_eth_rtrules(clt_indx, IPA_IP_v4))
   2575 	{
   2576 		IPACMERR("unbale to delete ecm-client v4 route rules for index: %d\n", clt_indx);
   2577 		return IPACM_FAILURE;
   2578 	}
   2579 
   2580 	if (delete_eth_rtrules(clt_indx, IPA_IP_v6))
   2581 	{
   2582 		IPACMERR("unbale to delete ecm-client v6 route rules for index: %d\n", clt_indx);
   2583 		return IPACM_FAILURE;
   2584 	}
   2585 
   2586 	/* Delete eth client header */
   2587 	if(get_client_memptr(eth_client, clt_indx)->ipv4_header_set == true)
   2588 	{
   2589 		if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, clt_indx)->hdr_hdl_v4)
   2590 				== false)
   2591 		{
   2592 			return IPACM_FAILURE;
   2593 		}
   2594 		get_client_memptr(eth_client, clt_indx)->ipv4_header_set = false;
   2595 	}
   2596 
   2597 	if(get_client_memptr(eth_client, clt_indx)->ipv6_header_set == true)
   2598 	{
   2599 		if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, clt_indx)->hdr_hdl_v6)
   2600 				== false)
   2601 		{
   2602 			return IPACM_FAILURE;
   2603 		}
   2604 		get_client_memptr(eth_client, clt_indx)->ipv6_header_set = false;
   2605 	}
   2606 
   2607 	/* Reset ip_set to 0*/
   2608 	get_client_memptr(eth_client, clt_indx)->ipv4_set = false;
   2609 	get_client_memptr(eth_client, clt_indx)->ipv6_set = 0;
   2610 	get_client_memptr(eth_client, clt_indx)->ipv4_header_set = false;
   2611 	get_client_memptr(eth_client, clt_indx)->ipv6_header_set = false;
   2612 	get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = false;
   2613 	get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = 0;
   2614 
   2615 	for (; clt_indx < num_eth_client_tmp - 1; clt_indx++)
   2616 	{
   2617 		memcpy(get_client_memptr(eth_client, clt_indx)->mac,
   2618 					 get_client_memptr(eth_client, (clt_indx + 1))->mac,
   2619 					 sizeof(get_client_memptr(eth_client, clt_indx)->mac));
   2620 
   2621 		get_client_memptr(eth_client, clt_indx)->hdr_hdl_v4 = get_client_memptr(eth_client, (clt_indx + 1))->hdr_hdl_v4;
   2622 		get_client_memptr(eth_client, clt_indx)->hdr_hdl_v6 = get_client_memptr(eth_client, (clt_indx + 1))->hdr_hdl_v6;
   2623 		get_client_memptr(eth_client, clt_indx)->v4_addr = get_client_memptr(eth_client, (clt_indx + 1))->v4_addr;
   2624 
   2625 		get_client_memptr(eth_client, clt_indx)->ipv4_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv4_set;
   2626 		get_client_memptr(eth_client, clt_indx)->ipv6_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv6_set;
   2627 		get_client_memptr(eth_client, clt_indx)->ipv4_header_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv4_header_set;
   2628 		get_client_memptr(eth_client, clt_indx)->ipv6_header_set = get_client_memptr(eth_client, (clt_indx + 1))->ipv6_header_set;
   2629 
   2630 		get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = get_client_memptr(eth_client, (clt_indx + 1))->route_rule_set_v4;
   2631 		get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = get_client_memptr(eth_client, (clt_indx + 1))->route_rule_set_v6;
   2632 
   2633         for (num_v6=0;num_v6< get_client_memptr(eth_client, clt_indx)->ipv6_set;num_v6++)
   2634 	    {
   2635 		    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];
   2636 		    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];
   2637 		    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];
   2638 		    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];
   2639         }
   2640 
   2641 		for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++)
   2642 		{
   2643 			get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4 =
   2644 				 get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v4;
   2645 
   2646 			for(num_v6=0;num_v6< get_client_memptr(eth_client, clt_indx)->route_rule_set_v6;num_v6++)
   2647 			{
   2648 			  get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6] =
   2649 			   	 get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6];
   2650 			  get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6] =
   2651 			   	 get_client_memptr(eth_client, (clt_indx + 1))->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[num_v6];
   2652 		    }
   2653 		}
   2654 	}
   2655 
   2656 	IPACMDBG_H(" %d eth client deleted successfully \n", num_eth_client);
   2657 	num_eth_client = num_eth_client - 1;
   2658 	IPACMDBG_H(" Number of eth client: %d\n", num_eth_client);
   2659 
   2660 	/* Del RM dependency */
   2661 	if(num_eth_client == 0)
   2662 	{
   2663 		/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule*/
   2664 		IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   2665 		if (tx_prop != NULL)
   2666 		{
   2667 			IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   2668 			IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   2669 		}
   2670 	}
   2671 
   2672 	return IPACM_SUCCESS;
   2673 }
   2674 
   2675 /*handle LAN iface down event*/
   2676 int IPACM_Lan::handle_down_evt()
   2677 {
   2678 	uint32_t i;
   2679 	int res = IPACM_SUCCESS;
   2680 
   2681 	IPACMDBG_H("lan handle_down_evt\n ");
   2682 	if (ipa_if_cate == ODU_IF)
   2683 	{
   2684 		/* delete ODU default RT rules */
   2685 		if (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true)
   2686 		{
   2687 			IPACMDBG_H("eMBMS enable, delete eMBMS DL RT rule\n");
   2688 			handle_odu_route_del();
   2689 		}
   2690 
   2691 		/* delete full header */
   2692 		if (ipv4_header_set)
   2693 		{
   2694 			if (m_header.DeleteHeaderHdl(ODU_hdr_hdl_v4)
   2695 					== false)
   2696 			{
   2697 					IPACMERR("ODU ipv4 header delete fail\n");
   2698 					res = IPACM_FAILURE;
   2699 					goto fail;
   2700 			}
   2701 			IPACMDBG_H("ODU ipv4 header delete success\n");
   2702 		}
   2703 
   2704 		if (ipv6_header_set)
   2705 		{
   2706 			if (m_header.DeleteHeaderHdl(ODU_hdr_hdl_v6)
   2707 					== false)
   2708 			{
   2709 				IPACMERR("ODU ipv6 header delete fail\n");
   2710 				res = IPACM_FAILURE;
   2711 				goto fail;
   2712 			}
   2713 			IPACMERR("ODU ipv6 header delete success\n");
   2714 		}
   2715 	}
   2716 
   2717 	/* no iface address up, directly close iface*/
   2718 	if (ip_type == IPACM_IP_NULL)
   2719 	{
   2720 		goto fail;
   2721 	}
   2722 
   2723 	/* delete wan filter rule */
   2724 	if (IPACM_Wan::isWanUP(ipa_if_num) && rx_prop != NULL)
   2725 	{
   2726 		IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode);
   2727 		handle_wan_down(IPACM_Wan::backhaul_is_sta_mode);
   2728 	}
   2729 
   2730 	if (IPACM_Wan::isWanUP_V6(ipa_if_num) && rx_prop != NULL)
   2731 	{
   2732 		IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode);
   2733 		handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode);
   2734 	}
   2735 
   2736 	/* delete default filter rules */
   2737 	if (ip_type != IPA_IP_v6 && rx_prop != NULL)
   2738 	{
   2739 		if(m_filtering.DeleteFilteringHdls(ipv4_icmp_flt_rule_hdl, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE) == false)
   2740 		{
   2741 			IPACMERR("Error Deleting ICMPv4 Filtering Rule, aborting...\n");
   2742 			res = IPACM_FAILURE;
   2743 			goto fail;
   2744 		}
   2745 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, NUM_IPV4_ICMP_FLT_RULE);
   2746 
   2747 		if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES) == false)
   2748 		{
   2749 			IPACMERR("Error Deleting Filtering Rule, aborting...\n");
   2750 			res = IPACM_FAILURE;
   2751 			goto fail;
   2752 		}
   2753 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
   2754 
   2755 		/* free private-subnet ipv4 filter rules */
   2756 		if (IPACM_Iface::ipacmcfg->ipa_num_private_subnet > IPA_PRIV_SUBNET_FILTER_RULE_HANDLES)
   2757 		{
   2758 			IPACMERR(" the number of rules are bigger than array, aborting...\n");
   2759 			res = IPACM_FAILURE;
   2760 			goto fail;
   2761 		}
   2762 
   2763 #ifdef FEATURE_IPA_ANDROID
   2764 		if(m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES) == false)
   2765 		{
   2766 			IPACMERR("Error deleting private subnet IPv4 flt rules.\n");
   2767 			res = IPACM_FAILURE;
   2768 			goto fail;
   2769 		}
   2770 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES);
   2771 #else
   2772 		if (m_filtering.DeleteFilteringHdls(private_fl_rule_hdl, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet) == false)
   2773 		{
   2774 			IPACMERR("Error deleting private subnet IPv4 flt rules.\n");
   2775 			res = IPACM_FAILURE;
   2776 			goto fail;
   2777 		}
   2778 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPACM_Iface::ipacmcfg->ipa_num_private_subnet);
   2779 #endif
   2780 		IPACMDBG_H("Deleted private subnet v4 filter rules successfully.\n");
   2781 	}
   2782 	IPACMDBG_H("Finished delete default iface ipv4 filtering rules \n ");
   2783 
   2784 	if (ip_type != IPA_IP_v4 && rx_prop != NULL)
   2785 	{
   2786 		if(m_filtering.DeleteFilteringHdls(ipv6_icmp_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE) == false)
   2787 		{
   2788 			IPACMERR("Error Deleting ICMPv6 Filtering Rule, aborting...\n");
   2789 			res = IPACM_FAILURE;
   2790 			goto fail;
   2791 		}
   2792 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_ICMP_FLT_RULE);
   2793 
   2794 		if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES) == false)
   2795 		{
   2796 			IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n");
   2797 			res = IPACM_FAILURE;
   2798 			goto fail;
   2799 		}
   2800 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
   2801 	}
   2802 	IPACMDBG_H("Finished delete default iface ipv6 filtering rules \n ");
   2803 
   2804 	if (ip_type != IPA_IP_v6)
   2805 	{
   2806 		if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4)
   2807 				== false)
   2808 		{
   2809 			IPACMERR("Routing rule deletion failed!\n");
   2810 			res = IPACM_FAILURE;
   2811 			goto fail;
   2812 		}
   2813 	}
   2814 	IPACMDBG_H("Finished delete default iface ipv4 rules \n ");
   2815 
   2816 	/* delete default v6 routing rule */
   2817 	if (ip_type != IPA_IP_v4)
   2818 	{
   2819 		/* may have multiple ipv6 iface-RT rules*/
   2820 		for (i = 0; i < 2*num_dft_rt_v6; i++)
   2821 		{
   2822 			if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + i], IPA_IP_v6)
   2823 					== false)
   2824 			{
   2825 				IPACMERR("Routing rule deletion failed!\n");
   2826 				res = IPACM_FAILURE;
   2827 				goto fail;
   2828 			}
   2829 		}
   2830 	}
   2831 
   2832 	IPACMDBG_H("Finished delete default iface ipv6 rules \n ");
   2833 
   2834 	/* free the edm clients cache */
   2835 	IPACMDBG_H("Free ecm clients cache\n");
   2836 
   2837 	/* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete all IPV4V6 RT-rule */
   2838 	IPACMDBG_H("dev %s delete producer dependency\n", dev_name);
   2839 	if (tx_prop != NULL)
   2840 	{
   2841 		IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   2842 		IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]);
   2843 	}
   2844 
   2845 	eth_bridge_post_event(IPA_ETH_BRIDGE_IFACE_DOWN, IPA_IP_MAX, NULL);
   2846 
   2847 /* Delete private subnet*/
   2848 #ifdef FEATURE_IPA_ANDROID
   2849 	if (ip_type != IPA_IP_v6)
   2850 	{
   2851 		IPACMDBG_H("current IPACM private subnet_addr number(%d)\n", IPACM_Iface::ipacmcfg->ipa_num_private_subnet);
   2852 		IPACMDBG_H(" Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet);
   2853 		if(IPACM_Iface::ipacmcfg->DelPrivateSubnet(if_ipv4_subnet, ipa_if_num) == false)
   2854 		{
   2855 			IPACMERR(" can't Delete IPACM private subnet_addr as: 0x%x \n", if_ipv4_subnet);
   2856 		}
   2857 	}
   2858 
   2859 	/* reset the IPA-client pipe enum */
   2860 	if(ipa_if_cate != WAN_IF)
   2861 	{
   2862 #ifdef FEATURE_IPACM_HAL
   2863 		handle_tethering_client(true, IPACM_CLIENT_MAX);
   2864 #else
   2865 		handle_tethering_client(true, IPACM_CLIENT_USB);
   2866 #endif
   2867 	}
   2868 #endif /* defined(FEATURE_IPA_ANDROID)*/
   2869 fail:
   2870 	/* clean eth-client header, routing rules */
   2871 	IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client);
   2872 	for (i = 0; i < num_eth_client; i++)
   2873 	{
   2874 		/* First reset nat rules and then route rules */
   2875 		if(get_client_memptr(eth_client, i)->ipv4_set == true)
   2876 		{
   2877 			IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(eth_client, i)->v4_addr);
   2878 			CtList->HandleNeighIpAddrDelEvt(get_client_memptr(eth_client, i)->v4_addr);
   2879 		}
   2880 
   2881 		if (delete_eth_rtrules(i, IPA_IP_v4))
   2882 		{
   2883 			IPACMERR("unbale to delete ecm-client v4 route rules for index %d\n", i);
   2884 			res = IPACM_FAILURE;
   2885 		}
   2886 
   2887 		if (delete_eth_rtrules(i, IPA_IP_v6))
   2888 		{
   2889 			IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i);
   2890 			res = IPACM_FAILURE;
   2891 		}
   2892 
   2893 		IPACMDBG_H("Delete %d client header\n", num_eth_client);
   2894 
   2895 		if(get_client_memptr(eth_client, i)->ipv4_header_set == true)
   2896 		{
   2897 			if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v4)
   2898 				== false)
   2899 			{
   2900 				res = IPACM_FAILURE;
   2901 			}
   2902 		}
   2903 
   2904 		if(get_client_memptr(eth_client, i)->ipv6_header_set == true)
   2905 		{
   2906 			if (m_header.DeleteHeaderHdl(get_client_memptr(eth_client, i)->hdr_hdl_v6)
   2907 					== false)
   2908 			{
   2909 				res = IPACM_FAILURE;
   2910 			}
   2911 		}
   2912 	} /* end of for loop */
   2913 
   2914 	/* check software routing fl rule hdl */
   2915 	if (softwarerouting_act == true && rx_prop != NULL)
   2916 	{
   2917 		handle_software_routing_disable();
   2918 	}
   2919 
   2920 	if (odu_route_rule_v4_hdl != NULL)
   2921 	{
   2922 		free(odu_route_rule_v4_hdl);
   2923 	}
   2924 	if (odu_route_rule_v6_hdl != NULL)
   2925 	{
   2926 		free(odu_route_rule_v6_hdl);
   2927 	}
   2928 	/* Delete corresponding ipa_rm_resource_name of RX-endpoint after delete all IPV4V6 FT-rule */
   2929 	if (rx_prop != NULL)
   2930 	{
   2931 		IPACMDBG_H("dev %s add producer dependency\n", dev_name);
   2932 		IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);
   2933 		IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);
   2934 		IPACMDBG_H("Finished delete dependency \n ");
   2935 		free(rx_prop);
   2936 	}
   2937 
   2938 	if (eth_client != NULL)
   2939 	{
   2940 		free(eth_client);
   2941 	}
   2942 
   2943 	if (tx_prop != NULL)
   2944 	{
   2945 		free(tx_prop);
   2946 	}
   2947 	if (iface_query != NULL)
   2948 	{
   2949 		free(iface_query);
   2950 	}
   2951 
   2952 	is_active = false;
   2953 	post_del_self_evt();
   2954 
   2955 	return res;
   2956 }
   2957 
   2958 /* install UL filter rule from Q6 */
   2959 int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptype, uint8_t xlat_mux_id)
   2960 {
   2961 	ipa_flt_rule_add flt_rule_entry;
   2962 	int len = 0, cnt, ret = IPACM_SUCCESS;
   2963 	ipa_ioc_add_flt_rule *pFilteringTable;
   2964 	ipa_fltr_installed_notif_req_msg_v01 flt_index;
   2965 	int fd;
   2966 	int i, index, eq_index;
   2967 	uint32_t value = 0;
   2968 
   2969 	IPACMDBG_H("Set modem UL flt rules\n");
   2970 
   2971 	if (rx_prop == NULL)
   2972 	{
   2973 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   2974 		return IPACM_SUCCESS;
   2975 	}
   2976 
   2977 	if(prop == NULL || prop->num_ext_props <= 0)
   2978 	{
   2979 		IPACMDBG_H("No extended property.\n");
   2980 		return IPACM_SUCCESS;
   2981 	}
   2982 
   2983 	fd = open(IPA_DEVICE_NAME, O_RDWR);
   2984 	if (0 == fd)
   2985 	{
   2986 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
   2987 		return IPACM_FAILURE;
   2988 	}
   2989 	if (prop->num_ext_props > MAX_WAN_UL_FILTER_RULES)
   2990 	{
   2991 		IPACMERR("number of modem UL rules > MAX_WAN_UL_FILTER_RULES, aborting...\n");
   2992 		close(fd);
   2993 		return IPACM_FAILURE;
   2994 	}
   2995 
   2996 	memset(&flt_index, 0, sizeof(flt_index));
   2997 	flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe);
   2998 	flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01;
   2999 #ifndef FEATURE_IPA_V3
   3000 	flt_index.filter_index_list_len = prop->num_ext_props;
   3001 #else /* defined (FEATURE_IPA_V3) */
   3002 	flt_index.rule_id_valid = 1;
   3003 	flt_index.rule_id_len = prop->num_ext_props;
   3004 #endif
   3005 	flt_index.embedded_pipe_index_valid = 1;
   3006 	flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD);
   3007 	flt_index.retain_header_valid = 1;
   3008 	flt_index.retain_header = 0;
   3009 	flt_index.embedded_call_mux_id_valid = 1;
   3010 	flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId();
   3011 #ifndef FEATURE_IPA_V3
   3012 	IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n",
   3013 		flt_index.source_pipe_index, flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id);
   3014 #else /* defined (FEATURE_IPA_V3) */
   3015 	IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n",
   3016 		flt_index.source_pipe_index, flt_index.rule_id_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id);
   3017 #endif
   3018 	len = sizeof(struct ipa_ioc_add_flt_rule) + prop->num_ext_props * sizeof(struct ipa_flt_rule_add);
   3019 	pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len);
   3020 	if (pFilteringTable == NULL)
   3021 	{
   3022 		IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   3023 		close(fd);
   3024 		return IPACM_FAILURE;
   3025 	}
   3026 	memset(pFilteringTable, 0, len);
   3027 
   3028 	pFilteringTable->commit = 1;
   3029 	pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   3030 	pFilteringTable->global = false;
   3031 	pFilteringTable->ip = iptype;
   3032 	pFilteringTable->num_rules = prop->num_ext_props;
   3033 
   3034 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); // Zero All Fields
   3035 	flt_rule_entry.at_rear = 1;
   3036 #ifdef FEATURE_IPA_V3
   3037 	if (flt_rule_entry.rule.eq_attrib.ipv4_frag_eq_present)
   3038 		flt_rule_entry.at_rear = 0;
   3039 #endif
   3040 	flt_rule_entry.flt_rule_hdl = -1;
   3041 	flt_rule_entry.status = -1;
   3042 
   3043 	flt_rule_entry.rule.retain_hdr = 0;
   3044 	flt_rule_entry.rule.to_uc = 0;
   3045 	flt_rule_entry.rule.eq_attrib_type = 1;
   3046 	if(iptype == IPA_IP_v4)
   3047 	{
   3048 		if (ipa_if_cate == ODU_IF && IPACM_Wan::isWan_Bridge_Mode())
   3049 		{
   3050 			IPACMDBG_H("WAN, ODU are in bridge mode \n");
   3051 			flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3052 		}
   3053 		else
   3054 		{
   3055 			flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT;
   3056 		}
   3057 	}
   3058 	else if(iptype == IPA_IP_v6)
   3059 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3060 	else
   3061 	{
   3062 		IPACMERR("IP type is not expected.\n");
   3063 		ret = IPACM_FAILURE;
   3064 		goto fail;
   3065 	}
   3066 
   3067 	index = IPACM_Iface::ipacmcfg->getFltRuleCount(rx_prop->rx[0].src_pipe, iptype);
   3068 
   3069 	for(cnt=0; cnt<prop->num_ext_props; cnt++)
   3070 	{
   3071 		memcpy(&flt_rule_entry.rule.eq_attrib,
   3072 					 &prop->prop[cnt].eq_attrib,
   3073 					 sizeof(prop->prop[cnt].eq_attrib));
   3074 		flt_rule_entry.rule.rt_tbl_idx = prop->prop[cnt].rt_tbl_idx;
   3075 
   3076 		/* Handle XLAT configuration */
   3077 		if ((iptype == IPA_IP_v4) && prop->prop[cnt].is_xlat_rule && (xlat_mux_id != 0))
   3078 		{
   3079 			/* fill the value of meta-data */
   3080 			value = xlat_mux_id;
   3081 			flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
   3082 			flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
   3083 			flt_rule_entry.rule.eq_attrib.metadata_meq32.value = (value & 0xFF) << 16;
   3084 			flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = 0x00FF0000;
   3085 			IPACMDBG_H("xlat meta-data is modified for rule: %d has index %d with xlat_mux_id: %d\n",
   3086 					cnt, index, xlat_mux_id);
   3087 		}
   3088 
   3089 #ifdef FEATURE_IPACM_HAL
   3090 		/* add prefix equation in modem UL rules */
   3091 		if(iptype == IPA_IP_v4)
   3092 		{
   3093 			flt_rule_entry.rule.eq_attrib.num_offset_meq_32++;
   3094 			if(flt_rule_entry.rule.eq_attrib.num_offset_meq_32 <= IPA_IPFLTR_NUM_MEQ_32_EQNS)
   3095 			{
   3096 				eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_32 - 1;
   3097 #ifdef FEATURE_IPA_V3
   3098 				if(eq_index == 0)
   3099 				{
   3100 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<5);
   3101 				}
   3102 				else
   3103 				{
   3104 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<6);
   3105 				}
   3106 #else
   3107 				if(eq_index == 0)
   3108 				{
   3109 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<2);
   3110 				}
   3111 				else
   3112 				{
   3113 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<3);
   3114 				}
   3115 #endif
   3116 				flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].offset = 12;
   3117 				flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].mask = prefix[IPA_IP_v4].v4Mask;
   3118 				flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].value = prefix[IPA_IP_v4].v4Addr;
   3119 			}
   3120 			else
   3121 			{
   3122 				IPACMERR("Run out of MEQ32 equation.\n");
   3123 				flt_rule_entry.rule.eq_attrib.num_offset_meq_32--;
   3124 			}
   3125 		}
   3126 		else
   3127 		{
   3128 			flt_rule_entry.rule.eq_attrib.num_offset_meq_128++;
   3129 			if(flt_rule_entry.rule.eq_attrib.num_offset_meq_128 <= IPA_IPFLTR_NUM_MEQ_128_EQNS)
   3130 			{
   3131 				eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_128 - 1;
   3132 #ifdef FEATURE_IPA_V3
   3133 				if(eq_index == 0)
   3134 				{
   3135 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<3);
   3136 				}
   3137 				else
   3138 				{
   3139 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<4);
   3140 				}
   3141 #else
   3142 				if(eq_index == 0)
   3143 				{
   3144 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
   3145 				}
   3146 				else
   3147 				{
   3148 					flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<10);
   3149 				}
   3150 #endif
   3151 				flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].offset = 8;
   3152 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 0)
   3153 					= prefix[IPA_IP_v6].v6Mask[3];
   3154 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 4)
   3155 					= prefix[IPA_IP_v6].v6Mask[2];
   3156 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 8)
   3157 					= prefix[IPA_IP_v6].v6Mask[1];
   3158 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 12)
   3159 					= prefix[IPA_IP_v6].v6Mask[0];
   3160 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 0)
   3161 					= prefix[IPA_IP_v6].v6Addr[3];
   3162 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 4)
   3163 					= prefix[IPA_IP_v6].v6Addr[2];
   3164 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 8)
   3165 					= prefix[IPA_IP_v6].v6Addr[1];
   3166 				*(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 12)
   3167 					= prefix[IPA_IP_v6].v6Addr[0];
   3168 			}
   3169 			else
   3170 			{
   3171 				IPACMERR("Run out of MEQ128 equation.\n");
   3172 				flt_rule_entry.rule.eq_attrib.num_offset_meq_128--;
   3173 			}
   3174 		}
   3175 #endif
   3176 
   3177 #ifdef FEATURE_IPA_V3
   3178 		flt_rule_entry.rule.hashable = prop->prop[cnt].is_rule_hashable;
   3179 		flt_rule_entry.rule.rule_id = prop->prop[cnt].rule_id;
   3180 		if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)	//turn on meta-data equation
   3181 		{
   3182 			flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
   3183 			flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
   3184 			flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
   3185 			flt_rule_entry.rule.eq_attrib.metadata_meq32.value |= rx_prop->rx[0].attrib.meta_data;
   3186 			flt_rule_entry.rule.eq_attrib.metadata_meq32.mask |= rx_prop->rx[0].attrib.meta_data_mask;
   3187 		}
   3188 #endif
   3189 		memcpy(&pFilteringTable->rules[cnt], &flt_rule_entry, sizeof(flt_rule_entry));
   3190 
   3191 		IPACMDBG_H("Modem UL filtering rule %d has index %d\n", cnt, index);
   3192 #ifndef FEATURE_IPA_V3
   3193 		flt_index.filter_index_list[cnt].filter_index = index;
   3194 		flt_index.filter_index_list[cnt].filter_handle = prop->prop[cnt].filter_hdl;
   3195 #else /* defined (FEATURE_IPA_V3) */
   3196 		flt_index.rule_id[cnt] = prop->prop[cnt].rule_id;
   3197 #endif
   3198 		index++;
   3199 	}
   3200 
   3201 	if(false == m_filtering.SendFilteringRuleIndex(&flt_index))
   3202 	{
   3203 		IPACMERR("Error sending filtering rule index, aborting...\n");
   3204 		ret = IPACM_FAILURE;
   3205 		goto fail;
   3206 	}
   3207 
   3208 	if(false == m_filtering.AddFilteringRule(pFilteringTable))
   3209 	{
   3210 		IPACMERR("Error Adding RuleTable to Filtering, aborting...\n");
   3211 		ret = IPACM_FAILURE;
   3212 		goto fail;
   3213 	}
   3214 	else
   3215 	{
   3216 		if(iptype == IPA_IP_v4)
   3217 		{
   3218 			for(i=0; i<pFilteringTable->num_rules; i++)
   3219 			{
   3220 				wan_ul_fl_rule_hdl_v4[num_wan_ul_fl_rule_v4] = pFilteringTable->rules[i].flt_rule_hdl;
   3221 				num_wan_ul_fl_rule_v4++;
   3222 			}
   3223 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules);
   3224 		}
   3225 		else if(iptype == IPA_IP_v6)
   3226 		{
   3227 			for(i=0; i<pFilteringTable->num_rules; i++)
   3228 			{
   3229 				wan_ul_fl_rule_hdl_v6[num_wan_ul_fl_rule_v6] = pFilteringTable->rules[i].flt_rule_hdl;
   3230 				num_wan_ul_fl_rule_v6++;
   3231 			}
   3232 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, iptype, pFilteringTable->num_rules);
   3233 		}
   3234 		else
   3235 		{
   3236 			IPACMERR("IP type is not expected.\n");
   3237 			goto fail;
   3238 		}
   3239 	}
   3240 
   3241 fail:
   3242 	free(pFilteringTable);
   3243 	close(fd);
   3244 	return ret;
   3245 }
   3246 
   3247 int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode)
   3248 {
   3249 	ipa_fltr_installed_notif_req_msg_v01 flt_index;
   3250 	int fd;
   3251 
   3252 	fd = open(IPA_DEVICE_NAME, O_RDWR);
   3253 	if (0 == fd)
   3254 	{
   3255 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
   3256 		return IPACM_FAILURE;
   3257 	}
   3258 
   3259 	delete_ipv6_prefix_flt_rule();
   3260 
   3261 	memset(ipv6_prefix, 0, sizeof(ipv6_prefix));
   3262 
   3263 	if(is_sta_mode == false && modem_ul_v6_set == true)
   3264 	{
   3265 		if (num_wan_ul_fl_rule_v6 > MAX_WAN_UL_FILTER_RULES)
   3266 		{
   3267 			IPACMERR(" the number of rules (%d) are bigger than array (%d), aborting...\n", num_wan_ul_fl_rule_v6, MAX_WAN_UL_FILTER_RULES);
   3268 			close(fd);
   3269 			return IPACM_FAILURE;
   3270 		}
   3271 		if (num_wan_ul_fl_rule_v6 == 0)
   3272 		{
   3273 			IPACMERR("No modem UL rules were installed, return...\n");
   3274 			close(fd);
   3275 			return IPACM_FAILURE;
   3276 		}
   3277 
   3278 		if (m_filtering.DeleteFilteringHdls(wan_ul_fl_rule_hdl_v6,
   3279 			IPA_IP_v6, num_wan_ul_fl_rule_v6) == false)
   3280 		{
   3281 			IPACMERR("Error Deleting RuleTable(1) to Filtering, aborting...\n");
   3282 			close(fd);
   3283 			return IPACM_FAILURE;
   3284 		}
   3285 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_wan_ul_fl_rule_v6);
   3286 		memset(wan_ul_fl_rule_hdl_v6, 0, MAX_WAN_UL_FILTER_RULES * sizeof(uint32_t));
   3287 		num_wan_ul_fl_rule_v6 = 0;
   3288 		modem_ul_v6_set = false;
   3289 
   3290 		memset(&flt_index, 0, sizeof(flt_index));
   3291 		flt_index.source_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[0].src_pipe);
   3292 		flt_index.install_status = IPA_QMI_RESULT_SUCCESS_V01;
   3293 #ifndef FEATURE_IPA_V3
   3294 		flt_index.filter_index_list_len = 0;
   3295 #else /* defined (FEATURE_IPA_V3) */
   3296 		flt_index.rule_id_valid = 1;
   3297 		flt_index.rule_id_len = 0;
   3298 #endif
   3299 		flt_index.embedded_pipe_index_valid = 1;
   3300 		flt_index.embedded_pipe_index = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, IPA_CLIENT_APPS_LAN_WAN_PROD);
   3301 		flt_index.retain_header_valid = 1;
   3302 		flt_index.retain_header = 0;
   3303 		flt_index.embedded_call_mux_id_valid = 1;
   3304 		flt_index.embedded_call_mux_id = IPACM_Iface::ipacmcfg->GetQmapId();
   3305 		if(false == m_filtering.SendFilteringRuleIndex(&flt_index))
   3306 		{
   3307 			IPACMERR("Error sending filtering rule index, aborting...\n");
   3308 			close(fd);
   3309 			return IPACM_FAILURE;
   3310 		}
   3311 	}
   3312 	else
   3313 	{
   3314 		if (m_filtering.DeleteFilteringHdls(&dft_v6fl_rule_hdl[IPV6_DEFAULT_FILTERTING_RULES],
   3315 																				IPA_IP_v6, 1) == false)
   3316 		{
   3317 			IPACMERR("Error Adding RuleTable(1) to Filtering, aborting...\n");
   3318 			close(fd);
   3319 			return IPACM_FAILURE;
   3320 		}
   3321 		IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   3322 	}
   3323 	close(fd);
   3324 	return IPACM_SUCCESS;
   3325 }
   3326 
   3327 int IPACM_Lan::reset_to_dummy_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl)
   3328 {
   3329 	int len, res = IPACM_SUCCESS;
   3330 	struct ipa_flt_rule_mdfy flt_rule;
   3331 	struct ipa_ioc_mdfy_flt_rule* pFilteringTable;
   3332 
   3333 	IPACMDBG_H("Reset flt rule to dummy, IP type: %d, hdl: %d\n", iptype, rule_hdl);
   3334 	len = sizeof(struct ipa_ioc_mdfy_flt_rule) + sizeof(struct ipa_flt_rule_mdfy);
   3335 	pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len);
   3336 
   3337 	if (pFilteringTable == NULL)
   3338 	{
   3339 		IPACMERR("Error allocate flt rule memory...\n");
   3340 		return IPACM_FAILURE;
   3341 	}
   3342 	memset(pFilteringTable, 0, len);
   3343 
   3344 	pFilteringTable->commit = 1;
   3345 	pFilteringTable->ip = iptype;
   3346 	pFilteringTable->num_rules = 1;
   3347 
   3348 	memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy));
   3349 	flt_rule.status = -1;
   3350 	flt_rule.rule_hdl = rule_hdl;
   3351 
   3352 	flt_rule.rule.retain_hdr = 0;
   3353 	flt_rule.rule.action = IPA_PASS_TO_EXCEPTION;
   3354 
   3355 	if(iptype == IPA_IP_v4)
   3356 	{
   3357 		IPACMDBG_H("Reset IPv4 flt rule to dummy\n");
   3358 
   3359 		flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR;
   3360 		flt_rule.rule.attrib.u.v4.dst_addr = ~0;
   3361 		flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0;
   3362 		flt_rule.rule.attrib.u.v4.src_addr = ~0;
   3363 		flt_rule.rule.attrib.u.v4.src_addr_mask = ~0;
   3364 
   3365 		memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy));
   3366 		if (false == m_filtering.ModifyFilteringRule(pFilteringTable))
   3367 		{
   3368 			IPACMERR("Error modifying filtering rule.\n");
   3369 			res = IPACM_FAILURE;
   3370 			goto fail;
   3371 		}
   3372 		else
   3373 		{
   3374 			IPACMDBG_H("Flt rule reset to dummy, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl,
   3375 						pFilteringTable->rules[0].status);
   3376 		}
   3377 	}
   3378 	else if(iptype == IPA_IP_v6)
   3379 	{
   3380 		IPACMDBG_H("Reset IPv6 flt rule to dummy\n");
   3381 
   3382 		flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR;
   3383 		flt_rule.rule.attrib.u.v6.src_addr[0] = ~0;
   3384 		flt_rule.rule.attrib.u.v6.src_addr[1] = ~0;
   3385 		flt_rule.rule.attrib.u.v6.src_addr[2] = ~0;
   3386 		flt_rule.rule.attrib.u.v6.src_addr[3] = ~0;
   3387 		flt_rule.rule.attrib.u.v6.src_addr_mask[0] = ~0;
   3388 		flt_rule.rule.attrib.u.v6.src_addr_mask[1] = ~0;
   3389 		flt_rule.rule.attrib.u.v6.src_addr_mask[2] = ~0;
   3390 		flt_rule.rule.attrib.u.v6.src_addr_mask[3] = ~0;
   3391 		flt_rule.rule.attrib.u.v6.dst_addr[0] = ~0;
   3392 		flt_rule.rule.attrib.u.v6.dst_addr[1] = ~0;
   3393 		flt_rule.rule.attrib.u.v6.dst_addr[2] = ~0;
   3394 		flt_rule.rule.attrib.u.v6.dst_addr[3] = ~0;
   3395 		flt_rule.rule.attrib.u.v6.dst_addr_mask[0] = ~0;
   3396 		flt_rule.rule.attrib.u.v6.dst_addr_mask[1] = ~0;
   3397 		flt_rule.rule.attrib.u.v6.dst_addr_mask[2] = ~0;
   3398 		flt_rule.rule.attrib.u.v6.dst_addr_mask[3] = ~0;
   3399 
   3400 
   3401 		memcpy(&(pFilteringTable->rules[0]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy));
   3402 		if (false == m_filtering.ModifyFilteringRule(pFilteringTable))
   3403 		{
   3404 			IPACMERR("Error modifying filtering rule.\n");
   3405 			res = IPACM_FAILURE;
   3406 			goto fail;
   3407 		}
   3408 		else
   3409 		{
   3410 			IPACMDBG_H("Flt rule reset to dummy, hdl: 0x%x, status: %d\n", pFilteringTable->rules[0].rule_hdl,
   3411 						pFilteringTable->rules[0].status);
   3412 		}
   3413 	}
   3414 	else
   3415 	{
   3416 		IPACMERR("IP type is not expected.\n");
   3417 		res = IPACM_FAILURE;
   3418 		goto fail;
   3419 	}
   3420 
   3421 fail:
   3422 	free(pFilteringTable);
   3423 	return res;
   3424 }
   3425 
   3426 void IPACM_Lan::post_del_self_evt()
   3427 {
   3428 	ipacm_cmd_q_data evt;
   3429 	ipacm_event_data_fid* fid;
   3430 	fid = (ipacm_event_data_fid*)malloc(sizeof(ipacm_event_data_fid));
   3431 	if(fid == NULL)
   3432 	{
   3433 		IPACMERR("Failed to allocate fid memory.\n");
   3434 		return;
   3435 	}
   3436 	memset(fid, 0, sizeof(ipacm_event_data_fid));
   3437 	memset(&evt, 0, sizeof(ipacm_cmd_q_data));
   3438 
   3439 	fid->if_index = ipa_if_num;
   3440 
   3441 	evt.evt_data = (void*)fid;
   3442 	evt.event = IPA_LAN_DELETE_SELF;
   3443 
   3444 	IPACMDBG_H("Posting event IPA_LAN_DELETE_SELF\n");
   3445 	IPACM_EvtDispatcher::PostEvt(&evt);
   3446 }
   3447 
   3448 /*handle reset usb-client rt-rules */
   3449 int IPACM_Lan::handle_lan_client_reset_rt(ipa_ip_type iptype)
   3450 {
   3451 	uint32_t i;
   3452 	int res = IPACM_SUCCESS;
   3453 
   3454 	/* clean eth-client routing rules */
   3455 	IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client);
   3456 	for (i = 0; i < num_eth_client; i++)
   3457 	{
   3458 		res = delete_eth_rtrules(i, iptype);
   3459 		if (res != IPACM_SUCCESS)
   3460 		{
   3461 			IPACMERR("Failed to delete old iptype(%d) rules.\n", iptype);
   3462 			return res;
   3463 		}
   3464 	} /* end of for loop */
   3465 
   3466 	/* Reset ip-address */
   3467 	for (i = 0; i < num_eth_client; i++)
   3468 	{
   3469 		if(iptype == IPA_IP_v4)
   3470 		{
   3471 			get_client_memptr(eth_client, i)->ipv4_set = false;
   3472 		}
   3473 		else
   3474 		{
   3475 			get_client_memptr(eth_client, i)->ipv6_set = 0;
   3476 		}
   3477 	} /* end of for loop */
   3478 	return res;
   3479 }
   3480 
   3481 int IPACM_Lan::install_ipv4_icmp_flt_rule()
   3482 {
   3483 	int len;
   3484 	struct ipa_ioc_add_flt_rule* flt_rule;
   3485 	struct ipa_flt_rule_add flt_rule_entry;
   3486 
   3487 	if(rx_prop != NULL)
   3488 	{
   3489 		len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
   3490 
   3491 		flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
   3492 		if (!flt_rule)
   3493 		{
   3494 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   3495 			return IPACM_FAILURE;
   3496 		}
   3497 
   3498 		flt_rule->commit = 1;
   3499 		flt_rule->ep = rx_prop->rx[0].src_pipe;
   3500 		flt_rule->global = false;
   3501 		flt_rule->ip = IPA_IP_v4;
   3502 		flt_rule->num_rules = 1;
   3503 
   3504 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3505 
   3506 		flt_rule_entry.rule.retain_hdr = 1;
   3507 		flt_rule_entry.rule.to_uc = 0;
   3508 		flt_rule_entry.rule.eq_attrib_type = 0;
   3509 		flt_rule_entry.at_rear = true;
   3510 		flt_rule_entry.flt_rule_hdl = -1;
   3511 		flt_rule_entry.status = -1;
   3512 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   3513 #ifdef FEATURE_IPA_V3
   3514 		flt_rule_entry.rule.hashable = true;
   3515 #endif
   3516 		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
   3517 
   3518 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
   3519 		flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP;
   3520 		memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3521 
   3522 		if (m_filtering.AddFilteringRule(flt_rule) == false)
   3523 		{
   3524 			IPACMERR("Error Adding Filtering rule, aborting...\n");
   3525 			free(flt_rule);
   3526 			return IPACM_FAILURE;
   3527 		}
   3528 		else
   3529 		{
   3530 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
   3531 			ipv4_icmp_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl;
   3532 			IPACMDBG_H("IPv4 icmp filter rule HDL:0x%x\n", ipv4_icmp_flt_rule_hdl[0]);
   3533                         free(flt_rule);
   3534 		}
   3535 	}
   3536 	return IPACM_SUCCESS;
   3537 }
   3538 
   3539 int IPACM_Lan::install_ipv6_icmp_flt_rule()
   3540 {
   3541 
   3542 	int len;
   3543 	struct ipa_ioc_add_flt_rule* flt_rule;
   3544 	struct ipa_flt_rule_add flt_rule_entry;
   3545 
   3546 	if(rx_prop != NULL)
   3547 	{
   3548 		len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
   3549 
   3550 		flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
   3551 		if (!flt_rule)
   3552 		{
   3553 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   3554 			return IPACM_FAILURE;
   3555 		}
   3556 
   3557 		flt_rule->commit = 1;
   3558 		flt_rule->ep = rx_prop->rx[0].src_pipe;
   3559 		flt_rule->global = false;
   3560 		flt_rule->ip = IPA_IP_v6;
   3561 		flt_rule->num_rules = 1;
   3562 
   3563 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3564 
   3565 		flt_rule_entry.rule.retain_hdr = 1;
   3566 		flt_rule_entry.rule.to_uc = 0;
   3567 		flt_rule_entry.rule.eq_attrib_type = 0;
   3568 		flt_rule_entry.at_rear = true;
   3569 		flt_rule_entry.flt_rule_hdl = -1;
   3570 		flt_rule_entry.status = -1;
   3571 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   3572 #ifdef FEATURE_IPA_V3
   3573 		flt_rule_entry.rule.hashable = false;
   3574 #endif
   3575 		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
   3576 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
   3577 		flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6;
   3578 		memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3579 
   3580 		if (m_filtering.AddFilteringRule(flt_rule) == false)
   3581 		{
   3582 			IPACMERR("Error Adding Filtering rule, aborting...\n");
   3583 			free(flt_rule);
   3584 			return IPACM_FAILURE;
   3585 		}
   3586 		else
   3587 		{
   3588 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   3589 			ipv6_icmp_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl;
   3590 			IPACMDBG_H("IPv6 icmp filter rule HDL:0x%x\n", ipv6_icmp_flt_rule_hdl[0]);
   3591 			free(flt_rule);
   3592 		}
   3593 	}
   3594 	return IPACM_SUCCESS;
   3595 }
   3596 
   3597 int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype)
   3598 {
   3599 	if(rx_prop == NULL)
   3600 	{
   3601 		IPACMDBG_H("There is no rx_prop for iface %s, not able to add dummy private subnet filtering rule.\n", dev_name);
   3602 		return 0;
   3603 	}
   3604 
   3605 	if(iptype == IPA_IP_v6)
   3606 	{
   3607 		IPACMDBG_H("There is no ipv6 dummy filter rules needed for iface %s\n", dev_name);
   3608 		return 0;
   3609 	}
   3610 	int i, len, res = IPACM_SUCCESS;
   3611 	struct ipa_flt_rule_add flt_rule;
   3612 	ipa_ioc_add_flt_rule* pFilteringTable;
   3613 
   3614 	len = sizeof(struct ipa_ioc_add_flt_rule) +	IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(struct ipa_flt_rule_add);
   3615 
   3616 	pFilteringTable = (struct ipa_ioc_add_flt_rule *)malloc(len);
   3617 	if (pFilteringTable == NULL)
   3618 	{
   3619 		IPACMERR("Error allocate flt table memory...\n");
   3620 		return IPACM_FAILURE;
   3621 	}
   3622 	memset(pFilteringTable, 0, len);
   3623 
   3624 	pFilteringTable->commit = 1;
   3625 	pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   3626 	pFilteringTable->global = false;
   3627 	pFilteringTable->ip = iptype;
   3628 	pFilteringTable->num_rules = IPA_MAX_PRIVATE_SUBNET_ENTRIES;
   3629 
   3630 	memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_add));
   3631 
   3632 	flt_rule.rule.retain_hdr = 0;
   3633 	flt_rule.at_rear = true;
   3634 	flt_rule.flt_rule_hdl = -1;
   3635 	flt_rule.status = -1;
   3636 	flt_rule.rule.action = IPA_PASS_TO_EXCEPTION;
   3637 #ifdef FEATURE_IPA_V3
   3638 	flt_rule.rule.hashable = true;
   3639 #endif
   3640 	memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib,
   3641 			sizeof(flt_rule.rule.attrib));
   3642 
   3643 	if(iptype == IPA_IP_v4)
   3644 	{
   3645 		flt_rule.rule.attrib.attrib_mask = IPA_FLT_SRC_ADDR | IPA_FLT_DST_ADDR;
   3646 		flt_rule.rule.attrib.u.v4.src_addr_mask = ~0;
   3647 		flt_rule.rule.attrib.u.v4.src_addr = ~0;
   3648 		flt_rule.rule.attrib.u.v4.dst_addr_mask = ~0;
   3649 		flt_rule.rule.attrib.u.v4.dst_addr = ~0;
   3650 
   3651 		for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
   3652 		{
   3653 			memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add));
   3654 		}
   3655 
   3656 		if (false == m_filtering.AddFilteringRule(pFilteringTable))
   3657 		{
   3658 			IPACMERR("Error adding dummy private subnet v4 flt rule\n");
   3659 			res = IPACM_FAILURE;
   3660 			goto fail;
   3661 		}
   3662 		else
   3663 		{
   3664 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPA_MAX_PRIVATE_SUBNET_ENTRIES);
   3665 			/* copy filter rule hdls */
   3666 			for (int i = 0; i < IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
   3667 			{
   3668 				if (pFilteringTable->rules[i].status == 0)
   3669 				{
   3670 					private_fl_rule_hdl[i] = pFilteringTable->rules[i].flt_rule_hdl;
   3671 					IPACMDBG_H("Private subnet v4 flt rule %d hdl:0x%x\n", i, private_fl_rule_hdl[i]);
   3672 				}
   3673 				else
   3674 				{
   3675 					IPACMERR("Failed adding lan2lan v4 flt rule %d\n", i);
   3676 					res = IPACM_FAILURE;
   3677 					goto fail;
   3678 				}
   3679 			}
   3680 		}
   3681 	}
   3682 fail:
   3683 	free(pFilteringTable);
   3684 	return res;
   3685 }
   3686 
   3687 int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype)
   3688 {
   3689 	int i, len, res = IPACM_SUCCESS;
   3690 	struct ipa_flt_rule_mdfy flt_rule;
   3691 	struct ipa_ioc_mdfy_flt_rule* pFilteringTable;
   3692 
   3693 	if (rx_prop == NULL)
   3694 	{
   3695 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   3696 		return IPACM_SUCCESS;
   3697 	}
   3698 
   3699 	if(iptype == IPA_IP_v6)
   3700 	{
   3701 		IPACMDBG_H("There is no ipv6 dummy filter rules needed for iface %s\n", dev_name);
   3702 		return 0;
   3703 	}
   3704 	else
   3705 	{
   3706 		for(i=0; i<IPA_MAX_PRIVATE_SUBNET_ENTRIES; i++)
   3707 		{
   3708 			reset_to_dummy_flt_rule(IPA_IP_v4, private_fl_rule_hdl[i]);
   3709 		}
   3710 
   3711 		len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (IPACM_Iface::ipacmcfg->ipa_num_private_subnet) * sizeof(struct ipa_flt_rule_mdfy);
   3712 		pFilteringTable = (struct ipa_ioc_mdfy_flt_rule*)malloc(len);
   3713 		if (!pFilteringTable)
   3714 		{
   3715 			IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n");
   3716 			return IPACM_FAILURE;
   3717 		}
   3718 		memset(pFilteringTable, 0, len);
   3719 
   3720 		pFilteringTable->commit = 1;
   3721 		pFilteringTable->ip = iptype;
   3722 		pFilteringTable->num_rules = (uint8_t)IPACM_Iface::ipacmcfg->ipa_num_private_subnet;
   3723 
   3724 		/* Make LAN-traffic always go A5, use default IPA-RT table */
   3725 		if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_default_v4))
   3726 		{
   3727 			IPACMERR("Failed to get routing table handle.\n");
   3728 			res = IPACM_FAILURE;
   3729 			goto fail;
   3730 		}
   3731 
   3732 		memset(&flt_rule, 0, sizeof(struct ipa_flt_rule_mdfy));
   3733 		flt_rule.status = -1;
   3734 
   3735 		flt_rule.rule.retain_hdr = 1;
   3736 		flt_rule.rule.to_uc = 0;
   3737 		flt_rule.rule.action = IPA_PASS_TO_ROUTING;
   3738 		flt_rule.rule.eq_attrib_type = 0;
   3739 		flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl;
   3740 		IPACMDBG_H("Private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name);
   3741 
   3742 		memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib));
   3743 		flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   3744 
   3745 		for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++)
   3746 		{
   3747 			flt_rule.rule_hdl = private_fl_rule_hdl[i];
   3748 			flt_rule.rule.attrib.u.v4.dst_addr_mask = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_mask;
   3749 			flt_rule.rule.attrib.u.v4.dst_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr;
   3750 			memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy));
   3751 			IPACMDBG_H(" IPACM private subnet_addr as: 0x%x entry(%d)\n", flt_rule.rule.attrib.u.v4.dst_addr, i);
   3752 		}
   3753 
   3754 		if (false == m_filtering.ModifyFilteringRule(pFilteringTable))
   3755 		{
   3756 			IPACMERR("Failed to modify private subnet filtering rules.\n");
   3757 			res = IPACM_FAILURE;
   3758 			goto fail;
   3759 		}
   3760 	}
   3761 fail:
   3762 	if(pFilteringTable != NULL)
   3763 	{
   3764 		free(pFilteringTable);
   3765 	}
   3766 	return res;
   3767 }
   3768 
   3769 int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix)
   3770 {
   3771 	if(prefix == NULL)
   3772 	{
   3773 		IPACMERR("IPv6 prefix is empty.\n");
   3774 		return IPACM_FAILURE;
   3775 	}
   3776 	IPACMDBG_H("Receive IPv6 prefix: 0x%08x%08x.\n", prefix[0], prefix[1]);
   3777 
   3778 	int len;
   3779 	struct ipa_ioc_add_flt_rule* flt_rule;
   3780 	struct ipa_flt_rule_add flt_rule_entry;
   3781 
   3782 	if(rx_prop != NULL)
   3783 	{
   3784 		len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
   3785 
   3786 		flt_rule = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
   3787 		if (!flt_rule)
   3788 		{
   3789 			IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
   3790 			return IPACM_FAILURE;
   3791 		}
   3792 
   3793 		flt_rule->commit = 1;
   3794 		flt_rule->ep = rx_prop->rx[0].src_pipe;
   3795 		flt_rule->global = false;
   3796 		flt_rule->ip = IPA_IP_v6;
   3797 		flt_rule->num_rules = 1;
   3798 
   3799 		memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
   3800 
   3801 		flt_rule_entry.rule.retain_hdr = 1;
   3802 		flt_rule_entry.rule.to_uc = 0;
   3803 		flt_rule_entry.rule.eq_attrib_type = 0;
   3804 		flt_rule_entry.at_rear = true;
   3805 		flt_rule_entry.flt_rule_hdl = -1;
   3806 		flt_rule_entry.status = -1;
   3807 		flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
   3808 #ifdef FEATURE_IPA_V3
   3809 		flt_rule_entry.rule.hashable = true;
   3810 #endif
   3811 		memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
   3812 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   3813 		flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[0];
   3814 		flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = prefix[1];
   3815 		flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x0;
   3816 		flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x0;
   3817 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF;
   3818 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF;
   3819 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x0;
   3820 		flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x0;
   3821 		memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
   3822 
   3823 		if (m_filtering.AddFilteringRule(flt_rule) == false)
   3824 		{
   3825 			IPACMERR("Error Adding Filtering rule, aborting...\n");
   3826 			free(flt_rule);
   3827 			return IPACM_FAILURE;
   3828 		}
   3829 		else
   3830 		{
   3831 			IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
   3832 			ipv6_prefix_flt_rule_hdl[0] = flt_rule->rules[0].flt_rule_hdl;
   3833 			IPACMDBG_H("IPv6 prefix filter rule HDL:0x%x\n", ipv6_prefix_flt_rule_hdl[0]);
   3834 			free(flt_rule);
   3835 		}
   3836 	}
   3837 	return IPACM_SUCCESS;
   3838 }
   3839 
   3840 void IPACM_Lan::delete_ipv6_prefix_flt_rule()
   3841 {
   3842 	if(m_filtering.DeleteFilteringHdls(ipv6_prefix_flt_rule_hdl, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE) == false)
   3843 	{
   3844 		IPACMERR("Failed to delete ipv6 prefix flt rule.\n");
   3845 		return;
   3846 	}
   3847 	IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, NUM_IPV6_PREFIX_FLT_RULE);
   3848 	return;
   3849 }
   3850 
   3851 int IPACM_Lan::handle_addr_evt_odu_bridge(ipacm_event_data_addr* data)
   3852 {
   3853 	int fd, res = IPACM_SUCCESS;
   3854 	struct in6_addr ipv6_addr;
   3855 	if(data == NULL)
   3856 	{
   3857 		IPACMERR("Failed to get interface IP address.\n");
   3858 		return IPACM_FAILURE;
   3859 	}
   3860 
   3861 	if(data->iptype == IPA_IP_v6)
   3862 	{
   3863 		fd = open(IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU, O_RDWR);
   3864 		if(fd == 0)
   3865 		{
   3866 			IPACMERR("Failed to open %s.\n", IPACM_Iface::ipacmcfg->DEVICE_NAME_ODU);
   3867 			return IPACM_FAILURE;
   3868 		}
   3869 
   3870 		memcpy(&ipv6_addr, data->ipv6_addr, sizeof(struct in6_addr));
   3871 
   3872 		if( ioctl(fd, ODU_BRIDGE_IOC_SET_LLV6_ADDR, &ipv6_addr) )
   3873 		{
   3874 			IPACMERR("Failed to write IPv6 address to odu driver.\n");
   3875 			res = IPACM_FAILURE;
   3876 		}
   3877 		num_dft_rt_v6++;
   3878 		close(fd);
   3879 	}
   3880 
   3881 	return res;
   3882 }
   3883 
   3884 ipa_hdr_proc_type IPACM_Lan::eth_bridge_get_hdr_proc_type(ipa_hdr_l2_type t1, ipa_hdr_l2_type t2)
   3885 {
   3886 	if(t1 == IPA_HDR_L2_ETHERNET_II)
   3887 	{
   3888 		if(t2 == IPA_HDR_L2_ETHERNET_II)
   3889 		{
   3890 			return IPA_HDR_PROC_ETHII_TO_ETHII;
   3891 		}
   3892 		if(t2 == IPA_HDR_L2_802_3)
   3893 		{
   3894 			return IPA_HDR_PROC_ETHII_TO_802_3;
   3895 		}
   3896 	}
   3897 
   3898 	if(t1 == IPA_HDR_L2_802_3)
   3899 	{
   3900 		if(t2 == IPA_HDR_L2_ETHERNET_II)
   3901 		{
   3902 			return IPA_HDR_PROC_802_3_TO_ETHII;
   3903 		}
   3904 		if(t2 == IPA_HDR_L2_802_3)
   3905 		{
   3906 			return IPA_HDR_PROC_802_3_TO_802_3;
   3907 		}
   3908 	}
   3909 
   3910 	return IPA_HDR_PROC_NONE;
   3911 }
   3912 
   3913 int IPACM_Lan::eth_bridge_get_hdr_template_hdl(uint32_t* hdr_hdl)
   3914 {
   3915 	if(hdr_hdl == NULL)
   3916 	{
   3917 		IPACMDBG_H("Hdr handle pointer is empty.\n");
   3918 		return IPACM_FAILURE;
   3919 	}
   3920 
   3921 	struct ipa_ioc_get_hdr hdr;
   3922 	memset(&hdr, 0, sizeof(hdr));
   3923 
   3924 	memcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name));
   3925 	if(m_header.GetHeaderHandle(&hdr) == false)
   3926 	{
   3927 		IPACMERR("Failed to get template hdr hdl.\n");
   3928 		return IPACM_FAILURE;
   3929 	}
   3930 
   3931 	*hdr_hdl = hdr.hdl;
   3932 	return IPACM_SUCCESS;
   3933 }
   3934 
   3935 int IPACM_Lan::handle_cradle_wan_mode_switch(bool is_wan_bridge_mode)
   3936 {
   3937 	struct ipa_flt_rule_mdfy flt_rule_entry;
   3938 	int len = 0;
   3939 	ipa_ioc_mdfy_flt_rule *m_pFilteringTable;
   3940 
   3941 	IPACMDBG_H("Handle wan mode swtich: is wan bridge mode?%d\n", is_wan_bridge_mode);
   3942 
   3943 	if (rx_prop == NULL)
   3944 	{
   3945 		IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
   3946 		return IPACM_SUCCESS;
   3947 	}
   3948 
   3949 	len = sizeof(struct ipa_ioc_mdfy_flt_rule) + (1 * sizeof(struct ipa_flt_rule_mdfy));
   3950 	m_pFilteringTable = (struct ipa_ioc_mdfy_flt_rule *)calloc(1, len);
   3951 	if (m_pFilteringTable == NULL)
   3952 	{
   3953 		PERROR("Error Locate ipa_ioc_mdfy_flt_rule memory...\n");
   3954 		return IPACM_FAILURE;
   3955 	}
   3956 
   3957 	m_pFilteringTable->commit = 1;
   3958 	m_pFilteringTable->ip = IPA_IP_v4;
   3959 	m_pFilteringTable->num_rules = (uint8_t)1;
   3960 
   3961 	IPACMDBG_H("Retrieving routing hanle for table: %s\n",
   3962 					 IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.name);
   3963 	if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4))
   3964 	{
   3965 		IPACMERR("m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v4=0x%p) Failed.\n",
   3966 						 &IPACM_Iface::ipacmcfg->rt_tbl_wan_v4);
   3967 		free(m_pFilteringTable);
   3968 		return IPACM_FAILURE;
   3969 	}
   3970 	IPACMDBG_H("Routing handle for table: %d\n", IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl);
   3971 
   3972 
   3973 	memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_mdfy)); // Zero All Fields
   3974 	flt_rule_entry.status = -1;
   3975 	flt_rule_entry.rule_hdl = lan_wan_fl_rule_hdl[0];
   3976 
   3977 	flt_rule_entry.rule.retain_hdr = 0;
   3978 	flt_rule_entry.rule.to_uc = 0;
   3979 	flt_rule_entry.rule.eq_attrib_type = 0;
   3980 	if(is_wan_bridge_mode)
   3981 	{
   3982 		flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   3983 	}
   3984 	else
   3985 	{
   3986 		flt_rule_entry.rule.action = IPA_PASS_TO_SRC_NAT;
   3987 	}
   3988 	flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v4.hdl;
   3989 
   3990 	memcpy(&flt_rule_entry.rule.attrib,
   3991 				 &rx_prop->rx[0].attrib,
   3992 				 sizeof(flt_rule_entry.rule.attrib));
   3993 
   3994 	flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
   3995 	flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0;
   3996 	flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0;
   3997 
   3998 	memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry));
   3999 	if (false == m_filtering.ModifyFilteringRule(m_pFilteringTable))
   4000 	{
   4001 		IPACMERR("Error Modifying RuleTable(0) to Filtering, aborting...\n");
   4002 		free(m_pFilteringTable);
   4003 		return IPACM_FAILURE;
   4004 	}
   4005 	else
   4006 	{
   4007 		IPACMDBG_H("flt rule hdl = %d, status = %d\n",
   4008 						 m_pFilteringTable->rules[0].rule_hdl,
   4009 						 m_pFilteringTable->rules[0].status);
   4010 	}
   4011 	free(m_pFilteringTable);
   4012 	return IPACM_SUCCESS;
   4013 }
   4014 
   4015 /*handle reset usb-client rt-rules */
   4016 int IPACM_Lan::handle_tethering_stats_event(ipa_get_data_stats_resp_msg_v01 *data)
   4017 {
   4018 	int fd;
   4019 	uint32_t pipe_len, cnt;
   4020 	uint64_t num_ul_packets, num_ul_bytes;
   4021 	uint64_t num_dl_packets, num_dl_bytes;
   4022 	bool ul_pipe_found, dl_pipe_found;
   4023 	FILE *fp = NULL;
   4024 
   4025 	fd = open(IPA_DEVICE_NAME, O_RDWR);
   4026 	if (fd < 0)
   4027 	{
   4028 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
   4029 		return IPACM_FAILURE;
   4030 	}
   4031 
   4032 
   4033 	ul_pipe_found = false;
   4034 	dl_pipe_found = false;
   4035 	num_ul_packets = 0;
   4036 	num_dl_packets = 0;
   4037 	num_ul_bytes = 0;
   4038 	num_dl_bytes = 0;
   4039 
   4040 	if (data->dl_dst_pipe_stats_list_valid)
   4041 	{
   4042 		if(tx_prop != NULL)
   4043 		{
   4044 			for (pipe_len = 0; pipe_len < data->dl_dst_pipe_stats_list_len; pipe_len++)
   4045 			{
   4046 				IPACMDBG_H("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, data->dl_dst_pipe_stats_list[pipe_len].pipe_index);
   4047 				for (cnt=0; cnt<tx_prop->num_tx_props; cnt++)
   4048 				{
   4049 					IPACMDBG_H("Check Tx_prop_entry(%d) pipe(%d)\n", cnt, ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe));
   4050 					if(ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe) == (int)data->dl_dst_pipe_stats_list[pipe_len].pipe_index)
   4051 					{
   4052 						/* update the DL stats */
   4053 						dl_pipe_found = true;
   4054 						num_dl_packets += data->dl_dst_pipe_stats_list[pipe_len].num_ipv4_packets;
   4055 						num_dl_packets += data->dl_dst_pipe_stats_list[pipe_len].num_ipv6_packets;
   4056 						num_dl_bytes += data->dl_dst_pipe_stats_list[pipe_len].num_ipv4_bytes;
   4057 						num_dl_bytes += data->dl_dst_pipe_stats_list[pipe_len].num_ipv6_bytes;
   4058 						IPACMDBG_H("Got matched dst-pipe (%d) from %d tx props\n", data->dl_dst_pipe_stats_list[pipe_len].pipe_index, cnt);
   4059 						IPACMDBG_H("DL_packets:(%lu) DL_bytes:(%lu) \n", num_dl_packets, num_dl_bytes);
   4060 						break;
   4061 					}
   4062 				}
   4063 			}
   4064 		}
   4065 	}
   4066 
   4067 	if (data->ul_src_pipe_stats_list_valid)
   4068 	{
   4069 		if(rx_prop != NULL)
   4070 		{
   4071 			for (pipe_len = 0; pipe_len < data->ul_src_pipe_stats_list_len; pipe_len++)
   4072 			{
   4073 				IPACMDBG_H("Check entry(%d) dl_dst_pipe(%d)\n", pipe_len, data->ul_src_pipe_stats_list[pipe_len].pipe_index);
   4074 				for (cnt=0; cnt < rx_prop->num_rx_props; cnt++)
   4075 				{
   4076 					IPACMDBG_H("Check Rx_prop_entry(%d) pipe(%d)\n", cnt, ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe));
   4077 					//Typecasting to avoid -Wall -Werror errors
   4078 					if(ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe) == (int)data->ul_src_pipe_stats_list[pipe_len].pipe_index)
   4079 					{
   4080 						/* update the UL stats */
   4081 						ul_pipe_found = true;
   4082 						num_ul_packets += data->ul_src_pipe_stats_list[pipe_len].num_ipv4_packets;
   4083 						num_ul_packets += data->ul_src_pipe_stats_list[pipe_len].num_ipv6_packets;
   4084 						num_ul_bytes += data->ul_src_pipe_stats_list[pipe_len].num_ipv4_bytes;
   4085 						num_ul_bytes += data->ul_src_pipe_stats_list[pipe_len].num_ipv6_bytes;
   4086 						IPACMDBG_H("Got matched dst-pipe (%d) from %d tx props\n", data->ul_src_pipe_stats_list[pipe_len].pipe_index, cnt);
   4087 						IPACMDBG_H("UL_packets:(%lu) UL_bytes:(%lu) \n", num_ul_packets, num_ul_bytes);
   4088 						break;
   4089 					}
   4090 				}
   4091 			}
   4092 		}
   4093 	}
   4094 	close(fd);
   4095 
   4096 	if (ul_pipe_found || dl_pipe_found)
   4097 	{
   4098 		IPACMDBG_H("Update IPA_TETHERING_STATS_UPDATE_EVENT, TX(P%lu/B%lu) RX(P%lu/B%lu) DEV(%s) to LTE(%s) \n",
   4099 					num_ul_packets,
   4100 						num_ul_bytes,
   4101 							num_dl_packets,
   4102 								num_dl_bytes,
   4103 									dev_name,
   4104 										IPACM_Wan::wan_up_dev_name);
   4105 		fp = fopen(IPA_PIPE_STATS_FILE_NAME, "w");
   4106 		if ( fp == NULL )
   4107 		{
   4108 			IPACMERR("Failed to write pipe stats to %s, error is %d - %s\n",
   4109 					IPA_PIPE_STATS_FILE_NAME, errno, strerror(errno));
   4110 			return IPACM_FAILURE;
   4111 		}
   4112 
   4113 		fprintf(fp, PIPE_STATS,
   4114 				dev_name,
   4115 					IPACM_Wan::wan_up_dev_name,
   4116 						num_ul_bytes,
   4117 						num_ul_packets,
   4118 							    num_dl_bytes,
   4119 							num_dl_packets);
   4120 		fclose(fp);
   4121 	}
   4122 	return IPACM_SUCCESS;
   4123 }
   4124 
   4125 /*handle tether client */
   4126 int IPACM_Lan::handle_tethering_client(bool reset, ipacm_client_enum ipa_client)
   4127 {
   4128 	int fd, ret = IPACM_SUCCESS;
   4129 	uint32_t cnt;
   4130 	int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR);
   4131 	wan_ioctl_set_tether_client_pipe tether_client;
   4132 
   4133 	if(fd_wwan_ioctl < 0)
   4134 	{
   4135 		IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME);
   4136 		return IPACM_FAILURE;
   4137 	}
   4138 
   4139 	fd = open(IPA_DEVICE_NAME, O_RDWR);
   4140 	if (fd < 0)
   4141 	{
   4142 		IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME);
   4143 		close(fd_wwan_ioctl);
   4144 		return IPACM_FAILURE;
   4145 	}
   4146 
   4147 	memset(&tether_client, 0, sizeof(tether_client));
   4148 	tether_client.reset_client = reset;
   4149 	tether_client.ipa_client = ipa_client;
   4150 
   4151 	if(tx_prop != NULL)
   4152 	{
   4153 		tether_client.dl_dst_pipe_len = tx_prop->num_tx_props;
   4154 		for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
   4155 		{
   4156 			IPACMDBG_H("Tx(%d), dst_pipe: %d, ipa_pipe: %d\n",
   4157 					cnt, tx_prop->tx[cnt].dst_pipe,
   4158 						ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe));
   4159 			tether_client.dl_dst_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, tx_prop->tx[cnt].dst_pipe);
   4160 		}
   4161 	}
   4162 
   4163 	if(rx_prop != NULL)
   4164 	{
   4165 		tether_client.ul_src_pipe_len = rx_prop->num_rx_props;
   4166 		for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
   4167 		{
   4168 			IPACMDBG_H("Rx(%d), src_pipe: %d, ipa_pipe: %d\n",
   4169 					cnt, rx_prop->rx[cnt].src_pipe,
   4170 						ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe));
   4171 			tether_client.ul_src_pipe_list[cnt] = ioctl(fd, IPA_IOC_QUERY_EP_MAPPING, rx_prop->rx[cnt].src_pipe);
   4172 		}
   4173 	}
   4174 
   4175 	ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, &tether_client);
   4176 	if (ret != 0)
   4177 	{
   4178 		IPACMERR("Failed set tether-client-pipe %p with ret %d\n ", &tether_client, ret);
   4179 	}
   4180 	IPACMDBG("Set tether-client-pipe %p\n", &tether_client);
   4181 	close(fd);
   4182 	close(fd_wwan_ioctl);
   4183 	return ret;
   4184 }
   4185 
   4186 /* mac address has to be provided for client related events */
   4187 void IPACM_Lan::eth_bridge_post_event(ipa_cm_event_id evt, ipa_ip_type iptype, uint8_t *mac)
   4188 {
   4189 	ipacm_cmd_q_data eth_bridge_evt;
   4190 	ipacm_event_eth_bridge *evt_data;
   4191 
   4192 	evt_data = (ipacm_event_eth_bridge*)malloc(sizeof(ipacm_event_eth_bridge));
   4193 	if(evt_data == NULL)
   4194 	{
   4195 		IPACMERR("Failed to allocate memory.\n");
   4196 		return;
   4197 	}
   4198 	memset(evt_data, 0, sizeof(ipacm_event_eth_bridge));
   4199 
   4200 	evt_data->p_iface = this;
   4201 	evt_data->iptype = iptype;
   4202 	if(mac)
   4203 	{
   4204 		IPACMDBG_H("Client mac: 0x%02x%02x%02x%02x%02x%02x \n",
   4205 			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
   4206 		memcpy(evt_data->mac_addr, mac, sizeof(evt_data->mac_addr));
   4207 	}
   4208 
   4209 	memset(&eth_bridge_evt, 0, sizeof(ipacm_cmd_q_data));
   4210 	eth_bridge_evt.evt_data = (void*)evt_data;
   4211 	eth_bridge_evt.event = evt;
   4212 
   4213 	IPACMDBG_H("Posting event %s\n",
   4214 		IPACM_Iface::ipacmcfg->getEventName(evt));
   4215 	IPACM_EvtDispatcher::PostEvt(&eth_bridge_evt);
   4216 }
   4217 
   4218 /* add header processing context and return handle to lan2lan controller */
   4219 int IPACM_Lan::eth_bridge_add_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_hdr_type, uint32_t *hdl)
   4220 {
   4221 	int len, res = IPACM_SUCCESS;
   4222 	uint32_t hdr_template;
   4223 	ipa_ioc_add_hdr_proc_ctx* pHeaderProcTable = NULL;
   4224 
   4225 	if(tx_prop == NULL)
   4226 	{
   4227 		IPACMERR("No tx prop.\n");
   4228 		return IPACM_FAILURE;
   4229 	}
   4230 
   4231 	len = sizeof(struct ipa_ioc_add_hdr_proc_ctx) + sizeof(struct ipa_hdr_proc_ctx_add);
   4232 	pHeaderProcTable = (ipa_ioc_add_hdr_proc_ctx*)malloc(len);
   4233 	if(pHeaderProcTable == NULL)
   4234 	{
   4235 		IPACMERR("Cannot allocate header processing context table.\n");
   4236 		return IPACM_FAILURE;
   4237 	}
   4238 
   4239 	memset(pHeaderProcTable, 0, len);
   4240 	pHeaderProcTable->commit = 1;
   4241 	pHeaderProcTable->num_proc_ctxs = 1;
   4242 	pHeaderProcTable->proc_ctx[0].type = eth_bridge_get_hdr_proc_type(peer_l2_hdr_type, tx_prop->tx[0].hdr_l2_type);
   4243 	eth_bridge_get_hdr_template_hdl(&hdr_template);
   4244 	pHeaderProcTable->proc_ctx[0].hdr_hdl = hdr_template;
   4245 	if (m_header.AddHeaderProcCtx(pHeaderProcTable) == false)
   4246 	{
   4247 		IPACMERR("Adding hdr proc ctx failed with status: %d\n", pHeaderProcTable->proc_ctx[0].status);
   4248 		res = IPACM_FAILURE;
   4249 		goto end;
   4250 	}
   4251 
   4252 	*hdl = pHeaderProcTable->proc_ctx[0].proc_ctx_hdl;
   4253 
   4254 end:
   4255 	free(pHeaderProcTable);
   4256 	return res;
   4257 }
   4258 
   4259 /* add routing rule and return handle to lan2lan controller */
   4260 int IPACM_Lan::eth_bridge_add_rt_rule(uint8_t *mac, char *rt_tbl_name, uint32_t hdr_proc_ctx_hdl,
   4261 		ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int *rt_rule_count)
   4262 {
   4263 	int len, res = IPACM_SUCCESS;
   4264 	uint32_t i, position, num_rt_rule;
   4265 	struct ipa_ioc_add_rt_rule* rt_rule_table = NULL;
   4266 	struct ipa_rt_rule_add rt_rule;
   4267 
   4268 	IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x.\n",
   4269 			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
   4270 
   4271 	num_rt_rule = each_client_rt_rule_count[iptype];
   4272 
   4273 	len = sizeof(ipa_ioc_add_rt_rule) + num_rt_rule * sizeof(ipa_rt_rule_add);
   4274 	rt_rule_table = (ipa_ioc_add_rt_rule*)malloc(len);
   4275 	if (rt_rule_table == NULL)
   4276 	{
   4277 		IPACMERR("Failed to allocate memory.\n");
   4278 		return IPACM_FAILURE;
   4279 	}
   4280 	memset(rt_rule_table, 0, len);
   4281 
   4282 	rt_rule_table->commit = 1;
   4283 	rt_rule_table->ip = iptype;
   4284 	rt_rule_table->num_rules = num_rt_rule;
   4285 	strlcpy(rt_rule_table->rt_tbl_name, rt_tbl_name, sizeof(rt_rule_table->rt_tbl_name));
   4286 	rt_rule_table->rt_tbl_name[IPA_RESOURCE_NAME_MAX-1] = 0;
   4287 
   4288 	memset(&rt_rule, 0, sizeof(ipa_rt_rule_add));
   4289 	rt_rule.at_rear = false;
   4290 	rt_rule.status = -1;
   4291 	rt_rule.rt_rule_hdl = -1;
   4292 #ifdef FEATURE_IPA_V3
   4293 	rt_rule.rule.hashable = true;
   4294 #endif
   4295 	rt_rule.rule.hdr_hdl = 0;
   4296 	rt_rule.rule.hdr_proc_ctx_hdl = hdr_proc_ctx_hdl;
   4297 
   4298 	position = 0;
   4299 	for(i=0; i<iface_query->num_tx_props; i++)
   4300 	{
   4301 		if(tx_prop->tx[i].ip == iptype)
   4302 		{
   4303 			if(position >= num_rt_rule || position >= MAX_NUM_PROP)
   4304 			{
   4305 				IPACMERR("Number of routing rules already exceeds limit.\n");
   4306 				res = IPACM_FAILURE;
   4307 				goto end;
   4308 			}
   4309 
   4310 			if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->isMCC_Mode)
   4311 			{
   4312 				IPACMDBG_H("In WLAN MCC mode, use alt dst pipe: %d\n",
   4313 						tx_prop->tx[i].alt_dst_pipe);
   4314 				rt_rule.rule.dst = tx_prop->tx[i].alt_dst_pipe;
   4315 			}
   4316 			else
   4317 			{
   4318 				IPACMDBG_H("It is not WLAN MCC mode, use dst pipe: %d\n",
   4319 						tx_prop->tx[i].dst_pipe);
   4320 				rt_rule.rule.dst = tx_prop->tx[i].dst_pipe;
   4321 			}
   4322 
   4323 			memcpy(&rt_rule.rule.attrib, &tx_prop->tx[i].attrib, sizeof(rt_rule.rule.attrib));
   4324 			if(peer_l2_hdr_type == IPA_HDR_L2_ETHERNET_II)
   4325 				rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
   4326 			else
   4327 				rt_rule.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
   4328 			memcpy(rt_rule.rule.attrib.dst_mac_addr, mac, sizeof(rt_rule.rule.attrib.dst_mac_addr));
   4329 			memset(rt_rule.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(rt_rule.rule.attrib.dst_mac_addr_mask));
   4330 
   4331 			memcpy(&(rt_rule_table->rules[position]), &rt_rule, sizeof(rt_rule_table->rules[position]));
   4332 			position++;
   4333 		}
   4334 	}
   4335 	if(false == m_routing.AddRoutingRule(rt_rule_table))
   4336 	{
   4337 		IPACMERR("Routing rule addition failed!\n");
   4338 		res = IPACM_FAILURE;
   4339 		goto end;
   4340 	}
   4341 	else
   4342 	{
   4343 		*rt_rule_count = position;
   4344 		for(i=0; i<position; i++)
   4345 			rt_rule_hdl[i] = rt_rule_table->rules[i].rt_rule_hdl;
   4346 	}
   4347 
   4348 end:
   4349 	free(rt_rule_table);
   4350 	return res;
   4351 }
   4352 
   4353 /* modify routing rule*/
   4354 int IPACM_Lan::eth_bridge_modify_rt_rule(uint8_t *mac, uint32_t hdr_proc_ctx_hdl,
   4355 		ipa_hdr_l2_type peer_l2_hdr_type, ipa_ip_type iptype, uint32_t *rt_rule_hdl, int rt_rule_count)
   4356 {
   4357 	struct ipa_ioc_mdfy_rt_rule *rt_rule = NULL;
   4358 	struct ipa_rt_rule_mdfy *rt_rule_entry;
   4359 	int len, res = IPACM_SUCCESS;
   4360 	uint32_t index;
   4361 
   4362 	if(tx_prop == NULL)
   4363 	{
   4364 		IPACMDBG_H("No tx properties \n");
   4365 		return IPACM_FAILURE;
   4366 	}
   4367 
   4368 	if(ipa_if_cate != WLAN_IF)
   4369 	{
   4370 		IPACMDBG_H("This is not WLAN IF, no need to modify rt rule.\n");
   4371 		return IPACM_SUCCESS;
   4372 	}
   4373 
   4374 	IPACMDBG_H("Receive WLAN client MAC 0x%02x%02x%02x%02x%02x%02x.\n",
   4375 			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
   4376 
   4377 	len = sizeof(struct ipa_ioc_mdfy_rt_rule) + rt_rule_count * sizeof(struct ipa_rt_rule_mdfy);
   4378 	rt_rule = (struct ipa_ioc_mdfy_rt_rule *)malloc(len);
   4379 	if(rt_rule == NULL)
   4380 	{
   4381 		IPACMERR("Unable to allocate memory for modify rt rule\n");
   4382 		return IPACM_FAILURE;
   4383 	}
   4384 	memset(rt_rule, 0, len);
   4385 
   4386 	rt_rule->commit = 1;
   4387 	rt_rule->num_rules = 0;
   4388 	rt_rule->ip = iptype;
   4389 
   4390 	for (index = 0; index < tx_prop->num_tx_props; index++)
   4391 	{
   4392 		if (tx_prop->tx[index].ip == iptype)
   4393 		{
   4394 			if (rt_rule->num_rules >= rt_rule_count ||
   4395 				rt_rule->num_rules >= MAX_NUM_PROP)
   4396 			{
   4397 				IPACMERR("Number of routing rules exceeds limit.\n");
   4398 				res = IPACM_FAILURE;
   4399 				goto end;
   4400 			}
   4401 
   4402 			rt_rule_entry = &rt_rule->rules[rt_rule->num_rules];
   4403 
   4404 			if (IPACM_Iface::ipacmcfg->isMCC_Mode)
   4405 			{
   4406 				IPACMDBG_H("In WLAN MCC mode, use alt dst pipe: %d\n",
   4407 						tx_prop->tx[index].alt_dst_pipe);
   4408 				rt_rule_entry->rule.dst = tx_prop->tx[index].alt_dst_pipe;
   4409 			}
   4410 			else
   4411 			{
   4412 				IPACMDBG_H("In WLAN SCC mode, use dst pipe: %d\n",
   4413 						tx_prop->tx[index].dst_pipe);
   4414 				rt_rule_entry->rule.dst = tx_prop->tx[index].dst_pipe;
   4415 			}
   4416 
   4417 			rt_rule_entry->rule.hdr_hdl = 0;
   4418 			rt_rule_entry->rule.hdr_proc_ctx_hdl = hdr_proc_ctx_hdl;
   4419 #ifdef FEATURE_IPA_V3
   4420 			rt_rule_entry->rule.hashable = true;
   4421 #endif
   4422 			memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[index].attrib,
   4423 					sizeof(rt_rule_entry->rule.attrib));
   4424 			if(peer_l2_hdr_type == IPA_HDR_L2_ETHERNET_II)
   4425 				rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
   4426 			else
   4427 				rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
   4428 			memcpy(rt_rule_entry->rule.attrib.dst_mac_addr, mac,
   4429 					sizeof(rt_rule_entry->rule.attrib.dst_mac_addr));
   4430 			memset(rt_rule_entry->rule.attrib.dst_mac_addr_mask, 0xFF,
   4431 					sizeof(rt_rule_entry->rule.attrib.dst_mac_addr_mask));
   4432 
   4433 			rt_rule_entry->rt_rule_hdl = rt_rule_hdl[rt_rule->num_rules];
   4434 			rt_rule->num_rules++;
   4435 		}
   4436 	}
   4437 
   4438 	if(m_routing.ModifyRoutingRule(rt_rule) == false)
   4439 	{
   4440 		IPACMERR("Failed to modify routing rules.\n");
   4441 		res = IPACM_FAILURE;
   4442 		goto end;
   4443 	}
   4444 	if(m_routing.Commit(iptype) == false)
   4445 	{
   4446 		IPACMERR("Failed to commit routing rules.\n");
   4447 		res = IPACM_FAILURE;
   4448 		goto end;
   4449 	}
   4450 	IPACMDBG("Modified routing rules successfully.\n");
   4451 
   4452 end:
   4453 	free(rt_rule);
   4454 	return res;
   4455 }
   4456 
   4457 int IPACM_Lan::eth_bridge_add_flt_rule(uint8_t *mac, uint32_t rt_tbl_hdl, ipa_ip_type iptype, uint32_t *flt_rule_hdl)
   4458 {
   4459 	int len, res = IPACM_SUCCESS;
   4460 	struct ipa_flt_rule_add flt_rule_entry;
   4461 	struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL;
   4462 
   4463 #ifdef FEATURE_IPA_V3
   4464 	if (rx_prop == NULL || tx_prop == NULL)
   4465 	{
   4466 		IPACMDBG_H("No rx or tx properties registered for iface %s\n", dev_name);
   4467 		return IPACM_FAILURE;
   4468 	}
   4469 
   4470 	IPACMDBG_H("Received client MAC 0x%02x%02x%02x%02x%02x%02x.\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
   4471 
   4472 	len = sizeof(struct ipa_ioc_add_flt_rule_after) + sizeof(struct ipa_flt_rule_add);
   4473 	pFilteringTable = (struct ipa_ioc_add_flt_rule_after*)malloc(len);
   4474 	if (!pFilteringTable)
   4475 	{
   4476 		IPACMERR("Failed to allocate ipa_ioc_add_flt_rule_after memory...\n");
   4477 		return IPACM_FAILURE;
   4478 	}
   4479 	memset(pFilteringTable, 0, len);
   4480 
   4481 	/* add mac based rule*/
   4482 	pFilteringTable->commit = 1;
   4483 	pFilteringTable->ep = rx_prop->rx[0].src_pipe;
   4484 	pFilteringTable->ip = iptype;
   4485 	pFilteringTable->num_rules = 1;
   4486 	pFilteringTable->add_after_hdl = eth_bridge_flt_rule_offset[iptype];
   4487 
   4488 	memset(&flt_rule_entry, 0, sizeof(flt_rule_entry));
   4489 	flt_rule_entry.at_rear = 1;
   4490 
   4491 	flt_rule_entry.rule.retain_hdr = 0;
   4492 	flt_rule_entry.rule.to_uc = 0;
   4493 	flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
   4494 	flt_rule_entry.rule.eq_attrib_type = 0;
   4495 	flt_rule_entry.rule.rt_tbl_hdl = rt_tbl_hdl;
   4496 	flt_rule_entry.rule.hashable = true;
   4497 
   4498 	memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib));
   4499 	if(tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_ETHERNET_II)
   4500 	{
   4501 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_ETHER_II;
   4502 	}
   4503 	else
   4504 	{
   4505 		flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_MAC_DST_ADDR_802_3;
   4506 	}
   4507 
   4508 	memcpy(flt_rule_entry.rule.attrib.dst_mac_addr, mac, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr));
   4509 	memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask));
   4510 
   4511 	memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry));
   4512 	if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable))
   4513 	{
   4514 		IPACMERR("Failed to add client filtering rules.\n");
   4515 		res = IPACM_FAILURE;
   4516 		goto end;
   4517 	}
   4518 	*flt_rule_hdl = pFilteringTable->rules[0].flt_rule_hdl;
   4519 
   4520 end:
   4521 	free(pFilteringTable);
   4522 #endif
   4523 	return res;
   4524 }
   4525 
   4526 int IPACM_Lan::eth_bridge_del_flt_rule(uint32_t flt_rule_hdl, ipa_ip_type iptype)
   4527 {
   4528 	if(m_filtering.DeleteFilteringHdls(&flt_rule_hdl, iptype, 1) == false)
   4529 	{
   4530 		IPACMERR("Failed to delete the client specific flt rule.\n");
   4531 		return IPACM_FAILURE;
   4532 	}
   4533 	return IPACM_SUCCESS;
   4534 }
   4535 
   4536 int IPACM_Lan::eth_bridge_del_rt_rule(uint32_t rt_rule_hdl, ipa_ip_type iptype)
   4537 {
   4538 	if(m_routing.DeleteRoutingHdl(rt_rule_hdl, iptype) == false)
   4539 	{
   4540 		IPACMERR("Failed to delete routing rule.\n");
   4541 		return IPACM_FAILURE;
   4542 	}
   4543 	return IPACM_SUCCESS;
   4544 }
   4545 
   4546 /* delete header processing context */
   4547 int IPACM_Lan::eth_bridge_del_hdr_proc_ctx(uint32_t hdr_proc_ctx_hdl)
   4548 {
   4549 	if(m_header.DeleteHeaderProcCtx(hdr_proc_ctx_hdl) == false)
   4550 	{
   4551 		IPACMERR("Failed to delete hdr proc ctx.\n");
   4552 		return IPACM_FAILURE;
   4553 	}
   4554 	return IPACM_SUCCESS;
   4555 }
   4556