Home | History | Annotate | Download | only in src
      1 /*
      2 Copyright (c) 2014, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7 		* Redistributions of source code must retain the above copyright
      8 			notice, this list of conditions and the following disclaimer.
      9 		* Redistributions in binary form must reproduce the above
     10 			copyright notice, this list of conditions and the following
     11 			disclaimer in the documentation and/or other materials provided
     12 			with the distribution.
     13 		* Neither the name of The Linux Foundation nor the names of its
     14 			contributors may be used to endorse or promote products derived
     15 			from this software without specific prior written permission.
     16 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 /*!
     30 	@file
     31 	IPACM_LanToLan.cpp
     32 
     33 	@brief
     34 	This file implements the functionality of offloading LAN to LAN traffic.
     35 
     36 	@Author
     37 	Shihuan Liu
     38 
     39 */
     40 
     41 #include <stdlib.h>
     42 #include "IPACM_LanToLan.h"
     43 #include "IPACM_Wlan.h"
     44 
     45 #define __stringify(x...) #x
     46 
     47 const char *ipa_l2_hdr_type[] = {
     48 	__stringify(NONE),
     49 	__stringify(ETH_II),
     50 	__stringify(802_3),
     51 	__stringify(L2_MAX)
     52 };
     53 
     54 IPACM_LanToLan_Iface::IPACM_LanToLan_Iface(IPACM_Lan *p_iface)
     55 {
     56 	int i;
     57 
     58 	m_p_iface = p_iface;
     59 	memset(m_is_ip_addr_assigned, 0, sizeof(m_is_ip_addr_assigned));
     60 	m_support_inter_iface_offload = true;
     61 	m_support_intra_iface_offload = false;
     62 	for(i = 0; i < IPA_HDR_L2_MAX; i++)
     63 	{
     64 		ref_cnt_peer_l2_hdr_type[i] = 0;
     65 		hdr_proc_ctx_for_inter_interface[i] = 0;
     66 	}
     67 	hdr_proc_ctx_for_intra_interface = 0;
     68 
     69 	if(p_iface->ipa_if_cate == WLAN_IF)
     70 	{
     71 		IPACMDBG_H("Interface %s is WLAN interface.\n", p_iface->dev_name);
     72 		m_support_intra_iface_offload = true;
     73 		if( ((IPACM_Wlan*)p_iface)->is_guest_ap() )
     74 		{
     75 			IPACMDBG_H("Interface %s is guest AP.\n", p_iface->dev_name);
     76 			m_support_inter_iface_offload = false;
     77 		}
     78 	}
     79 	return;
     80 }
     81 
     82 IPACM_LanToLan_Iface::~IPACM_LanToLan_Iface()
     83 {
     84 }
     85 
     86 IPACM_LanToLan::IPACM_LanToLan()
     87 {
     88 	IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_IFACE_UP, this);
     89 	IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_IFACE_DOWN, this);
     90 	IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_CLIENT_ADD, this);
     91 	IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_CLIENT_DEL, this);
     92 	IPACM_EvtDispatcher::registr(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, this);
     93 
     94 	return;
     95 }
     96 
     97 IPACM_LanToLan::~IPACM_LanToLan()
     98 {
     99 	IPACMDBG_DMESG("WARNING: UNEXPECTEDLY KILL LAN2LAN CONTROLLER!\n");
    100 	return;
    101 }
    102 
    103 void IPACM_LanToLan::event_callback(ipa_cm_event_id event, void* param)
    104 {
    105 	ipacm_event_eth_bridge *data = (ipacm_event_eth_bridge*)param;
    106 	IPACMDBG_H("Get %s event.\n", IPACM_Iface::ipacmcfg->getEventName(event));
    107 
    108 	switch(event)
    109 	{
    110 		case IPA_ETH_BRIDGE_IFACE_UP:
    111 		{
    112 			handle_iface_up(data);
    113 			break;
    114 		}
    115 
    116 		case IPA_ETH_BRIDGE_IFACE_DOWN:
    117 		{
    118 			handle_iface_down(data);
    119 			break;
    120 		}
    121 
    122 		case IPA_ETH_BRIDGE_CLIENT_ADD:
    123 		{
    124 			handle_client_add(data);
    125 			break;
    126 		}
    127 
    128 		case IPA_ETH_BRIDGE_CLIENT_DEL:
    129 		{
    130 			handle_client_del(data);
    131 			break;
    132 		}
    133 
    134 		case IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH:
    135 		{
    136 			handle_wlan_scc_mcc_switch(data);
    137 			break;
    138 		}
    139 		default:
    140 			break;
    141 	}
    142 
    143 	print_data_structure_info();
    144 	return;
    145 }
    146 
    147 void IPACM_LanToLan::handle_iface_up(ipacm_event_eth_bridge *data)
    148 {
    149 	list<IPACM_LanToLan_Iface>::iterator it;
    150 
    151 	IPACMDBG_H("Interface name: %s IP type: %d\n", data->p_iface->dev_name, data->iptype);
    152 	for(it = m_iface.begin(); it != m_iface.end(); it++)
    153 	{
    154 		if(it->get_iface_pointer() == data->p_iface)
    155 		{
    156 			IPACMDBG_H("Found the interface.\n");
    157 			if(it->get_m_is_ip_addr_assigned(data->iptype) == false)
    158 			{
    159 				IPACMDBG_H("IP type %d was not active before, activating it now.\n", data->iptype);
    160 				it->set_m_is_ip_addr_assigned(data->iptype, true);
    161 
    162 				/* install inter-interface rules */
    163 				if(it->get_m_support_inter_iface_offload())
    164 					it->add_all_inter_interface_client_flt_rule(data->iptype);
    165 
    166 				/* install intra-BSS rules */
    167 				if(it->get_m_support_intra_iface_offload())
    168 					it->add_all_intra_interface_client_flt_rule(data->iptype);
    169 			}
    170 			break;
    171 		}
    172 	}
    173 
    174 	if(it == m_iface.end())	//If the interface has not been created before
    175 	{
    176 		if(m_iface.size() == MAX_NUM_IFACE)
    177 		{
    178 			IPACMERR("The number of interfaces has reached maximum %d.\n", MAX_NUM_IFACE);
    179 			return;
    180 		}
    181 
    182 		if(!data->p_iface->tx_prop || !data->p_iface->rx_prop)
    183 		{
    184 			IPACMERR("The interface %s does not have tx_prop or rx_prop.\n", data->p_iface->dev_name);
    185 			return;
    186 		}
    187 
    188 		if(data->p_iface->tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_NONE || data->p_iface->tx_prop->tx[0].hdr_l2_type == IPA_HDR_L2_MAX)
    189 		{
    190 			IPACMERR("Invalid l2 header type %s!\n", ipa_l2_hdr_type[data->p_iface->tx_prop->tx[0].hdr_l2_type]);
    191 			return;
    192 		}
    193 
    194 		IPACMDBG_H("Does not find the interface, insert a new one.\n");
    195 		IPACM_LanToLan_Iface new_iface(data->p_iface);
    196 		new_iface.set_m_is_ip_addr_assigned(data->iptype, true);
    197 
    198 		m_iface.push_front(new_iface);
    199 		IPACMDBG_H("Now the total number of interfaces is %d.\n", m_iface.size());
    200 
    201 		IPACM_LanToLan_Iface &front_iface = m_iface.front();
    202 
    203 		/* install inter-interface rules */
    204 		if(front_iface.get_m_support_inter_iface_offload())
    205 		{
    206 			for(it = ++m_iface.begin(); it != m_iface.end(); it++)
    207 			{
    208 				/* add peer info only when both interfaces support inter-interface communication */
    209 				if(it->get_m_support_inter_iface_offload())
    210 				{
    211 					/* populate hdr_proc_ctx and routing table handle */
    212 					handle_new_iface_up(&front_iface, &(*it));
    213 
    214 					/* add client specific routing rule on existing interface */
    215 					it->add_client_rt_rule_for_new_iface();
    216 				}
    217 			}
    218 
    219 			/* add client specific filtering rule on new interface */
    220 			front_iface.add_all_inter_interface_client_flt_rule(data->iptype);
    221 		}
    222 
    223 		/* populate the intra-interface information */
    224 		if(front_iface.get_m_support_intra_iface_offload())
    225 		{
    226 			front_iface.handle_intra_interface_info();
    227 		}
    228 
    229 		/* handle cached client add event */
    230 		handle_cached_client_add_event(front_iface.get_iface_pointer());
    231 	}
    232 	return;
    233 }
    234 
    235 void IPACM_LanToLan::handle_iface_down(ipacm_event_eth_bridge *data)
    236 {
    237 	list<IPACM_LanToLan_Iface>::iterator it_target_iface;
    238 
    239 	IPACMDBG_H("Interface name: %s\n", data->p_iface->dev_name);
    240 
    241 	for(it_target_iface = m_iface.begin(); it_target_iface != m_iface.end(); it_target_iface++)
    242 	{
    243 		if(it_target_iface->get_iface_pointer() == data->p_iface)
    244 		{
    245 			IPACMDBG_H("Found the interface.\n");
    246 			break;
    247 		}
    248 	}
    249 
    250 	if(it_target_iface == m_iface.end())
    251 	{
    252 		IPACMDBG_H("The interface has not been found.\n");
    253 		/* clear cached client add event for the unfound interface*/
    254 		clear_cached_client_add_event(data->p_iface);
    255 		return;
    256 	}
    257 
    258 	it_target_iface->handle_down_event();
    259 	m_iface.erase(it_target_iface);
    260 
    261 	return;
    262 }
    263 
    264 void IPACM_LanToLan::handle_new_iface_up(IPACM_LanToLan_Iface *new_iface, IPACM_LanToLan_Iface *exist_iface)
    265 {
    266 	char rt_tbl_name_for_flt[IPA_IP_MAX][IPA_RESOURCE_NAME_MAX];
    267 	char rt_tbl_name_for_rt[IPA_IP_MAX][IPA_RESOURCE_NAME_MAX];
    268 
    269 	IPACMDBG_H("Populate peer info between: new_iface %s, existing iface %s\n", new_iface->get_iface_pointer()->dev_name,
    270 		exist_iface->get_iface_pointer()->dev_name);
    271 
    272 	/* populate the routing table information */
    273 	snprintf(rt_tbl_name_for_flt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX, "eth_v4_%s_to_%s",
    274 		ipa_l2_hdr_type[exist_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type],
    275 		ipa_l2_hdr_type[new_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type]);
    276 	IPACMDBG_H("IPv4 routing table for flt name: %s\n", rt_tbl_name_for_flt[IPA_IP_v4]);
    277 
    278 	snprintf(rt_tbl_name_for_flt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX, "eth_v6_%s_to_%s",
    279 		ipa_l2_hdr_type[exist_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type],
    280 		ipa_l2_hdr_type[new_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type]);
    281 	IPACMDBG_H("IPv6 routing table for flt name: %s\n", rt_tbl_name_for_flt[IPA_IP_v6]);
    282 
    283 	snprintf(rt_tbl_name_for_rt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX, "eth_v4_%s_to_%s",
    284 		ipa_l2_hdr_type[new_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type],
    285 		ipa_l2_hdr_type[exist_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type]);
    286 	IPACMDBG_H("IPv4 routing table for rt name: %s\n", rt_tbl_name_for_rt[IPA_IP_v4]);
    287 
    288 	snprintf(rt_tbl_name_for_rt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX, "eth_v6_%s_to_%s",
    289 		ipa_l2_hdr_type[new_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type],
    290 		ipa_l2_hdr_type[exist_iface->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type]);
    291 	IPACMDBG_H("IPv6 routing table for rt name: %s\n", rt_tbl_name_for_rt[IPA_IP_v6]);
    292 
    293 	/* add new peer info in both new iface and existing iface */
    294 	exist_iface->handle_new_iface_up(rt_tbl_name_for_flt, rt_tbl_name_for_rt, new_iface);
    295 
    296 	new_iface->handle_new_iface_up(rt_tbl_name_for_rt, rt_tbl_name_for_flt, exist_iface);
    297 
    298 	return;
    299 }
    300 
    301 void IPACM_LanToLan::handle_client_add(ipacm_event_eth_bridge *data)
    302 {
    303 	list<IPACM_LanToLan_Iface>::iterator it_iface;
    304 
    305 	IPACMDBG_H("Incoming client MAC: 0x%02x%02x%02x%02x%02x%02x, interface: %s\n", data->mac_addr[0], data->mac_addr[1],
    306 		data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], data->p_iface->dev_name);
    307 
    308 	for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++)
    309 	{
    310 		if(it_iface->get_iface_pointer() == data->p_iface)	//find the interface
    311 		{
    312 			IPACMDBG_H("Found the interface.\n");
    313 			it_iface->handle_client_add(data->mac_addr);
    314 			break;
    315 		}
    316 	}
    317 
    318 	/* if the iface was not found, cache the client add event */
    319 	if(it_iface == m_iface.end())
    320 	{
    321 		IPACMDBG_H("The interface is not found.\n");
    322 		if(m_cached_client_add_event.size() < MAX_NUM_CACHED_CLIENT_ADD_EVENT)
    323 		{
    324 			IPACMDBG_H("Cached the client information.\n");
    325 			m_cached_client_add_event.push_front(*data);
    326 		}
    327 		else
    328 		{
    329 			IPACMDBG_H("Cached client add event has reached maximum number.\n");
    330 		}
    331 	}
    332 	return;
    333 }
    334 
    335 void IPACM_LanToLan::handle_client_del(ipacm_event_eth_bridge *data)
    336 {
    337 	list<IPACM_LanToLan_Iface>::iterator it_iface;
    338 
    339 	IPACMDBG_H("Incoming client MAC: 0x%02x%02x%02x%02x%02x%02x, interface: %s\n", data->mac_addr[0], data->mac_addr[1],
    340 		data->mac_addr[2], data->mac_addr[3], data->mac_addr[4], data->mac_addr[5], data->p_iface->dev_name);
    341 
    342 	for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++)
    343 	{
    344 		if(it_iface->get_iface_pointer() == data->p_iface)	//found the interface
    345 		{
    346 			IPACMDBG_H("Found the interface.\n");
    347 			it_iface->handle_client_del(data->mac_addr);
    348 			break;
    349 		}
    350 	}
    351 
    352 	if(it_iface == m_iface.end())
    353 	{
    354 		IPACMDBG_H("The interface is not found.\n");
    355 	}
    356 
    357 	return;
    358 }
    359 
    360 void IPACM_LanToLan::handle_wlan_scc_mcc_switch(ipacm_event_eth_bridge *data)
    361 {
    362 	list<IPACM_LanToLan_Iface>::iterator it_iface;
    363 
    364 	IPACMDBG_H("Incoming interface: %s\n", data->p_iface->dev_name);
    365 	for(it_iface = m_iface.begin(); it_iface != m_iface.end(); it_iface++)
    366 	{
    367 		if(it_iface->get_iface_pointer() == data->p_iface)
    368 		{
    369 			it_iface->handle_wlan_scc_mcc_switch();
    370 			break;
    371 		}
    372 	}
    373 	return;
    374 }
    375 
    376 void IPACM_LanToLan::handle_cached_client_add_event(IPACM_Lan *p_iface)
    377 {
    378 	list<ipacm_event_eth_bridge>::iterator it;
    379 
    380 	it = m_cached_client_add_event.begin();
    381 	while(it != m_cached_client_add_event.end())
    382 	{
    383 		if(it->p_iface == p_iface)
    384 		{
    385 			IPACMDBG_H("Found client with MAC: 0x%02x%02x%02x%02x%02x%02x\n", it->mac_addr[0], it->mac_addr[1],
    386 				it->mac_addr[2], it->mac_addr[3], it->mac_addr[4], it->mac_addr[5]);
    387 			handle_client_add(&(*it));
    388 			it = m_cached_client_add_event.erase(it);
    389 		}
    390 		else
    391 		{
    392 			it++;
    393 		}
    394 	}
    395 	return;
    396 }
    397 
    398 void IPACM_LanToLan::clear_cached_client_add_event(IPACM_Lan *p_iface)
    399 {
    400 	list<ipacm_event_eth_bridge>::iterator it;
    401 
    402 	it = m_cached_client_add_event.begin();
    403 	while(it != m_cached_client_add_event.end())
    404 	{
    405 		if(it->p_iface == p_iface)
    406 		{
    407 			IPACMDBG_H("Found client with MAC: 0x%02x%02x%02x%02x%02x%02x\n", it->mac_addr[0], it->mac_addr[1],
    408 				it->mac_addr[2], it->mac_addr[3], it->mac_addr[4], it->mac_addr[5]);
    409 			it = m_cached_client_add_event.erase(it);
    410 		}
    411 		else
    412 		{
    413 			it++;
    414 		}
    415 	}
    416 	return;
    417 }
    418 
    419 void IPACM_LanToLan::print_data_structure_info()
    420 {
    421 	list<IPACM_LanToLan_Iface>::iterator it;
    422 	list<ipacm_event_eth_bridge>::iterator it_event;
    423 	int i;
    424 
    425 	IPACMDBG_H("There are %d interfaces in total.\n", m_iface.size());
    426 
    427 	for(it = m_iface.begin(); it != m_iface.end(); it++)
    428 	{
    429 		it->print_data_structure_info();
    430 	}
    431 
    432 	IPACMDBG_H("There are %d cached client add events in total.\n", m_cached_client_add_event.size());
    433 
    434 	i = 1;
    435 	for(it_event = m_cached_client_add_event.begin(); it_event != m_cached_client_add_event.end(); it_event++)
    436 	{
    437 		IPACMDBG_H("Client %d MAC: 0x%02x%02x%02x%02x%02x%02x, interface: %s\n", i, it_event->mac_addr[0], it_event->mac_addr[1], it_event->mac_addr[2],
    438 			it_event->mac_addr[3], it_event->mac_addr[4], it_event->mac_addr[5], it_event->p_iface->dev_name);
    439 		i++;
    440 	}
    441 
    442 	return;
    443 }
    444 
    445 void IPACM_LanToLan_Iface::add_client_rt_rule_for_new_iface()
    446 {
    447 	list<client_info>::iterator it;
    448 	ipa_hdr_l2_type peer_l2_type;
    449 	peer_iface_info &peer = m_peer_iface_info.front();
    450 
    451 	peer_l2_type = peer.peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type;
    452 	if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 1)
    453 	{
    454 		for(it = m_client_info.begin(); it != m_client_info.end(); it++)
    455 		{
    456 			add_client_rt_rule(&peer, &(*it));
    457 		}
    458 	}
    459 
    460 	return;
    461 }
    462 
    463 void IPACM_LanToLan_Iface::add_client_rt_rule(peer_iface_info *peer_info, client_info *client)
    464 {
    465 	int i, num_rt_rule;
    466 	uint32_t rt_rule_hdl[MAX_NUM_PROP];
    467 	ipa_hdr_l2_type peer_l2_hdr_type;
    468 
    469 	peer_l2_hdr_type = peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type;
    470 
    471 	/* if the peer info is not for intra interface communication */
    472 	if(peer_info->peer != this)
    473 	{
    474 		IPACMDBG_H("This is for inter interface communication.\n");
    475 
    476 		m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v4], hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type],
    477 			peer_l2_hdr_type, IPA_IP_v4, rt_rule_hdl, &num_rt_rule);
    478 
    479 		client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4] = num_rt_rule;
    480 		IPACMDBG_H("Number of IPv4 routing rule is %d.\n", num_rt_rule);
    481 		for(i=0; i<num_rt_rule; i++)
    482 		{
    483 			IPACMDBG_H("Routing rule %d handle %d\n", i, rt_rule_hdl[i]);
    484 			client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i] = rt_rule_hdl[i];
    485 		}
    486 
    487 		m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v6], hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type],
    488 			peer_l2_hdr_type, IPA_IP_v6, rt_rule_hdl, &num_rt_rule);
    489 
    490 		client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6] = num_rt_rule;
    491 		IPACMDBG_H("Number of IPv6 routing rule is %d.\n", num_rt_rule);
    492 		for(i=0; i<num_rt_rule; i++)
    493 		{
    494 			IPACMDBG_H("Routing rule %d handle %d\n", i, rt_rule_hdl[i]);
    495 			client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i] = rt_rule_hdl[i];
    496 		}
    497 	}
    498 	else
    499 	{
    500 		IPACMDBG_H("This is for intra interface communication.\n");
    501 		m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v4], hdr_proc_ctx_for_intra_interface,
    502 			peer_l2_hdr_type, IPA_IP_v4, rt_rule_hdl, &num_rt_rule);
    503 
    504 		client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4] = num_rt_rule;
    505 		IPACMDBG_H("Number of IPv4 routing rule is %d.\n", num_rt_rule);
    506 		for(i=0; i<num_rt_rule; i++)
    507 		{
    508 			IPACMDBG_H("Routing rule %d handle %d\n", i, rt_rule_hdl[i]);
    509 			client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i] = rt_rule_hdl[i];
    510 		}
    511 
    512 		m_p_iface->eth_bridge_add_rt_rule(client->mac_addr, peer_info->rt_tbl_name_for_rt[IPA_IP_v6], hdr_proc_ctx_for_intra_interface,
    513 			peer_l2_hdr_type, IPA_IP_v6, rt_rule_hdl, &num_rt_rule);
    514 
    515 		client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6] = num_rt_rule;
    516 		IPACMDBG_H("Number of IPv6 routing rule is %d.\n", num_rt_rule);
    517 		for(i=0; i<num_rt_rule; i++)
    518 		{
    519 			IPACMDBG_H("Routing rule %d handle %d\n", i, rt_rule_hdl[i]);
    520 			client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i] = rt_rule_hdl[i];
    521 		}
    522 	}
    523 
    524 	return;
    525 }
    526 
    527 void IPACM_LanToLan_Iface::add_all_inter_interface_client_flt_rule(ipa_ip_type iptype)
    528 {
    529 	list<peer_iface_info>::iterator it_iface;
    530 	list<client_info>::iterator it_client;
    531 
    532 	for(it_iface = m_peer_iface_info.begin(); it_iface != m_peer_iface_info.end(); it_iface++)
    533 	{
    534 		IPACMDBG_H("Add flt rules for clients of interface %s.\n", it_iface->peer->get_iface_pointer()->dev_name);
    535 		for(it_client = it_iface->peer->m_client_info.begin(); it_client != it_iface->peer->m_client_info.end(); it_client++)
    536 		{
    537 			add_client_flt_rule(&(*it_iface), &(*it_client), iptype);
    538 		}
    539 	}
    540 	return;
    541 }
    542 
    543 void IPACM_LanToLan_Iface::add_all_intra_interface_client_flt_rule(ipa_ip_type iptype)
    544 {
    545 	list<client_info>::iterator it_client;
    546 
    547 	IPACMDBG_H("Add flt rules for own clients.\n");
    548 	for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
    549 	{
    550 		add_client_flt_rule(&m_intra_interface_info, &(*it_client), iptype);
    551 	}
    552 
    553 	return;
    554 }
    555 
    556 void IPACM_LanToLan_Iface::add_one_client_flt_rule(IPACM_LanToLan_Iface *peer_iface, client_info *client)
    557 {
    558 	list<peer_iface_info>::iterator it;
    559 
    560 	for(it = m_peer_iface_info.begin(); it != m_peer_iface_info.end(); it++)
    561 	{
    562 		if(it->peer == peer_iface)
    563 		{
    564 			IPACMDBG_H("Found the peer iface info.\n");
    565 			if(m_is_ip_addr_assigned[IPA_IP_v4])
    566 			{
    567 				add_client_flt_rule(&(*it), client, IPA_IP_v4);
    568 			}
    569 			if(m_is_ip_addr_assigned[IPA_IP_v6])
    570 			{
    571 				add_client_flt_rule(&(*it), client, IPA_IP_v6);
    572 			}
    573 
    574 			break;
    575 		}
    576 	}
    577 	return;
    578 }
    579 
    580 void IPACM_LanToLan_Iface::add_client_flt_rule(peer_iface_info *peer, client_info *client, ipa_ip_type iptype)
    581 {
    582 	list<flt_rule_info>::iterator it_flt;
    583 	uint32_t flt_rule_hdl;
    584 	flt_rule_info new_flt_info;
    585 	ipa_ioc_get_rt_tbl rt_tbl;
    586 
    587 	rt_tbl.ip = iptype;
    588 	memcpy(rt_tbl.name, peer->rt_tbl_name_for_flt[iptype], sizeof(rt_tbl.name));
    589 	IPACMDBG_H("This flt rule points to rt tbl %s.\n", rt_tbl.name);
    590 
    591 	if(IPACM_Iface::m_routing.GetRoutingTable(&rt_tbl) == false)
    592 	{
    593 		IPACMERR("Failed to get routing table.\n");
    594 		return;
    595 	}
    596 
    597 	m_p_iface->eth_bridge_add_flt_rule(client->mac_addr, rt_tbl.hdl,
    598 		iptype, &flt_rule_hdl);
    599 	IPACMDBG_H("Installed flt rule for IP type %d: handle %d\n", iptype, flt_rule_hdl);
    600 
    601 	for(it_flt = peer->flt_rule.begin(); it_flt != peer->flt_rule.end(); it_flt++)
    602 	{
    603 		if(it_flt->p_client == client)	//the client is already in the flt info list
    604 		{
    605 			IPACMDBG_H("The client is found in flt info list.\n");
    606 			it_flt->flt_rule_hdl[iptype] = flt_rule_hdl;
    607 			break;
    608 		}
    609 	}
    610 
    611 	if(it_flt == peer->flt_rule.end())	//the client is not in the flt info list
    612 	{
    613 		IPACMDBG_H("The client is not found in flt info list, insert a new one.\n");
    614 		memset(&new_flt_info, 0, sizeof(new_flt_info));
    615 		new_flt_info.p_client = client;
    616 		new_flt_info.flt_rule_hdl[iptype] = flt_rule_hdl;
    617 
    618 		peer->flt_rule.push_front(new_flt_info);
    619 	}
    620 
    621 	return;
    622 }
    623 
    624 void IPACM_LanToLan_Iface::del_one_client_flt_rule(IPACM_LanToLan_Iface *peer_iface, client_info *client)
    625 {
    626 	list<peer_iface_info>::iterator it;
    627 
    628 	for(it = m_peer_iface_info.begin(); it != m_peer_iface_info.end(); it++)
    629 	{
    630 		if(it->peer == peer_iface)
    631 		{
    632 			IPACMDBG_H("Found the peer iface info.\n");
    633 			del_client_flt_rule(&(*it), client);
    634 			break;
    635 		}
    636 	}
    637 	return;
    638 }
    639 
    640 void IPACM_LanToLan_Iface::del_client_flt_rule(peer_iface_info *peer, client_info *client)
    641 {
    642 	list<flt_rule_info>::iterator it_flt;
    643 
    644 	for(it_flt = peer->flt_rule.begin(); it_flt != peer->flt_rule.end(); it_flt++)
    645 	{
    646 		if(it_flt->p_client == client)	//found the client in flt info list
    647 		{
    648 			IPACMDBG_H("Found the client in flt info list.\n");
    649 			if(m_is_ip_addr_assigned[IPA_IP_v4])
    650 			{
    651 				m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4);
    652 				IPACMDBG_H("IPv4 flt rule %d is deleted.\n", it_flt->flt_rule_hdl[IPA_IP_v4]);
    653 			}
    654 			if(m_is_ip_addr_assigned[IPA_IP_v6])
    655 			{
    656 				m_p_iface->eth_bridge_del_flt_rule(it_flt->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6);
    657 				IPACMDBG_H("IPv6 flt rule %d is deleted.\n", it_flt->flt_rule_hdl[IPA_IP_v6]);
    658 			}
    659 
    660 			peer->flt_rule.erase(it_flt);
    661 			break;
    662 		}
    663 	}
    664 	return;
    665 }
    666 
    667 void IPACM_LanToLan_Iface::del_client_rt_rule(peer_iface_info *peer, client_info *client)
    668 {
    669 	ipa_hdr_l2_type peer_l2_hdr_type;
    670 	int i, num_rules;
    671 
    672 	peer_l2_hdr_type = peer->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type;
    673 	/* if the peer info is not for intra interface communication */
    674 	if(peer->peer != this)
    675 	{
    676 		IPACMDBG_H("Delete routing rules for inter interface communication.\n");
    677 
    678 		num_rules = client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4];
    679 		for(i = 0; i < num_rules; i++)
    680 		{
    681 			m_p_iface->eth_bridge_del_rt_rule(client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i], IPA_IP_v4);
    682 			IPACMDBG_H("IPv4 rt rule %d is deleted.\n", client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i]);
    683 		}
    684 		client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4] = 0;
    685 
    686 		num_rules = client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6];
    687 		for(i = 0; i < num_rules; i++)
    688 		{
    689 			m_p_iface->eth_bridge_del_rt_rule(client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i], IPA_IP_v6);
    690 			IPACMDBG_H("IPv6 rt rule %d is deleted.\n", client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i]);
    691 		}
    692 		client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6] = 0;
    693 	}
    694 	else
    695 	{
    696 		IPACMDBG_H("Delete routing rules for intra interface communication.\n");
    697 		num_rules = client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4];
    698 		for(i = 0; i < num_rules; i++)
    699 		{
    700 			m_p_iface->eth_bridge_del_rt_rule(client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i], IPA_IP_v4);
    701 			IPACMDBG_H("IPv4 rt rule %d is deleted.\n", client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i]);
    702 		}
    703 		client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4] = 0;
    704 
    705 		num_rules = client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6];
    706 		for(i = 0; i < num_rules; i++)
    707 		{
    708 			m_p_iface->eth_bridge_del_rt_rule(client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i], IPA_IP_v6);
    709 			IPACMDBG_H("IPv6 rt rule %d is deleted.\n", client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i]);
    710 		}
    711 		client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6] = 0;
    712 	}
    713 
    714 	return;
    715 }
    716 
    717 void IPACM_LanToLan_Iface::handle_down_event()
    718 {
    719 	list<IPACM_LanToLan_Iface>::iterator it_other_iface;
    720 	list<peer_iface_info>::iterator it_own_peer_info, it_other_iface_peer_info;
    721 	IPACM_LanToLan_Iface *other_iface;
    722 
    723 	/* clear inter-interface rules */
    724 	if(m_support_inter_iface_offload)
    725 	{
    726 		for(it_own_peer_info = m_peer_iface_info.begin(); it_own_peer_info != m_peer_iface_info.end();
    727 			it_own_peer_info++)
    728 		{
    729 			/* decrement reference count of peer l2 header type on both interfaces*/
    730 			decrement_ref_cnt_peer_l2_hdr_type(it_own_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type);
    731 			it_own_peer_info->peer->decrement_ref_cnt_peer_l2_hdr_type(m_p_iface->tx_prop->tx[0].hdr_l2_type);
    732 
    733 			/* first clear all flt rule on target interface */
    734 			IPACMDBG_H("Clear all flt rule on target interface.\n");
    735 			clear_all_flt_rule_for_one_peer_iface(&(*it_own_peer_info));
    736 
    737 			other_iface = it_own_peer_info->peer;
    738 			/* then clear all flt/rt rule and hdr proc ctx for target interface on peer interfaces */
    739 			IPACMDBG_H("Clear all flt/rt rules and hdr proc ctx for target interface on peer interfaces %s.\n",
    740 				it_own_peer_info->peer->get_iface_pointer()->dev_name);
    741 			for(it_other_iface_peer_info = other_iface->m_peer_iface_info.begin();
    742 				it_other_iface_peer_info != other_iface->m_peer_iface_info.end();
    743 				it_other_iface_peer_info++)
    744 			{
    745 				if(it_other_iface_peer_info->peer == this)	//found myself in other iface's peer info list
    746 				{
    747 					IPACMDBG_H("Found the right peer info on other iface.\n");
    748 					other_iface->clear_all_flt_rule_for_one_peer_iface(&(*it_other_iface_peer_info));
    749 					other_iface->clear_all_rt_rule_for_one_peer_iface(&(*it_other_iface_peer_info));
    750 					/* remove the peer info from the list */
    751 					other_iface->m_peer_iface_info.erase(it_other_iface_peer_info);
    752 					other_iface->del_hdr_proc_ctx(m_p_iface->tx_prop->tx[0].hdr_l2_type);
    753 					break;
    754 				}
    755 			}
    756 
    757 			/* then clear rt rule and hdr proc ctx and release rt table on target interface */
    758 			IPACMDBG_H("Clear rt rules and hdr proc ctx and release rt table on target interface.\n");
    759 			clear_all_rt_rule_for_one_peer_iface(&(*it_own_peer_info));
    760 			del_hdr_proc_ctx(it_own_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type);
    761 		}
    762 		m_peer_iface_info.clear();
    763 	}
    764 
    765 	/* clear intra interface rules */
    766 	if(m_support_intra_iface_offload)
    767 	{
    768 		IPACMDBG_H("Clear intra interface flt/rt rules and hdr proc ctx, release rt tables.\n");
    769 		clear_all_flt_rule_for_one_peer_iface(&m_intra_interface_info);
    770 		clear_all_rt_rule_for_one_peer_iface(&m_intra_interface_info);
    771 		m_p_iface->eth_bridge_del_hdr_proc_ctx(hdr_proc_ctx_for_intra_interface);
    772 		IPACMDBG_H("Hdr proc ctx with hdl %d is deleted.\n", hdr_proc_ctx_for_intra_interface);
    773 	}
    774 
    775 	/* then clear the client info list */
    776 	m_client_info.clear();
    777 
    778 	return;
    779 }
    780 
    781 void IPACM_LanToLan_Iface::clear_all_flt_rule_for_one_peer_iface(peer_iface_info *peer)
    782 {
    783 	list<flt_rule_info>::iterator it;
    784 
    785 	for(it = peer->flt_rule.begin(); it != peer->flt_rule.end(); it++)
    786 	{
    787 		if(m_is_ip_addr_assigned[IPA_IP_v4])
    788 		{
    789 			m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v4], IPA_IP_v4);
    790 			IPACMDBG_H("IPv4 flt rule %d is deleted.\n", it->flt_rule_hdl[IPA_IP_v4]);
    791 		}
    792 		if(m_is_ip_addr_assigned[IPA_IP_v6])
    793 		{
    794 			m_p_iface->eth_bridge_del_flt_rule(it->flt_rule_hdl[IPA_IP_v6], IPA_IP_v6);
    795 			IPACMDBG_H("IPv6 flt rule %d is deleted.\n", it->flt_rule_hdl[IPA_IP_v6]);
    796 		}
    797 	}
    798 	peer->flt_rule.clear();
    799 	return;
    800 }
    801 
    802 void IPACM_LanToLan_Iface::clear_all_rt_rule_for_one_peer_iface(peer_iface_info *peer)
    803 {
    804 	list<client_info>::iterator it;
    805 	ipa_hdr_l2_type peer_l2_type;
    806 
    807 	peer_l2_type = peer->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type;
    808 	if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 0)
    809 	{
    810 		for(it = m_client_info.begin(); it != m_client_info.end(); it++)
    811 		{
    812 			del_client_rt_rule(peer, &(*it));
    813 		}
    814 	}
    815 
    816 	return;
    817 }
    818 
    819 void IPACM_LanToLan_Iface::handle_wlan_scc_mcc_switch()
    820 {
    821 	list<peer_iface_info>::iterator it_peer_info;
    822 	list<client_info>::iterator it_client;
    823 	ipa_hdr_l2_type peer_l2_hdr_type;
    824 	bool flag[IPA_HDR_L2_MAX];
    825 	int i;
    826 
    827 	/* modify inter-interface routing rules */
    828 	if(m_support_inter_iface_offload)
    829 	{
    830 		IPACMDBG_H("Modify rt rules for peer interfaces.\n");
    831 		memset(flag, 0, sizeof(flag));
    832 		for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); it_peer_info++)
    833 		{
    834 			peer_l2_hdr_type = it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type;
    835 			if(flag[peer_l2_hdr_type] == false)
    836 			{
    837 				flag[peer_l2_hdr_type] = true;
    838 				for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
    839 				{
    840 					m_p_iface->eth_bridge_modify_rt_rule(it_client->mac_addr, hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type],
    841 						peer_l2_hdr_type, IPA_IP_v4, it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4],
    842 						it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4]);
    843 					IPACMDBG_H("The following IPv4 routing rules are modified:\n");
    844 					for(i = 0; i < it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v4]; i++)
    845 					{
    846 						IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v4][i]);
    847 					}
    848 
    849 					m_p_iface->eth_bridge_modify_rt_rule(it_client->mac_addr, hdr_proc_ctx_for_inter_interface[peer_l2_hdr_type],
    850 						peer_l2_hdr_type, IPA_IP_v6, it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6],
    851 						it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6]);
    852 					IPACMDBG_H("The following IPv6 routing rules are modified:\n");
    853 					for(i = 0; i < it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].num_hdl[IPA_IP_v6]; i++)
    854 					{
    855 						IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[peer_l2_hdr_type].rule_hdl[IPA_IP_v6][i]);
    856 					}
    857 				}
    858 			}
    859 		}
    860 	}
    861 
    862 	/* modify routing rules for intra-interface communication */
    863 	IPACMDBG_H("Modify rt rules for intra-interface communication.\n");
    864 	if(m_support_intra_iface_offload)
    865 	{
    866 		for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
    867 		{
    868 			m_p_iface->eth_bridge_modify_rt_rule(it_client->mac_addr, hdr_proc_ctx_for_intra_interface,
    869 				m_p_iface->tx_prop->tx[0].hdr_l2_type, IPA_IP_v4, it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4],
    870 				it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]);
    871 			IPACMDBG_H("The following IPv4 routing rules are modified:\n");
    872 			for(i = 0; i < it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]; i++)
    873 			{
    874 				IPACMDBG_H("%d\n", it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][i]);
    875 			}
    876 
    877 			m_p_iface->eth_bridge_modify_rt_rule(it_client->mac_addr, hdr_proc_ctx_for_intra_interface,
    878 				m_p_iface->tx_prop->tx[0].hdr_l2_type, IPA_IP_v6, it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6],
    879 				it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]);
    880 			IPACMDBG_H("The following IPv6 routing rules are modified:\n");
    881 			for(i = 0; i < it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]; i++)
    882 			{
    883 				IPACMDBG_H("%d\n", it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][i]);
    884 			}
    885 		}
    886 	}
    887 
    888 	return;
    889 }
    890 
    891 void IPACM_LanToLan_Iface::handle_intra_interface_info()
    892 {
    893 	uint32_t hdr_proc_ctx_hdl;
    894 
    895 	if(m_p_iface->tx_prop == NULL)
    896 	{
    897 		IPACMERR("No tx prop.\n");
    898 		return;
    899 	}
    900 
    901 	m_intra_interface_info.peer = this;
    902 
    903 	snprintf(m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX,
    904 		"eth_v4_intra_interface");
    905 	IPACMDBG_H("IPv4 routing table for flt name: %s\n", m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4]);
    906 	snprintf(m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX,
    907 		"eth_v6_intra_interface");
    908 	IPACMDBG_H("IPv6 routing table for flt name: %s\n", m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6]);
    909 
    910 	memcpy(m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v4], m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v4],
    911 		IPA_RESOURCE_NAME_MAX);
    912 	IPACMDBG_H("IPv4 routing table for rt name: %s\n", m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v4]);
    913 	memcpy(m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v6], m_intra_interface_info.rt_tbl_name_for_flt[IPA_IP_v6],
    914 		IPA_RESOURCE_NAME_MAX);
    915 	IPACMDBG_H("IPv6 routing table for rt name: %s\n", m_intra_interface_info.rt_tbl_name_for_rt[IPA_IP_v6]);
    916 
    917 	m_p_iface->eth_bridge_add_hdr_proc_ctx(m_p_iface->tx_prop->tx[0].hdr_l2_type,
    918 		&hdr_proc_ctx_hdl);
    919 	hdr_proc_ctx_for_intra_interface = hdr_proc_ctx_hdl;
    920 	IPACMDBG_H("Hdr proc ctx for intra-interface communication: hdl %d\n", hdr_proc_ctx_hdl);
    921 
    922 	return;
    923 }
    924 
    925 void IPACM_LanToLan_Iface::handle_new_iface_up(char rt_tbl_name_for_flt[][IPA_RESOURCE_NAME_MAX], char rt_tbl_name_for_rt[][IPA_RESOURCE_NAME_MAX],
    926 		IPACM_LanToLan_Iface *peer_iface)
    927 {
    928 	peer_iface_info new_peer;
    929 	ipa_hdr_l2_type peer_l2_hdr_type;
    930 
    931 	new_peer.peer = peer_iface;
    932 	memcpy(new_peer.rt_tbl_name_for_rt[IPA_IP_v4], rt_tbl_name_for_rt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX);
    933 	memcpy(new_peer.rt_tbl_name_for_rt[IPA_IP_v6], rt_tbl_name_for_rt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX);
    934 	memcpy(new_peer.rt_tbl_name_for_flt[IPA_IP_v4], rt_tbl_name_for_flt[IPA_IP_v4], IPA_RESOURCE_NAME_MAX);
    935 	memcpy(new_peer.rt_tbl_name_for_flt[IPA_IP_v6], rt_tbl_name_for_flt[IPA_IP_v6], IPA_RESOURCE_NAME_MAX);
    936 
    937 	peer_l2_hdr_type = peer_iface->m_p_iface->tx_prop->tx[0].hdr_l2_type;
    938 	increment_ref_cnt_peer_l2_hdr_type(peer_l2_hdr_type);
    939 	add_hdr_proc_ctx(peer_l2_hdr_type);
    940 
    941 	/* push the new peer_iface_info into the list */
    942 	m_peer_iface_info.push_front(new_peer);
    943 
    944 	return;
    945 }
    946 
    947 void IPACM_LanToLan_Iface::handle_client_add(uint8_t *mac)
    948 {
    949 	list<client_info>::iterator it_client;
    950 	list<peer_iface_info>::iterator it_peer_info;
    951 	client_info new_client;
    952 	bool flag[IPA_HDR_L2_MAX];
    953 
    954 	for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
    955 	{
    956 		if(memcmp(it_client->mac_addr, mac, sizeof(it_client->mac_addr)) == 0)
    957 		{
    958 			IPACMDBG_H("This client has been added before.\n");
    959 			return;
    960 		}
    961 	}
    962 
    963 	if(m_client_info.size() == MAX_NUM_CLIENT)
    964 	{
    965 		IPACMDBG_H("The number of clients has reached maximum %d.\n", MAX_NUM_CLIENT);
    966 		return;
    967 	}
    968 
    969 	memcpy(new_client.mac_addr, mac, sizeof(new_client.mac_addr));
    970 	m_client_info.push_front(new_client);
    971 
    972 	client_info &front_client = m_client_info.front();
    973 
    974 	/* install inter-interface rules */
    975 	if(m_support_inter_iface_offload)
    976 	{
    977 		memset(flag, 0, sizeof(flag));
    978 		for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end(); it_peer_info++)
    979 		{
    980 			/* make sure add routing rule only once for each peer l2 header type */
    981 			if(flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] == false)
    982 			{
    983 				/* add client routing rule for each peer interface */
    984 				add_client_rt_rule(&(*it_peer_info), &front_client);
    985 				flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] = true;
    986 			}
    987 
    988 			/* add client filtering rule on peer interfaces */
    989 			it_peer_info->peer->add_one_client_flt_rule(this, &front_client);
    990 		}
    991 	}
    992 
    993 	/* install intra-interface rules */
    994 	if(m_support_intra_iface_offload)
    995 	{
    996 		/* add routing rule first */
    997 		add_client_rt_rule(&m_intra_interface_info, &front_client);
    998 
    999 		/* add filtering rule */
   1000 		if(m_is_ip_addr_assigned[IPA_IP_v4])
   1001 		{
   1002 			add_client_flt_rule(&m_intra_interface_info, &front_client, IPA_IP_v4);
   1003 		}
   1004 		if(m_is_ip_addr_assigned[IPA_IP_v6])
   1005 		{
   1006 			add_client_flt_rule(&m_intra_interface_info, &front_client, IPA_IP_v6);
   1007 		}
   1008 	}
   1009 
   1010 	return;
   1011 }
   1012 
   1013 void IPACM_LanToLan_Iface::handle_client_del(uint8_t *mac)
   1014 {
   1015 	list<client_info>::iterator it_client;
   1016 	list<peer_iface_info>::iterator it_peer_info;
   1017 	bool flag[IPA_HDR_L2_MAX];
   1018 
   1019 	for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
   1020 	{
   1021 		if(memcmp(it_client->mac_addr, mac, sizeof(it_client->mac_addr)) == 0)	//found the client
   1022 		{
   1023 			IPACMDBG_H("Found the client.\n");
   1024 			break;
   1025 		}
   1026 	}
   1027 
   1028 	if(it_client != m_client_info.end())	//if we found the client
   1029 	{
   1030 		/* uninstall inter-interface rules */
   1031 		if(m_support_inter_iface_offload)
   1032 		{
   1033 			memset(flag, 0, sizeof(flag));
   1034 			for(it_peer_info = m_peer_iface_info.begin(); it_peer_info != m_peer_iface_info.end();
   1035 				it_peer_info++)
   1036 			{
   1037 				IPACMDBG_H("Delete client filtering rule on peer interface.\n");
   1038 				it_peer_info->peer->del_one_client_flt_rule(this, &(*it_client));
   1039 
   1040 				/* make sure to delete routing rule only once for each peer l2 header type */
   1041 				if(flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] == false)
   1042 				{
   1043 					IPACMDBG_H("Delete client routing rule for peer interface.\n");
   1044 					del_client_rt_rule(&(*it_peer_info), &(*it_client));
   1045 					flag[it_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type] = true;
   1046 				}
   1047 			}
   1048 		}
   1049 
   1050 		/* uninstall intra-interface rules */
   1051 		if(m_support_intra_iface_offload)
   1052 		{
   1053 			/* delete filtering rule first */
   1054 			IPACMDBG_H("Delete client filtering rule for intra-interface communication.\n");
   1055 			del_client_flt_rule(&m_intra_interface_info, &(*it_client));
   1056 
   1057 			/* delete routing rule */
   1058 			IPACMDBG_H("Delete client routing rule for intra-interface communication.\n");
   1059 			del_client_rt_rule(&m_intra_interface_info, &(*it_client));
   1060 		}
   1061 
   1062 		/* erase the client from client info list */
   1063 		m_client_info.erase(it_client);
   1064 	}
   1065 	else
   1066 	{
   1067 		IPACMDBG_H("The client is not found.\n");
   1068 	}
   1069 
   1070 	return;
   1071 }
   1072 
   1073 void IPACM_LanToLan_Iface::add_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type)
   1074 {
   1075 	uint32_t hdr_proc_ctx_hdl;
   1076 
   1077 	if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 1)
   1078 	{
   1079 		m_p_iface->eth_bridge_add_hdr_proc_ctx(peer_l2_type, &hdr_proc_ctx_hdl);
   1080 		hdr_proc_ctx_for_inter_interface[peer_l2_type] = hdr_proc_ctx_hdl;
   1081 		IPACMDBG_H("Installed inter-interface hdr proc ctx on iface %s: handle %d\n", m_p_iface->dev_name, hdr_proc_ctx_hdl);
   1082 	}
   1083 	return;
   1084 }
   1085 
   1086 void IPACM_LanToLan_Iface::del_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type)
   1087 {
   1088 	if(ref_cnt_peer_l2_hdr_type[peer_l2_type] == 0)
   1089 	{
   1090 		m_p_iface->eth_bridge_del_hdr_proc_ctx(hdr_proc_ctx_for_inter_interface[peer_l2_type]);
   1091 		IPACMDBG_H("Hdr proc ctx with hdl %d is deleted.\n", hdr_proc_ctx_for_inter_interface[peer_l2_type]);
   1092 	}
   1093 	return;
   1094 }
   1095 
   1096 void IPACM_LanToLan_Iface::print_data_structure_info()
   1097 {
   1098 	list<peer_iface_info>::iterator it_peer;
   1099 	list<client_info>::iterator it_client;
   1100 	int i, j, k;
   1101 
   1102 	IPACMDBG_H("\n");
   1103 	IPACMDBG_H("Interface %s:\n", m_p_iface->dev_name);
   1104 	IPACMDBG_H("Is IPv4 addr assigned? %d\n", m_is_ip_addr_assigned[IPA_IP_v4]);
   1105 	IPACMDBG_H("Is IPv6 addr assigned? %d\n", m_is_ip_addr_assigned[IPA_IP_v6]);
   1106 	IPACMDBG_H("Support inter interface offload? %d\n", m_support_inter_iface_offload);
   1107 	IPACMDBG_H("Support intra interface offload? %d\n", m_support_intra_iface_offload);
   1108 
   1109 	if(m_support_inter_iface_offload)
   1110 	{
   1111 		for(i = 0; i < IPA_HDR_L2_MAX; i++)
   1112 		{
   1113 			IPACMDBG_H("Ref_cnt of peer l2 type %s is %d.\n", ipa_l2_hdr_type[i], ref_cnt_peer_l2_hdr_type[i]);
   1114 			if(ref_cnt_peer_l2_hdr_type[i] > 0)
   1115 			{
   1116 				IPACMDBG_H("Hdr proc ctx for peer l2 type %s: %d\n", ipa_l2_hdr_type[i], hdr_proc_ctx_for_inter_interface[i]);
   1117 			}
   1118 		}
   1119 	}
   1120 
   1121 	if(m_support_intra_iface_offload)
   1122 	{
   1123 		IPACMDBG_H("Hdr proc ctx for intra-interface: %d\n", hdr_proc_ctx_for_intra_interface);
   1124 	}
   1125 
   1126 	i = 1;
   1127 	IPACMDBG_H("There are %d clients in total.\n", m_client_info.size());
   1128 	for(it_client = m_client_info.begin(); it_client != m_client_info.end(); it_client++)
   1129 	{
   1130 		IPACMDBG_H("Client %d MAC: 0x%02x%02x%02x%02x%02x%02x Pointer: 0x%08x\n", i, it_client->mac_addr[0], it_client->mac_addr[1],
   1131 			it_client->mac_addr[2], it_client->mac_addr[3], it_client->mac_addr[4], it_client->mac_addr[5], &(*it_client));
   1132 
   1133 		if(m_support_inter_iface_offload)
   1134 		{
   1135 			for(j = 0; j < IPA_HDR_L2_MAX; j++)
   1136 			{
   1137 				if(ref_cnt_peer_l2_hdr_type[j] > 0)
   1138 				{
   1139 					IPACMDBG_H("Printing routing rule info for inter-interface communication for peer l2 type %s.\n",
   1140 						ipa_l2_hdr_type[j]);
   1141 					IPACMDBG_H("Number of IPv4 routing rules is %d, handles:\n", it_client->inter_iface_rt_rule_hdl[j].num_hdl[IPA_IP_v4]);
   1142 					for(k = 0; k < it_client->inter_iface_rt_rule_hdl[j].num_hdl[IPA_IP_v4]; k++)
   1143 					{
   1144 						IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[j].rule_hdl[IPA_IP_v4][k]);
   1145 					}
   1146 
   1147 					IPACMDBG_H("Number of IPv6 routing rules is %d, handles:\n", it_client->inter_iface_rt_rule_hdl[j].num_hdl[IPA_IP_v6]);
   1148 					for(k = 0; k < it_client->inter_iface_rt_rule_hdl[j].num_hdl[IPA_IP_v6]; k++)
   1149 					{
   1150 						IPACMDBG_H("%d\n", it_client->inter_iface_rt_rule_hdl[j].rule_hdl[IPA_IP_v6][k]);
   1151 					}
   1152 				}
   1153 			}
   1154 		}
   1155 
   1156 		if(m_support_intra_iface_offload)
   1157 		{
   1158 			IPACMDBG_H("Printing routing rule info for intra-interface communication.\n");
   1159 			IPACMDBG_H("Number of IPv4 routing rules is %d, handles:\n", it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]);
   1160 			for(j = 0; j < it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v4]; j++)
   1161 			{
   1162 				IPACMDBG_H("%d\n", it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v4][j]);
   1163 			}
   1164 
   1165 			IPACMDBG_H("Number of IPv6 routing rules is %d, handles:\n", it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]);
   1166 			for(j = 0; j < it_client->intra_iface_rt_rule_hdl.num_hdl[IPA_IP_v6]; j++)
   1167 			{
   1168 				IPACMDBG_H("%d\n", it_client->intra_iface_rt_rule_hdl.rule_hdl[IPA_IP_v6][j]);
   1169 			}
   1170 		}
   1171 		i++;
   1172 	}
   1173 
   1174 	IPACMDBG_H("There are %d peer interfaces in total.\n", m_peer_iface_info.size());
   1175 	for(it_peer = m_peer_iface_info.begin(); it_peer != m_peer_iface_info.end(); it_peer++)
   1176 	{
   1177 		print_peer_info(&(*it_peer));
   1178 	}
   1179 
   1180 	if(m_support_intra_iface_offload)
   1181 	{
   1182 		IPACMDBG_H("This interface supports intra-interface communication, printing info:\n");
   1183 		print_peer_info(&m_intra_interface_info);
   1184 	}
   1185 
   1186 	return;
   1187 }
   1188 
   1189 void IPACM_LanToLan_Iface::print_peer_info(peer_iface_info *peer_info)
   1190 {
   1191 	list<flt_rule_info>::iterator it_flt;
   1192 	list<rt_rule_info>::iterator it_rt;
   1193 
   1194 	IPACMDBG_H("Printing peer info for iface %s:\n", peer_info->peer->m_p_iface->dev_name);
   1195 
   1196 	IPACMDBG_H("There are %d flt info in total.\n", peer_info->flt_rule.size());
   1197 	for(it_flt = peer_info->flt_rule.begin(); it_flt != peer_info->flt_rule.end(); it_flt++)
   1198 	{
   1199 		IPACMDBG_H("Flt rule handle for client 0x%08x:\n", it_flt->p_client);
   1200 		if(m_is_ip_addr_assigned[IPA_IP_v4])
   1201 		{
   1202 			IPACMDBG_H("IPv4 %d\n", it_flt->flt_rule_hdl[IPA_IP_v4]);
   1203 		}
   1204 		if(m_is_ip_addr_assigned[IPA_IP_v6])
   1205 		{
   1206 			IPACMDBG_H("IPv6 %d\n", it_flt->flt_rule_hdl[IPA_IP_v6]);
   1207 		}
   1208 	}
   1209 
   1210 	return;
   1211 }
   1212 
   1213 IPACM_Lan* IPACM_LanToLan_Iface::get_iface_pointer()
   1214 {
   1215 	return m_p_iface;
   1216 }
   1217 
   1218 bool IPACM_LanToLan_Iface::get_m_is_ip_addr_assigned(ipa_ip_type iptype)
   1219 {
   1220 	IPACMDBG_H("Has IP address been assigned to interface %s for IP type %d? %d\n",
   1221 		m_p_iface->dev_name, iptype, m_is_ip_addr_assigned[iptype]);
   1222 	return m_is_ip_addr_assigned[iptype];
   1223 }
   1224 
   1225 void IPACM_LanToLan_Iface::set_m_is_ip_addr_assigned(ipa_ip_type iptype, bool value)
   1226 {
   1227 	IPACMDBG_H("Is IP address of IP type %d assigned to interface %s? %d\n", iptype,
   1228 		m_p_iface->dev_name, value);
   1229 	m_is_ip_addr_assigned[iptype] = value;
   1230 }
   1231 
   1232 bool IPACM_LanToLan_Iface::get_m_support_inter_iface_offload()
   1233 {
   1234 	IPACMDBG_H("Support inter interface offload on %s? %d\n", m_p_iface->dev_name,
   1235 		m_support_inter_iface_offload);
   1236 	return m_support_inter_iface_offload;
   1237 }
   1238 
   1239 bool IPACM_LanToLan_Iface::get_m_support_intra_iface_offload()
   1240 {
   1241 	IPACMDBG_H("Support intra interface offload on %s? %d\n", m_p_iface->dev_name,
   1242 		m_support_intra_iface_offload);
   1243 	return m_support_intra_iface_offload;
   1244 }
   1245 
   1246 void IPACM_LanToLan_Iface::increment_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type)
   1247 {
   1248 	ref_cnt_peer_l2_hdr_type[peer_l2_type]++;
   1249 	IPACMDBG_H("Now the ref_cnt of peer l2 hdr type %s is %d.\n", ipa_l2_hdr_type[peer_l2_type],
   1250 		ref_cnt_peer_l2_hdr_type[peer_l2_type]);
   1251 
   1252 	return;
   1253 }
   1254 
   1255 void IPACM_LanToLan_Iface::decrement_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type)
   1256 {
   1257 	ref_cnt_peer_l2_hdr_type[peer_l2_type]--;
   1258 	IPACMDBG_H("Now the ref_cnt of peer l2 hdr type %s is %d.\n", ipa_l2_hdr_type[peer_l2_type],
   1259 		ref_cnt_peer_l2_hdr_type[peer_l2_type]);
   1260 
   1261 	return;
   1262 }
   1263