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