• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IPACM_LanToLan_Iface(IPACM_Lan * p_iface)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 
~IPACM_LanToLan_Iface()82 IPACM_LanToLan_Iface::~IPACM_LanToLan_Iface()
83 {
84 }
85 
IPACM_LanToLan()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 
~IPACM_LanToLan()97 IPACM_LanToLan::~IPACM_LanToLan()
98 {
99 	IPACMDBG_DMESG("WARNING: UNEXPECTEDLY KILL LAN2LAN CONTROLLER!\n");
100 	return;
101 }
102 
event_callback(ipa_cm_event_id event,void * param)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 
handle_iface_up(ipacm_event_eth_bridge * data)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 
handle_iface_down(ipacm_event_eth_bridge * data)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 
handle_new_iface_up(IPACM_LanToLan_Iface * new_iface,IPACM_LanToLan_Iface * exist_iface)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 
handle_client_add(ipacm_event_eth_bridge * data)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 
handle_client_del(ipacm_event_eth_bridge * data)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 
handle_wlan_scc_mcc_switch(ipacm_event_eth_bridge * data)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 
handle_cached_client_add_event(IPACM_Lan * p_iface)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 
clear_cached_client_add_event(IPACM_Lan * p_iface)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 
print_data_structure_info()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 
add_client_rt_rule_for_new_iface()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 
add_client_rt_rule(peer_iface_info * peer_info,client_info * client)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 
add_all_inter_interface_client_flt_rule(ipa_ip_type iptype)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 
add_all_intra_interface_client_flt_rule(ipa_ip_type iptype)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 
add_one_client_flt_rule(IPACM_LanToLan_Iface * peer_iface,client_info * client)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 
add_client_flt_rule(peer_iface_info * peer,client_info * client,ipa_ip_type iptype)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 
del_one_client_flt_rule(IPACM_LanToLan_Iface * peer_iface,client_info * client)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 
del_client_flt_rule(peer_iface_info * peer,client_info * client)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 
del_client_rt_rule(peer_iface_info * peer,client_info * client)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 
handle_down_event()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 
clear_all_flt_rule_for_one_peer_iface(peer_iface_info * peer)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 
clear_all_rt_rule_for_one_peer_iface(peer_iface_info * peer)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 
handle_wlan_scc_mcc_switch()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 
handle_intra_interface_info()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 
handle_new_iface_up(char rt_tbl_name_for_flt[][IPA_RESOURCE_NAME_MAX],char rt_tbl_name_for_rt[][IPA_RESOURCE_NAME_MAX],IPACM_LanToLan_Iface * peer_iface)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 
handle_client_add(uint8_t * mac)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 
handle_client_del(uint8_t * mac)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 
add_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type)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 
del_hdr_proc_ctx(ipa_hdr_l2_type peer_l2_type)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 
print_data_structure_info()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 
print_peer_info(peer_iface_info * peer_info)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 
get_iface_pointer()1213 IPACM_Lan* IPACM_LanToLan_Iface::get_iface_pointer()
1214 {
1215 	return m_p_iface;
1216 }
1217 
get_m_is_ip_addr_assigned(ipa_ip_type iptype)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 
set_m_is_ip_addr_assigned(ipa_ip_type iptype,bool value)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 
get_m_support_inter_iface_offload()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 
get_m_support_intra_iface_offload()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 
increment_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type)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 
decrement_ref_cnt_peer_l2_hdr_type(ipa_hdr_l2_type peer_l2_type)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