1/*
2Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7* Redistributions of source code must retain the above copyright
8notice, this list of conditions and the following disclaimer.
9
10* Redistributions in binary form must reproduce the above
11copyright notice, this list of conditions and the following
12disclaimer in the documentation and/or other materials provided
13with the distribution.
14
15* Neither the name of The Linux Foundation nor the names of its
16contributors may be used to endorse or promote products derived
17from this software without specific prior written permission.
18
19THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29IF 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
58bool IPACM_Lan::odu_up = false;
59
60IPACM_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
206IPACM_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 */
215void 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
966int 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*/
1048int 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*/
1120int 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
1308fail:
1309	free(rt_rule);
1310	return res;
1311}
1312
1313/* configure private subnet filter rules*/
1314int 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*/
1405int 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
1583int 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) */
1632int 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	}
1901fail:
1902	free(pHeaderDescriptor);
1903	return res;
1904}
1905
1906/*handle eth client */
1907int 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*/
2019int 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) */
2222int 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	}
2398fail:
2399	free(pHeaderDescriptor);
2400	return res;
2401}
2402
2403
2404/* handle odu default route rule configuration */
2405int 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 */
2509int 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*/
2551int 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*/
2676int 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)*/
2869fail:
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 */
2959int 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
3241fail:
3242	free(pFilteringTable);
3243	close(fd);
3244	return ret;
3245}
3246
3247int 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
3327int 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
3421fail:
3422	free(pFilteringTable);
3423	return res;
3424}
3425
3426void 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 */
3449int 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
3481int 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
3539int 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
3597int 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	}
3682fail:
3683	free(pFilteringTable);
3684	return res;
3685}
3686
3687int 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	}
3761fail:
3762	if(pFilteringTable != NULL)
3763	{
3764		free(pFilteringTable);
3765	}
3766	return res;
3767}
3768
3769int 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
3840void 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
3851int 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
3884ipa_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
3913int 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
3935int 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 */
4016int 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 */
4126int 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 */
4187void 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 */
4219int 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
4254end:
4255	free(pHeaderProcTable);
4256	return res;
4257}
4258
4259/* add routing rule and return handle to lan2lan controller */
4260int 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
4348end:
4349	free(rt_rule_table);
4350	return res;
4351}
4352
4353/* modify routing rule*/
4354int 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
4452end:
4453	free(rt_rule);
4454	return res;
4455}
4456
4457int 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
4520end:
4521	free(pFilteringTable);
4522#endif
4523	return res;
4524}
4525
4526int 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
4536int 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 */
4547int 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