blob: ad7b1a5fb83d5ce197a015008252b4512ea05681 [file] [log] [blame]
Ben Menchaca84f36632014-02-28 20:57:38 +00001/*
2 **************************************************************************
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003 * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
Ben Menchaca84f36632014-02-28 20:57:38 +00004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
16
Murat Sezginb3731e82014-11-26 12:20:59 -080017#include <linux/version.h>
Ben Menchaca84f36632014-02-28 20:57:38 +000018#include <linux/types.h>
19#include <linux/ip.h>
20#include <linux/tcp.h>
21#include <linux/module.h>
22#include <linux/skbuff.h>
23#include <linux/icmp.h>
Ben Menchaca84f36632014-02-28 20:57:38 +000024#include <linux/kthread.h>
Ben Menchaca84f36632014-02-28 20:57:38 +000025#include <linux/pkt_sched.h>
26#include <linux/string.h>
27#include <net/ip6_route.h>
28#include <net/ip6_fib.h>
29#include <net/ipv6.h>
30#include <net/route.h>
Gareth Williams46f4b5f2014-06-01 23:35:23 +010031#include <net/ip_fib.h>
Ben Menchaca84f36632014-02-28 20:57:38 +000032#include <net/ip.h>
33#include <net/tcp.h>
34#include <asm/unaligned.h>
35#include <asm/uaccess.h> /* for put_user */
36#include <linux/inet.h>
37#include <linux/in6.h>
38#include <linux/in.h>
39#include <linux/udp.h>
40#include <linux/tcp.h>
Murat Sezgina205b042016-07-19 14:18:14 -070041#include <linux/kernel.h>
42#include <linux/netlink.h>
43#include <linux/rtnetlink.h>
44#include <linux/socket.h>
45#include <linux/wireless.h>
46
Murat Sezgin8c345822015-05-27 15:35:38 -070047#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +053048#include <linux/if_bridge.h>
Murat Sezgin8c345822015-05-27 15:35:38 -070049#endif
Ben Menchaca84f36632014-02-28 20:57:38 +000050#include <linux/inetdevice.h>
Murat Sezginc1402562015-03-12 12:32:20 -070051#if defined(ECM_INTERFACE_TUNIPIP6_ENABLE) || defined(ECM_INTERFACE_SIT_ENABLE)
Tushar Mathur39f63f62015-06-19 14:31:14 +053052#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 9, 0))
Ben Menchaca84f36632014-02-28 20:57:38 +000053#include <net/ipip.h>
Tushar Mathur39f63f62015-06-19 14:31:14 +053054#else
55#include <net/ip_tunnels.h>
56#endif
Murat Sezginb3731e82014-11-26 12:20:59 -080057#endif
Ben Menchaca84f36632014-02-28 20:57:38 +000058#include <net/ip6_tunnel.h>
Gareth Williams43fc0852014-05-26 19:10:00 +010059#include <net/addrconf.h>
Ben Menchaca84f36632014-02-28 20:57:38 +000060#include <linux/if_arp.h>
61#include <linux/netfilter_ipv4.h>
62#include <linux/netfilter_bridge.h>
63#include <linux/if_bridge.h>
64#include <net/arp.h>
65#include <net/netfilter/nf_conntrack.h>
66#include <net/netfilter/nf_conntrack_acct.h>
67#include <net/netfilter/nf_conntrack_helper.h>
68#include <net/netfilter/nf_conntrack_l4proto.h>
69#include <net/netfilter/nf_conntrack_l3proto.h>
70#include <net/netfilter/nf_conntrack_zones.h>
71#include <net/netfilter/nf_conntrack_core.h>
ratheesh kannotha6d25952016-04-11 12:23:26 +053072#include <linux/netfilter_ipv6/ip6_tables.h>
Ben Menchaca84f36632014-02-28 20:57:38 +000073#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
74#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
Gareth Williams141d2382014-11-25 11:35:19 -080075#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +000076#include <linux/../../net/8021q/vlan.h>
77#include <linux/if_vlan.h>
Gareth Williams141d2382014-11-25 11:35:19 -080078#endif
Murat Sezgina683edd2015-01-20 10:48:30 -080079#ifdef ECM_INTERFACE_PPP_ENABLE
80#include <linux/if_pppox.h>
ratheesh kannotha32fdd12015-09-09 08:02:58 +053081#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannoth08b8e442015-10-02 00:24:55 +053082#include <linux/if_pppol2tp.h>
ratheesh kannotha32fdd12015-09-09 08:02:58 +053083#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +053084#ifdef ECM_INTERFACE_PPTP_ENABLE
85#include <linux/netfilter/nf_conntrack_proto_gre.h>
86#endif
Murat Sezgina683edd2015-01-20 10:48:30 -080087#endif
ratheesh kannothcfdcb332015-12-24 07:19:18 +053088#ifdef ECM_INTERFACE_MAP_T_ENABLE
89#include <nat46-core.h>
90#endif
Ben Menchaca84f36632014-02-28 20:57:38 +000091
92/*
93 * Debug output levels
94 * 0 = OFF
95 * 1 = ASSERTS / ERRORS
96 * 2 = 1 + WARN
97 * 3 = 2 + INFO
98 * 4 = 3 + TRACE
99 */
100#define DEBUG_LEVEL ECM_INTERFACE_DEBUG_LEVEL
101
Shyam Sunder6358b862015-05-04 15:06:24 +0530102#ifdef ECM_MULTICAST_ENABLE
103#include <mc_ecm.h>
104#endif
105
Ben Menchaca84f36632014-02-28 20:57:38 +0000106#include "ecm_types.h"
107#include "ecm_db_types.h"
Gareth Williamsd5618a82015-05-20 11:13:32 +0100108#include "ecm_state.h"
Ben Menchaca84f36632014-02-28 20:57:38 +0000109#include "ecm_tracker.h"
110#include "ecm_classifier.h"
111#include "ecm_front_end_types.h"
112#include "ecm_tracker_datagram.h"
113#include "ecm_tracker_udp.h"
114#include "ecm_tracker_tcp.h"
115#include "ecm_db.h"
116#include "ecm_interface.h"
117
Murat Sezgina205b042016-07-19 14:18:14 -0700118/*
119 * Wifi event handler structure.
120 */
121struct ecm_interface_wifi_event {
122 struct task_struct *thread;
123 struct socket *sock;
124};
125
126static struct ecm_interface_wifi_event __ewn;
127
Gareth Williams8ac34292015-03-17 14:06:58 +0000128#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000129/*
Gareth Williamsadf425f2014-05-26 19:29:02 +0100130 * TODO: Remove once the Linux image and headers get propogated.
131 */
132struct net_device *ipv6_dev_find(struct net *net, struct in6_addr *addr, int strict);
Murat Sezgin49465a42014-11-24 15:37:48 -0800133#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +0100134
135/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000136 * Locking - concurrency control
137 */
Murat Sezgin908ecb32015-05-10 20:54:36 -0700138static DEFINE_SPINLOCK(ecm_interface_lock); /* Protect against SMP access between netfilter, events and private threaded function. */
Ben Menchaca84f36632014-02-28 20:57:38 +0000139
140/*
141 * Management thread control
142 */
143static bool ecm_interface_terminate_pending = false; /* True when the user has signalled we should quit */
Ben Menchaca84f36632014-02-28 20:57:38 +0000144
145/*
Murat Sezginb3731e82014-11-26 12:20:59 -0800146 * ecm_interface_get_and_hold_dev_master()
147 * Returns the master device of a net device if any.
148 */
149struct net_device *ecm_interface_get_and_hold_dev_master(struct net_device *dev)
150{
151 struct net_device *master;
152#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,6,0))
153 rcu_read_lock();
154 master = netdev_master_upper_dev_get_rcu(dev);
155 if (!master) {
156 rcu_read_unlock();
157 return NULL;
158 }
159 dev_hold(master);
160 rcu_read_unlock();
161#else
162 master = dev->master;
163 if (!master) {
164 return NULL;
165 }
166 dev_hold(master);
167#endif
168 return master;
169}
170EXPORT_SYMBOL(ecm_interface_get_and_hold_dev_master);
171
172/*
Shyam Sunder9db20852016-03-09 19:04:49 +0530173 * ecm_interface_vlan_real_dev()
174 * Return immediate VLAN net device or Physical device pointer
175 */
176static inline struct net_device *ecm_interface_vlan_real_dev(struct net_device *vlan_dev)
177{
178#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 6, 0))
179 return vlan_dev_next_dev(vlan_dev);
180#else
181 return vlan_dev_real_dev(vlan_dev);
182#endif
183}
184
185/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100186 * ecm_interface_dev_find_by_local_addr_ipv4()
Shyam Sunder9db20852016-03-09 19:04:49 +0530187 * Return a hold to the device for the given local IP address. Returns NULL on failure.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100188 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100189static struct net_device *ecm_interface_dev_find_by_local_addr_ipv4(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100190{
191 __be32 be_addr;
192 struct net_device *dev;
193
194 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, addr);
195 dev = ip_dev_find(&init_net, be_addr);
196 return dev;
197}
198
Gareth Williams8ac34292015-03-17 14:06:58 +0000199#ifdef ECM_IPV6_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +0100200/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100201 * ecm_interface_dev_find_by_local_addr_ipv6()
202 * Return a hold to the device for the given local IP address. Returns NULL on failure.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100203 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100204static struct net_device *ecm_interface_dev_find_by_local_addr_ipv6(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100205{
206 struct in6_addr addr6;
207 struct net_device *dev;
208
209 ECM_IP_ADDR_TO_NIN6_ADDR(addr6, addr);
210 dev = (struct net_device *)ipv6_dev_find(&init_net, &addr6, 1);
211 return dev;
212}
Murat Sezgin49465a42014-11-24 15:37:48 -0800213#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +0100214
215/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100216 * ecm_interface_dev_find_by_local_addr()
217 * Return the device on which the local address resides.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100218 *
219 * Returns a hold to the device or NULL on failure.
220 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100221struct net_device *ecm_interface_dev_find_by_local_addr(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100222{
223 char __attribute__((unused)) addr_str[40];
224
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100225 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
Gareth Williamsadf425f2014-05-26 19:29:02 +0100226 DEBUG_TRACE("Locate dev for: %s\n", addr_str);
227
228 if (ECM_IP_ADDR_IS_V4(addr)) {
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100229 return ecm_interface_dev_find_by_local_addr_ipv4(addr);
Gareth Williamsadf425f2014-05-26 19:29:02 +0100230 }
231
Gareth Williams8ac34292015-03-17 14:06:58 +0000232#ifdef ECM_IPV6_ENABLE
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100233 return ecm_interface_dev_find_by_local_addr_ipv6(addr);
Murat Sezgin49465a42014-11-24 15:37:48 -0800234#else
235 return NULL;
236#endif
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100237}
238EXPORT_SYMBOL(ecm_interface_dev_find_by_local_addr);
239
240/*
241 * ecm_interface_dev_find_by_addr()
242 * Return the net device on which the given IP address resides. Returns NULL on faiure.
243 *
244 * NOTE: The device may be the device upon which has a default gateway to reach the address.
245 * from_local_addr is true when the device was found by a local address search.
246 */
247struct net_device *ecm_interface_dev_find_by_addr(ip_addr_t addr, bool *from_local_addr)
248{
249 char __attribute__((unused)) addr_str[40];
250 struct ecm_interface_route ecm_rt;
251 struct net_device *dev;
252 struct dst_entry *dst;
253
254 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
255
256 /*
257 * Is the address a local IP?
258 */
259 DEBUG_TRACE("find net device for address: %s\n", addr_str);
260 dev = ecm_interface_dev_find_by_local_addr(addr);
261 if (dev) {
262 *from_local_addr = true;
263 DEBUG_TRACE("addr: %s is local: %p (%s)\n", addr_str, dev, dev->name);
264 return dev;
265 }
266
267 DEBUG_TRACE("addr: %s is not local\n", addr_str);
268
269 /*
270 * Try a route to the address instead
271 * NOTE: This will locate a route entry in the route destination *cache*.
272 */
273 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
274 DEBUG_WARN("addr: %s - no dev locatable\n", addr_str);
275 return NULL;
276 }
277
278 *from_local_addr = false;
279 dst = ecm_rt.dst;
280 dev = dst->dev;
281 dev_hold(dev);
282 ecm_interface_route_release(&ecm_rt);
283 DEBUG_TRACE("dest_addr: %s uses dev: %p(%s)\n", addr_str, dev, dev->name);
284 return dev;
Gareth Williamsadf425f2014-05-26 19:29:02 +0100285}
286EXPORT_SYMBOL(ecm_interface_dev_find_by_addr);
287
Gareth Williams8ac34292015-03-17 14:06:58 +0000288#ifdef ECM_IPV6_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +0100289/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000290 * ecm_interface_mac_addr_get_ipv6()
291 * Return mac for an IPv6 address
292 *
293 * GGG TODO Need to make sure this also works for local IP addresses too.
294 */
295static bool ecm_interface_mac_addr_get_ipv6(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
296{
297 struct in6_addr daddr;
298 struct ecm_interface_route ecm_rt;
299 struct neighbour *neigh;
300 struct rt6_info *rt;
301 struct dst_entry *dst;
302
303 /*
304 * Get the MAC address that corresponds to IP address given.
305 * We look up the rt6_info entries and, from its neighbour structure, obtain the hardware address.
306 * This means we will also work if the neighbours are routers too.
307 */
308 ECM_IP_ADDR_TO_NIN6_ADDR(daddr, addr);
309 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
Kiran Kumar C. S. K7d178222014-06-27 18:47:29 +0530310 *on_link = false;
Ben Menchaca84f36632014-02-28 20:57:38 +0000311 return false;
312 }
313 DEBUG_ASSERT(!ecm_rt.v4_route, "Did not locate a v6 route!\n");
314
315 /*
316 * Is this destination on link or off-link via a gateway?
317 */
318 rt = ecm_rt.rt.rtv6;
319 if (!ECM_IP_ADDR_MATCH(rt->rt6i_dst.addr.in6_u.u6_addr32, rt->rt6i_gateway.in6_u.u6_addr32) || (rt->rt6i_flags & RTF_GATEWAY)) {
320 *on_link = false;
321 ECM_NIN6_ADDR_TO_IP_ADDR(gw_addr, rt->rt6i_gateway)
322 } else {
323 *on_link = true;
324 }
325
326 rcu_read_lock();
327 dst = ecm_rt.dst;
Murat Sezgine9b84582015-01-27 17:34:14 -0800328#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000329 neigh = dst_get_neighbour_noref(dst);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700330 if (neigh) {
331 neigh_hold(neigh);
Murat Sezgine9b84582015-01-27 17:34:14 -0800332 }
333#else
334 neigh = dst_neigh_lookup(dst, &daddr);
335#endif
336 if (!neigh) {
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700337 neigh = neigh_lookup(&nd_tbl, &daddr, dst->dev);
338 }
Murat Sezgine9b84582015-01-27 17:34:14 -0800339
Ben Menchaca84f36632014-02-28 20:57:38 +0000340 if (!neigh) {
341 rcu_read_unlock();
342 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700343 DEBUG_WARN("No neigh reference\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000344 return false;
345 }
346 if (!(neigh->nud_state & NUD_VALID)) {
347 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700348 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000349 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700350 DEBUG_WARN("NUD invalid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000351 return false;
352 }
353 if (!neigh->dev) {
354 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700355 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000356 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700357 DEBUG_WARN("Neigh dev invalid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000358 return false;
359 }
360
361 /*
362 * If neigh->dev is a loopback then addr is a local address in which case we take the MAC from given device
363 */
364 if (neigh->dev->flags & IFF_LOOPBACK) {
365 // GGG TODO Create an equivalent logic to that for ipv4, maybe need to create an ip6_dev_find()?
366 DEBUG_TRACE("local address " ECM_IP_ADDR_OCTAL_FMT " (found loopback)\n", ECM_IP_ADDR_TO_OCTAL(addr));
367 memset(mac_addr, 0, 6);
368 } else {
369 memcpy(mac_addr, neigh->ha, 6);
370 }
371 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700372 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000373 ecm_interface_route_release(&ecm_rt);
374
375 DEBUG_TRACE(ECM_IP_ADDR_OCTAL_FMT " maps to %pM\n", ECM_IP_ADDR_TO_OCTAL(addr), mac_addr);
376 return true;
377}
Murat Sezgin5dae8832015-12-03 14:23:19 -0800378
379/*
380 * ecm_interface_find_gateway_ipv6()
381 * Finds the ipv6 gateway ip address of a given ipv6 address.
382 */
383static bool ecm_interface_find_gateway_ipv6(ip_addr_t addr, ip_addr_t gw_addr)
384{
385 struct ecm_interface_route ecm_rt;
386 struct rt6_info *rt;
387
388 /*
389 * Find the ipv6 route of the given ip address to look up
390 * whether we have a gateway to reach to that ip address or not.
391 */
392 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
393 return false;
394 }
395 DEBUG_ASSERT(!ecm_rt.v4_route, "Did not locate a v6 route!\n");
396 DEBUG_TRACE("Found route\n");
397
398 /*
399 * Is this destination reachable via a gateway?
400 */
401 rt = ecm_rt.rt.rtv6;
402 if (ECM_IP_ADDR_MATCH(rt->rt6i_dst.addr.in6_u.u6_addr32, rt->rt6i_gateway.in6_u.u6_addr32) && !(rt->rt6i_flags & RTF_GATEWAY)) {
403 return false;
404 }
405
406 ECM_NIN6_ADDR_TO_IP_ADDR(gw_addr, rt->rt6i_gateway)
407 return true;
408}
Murat Sezgin49465a42014-11-24 15:37:48 -0800409#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000410
411/*
Murat Sezgin5dae8832015-12-03 14:23:19 -0800412 * ecm_interface_find_gateway_ipv4()
413 * Finds the ipv4 gateway address of a given ipv4 address.
414 */
415static bool ecm_interface_find_gateway_ipv4(ip_addr_t addr, ip_addr_t gw_addr)
416{
417 struct ecm_interface_route ecm_rt;
418 struct rtable *rt;
419
420 /*
421 * Find the ipv4 route of the given ip address to look up
422 * whether we have a gateway to reach to that ip address or not.
423 */
424 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
425 return false;
426 }
427 DEBUG_ASSERT(ecm_rt.v4_route, "Did not locate a v4 route!\n");
428 DEBUG_TRACE("Found route\n");
429
430 /*
431 * Is this destination reachable via a gateway?
432 */
433 rt = ecm_rt.rt.rtv4;
434#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
435 if (!(rt->rt_dst != rt->rt_gateway) && !(rt->rt_flags & RTF_GATEWAY)) {
436#else
437 if (!rt->rt_uses_gateway && !(rt->rt_flags & RTF_GATEWAY)) {
438#endif
439 return false;
440 }
441
442 ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway)
443 return true;
444}
445
446/*
447 * ecm_interface_find_gateway()
448 * Finds the gateway ip address of a given ECM ip address type.
449 */
450bool ecm_interface_find_gateway(ip_addr_t addr, ip_addr_t gw_addr)
451{
452 if (ECM_IP_ADDR_IS_V4(addr)) {
453 return ecm_interface_find_gateway_ipv4(addr, gw_addr);
454 }
455
456#ifdef ECM_IPV6_ENABLE
457 return ecm_interface_find_gateway_ipv6(addr, gw_addr);
458#else
459 return false;
460#endif
461}
462EXPORT_SYMBOL(ecm_interface_find_gateway);
463
464/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000465 * ecm_interface_mac_addr_get_ipv4()
466 * Return mac for an IPv4 address
467 */
468static bool ecm_interface_mac_addr_get_ipv4(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
469{
470 struct neighbour *neigh;
471 struct ecm_interface_route ecm_rt;
472 struct rtable *rt;
473 struct dst_entry *dst;
474 __be32 ipv4_addr;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530475
Ben Menchaca84f36632014-02-28 20:57:38 +0000476 /*
477 * Get the MAC address that corresponds to IP address given.
478 * We look up the rtable entries and, from its neighbour structure, obtain the hardware address.
479 * This means we will also work if the neighbours are routers too.
480 * We also locate the MAC if the address is a local host address.
481 */
482 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
483 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
Kiran Kumar C. S. K7d178222014-06-27 18:47:29 +0530484 *on_link = false;
Ben Menchaca84f36632014-02-28 20:57:38 +0000485 return false;
486 }
487 DEBUG_ASSERT(ecm_rt.v4_route, "Did not locate a v4 route!\n");
Murat Sezginb3731e82014-11-26 12:20:59 -0800488 DEBUG_TRACE("Found route\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000489
490 /*
491 * Is this destination on link or off-link via a gateway?
492 */
493 rt = ecm_rt.rt.rtv4;
Murat Sezginb3731e82014-11-26 12:20:59 -0800494#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000495 if ((rt->rt_dst != rt->rt_gateway) || (rt->rt_flags & RTF_GATEWAY)) {
Murat Sezginb3731e82014-11-26 12:20:59 -0800496#else
497 if (rt->rt_uses_gateway || (rt->rt_flags & RTF_GATEWAY)) {
498#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000499 *on_link = false;
500 ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway)
501 } else {
502 *on_link = true;
503 }
504
505 /*
506 * Get the neighbour entry for the address
507 */
508 rcu_read_lock();
509 dst = ecm_rt.dst;
Murat Sezginb3731e82014-11-26 12:20:59 -0800510#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000511 neigh = dst_get_neighbour_noref(dst);
512 if (neigh) {
513 neigh_hold(neigh);
Murat Sezginb3731e82014-11-26 12:20:59 -0800514 }
515#else
516 neigh = dst_neigh_lookup(dst, &ipv4_addr);
517#endif
518 if (!neigh) {
Ben Menchaca84f36632014-02-28 20:57:38 +0000519 neigh = neigh_lookup(&arp_tbl, &ipv4_addr, dst->dev);
520 }
521 if (!neigh) {
522 rcu_read_unlock();
523 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800524 DEBUG_WARN("no neigh\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000525 return false;
526 }
527 if (!(neigh->nud_state & NUD_VALID)) {
528 rcu_read_unlock();
529 neigh_release(neigh);
530 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800531 DEBUG_WARN("neigh nud state is not valid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000532 return false;
533 }
534 if (!neigh->dev) {
535 rcu_read_unlock();
536 neigh_release(neigh);
537 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800538 DEBUG_WARN("neigh has no device\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000539 return false;
540 }
541
542 /*
543 * If the device is loopback this will be because the address is a local address
544 * In this case locate the device that has this local address and get its mac.
545 */
546 if (neigh->dev->type == ARPHRD_LOOPBACK) {
547 struct net_device *dev;
548
549 DEBUG_TRACE("%pI4 finds loopback device, dev: %p (%s)\n", &ipv4_addr, neigh->dev, neigh->dev->name);
550 rcu_read_unlock();
551 neigh_release(neigh);
552 ecm_interface_route_release(&ecm_rt);
553
554 /*
555 * Lookup the device that has this IP address assigned
556 */
557 dev = ip_dev_find(&init_net, ipv4_addr);
558 if (!dev) {
559 DEBUG_WARN("Unable to locate dev for: %pI4\n", &ipv4_addr);
560 return false;
561 }
562 memcpy(mac_addr, dev->dev_addr, (size_t)dev->addr_len);
563 DEBUG_TRACE("is local addr: %pI4, mac: %pM, dev ifindex: %d, dev: %p (%s), dev_type: %d\n",
564 &ipv4_addr, mac_addr, dev->ifindex, dev, dev->name, dev->type);
565 dev_put(dev);
566 return true;
567 }
568
569 if (!(neigh->dev->flags & IFF_NOARP)) {
570 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
571 } else {
572 DEBUG_TRACE("non-arp device: %p (%s, type: %d) to reach %pI4\n", neigh->dev, neigh->dev->name, neigh->dev->type, &ipv4_addr);
573 memset(mac_addr, 0, 6);
574 }
575 DEBUG_TRACE("addr: %pI4, mac: %pM, iif: %d, neigh dev ifindex: %d, dev: %p (%s), dev_type: %d\n",
576 &ipv4_addr, mac_addr, rt->rt_iif, neigh->dev->ifindex, neigh->dev, neigh->dev->name, neigh->dev->type);
577
578 rcu_read_unlock();
579 neigh_release(neigh);
580 ecm_interface_route_release(&ecm_rt);
581 return true;
582}
583
584/*
585 * ecm_interface_mac_addr_get()
586 * Return the mac address for the given IP address. Returns false on failure.
Ben Menchaca84f36632014-02-28 20:57:38 +0000587 */
588bool ecm_interface_mac_addr_get(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
589{
590 if (ECM_IP_ADDR_IS_V4(addr)) {
591 return ecm_interface_mac_addr_get_ipv4(addr, mac_addr, on_link, gw_addr);
592 }
593
Gareth Williams8ac34292015-03-17 14:06:58 +0000594#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000595 return ecm_interface_mac_addr_get_ipv6(addr, mac_addr, on_link, gw_addr);
Murat Sezgin49465a42014-11-24 15:37:48 -0800596#else
597 return false;
598#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000599}
600EXPORT_SYMBOL(ecm_interface_mac_addr_get);
601
Murat Sezgin5dae8832015-12-03 14:23:19 -0800602#ifdef ECM_IPV6_ENABLE
603/*
604 * ecm_interface_mac_addr_get_ipv6_no_route()
605 * Finds the mac address of a node from its ip address reachable via
606 * the given device. It looks up the mac address in the neighbour entries.
607 * It doesn't do any route lookup to find the dst entry.
608 */
609static bool ecm_interface_mac_addr_get_ipv6_no_route(struct net_device *dev, ip_addr_t addr, uint8_t *mac_addr)
610{
611 struct in6_addr daddr;
612 struct neighbour *neigh;
613 struct net_device *local_dev;
614
615 memset(mac_addr, 0, ETH_ALEN);
616
617 /*
618 * Get the MAC address that corresponds to IP address given.
619 */
620 ECM_IP_ADDR_TO_NIN6_ADDR(daddr, addr);
621 local_dev = ipv6_dev_find(&init_net, &daddr, 1);
622 if (local_dev) {
623 DEBUG_TRACE("%pi6 is a local address\n", &daddr);
624 memcpy(mac_addr, dev->dev_addr, ETH_ALEN);
625 dev_put(local_dev);
626 return true;
627 }
628
629 rcu_read_lock();
630 neigh = neigh_lookup(&nd_tbl, &daddr, dev);
631 if (!neigh) {
632 rcu_read_unlock();
633 DEBUG_WARN("No neigh reference\n");
634 return false;
635 }
636 if (!(neigh->nud_state & NUD_VALID)) {
637 neigh_release(neigh);
638 rcu_read_unlock();
639 DEBUG_WARN("NUD invalid\n");
640 return false;
641 }
642 if (!neigh->dev) {
643 neigh_release(neigh);
644 rcu_read_unlock();
645 DEBUG_WARN("Neigh dev invalid\n");
646 return false;
647 }
648
649 if (neigh->dev->flags & IFF_NOARP) {
650 neigh_release(neigh);
651 rcu_read_unlock();
652 DEBUG_TRACE("dest MAC is zero: %pM\n", mac_addr);
653 return true;
654 }
655
656 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
657 neigh_release(neigh);
658 rcu_read_unlock();
659 DEBUG_TRACE(ECM_IP_ADDR_OCTAL_FMT " maps to %pM\n", ECM_IP_ADDR_TO_OCTAL(addr), mac_addr);
660 return true;
661}
662#endif
663
664/*
665 * ecm_interface_mac_addr_get_ipv4_no_route()
666 * Finds the mac address of a node from its ip address reachable via
667 * the given device. It looks up the mac address in the neighbour entries.
668 * It doesn't do any route lookup to find the dst entry.
669 */
670static bool ecm_interface_mac_addr_get_ipv4_no_route(struct net_device *dev, ip_addr_t ip_addr, uint8_t *mac_addr)
671{
672 struct neighbour *neigh;
673 __be32 be_addr;
674 struct net_device *local_dev;
675
676 memset(mac_addr, 0, ETH_ALEN);
677
678 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, ip_addr);
679 local_dev = ip_dev_find(&init_net, be_addr);
680 if (local_dev) {
681 DEBUG_TRACE("%pI4n is a local address\n", &be_addr);
682 memcpy(mac_addr, dev->dev_addr, ETH_ALEN);
683 dev_put(local_dev);
684 return true;
685 }
686
687 rcu_read_lock();
688 neigh = neigh_lookup(&arp_tbl, &be_addr, dev);
689 if (!neigh) {
690 rcu_read_unlock();
691 DEBUG_WARN("no neigh\n");
692 return false;
693 }
694 if (!(neigh->nud_state & NUD_VALID)) {
695 neigh_release(neigh);
696 rcu_read_unlock();
697 DEBUG_WARN("neigh nud state is not valid\n");
698 return false;
699 }
700 if (!neigh->dev) {
701 neigh_release(neigh);
702 rcu_read_unlock();
703 DEBUG_WARN("neigh has no device\n");
704 return false;
705 }
706
707 if (neigh->dev->flags & IFF_NOARP) {
708 neigh_release(neigh);
709 rcu_read_unlock();
710 DEBUG_TRACE("dest MAC is zero: %pM\n", mac_addr);
711 return true;
712 }
713
714 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
715 neigh_release(neigh);
716 rcu_read_unlock();
717 DEBUG_TRACE("dest MAC: %pM\n", mac_addr);
718 return true;
719
720}
721
722/*
723 * ecm_interface_mac_addr_get_no_route()
724 * Return the mac address for the given IP address reacahble via the given device.
725 * Return false on failure, true on success.
726 */
727bool ecm_interface_mac_addr_get_no_route(struct net_device *dev, ip_addr_t addr, uint8_t *mac_addr)
728{
729 if (ECM_IP_ADDR_IS_V4(addr)) {
730 return ecm_interface_mac_addr_get_ipv4_no_route(dev, addr, mac_addr);
731 }
732
733#ifdef ECM_IPV6_ENABLE
734 return ecm_interface_mac_addr_get_ipv6_no_route(dev, addr, mac_addr);
735#else
736 return false;
737#endif
738}
739EXPORT_SYMBOL(ecm_interface_mac_addr_get_no_route);
740
Shyam Sunder6358b862015-05-04 15:06:24 +0530741#ifdef ECM_MULTICAST_ENABLE
742/*
743 * ecm_interface_multicast_check_for_br_dev()
744 * Find a bridge dev is present or not in an
745 * array of Ifindexs
746 */
747bool ecm_interface_multicast_check_for_br_dev(uint32_t dest_if[], uint8_t max_if)
748{
749 struct net_device *br_dev;
750 int i;
751
752 for (i = 0; i < max_if; i++) {
753 br_dev = dev_get_by_index(&init_net, dest_if[i]);
754 if (!br_dev) {
755 DEBUG_ASSERT(NULL, "expected only valid netdev here\n");
756 continue;
757 }
758
759 if (ecm_front_end_is_bridge_device(br_dev)) {
760 dev_put(br_dev);
761 return true;
762 }
763 dev_put(br_dev);
764 }
765 return false;
766}
767EXPORT_SYMBOL(ecm_interface_multicast_check_for_br_dev);
Shyam Sundera2e08ee2015-06-18 21:32:13 +0530768
769/*
770 * ecm_interface_multicast_check_for_src_if_index()
771 * Find if a source netdev ifindex is matching with list of
772 * multicast destination netdev ifindex. If find a match then
773 * returns a new list of destination netdev ifindex excluding
774 * the ifindex of source netdev.
775 */
776int32_t ecm_interface_multicast_check_for_src_ifindex(int32_t mc_if_index[], int32_t max_if_index, int32_t if_num)
777{
778 int32_t i;
779 int32_t valid_index;
780
781 for (i = 0, valid_index = 0; i < max_if_index; i++) {
782 if (mc_if_index[i] == 0) {
783 break;
784 }
785
786 if (mc_if_index[i] != if_num) {
787 mc_if_index[valid_index] = mc_if_index[i];
788 valid_index++;
789 continue;
790 }
791 }
792
793 return valid_index;
794}
795EXPORT_SYMBOL(ecm_interface_multicast_check_for_src_ifindex);
Shyam Sunder6358b862015-05-04 15:06:24 +0530796#endif
797
Ben Menchaca84f36632014-02-28 20:57:38 +0000798/*
799 * ecm_interface_addr_find_route_by_addr_ipv4()
800 * Return the route for the given IP address. Returns NULL on failure.
801 */
802static bool ecm_interface_find_route_by_addr_ipv4(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
803{
804 __be32 be_addr;
805
806 /*
807 * Get a route to the given IP address, this will allow us to also find the interface
808 * it is using to communicate with that IP address.
809 */
810 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, addr);
811 ecm_rt->rt.rtv4 = ip_route_output(&init_net, be_addr, 0, 0, 0);
812 if (IS_ERR(ecm_rt->rt.rtv4)) {
813 DEBUG_TRACE("No output route to: %pI4n\n", &be_addr);
814 return false;
815 }
816 DEBUG_TRACE("Output route to: %pI4n is: %p\n", &be_addr, ecm_rt->rt.rtv4);
817 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv4;
818 ecm_rt->v4_route = true;
819 return true;
820}
821
Gareth Williams8ac34292015-03-17 14:06:58 +0000822#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000823/*
824 * ecm_interface_addr_find_route_by_addr_ipv6()
825 * Return the route for the given IP address. Returns NULL on failure.
826 */
827static bool ecm_interface_find_route_by_addr_ipv6(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
828{
829 struct in6_addr naddr;
830
831 ECM_IP_ADDR_TO_NIN6_ADDR(naddr, addr);
832
833 /*
834 * Get a route to the given IP address, this will allow us to also find the interface
835 * it is using to communicate with that IP address.
836 */
837 ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, 0);
838 if (!ecm_rt->rt.rtv6) {
839 DEBUG_TRACE("No output route to: " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
840 return NULL;
841 }
842 DEBUG_TRACE("Output route to: " ECM_IP_ADDR_OCTAL_FMT " is: %p\n", ECM_IP_ADDR_TO_OCTAL(addr), ecm_rt->rt.rtv6);
843 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv6;
844 ecm_rt->v4_route = false;
845 return true;
846}
Murat Sezgin49465a42014-11-24 15:37:48 -0800847#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000848
849/*
850 * ecm_interface_addr_find_route_by_addr()
851 * Return the route (in the given parameter) for the given IP address. Returns false on failure.
852 *
853 * Route is the device on which the addr is reachable, which may be loopback for local addresses.
854 *
855 * Returns true if the route was able to be located. The route must be released using ecm_interface_route_release().
856 */
857bool ecm_interface_find_route_by_addr(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
858{
859 char __attribute__((unused)) addr_str[40];
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530860
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100861 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
Ben Menchaca84f36632014-02-28 20:57:38 +0000862 DEBUG_TRACE("Locate route to: %s\n", addr_str);
863
864 if (ECM_IP_ADDR_IS_V4(addr)) {
865 return ecm_interface_find_route_by_addr_ipv4(addr, ecm_rt);
866 }
867
Gareth Williams8ac34292015-03-17 14:06:58 +0000868#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000869 return ecm_interface_find_route_by_addr_ipv6(addr, ecm_rt);
Murat Sezgin49465a42014-11-24 15:37:48 -0800870#else
871 return false;
872#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000873}
874EXPORT_SYMBOL(ecm_interface_find_route_by_addr);
875
876/*
877 * ecm_interface_route_release()
878 * Release an ecm route
879 */
880void ecm_interface_route_release(struct ecm_interface_route *rt)
881{
882 dst_release(rt->dst);
883}
884EXPORT_SYMBOL(ecm_interface_route_release);
885
Murat Sezgin188b4a32015-06-03 10:58:59 -0700886#ifdef ECM_IPV6_ENABLE
887/*
888 * ecm_interface_send_neighbour_solicitation()
889 * Issue an IPv6 Neighbour soliciation request.
890 */
891void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t addr)
892{
893 struct in6_addr dst_addr, src_addr;
894 struct in6_addr mc_dst_addr;
895 struct rt6_info *rt6i;
896 struct neighbour *neigh;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700897 struct net *netf = dev_net(dev);
898 int ret;
899
Murat Sezgin188b4a32015-06-03 10:58:59 -0700900 /*
901 * Find source and destination addresses in Linux format. We need
902 * mcast destination address as well.
903 */
904 ECM_IP_ADDR_TO_NIN6_ADDR(dst_addr, addr);
905 addrconf_addr_solict_mult(&dst_addr, &mc_dst_addr);
906 ret = ipv6_dev_get_saddr(netf, dev, &dst_addr, 0, &src_addr);
907
908 /*
Murat Sezgin188b4a32015-06-03 10:58:59 -0700909 * Find the route entry
910 */
911 rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0);
912 if (!rt6i) {
Murat Sezginf21210e2016-04-04 13:58:20 -0700913 DEBUG_TRACE("IPv6 Route lookup failure for destination IPv6 address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
Murat Sezgin188b4a32015-06-03 10:58:59 -0700914 return;
915 }
916
917 /*
918 * Find the neighbor entry
919 */
920#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
921 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, &dst_addr);
922#else
923 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr);
924#endif
925 if (neigh == NULL) {
Murat Sezginf21210e2016-04-04 13:58:20 -0700926 DEBUG_TRACE("Neighbour lookup failure for destination IPv6 address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
Murat Sezgin188b4a32015-06-03 10:58:59 -0700927 dst_release(&rt6i->dst);
928 return;
929 }
930
931 /*
932 * Issue a Neighbour soliciation request
933 */
934 DEBUG_TRACE("Issue Neighbour solicitation request\n");
Murat Sezgine1c51d82016-02-10 16:42:58 -0800935#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
Murat Sezgin188b4a32015-06-03 10:58:59 -0700936 ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr);
Murat Sezgine1c51d82016-02-10 16:42:58 -0800937#else
938 ndisc_send_ns(dev, &dst_addr, &mc_dst_addr, &src_addr);
939#endif
Murat Sezgin188b4a32015-06-03 10:58:59 -0700940 neigh_release(neigh);
941 dst_release(&rt6i->dst);
942}
943EXPORT_SYMBOL(ecm_interface_send_neighbour_solicitation);
944#endif
945
946/*
947 * ecm_interface_send_arp_request()
948 * Issue and ARP request.
949 */
950void ecm_interface_send_arp_request(struct net_device *dest_dev, ip_addr_t dest_addr, bool on_link, ip_addr_t gw_addr)
951{
952 /*
953 * Possible ARP does not know the address yet
954 */
Murat Sezgin4c093212016-03-24 14:59:02 -0700955 struct neighbour *neigh;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700956 __be32 ipv4_addr;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700957
958 /*
Murat Sezgin987493e2016-04-15 12:33:47 -0700959 * Convert the ECM IP address type to network order IPv4 address.
Murat Sezgin188b4a32015-06-03 10:58:59 -0700960 */
961 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700962
963 /*
964 * If we have a GW for this address, then we have to send ARP request to the GW
965 */
966 if (!on_link && !ECM_IP_ADDR_IS_NULL(gw_addr)) {
967 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, gw_addr);
968 }
969
Murat Sezgin4c093212016-03-24 14:59:02 -0700970 /*
971 * If we don't have this neighbor, create it before sending the arp request,
972 * so that when we receive the arp reply we update the neigh entry.
973 */
974 neigh = neigh_lookup(&arp_tbl, &ipv4_addr, dest_dev);
975 if (!neigh) {
Murat Sezgin987493e2016-04-15 12:33:47 -0700976 neigh = neigh_create(&arp_tbl, &ipv4_addr, dest_dev);
977 if (IS_ERR(neigh)) {
978 DEBUG_WARN("Unable to create ARP request neigh for %pI4\n", &ipv4_addr);
979 return;
980 }
Murat Sezgin4c093212016-03-24 14:59:02 -0700981 }
Murat Sezgin188b4a32015-06-03 10:58:59 -0700982
Murat Sezgin987493e2016-04-15 12:33:47 -0700983 DEBUG_TRACE("Send ARP for %pI4\n", &ipv4_addr);
984 neigh_event_send(neigh, NULL);
985 neigh_release(neigh);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700986}
987EXPORT_SYMBOL(ecm_interface_send_arp_request);
988
Xiaoping Fanc7735462015-08-09 18:57:26 -0700989/*
990 * ecm_interface_ipv4_neigh_get()
991 * Returns neighbour reference for a given IP address which must be released when you are done with it.
992 *
993 * Returns NULL on fail.
994 */
995struct neighbour *ecm_interface_ipv4_neigh_get(ip_addr_t addr)
996{
997 struct neighbour *neigh;
998 struct rtable *rt;
999 struct dst_entry *dst;
1000 __be32 ipv4_addr;
1001
1002 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
1003 rt = ip_route_output(&init_net, ipv4_addr, 0, 0, 0);
1004 if (IS_ERR(rt)) {
1005 return NULL;
1006 }
1007 dst = (struct dst_entry *)rt;
1008 neigh = dst_neigh_lookup(dst, &ipv4_addr);
1009 ip_rt_put(rt);
1010 return neigh;
1011}
1012
1013#ifdef ECM_IPV6_ENABLE
1014/*
1015 * ecm_interface_ipv6_neigh_get()
1016 * Returns neighbour reference for a given IP address which must be released when you are done with it.
1017 *
1018 * Returns NULL on fail.
1019 */
1020struct neighbour *ecm_interface_ipv6_neigh_get(ip_addr_t addr)
1021{
1022 struct neighbour *neigh;
1023 struct rt6_info *rt;
1024 struct dst_entry *dst;
1025 struct in6_addr ipv6_addr;
1026
1027 ECM_IP_ADDR_TO_NIN6_ADDR(ipv6_addr, addr);
1028 rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0);
1029 if (!rt) {
1030 return NULL;
1031 }
1032 dst = (struct dst_entry *)rt;
1033 neigh = dst_neigh_lookup(dst, &ipv6_addr);
1034 dst_release(dst);
1035 return neigh;
1036}
1037#endif
1038
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301039/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301040 * ecm_interface_is_pptp()
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301041 * skip pptp tunnel encapsulated traffic
1042 *
Shyam Sunder23f2e542015-09-28 14:56:49 +05301043 * ECM does not handle PPTP,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301044 * this function detects packets of that type so they can be skipped over to improve their throughput.
1045 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301046bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out)
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301047{
1048 struct ppp_channel *ppp_chan[1];
1049 int px_proto;
1050 struct net_device *in;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301051
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301052 if (out->type == ARPHRD_PPP) {
1053 if (ppp_hold_channels((struct net_device *)out, ppp_chan, 1) != 1) {
1054 return true;
1055 }
1056
1057 px_proto = ppp_channel_get_protocol(ppp_chan[0]);
1058
1059 /*
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301060 * Skip PPTP packets
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301061 */
1062 if (px_proto == PX_PROTO_PPTP) {
1063 ppp_release_channels(ppp_chan, 1);
1064 return true;
1065 }
1066
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301067 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301068 }
1069
1070 in = dev_get_by_index(&init_net, skb->skb_iif);
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301071 if (!in) {
1072 return true;
1073 }
1074
1075 if (in->type == ARPHRD_PPP) {
1076 if (__ppp_hold_channels((struct net_device *)in, ppp_chan, 1) != 1) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301077 dev_put(in);
1078 return true;
1079 }
1080
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301081 px_proto = ppp_channel_get_protocol(ppp_chan[0]);
1082
1083 /*
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301084 * Skip PPTP pkts
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301085 */
1086 if (px_proto == PX_PROTO_PPTP) {
1087 ppp_release_channels(ppp_chan, 1);
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301088 dev_put(in);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301089 return true;
1090 }
1091
Shyam Sunder23f2e542015-09-28 14:56:49 +05301092 ppp_release_channels(ppp_chan, 1);
1093 }
1094
1095 dev_put(in);
1096 return false;
1097}
1098
Shyam Sunder2ca02492016-08-05 20:55:12 +05301099#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder23f2e542015-09-28 14:56:49 +05301100/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301101 * ecm_interface_is_l2tp_packet_by_version()
Shyam Sunder23f2e542015-09-28 14:56:49 +05301102 * Check version of l2tp tunnel encapsulated traffic
1103 *
1104 * ECM does not handle l2tp,
1105 * this function detects packets of that type so they can be skipped over to improve their throughput.
1106 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301107bool ecm_interface_is_l2tp_packet_by_version(struct sk_buff *skb, const struct net_device *out, int ver)
Shyam Sunder23f2e542015-09-28 14:56:49 +05301108{
1109 struct ppp_channel *ppp_chan[1];
1110 int px_proto;
1111 struct net_device *in;
1112
1113 if (out->type == ARPHRD_PPP) {
1114 if (ppp_hold_channels((struct net_device *)out, ppp_chan, 1) != 1) {
1115 return true;
1116 }
1117
1118 px_proto = ppp_channel_get_protocol(ppp_chan[0]);
1119
1120 /*
1121 * Check for L2TPv3 packets
1122 */
1123 if (px_proto == PX_PROTO_OL2TP) {
1124 struct pppol2tp_common_addr info;
1125 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
1126 ppp_release_channels(ppp_chan, 1);
1127 return true;
1128 }
1129
1130 if (info.tunnel_version == ver) {
1131 ppp_release_channels(ppp_chan, 1);
1132 return true;
1133 }
1134 }
1135 ppp_release_channels(ppp_chan, 1);
1136 }
1137
1138 in = dev_get_by_index(&init_net, skb->skb_iif);
1139 if (!in) {
1140 return true;
1141 }
1142
1143 if (in->type == ARPHRD_PPP) {
1144 if (__ppp_hold_channels((struct net_device *)in, ppp_chan, 1) != 1) {
1145 dev_put(in);
1146 return true;
1147 }
1148
1149 px_proto = ppp_channel_get_protocol(ppp_chan[0]);
1150
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301151 /*
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301152 * Check for L2TPv3 pkts
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301153 */
1154 if (px_proto == PX_PROTO_OL2TP) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301155 struct pppol2tp_common_addr info;
1156 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301157 ppp_release_channels(ppp_chan, 1);
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301158 dev_put(in);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301159 return true;
1160 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05301161
1162 if (info.tunnel_version == ver) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301163 ppp_release_channels(ppp_chan, 1);
1164 dev_put(in);
1165 return true;
1166 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301167 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301168 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301169 }
1170
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301171 dev_put(in);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301172 return false;
1173}
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301174
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001175/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301176 * ecm_interface_is_l2tp_pptp()
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001177 * skip l2tp/pptp tunnel encapsulated traffic
1178 *
1179 * ECM does not handle L2TP or PPTP encapsulated packets,
1180 * this function detects packets of that type so they can be skipped over to improve their throughput.
1181 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301182bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *out)
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001183{
1184 struct ppp_channel *ppp_chan[1];
1185 int px_proto;
1186
1187 /*
1188 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1189 */
1190 if (out->type == ARPHRD_PPP) {
1191 if (ppp_hold_channels((struct net_device *)out, ppp_chan, 1) == 1) {
1192 px_proto = ppp_channel_get_protocol(ppp_chan[0]);
1193 ppp_release_channels(ppp_chan, 1);
1194 return ((px_proto == PX_PROTO_OL2TP) || (px_proto == PX_PROTO_PPTP));
1195 }
1196 }
1197
1198 /*
1199 * skip second pass of l2tp tunnel encapsulated traffic
1200 */
1201 if (!skb->sk) {
1202 return false;
1203 }
1204
1205 if (skb->sk->sk_protocol != IPPROTO_UDP) {
1206 return false;
1207 }
1208
1209 if (unlikely(udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
1210 return true;
1211 }
1212
1213 return false;
1214}
1215#endif
1216
Gareth Williams141d2382014-11-25 11:35:19 -08001217#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001218/*
Ben Menchaca84f36632014-02-28 20:57:38 +00001219 * ecm_interface_vlan_interface_establish()
1220 * Returns a reference to a iface of the VLAN type, possibly creating one if necessary.
1221 * Returns NULL on failure or a reference to interface.
1222 */
1223static struct ecm_db_iface_instance *ecm_interface_vlan_interface_establish(struct ecm_db_interface_info_vlan *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001224 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001225{
1226 struct ecm_db_iface_instance *nii;
1227 struct ecm_db_iface_instance *ii;
1228
Murat Sezgin91c5d712015-06-12 15:16:22 -07001229 DEBUG_INFO("Establish VLAN iface: %s with address: %pM, vlan tag: %u, vlan_tpid: %x MTU: %d, if num: %d, accel engine if id: %d\n",
1230 dev_name, type_info->address, type_info->vlan_tag, type_info->vlan_tpid, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001231
1232 /*
1233 * Locate the iface
1234 */
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301235 ii = ecm_db_iface_find_and_ref_vlan(type_info->address, type_info->vlan_tag, type_info->vlan_tpid);
Ben Menchaca84f36632014-02-28 20:57:38 +00001236 if (ii) {
1237 DEBUG_TRACE("%p: iface established\n", ii);
1238 return ii;
1239 }
1240
1241 /*
1242 * No iface - create one
1243 */
1244 nii = ecm_db_iface_alloc();
1245 if (!nii) {
1246 DEBUG_WARN("Failed to establish iface\n");
1247 return NULL;
1248 }
1249
1250 /*
1251 * Add iface into the database, atomically to avoid races creating the same thing
1252 */
1253 spin_lock_bh(&ecm_interface_lock);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301254 ii = ecm_db_iface_find_and_ref_vlan(type_info->address, type_info->vlan_tag, type_info->vlan_tpid);
Ben Menchaca84f36632014-02-28 20:57:38 +00001255 if (ii) {
1256 spin_unlock_bh(&ecm_interface_lock);
1257 ecm_db_iface_deref(nii);
1258 return ii;
1259 }
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301260 ecm_db_iface_add_vlan(nii, type_info->address, type_info->vlan_tag, type_info->vlan_tpid, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001261 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001262 spin_unlock_bh(&ecm_interface_lock);
1263
1264 DEBUG_TRACE("%p: vlan iface established\n", nii);
1265 return nii;
1266}
Gareth Williams141d2382014-11-25 11:35:19 -08001267#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001268
1269/*
1270 * ecm_interface_bridge_interface_establish()
1271 * Returns a reference to a iface of the BRIDGE type, possibly creating one if necessary.
1272 * Returns NULL on failure or a reference to interface.
1273 */
1274static struct ecm_db_iface_instance *ecm_interface_bridge_interface_establish(struct ecm_db_interface_info_bridge *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001275 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001276{
1277 struct ecm_db_iface_instance *nii;
1278 struct ecm_db_iface_instance *ii;
1279
Murat Sezgin91c5d712015-06-12 15:16:22 -07001280 DEBUG_INFO("Establish BRIDGE iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1281 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001282
1283 /*
1284 * Locate the iface
1285 */
1286 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1287 if (ii) {
1288 DEBUG_TRACE("%p: iface established\n", ii);
1289 return ii;
1290 }
1291
1292 /*
1293 * No iface - create one
1294 */
1295 nii = ecm_db_iface_alloc();
1296 if (!nii) {
1297 DEBUG_WARN("Failed to establish iface\n");
1298 return NULL;
1299 }
1300
1301 /*
1302 * Add iface into the database, atomically to avoid races creating the same thing
1303 */
1304 spin_lock_bh(&ecm_interface_lock);
1305 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1306 if (ii) {
1307 spin_unlock_bh(&ecm_interface_lock);
1308 ecm_db_iface_deref(nii);
1309 return ii;
1310 }
1311 ecm_db_iface_add_bridge(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001312 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001313 spin_unlock_bh(&ecm_interface_lock);
1314
1315 DEBUG_TRACE("%p: bridge iface established\n", nii);
1316 return nii;
1317}
1318
Murat Sezgin910c9662015-03-11 16:15:06 -07001319#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001320/*
1321 * ecm_interface_lag_interface_establish()
1322 * Returns a reference to a iface of the LAG type, possibly creating one if necessary.
1323 * Returns NULL on failure or a reference to interface.
1324 */
1325static struct ecm_db_iface_instance *ecm_interface_lag_interface_establish(struct ecm_db_interface_info_lag *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001326 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001327{
1328 struct ecm_db_iface_instance *nii;
1329 struct ecm_db_iface_instance *ii;
1330
Murat Sezgin91c5d712015-06-12 15:16:22 -07001331 DEBUG_INFO("Establish LAG iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1332 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001333
1334 /*
1335 * Locate the iface
1336 */
1337 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1338 if (ii) {
1339 DEBUG_TRACE("%p: iface established\n", ii);
1340 return ii;
1341 }
1342
1343 /*
1344 * No iface - create one
1345 */
1346 nii = ecm_db_iface_alloc();
1347 if (!nii) {
1348 DEBUG_WARN("Failed to establish iface\n");
1349 return NULL;
1350 }
1351
1352 /*
1353 * Add iface into the database, atomically to avoid races creating the same thing
1354 */
1355 spin_lock_bh(&ecm_interface_lock);
1356 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1357 if (ii) {
1358 spin_unlock_bh(&ecm_interface_lock);
1359 ecm_db_iface_deref(nii);
1360 return ii;
1361 }
1362 ecm_db_iface_add_lag(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001363 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001364 spin_unlock_bh(&ecm_interface_lock);
1365
1366 DEBUG_TRACE("%p: lag iface established\n", nii);
1367 return nii;
1368}
Murat Sezgin910c9662015-03-11 16:15:06 -07001369#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001370
1371/*
1372 * ecm_interface_ethernet_interface_establish()
1373 * Returns a reference to a iface of the ETHERNET type, possibly creating one if necessary.
1374 * Returns NULL on failure or a reference to interface.
1375 */
1376static struct ecm_db_iface_instance *ecm_interface_ethernet_interface_establish(struct ecm_db_interface_info_ethernet *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001377 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001378{
1379 struct ecm_db_iface_instance *nii;
1380 struct ecm_db_iface_instance *ii;
1381
Murat Sezgin91c5d712015-06-12 15:16:22 -07001382 DEBUG_INFO("Establish ETHERNET iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1383 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001384
1385 /*
1386 * Locate the iface
1387 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301388 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
1389
Ben Menchaca84f36632014-02-28 20:57:38 +00001390 if (ii) {
1391 DEBUG_TRACE("%p: iface established\n", ii);
Murat Sezgin5f2947a2016-06-28 12:09:33 -07001392 /*
1393 * Update the accel engine interface identifier, just in case it was changed.
1394 */
1395 ecm_db_iface_ae_interface_identifier_set(ii, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001396 return ii;
1397 }
1398
1399 /*
1400 * No iface - create one
1401 */
1402 nii = ecm_db_iface_alloc();
1403 if (!nii) {
1404 DEBUG_WARN("Failed to establish iface\n");
1405 return NULL;
1406 }
1407
1408 /*
1409 * Add iface into the database, atomically to avoid races creating the same thing
1410 */
1411 spin_lock_bh(&ecm_interface_lock);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301412 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001413 if (ii) {
1414 spin_unlock_bh(&ecm_interface_lock);
1415 ecm_db_iface_deref(nii);
1416 return ii;
1417 }
1418 ecm_db_iface_add_ethernet(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001419 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001420 spin_unlock_bh(&ecm_interface_lock);
1421
1422 DEBUG_TRACE("%p: ethernet iface established\n", nii);
1423 return nii;
1424}
1425
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301426#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001427/*
1428 * ecm_interface_pppoe_interface_establish()
1429 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1430 * Returns NULL on failure or a reference to interface.
1431 */
1432static struct ecm_db_iface_instance *ecm_interface_pppoe_interface_establish(struct ecm_db_interface_info_pppoe *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001433 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001434{
1435 struct ecm_db_iface_instance *nii;
1436 struct ecm_db_iface_instance *ii;
1437
Murat Sezgin91c5d712015-06-12 15:16:22 -07001438 DEBUG_INFO("Establish PPPoE iface: %s with session id: %u, remote mac: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1439 dev_name, type_info->pppoe_session_id, type_info->remote_mac, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001440
1441 /*
1442 * Locate the iface
1443 */
1444 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1445 if (ii) {
1446 DEBUG_TRACE("%p: iface established\n", ii);
1447 return ii;
1448 }
1449
1450 /*
1451 * No iface - create one
1452 */
1453 nii = ecm_db_iface_alloc();
1454 if (!nii) {
1455 DEBUG_WARN("Failed to establish iface\n");
1456 return NULL;
1457 }
1458
1459 /*
1460 * Add iface into the database, atomically to avoid races creating the same thing
1461 */
1462 spin_lock_bh(&ecm_interface_lock);
1463 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1464 if (ii) {
1465 spin_unlock_bh(&ecm_interface_lock);
1466 ecm_db_iface_deref(nii);
1467 return ii;
1468 }
1469 ecm_db_iface_add_pppoe(nii, type_info->pppoe_session_id, type_info->remote_mac, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001470 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001471 spin_unlock_bh(&ecm_interface_lock);
1472
1473 DEBUG_TRACE("%p: pppoe iface established\n", nii);
1474 return nii;
1475}
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001476#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001477
ratheesh kannothcfdcb332015-12-24 07:19:18 +05301478#ifdef ECM_INTERFACE_MAP_T_ENABLE
1479/*
1480 * ecm_interface_map_t_interface_establish()
1481 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1482 * Returns NULL on failure or a reference to interface.
1483 */
1484static struct ecm_db_iface_instance *ecm_interface_map_t_interface_establish(struct ecm_db_interface_info_map_t *type_info,
1485 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1486{
1487 struct ecm_db_iface_instance *nii;
1488 struct ecm_db_iface_instance *ii;
1489
1490 DEBUG_TRACE("Establish MAP-T iface: %s MTU: %d, if num: %d, accel engine if id: %d\n",
1491 dev_name, mtu, dev_interface_num, ae_interface_num);
1492
1493 /*
1494 * Locate the iface
1495 */
1496 ii = ecm_db_iface_find_and_ref_map_t(type_info->if_index);
1497 if (ii) {
1498 DEBUG_TRACE("%p: iface established\n", ii);
1499 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1500 return ii;
1501 }
1502
1503 /*
1504 * No iface - create one
1505 */
1506 nii = ecm_db_iface_alloc();
1507 if (!nii) {
1508 DEBUG_WARN("Failed to establish iface\n");
1509 return NULL;
1510 }
1511
1512 /*
1513 * Add iface into the database, atomically to avoid races creating the same thing
1514 */
1515 spin_lock_bh(&ecm_interface_lock);
1516 ii = ecm_db_iface_find_and_ref_map_t(type_info->if_index);
1517 if (ii) {
1518 spin_unlock_bh(&ecm_interface_lock);
1519 ecm_db_iface_deref(nii);
1520 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1521 return ii;
1522 }
1523 ecm_db_iface_add_map_t(nii, type_info, dev_name,
1524 mtu, dev_interface_num, ae_interface_num, NULL, nii);
1525 spin_unlock_bh(&ecm_interface_lock);
1526
1527 DEBUG_TRACE("%p: map_t iface established\n", nii);
1528 return nii;
1529}
1530#endif
1531
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301532#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1533/*
1534 * ecm_interface_pppol2tpv2_interface_establish()
1535 * Returns a reference to a iface of the PPPoL2TPV2 type, possibly creating one if necessary.
1536 * Returns NULL on failure or a reference to interface.
1537 */
1538static struct ecm_db_iface_instance *ecm_interface_pppol2tpv2_interface_establish(struct ecm_db_interface_info_pppol2tpv2 *type_info,
1539 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1540{
1541 struct ecm_db_iface_instance *nii;
1542 struct ecm_db_iface_instance *ii;
1543
1544 DEBUG_INFO("Establish PPPol2tp iface: %s with tunnel id=%u session id %u\n", dev_name, type_info->l2tp.tunnel.tunnel_id,
1545 type_info->l2tp.session.session_id);
1546 /*
1547 * Locate the iface
1548 */
1549 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1550 if (ii) {
1551 DEBUG_TRACE("%p: iface established\n", ii);
ratheesh kannothed721852015-09-28 12:39:52 +05301552 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301553 return ii;
1554 }
1555
1556 /*
1557 * No iface - create one
1558 */
1559 nii = ecm_db_iface_alloc();
1560 if (!nii) {
1561 DEBUG_WARN("Failed to establish iface\n");
1562 return NULL;
1563 }
1564
1565 /*
1566 * Add iface into the database, atomically to avoid races creating the same thing
1567 */
1568 spin_lock_bh(&ecm_interface_lock);
1569 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1570 if (ii) {
1571 spin_unlock_bh(&ecm_interface_lock);
1572 ecm_db_iface_deref(nii);
ratheesh kannothed721852015-09-28 12:39:52 +05301573 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301574 return ii;
1575 }
1576
1577 ecm_db_iface_add_pppol2tpv2(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1578 spin_unlock_bh(&ecm_interface_lock);
1579
1580 DEBUG_TRACE("%p: pppol2tpv2 iface established\n", nii);
1581 return nii;
1582}
1583
1584#endif
1585
Shyam Sunder23f2e542015-09-28 14:56:49 +05301586#ifdef ECM_INTERFACE_PPTP_ENABLE
1587/*
1588 * ecm_interface_pptp_interface_establish()
1589 * Returns a reference to a iface of the PPTP type, possibly creating one if necessary.
1590 * Returns NULL on failure or a reference to interface.
1591 */
1592static struct ecm_db_iface_instance *ecm_interface_pptp_interface_establish(struct ecm_db_interface_info_pptp *type_info,
1593 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1594{
1595 struct ecm_db_iface_instance *nii;
1596 struct ecm_db_iface_instance *ii;
1597
1598 DEBUG_INFO("Establish PPTP iface: %s with local call id %u peer call id %u\n", dev_name, type_info->src_call_id,
1599 type_info->dst_call_id);
1600 /*
1601 * Locate the iface
1602 */
1603 ii = ecm_db_iface_find_and_ref_pptp(type_info->src_call_id, type_info->dst_call_id);
1604 if (ii) {
1605 DEBUG_TRACE("%p: iface established\n", ii);
1606 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1607 return ii;
1608 }
1609
1610 /*
1611 * No iface - create one
1612 */
1613 nii = ecm_db_iface_alloc();
1614 if (!nii) {
1615 DEBUG_WARN("Failed to establish iface\n");
1616 return NULL;
1617 }
1618
1619 /*
1620 * Add iface into the database, atomically to avoid races creating the same thing
1621 */
1622 spin_lock_bh(&ecm_interface_lock);
1623 ii = ecm_db_iface_find_and_ref_pptp(type_info->src_call_id, type_info->dst_call_id);
1624 if (ii) {
1625 spin_unlock_bh(&ecm_interface_lock);
1626 ecm_db_iface_deref(nii);
1627 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1628 return ii;
1629 }
1630
1631 ecm_db_iface_add_pptp(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1632 spin_unlock_bh(&ecm_interface_lock);
1633
1634 DEBUG_TRACE("%p: pptp iface established\n", nii);
1635 return nii;
1636}
1637#endif
1638
Ben Menchaca84f36632014-02-28 20:57:38 +00001639/*
1640 * ecm_interface_unknown_interface_establish()
1641 * Returns a reference to a iface of the UNKNOWN type, possibly creating one if necessary.
1642 * Returns NULL on failure or a reference to interface.
1643 */
1644static struct ecm_db_iface_instance *ecm_interface_unknown_interface_establish(struct ecm_db_interface_info_unknown *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001645 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001646{
1647 struct ecm_db_iface_instance *nii;
1648 struct ecm_db_iface_instance *ii;
1649
Murat Sezgin91c5d712015-06-12 15:16:22 -07001650 DEBUG_INFO("Establish UNKNOWN iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1651 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001652
1653 /*
1654 * Locate the iface
1655 */
1656 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1657 if (ii) {
1658 DEBUG_TRACE("%p: iface established\n", ii);
1659 return ii;
1660 }
1661
1662 /*
1663 * No iface - create one
1664 */
1665 nii = ecm_db_iface_alloc();
1666 if (!nii) {
1667 DEBUG_WARN("Failed to establish iface\n");
1668 return NULL;
1669 }
1670
1671 /*
1672 * Add iface into the database, atomically to avoid races creating the same thing
1673 */
1674 spin_lock_bh(&ecm_interface_lock);
1675 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1676 if (ii) {
1677 spin_unlock_bh(&ecm_interface_lock);
1678 ecm_db_iface_deref(nii);
1679 return ii;
1680 }
1681 ecm_db_iface_add_unknown(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001682 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001683 spin_unlock_bh(&ecm_interface_lock);
1684
1685 DEBUG_TRACE("%p: unknown iface established\n", nii);
1686 return nii;
1687}
1688
1689/*
1690 * ecm_interface_loopback_interface_establish()
1691 * Returns a reference to a iface of the LOOPBACK type, possibly creating one if necessary.
1692 * Returns NULL on failure or a reference to interface.
1693 */
1694static struct ecm_db_iface_instance *ecm_interface_loopback_interface_establish(struct ecm_db_interface_info_loopback *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001695 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001696{
1697 struct ecm_db_iface_instance *nii;
1698 struct ecm_db_iface_instance *ii;
1699
Murat Sezgin91c5d712015-06-12 15:16:22 -07001700 DEBUG_INFO("Establish LOOPBACK iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1701 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001702
1703 /*
1704 * Locate the iface
1705 */
1706 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1707 if (ii) {
1708 DEBUG_TRACE("%p: iface established\n", ii);
1709 return ii;
1710 }
1711
1712 /*
1713 * No iface - create one
1714 */
1715 nii = ecm_db_iface_alloc();
1716 if (!nii) {
1717 DEBUG_WARN("Failed to establish iface\n");
1718 return NULL;
1719 }
1720
1721 /*
1722 * Add iface into the database, atomically to avoid races creating the same thing
1723 */
1724 spin_lock_bh(&ecm_interface_lock);
1725 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1726 if (ii) {
1727 spin_unlock_bh(&ecm_interface_lock);
1728 ecm_db_iface_deref(nii);
1729 return ii;
1730 }
1731 ecm_db_iface_add_loopback(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001732 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001733 spin_unlock_bh(&ecm_interface_lock);
1734
1735 DEBUG_TRACE("%p: loopback iface established\n", nii);
1736 return nii;
1737}
1738
Murat Sezgin69a27532015-03-12 14:09:40 -07001739#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001740/*
1741 * ecm_interface_ipsec_tunnel_interface_establish()
1742 * Returns a reference to a iface of the IPSEC_TUNNEL type, possibly creating one if necessary.
1743 * Returns NULL on failure or a reference to interface.
1744 *
1745 * NOTE: GGG TODO THIS NEEDS TO TAKE A PROPER APPROACH TO IPSEC TUNNELS USING ENDPOINT ADDRESSING AS THE TYPE INFO KEYS
1746 */
1747static struct ecm_db_iface_instance *ecm_interface_ipsec_tunnel_interface_establish(struct ecm_db_interface_info_ipsec_tunnel *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001748 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001749{
1750 struct ecm_db_iface_instance *nii;
1751 struct ecm_db_iface_instance *ii;
1752
Murat Sezgin91c5d712015-06-12 15:16:22 -07001753 DEBUG_INFO("Establish IPSEC_TUNNEL iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1754 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001755
1756 /*
1757 * Locate the iface
1758 */
1759 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1760 if (ii) {
1761 DEBUG_TRACE("%p: iface established\n", ii);
1762 return ii;
1763 }
1764
1765 /*
1766 * No iface - create one
1767 */
1768 nii = ecm_db_iface_alloc();
1769 if (!nii) {
1770 DEBUG_WARN("Failed to establish iface\n");
1771 return NULL;
1772 }
1773
1774 /*
1775 * Add iface into the database, atomically to avoid races creating the same thing
1776 */
1777 spin_lock_bh(&ecm_interface_lock);
1778 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1779 if (ii) {
1780 spin_unlock_bh(&ecm_interface_lock);
1781 ecm_db_iface_deref(nii);
1782 return ii;
1783 }
1784 ecm_db_iface_add_ipsec_tunnel(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001785 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001786 spin_unlock_bh(&ecm_interface_lock);
1787
1788 DEBUG_TRACE("%p: ipsec_tunnel iface established\n", nii);
1789 return nii;
1790}
Murat Sezgin69a27532015-03-12 14:09:40 -07001791#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001792
Murat Sezginb3731e82014-11-26 12:20:59 -08001793#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07001794#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00001795/*
1796 * ecm_interface_sit_interface_establish()
1797 * Returns a reference to a iface of the SIT type, possibly creating one if necessary.
1798 * Returns NULL on failure or a reference to interface.
1799 */
1800static struct ecm_db_iface_instance *ecm_interface_sit_interface_establish(struct ecm_db_interface_info_sit *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001801 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001802{
1803 struct ecm_db_iface_instance *nii;
1804 struct ecm_db_iface_instance *ii;
1805
Murat Sezgin91c5d712015-06-12 15:16:22 -07001806 DEBUG_INFO("Establish SIT iface: %s with saddr: " ECM_IP_ADDR_OCTAL_FMT ", daddr: " ECM_IP_ADDR_OCTAL_FMT ", MTU: %d, if num: %d, accel engine if id: %d\n",
1807 dev_name, ECM_IP_ADDR_TO_OCTAL(type_info->saddr), ECM_IP_ADDR_TO_OCTAL(type_info->daddr), mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001808
1809 /*
1810 * Locate the iface
1811 */
1812 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr);
1813 if (ii) {
1814 DEBUG_TRACE("%p: iface established\n", ii);
1815 return ii;
1816 }
1817
1818 /*
1819 * No iface - create one
1820 */
1821 nii = ecm_db_iface_alloc();
1822 if (!nii) {
1823 DEBUG_WARN("Failed to establish iface\n");
1824 return NULL;
1825 }
1826
1827 /*
1828 * Add iface into the database, atomically to avoid races creating the same thing
1829 */
1830 spin_lock_bh(&ecm_interface_lock);
1831 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr);
1832 if (ii) {
1833 spin_unlock_bh(&ecm_interface_lock);
1834 ecm_db_iface_deref(nii);
1835 return ii;
1836 }
1837 ecm_db_iface_add_sit(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001838 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001839 spin_unlock_bh(&ecm_interface_lock);
1840
1841 DEBUG_TRACE("%p: sit iface established\n", nii);
1842 return nii;
1843}
Murat Sezgincc6eedf2014-05-09 23:59:19 -07001844#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08001845#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001846
Murat Sezginc1402562015-03-12 12:32:20 -07001847#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001848#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001849/*
1850 * ecm_interface_tunipip6_interface_establish()
1851 * Returns a reference to a iface of the TUNIPIP6 type, possibly creating one if necessary.
1852 * Returns NULL on failure or a reference to interface.
1853 */
1854static struct ecm_db_iface_instance *ecm_interface_tunipip6_interface_establish(struct ecm_db_interface_info_tunipip6 *type_info,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001855 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001856{
1857 struct ecm_db_iface_instance *nii;
1858 struct ecm_db_iface_instance *ii;
1859
Murat Sezgin91c5d712015-06-12 15:16:22 -07001860 DEBUG_INFO("Establish TUNIPIP6 iface: %s with saddr: " ECM_IP_ADDR_OCTAL_FMT ", daddr: " ECM_IP_ADDR_OCTAL_FMT ", MTU: %d, if num: %d, accel engine if id: %d\n",
1861 dev_name, ECM_IP_ADDR_TO_OCTAL(type_info->saddr), ECM_IP_ADDR_TO_OCTAL(type_info->daddr), mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001862
1863 /*
1864 * Locate the iface
1865 */
1866 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1867 if (ii) {
1868 DEBUG_TRACE("%p: iface established\n", ii);
1869 return ii;
1870 }
1871
1872 /*
1873 * No iface - create one
1874 */
1875 nii = ecm_db_iface_alloc();
1876 if (!nii) {
1877 DEBUG_WARN("Failed to establish iface\n");
1878 return NULL;
1879 }
1880
1881 /*
1882 * Add iface into the database, atomically to avoid races creating the same thing
1883 */
1884 spin_lock_bh(&ecm_interface_lock);
1885 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1886 if (ii) {
1887 spin_unlock_bh(&ecm_interface_lock);
1888 ecm_db_iface_deref(nii);
1889 return ii;
1890 }
1891 ecm_db_iface_add_tunipip6(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001892 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001893 spin_unlock_bh(&ecm_interface_lock);
1894
1895 DEBUG_TRACE("%p: tunipip6 iface established\n", nii);
1896 return nii;
1897}
Murat Sezginc1402562015-03-12 12:32:20 -07001898#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001899#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001900
1901/*
1902 * ecm_interface_establish_and_ref()
1903 * Establish an interface instance for the given interface detail.
1904 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001905struct ecm_db_iface_instance *ecm_interface_establish_and_ref(struct ecm_front_end_connection_instance *feci,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301906 struct net_device *dev, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00001907{
1908 int32_t dev_interface_num;
1909 char *dev_name;
1910 int32_t dev_type;
1911 int32_t dev_mtu;
Murat Sezgin91c5d712015-06-12 15:16:22 -07001912 int32_t ae_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00001913 struct ecm_db_iface_instance *ii;
1914 union {
1915 struct ecm_db_interface_info_ethernet ethernet; /* type == ECM_DB_IFACE_TYPE_ETHERNET */
Gareth Williams141d2382014-11-25 11:35:19 -08001916#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001917 struct ecm_db_interface_info_vlan vlan; /* type == ECM_DB_IFACE_TYPE_VLAN */
Gareth Williams141d2382014-11-25 11:35:19 -08001918#endif
Murat Sezgin910c9662015-03-11 16:15:06 -07001919#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001920 struct ecm_db_interface_info_lag lag; /* type == ECM_DB_IFACE_TYPE_LAG */
Murat Sezgin910c9662015-03-11 16:15:06 -07001921#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001922 struct ecm_db_interface_info_bridge bridge; /* type == ECM_DB_IFACE_TYPE_BRIDGE */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301923#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001924 struct ecm_db_interface_info_pppoe pppoe; /* type == ECM_DB_IFACE_TYPE_PPPOE */
Murat Sezginaad635c2015-03-06 16:11:41 -08001925#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301926#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1927 struct ecm_db_interface_info_pppol2tpv2 pppol2tpv2; /* type == ECM_DB_IFACE_TYPE_PPPOL2TPV2 */
1928#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301929#ifdef ECM_INTERFACE_PPTP_ENABLE
1930 struct ecm_db_interface_info_pptp pptp; /* type == ECM_DB_IFACE_TYPE_PPTP */
1931#endif
ratheesh kannothcfdcb332015-12-24 07:19:18 +05301932#ifdef ECM_INTERFACE_MAP_T_ENABLE
1933 struct ecm_db_interface_info_map_t map_t; /* type == ECM_DB_IFACE_TYPE_MAP_T */
1934#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001935 struct ecm_db_interface_info_unknown unknown; /* type == ECM_DB_IFACE_TYPE_UNKNOWN */
1936 struct ecm_db_interface_info_loopback loopback; /* type == ECM_DB_IFACE_TYPE_LOOPBACK */
Murat Sezgin69a27532015-03-12 14:09:40 -07001937#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001938 struct ecm_db_interface_info_ipsec_tunnel ipsec_tunnel; /* type == ECM_DB_IFACE_TYPE_IPSEC_TUNNEL */
Murat Sezgin69a27532015-03-12 14:09:40 -07001939#endif
Murat Sezginbde55f92015-03-11 16:44:11 -07001940#ifdef ECM_INTERFACE_SIT_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001941 struct ecm_db_interface_info_sit sit; /* type == ECM_DB_IFACE_TYPE_SIT */
Murat Sezginbde55f92015-03-11 16:44:11 -07001942#endif
Murat Sezginc1402562015-03-12 12:32:20 -07001943#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001944#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001945 struct ecm_db_interface_info_tunipip6 tunipip6; /* type == ECM_DB_IFACE_TYPE_TUNIPIP6 */
Murat Sezginc1402562015-03-12 12:32:20 -07001946#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001947#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001948 } type_info;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001949
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08001950#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001951 int channel_count;
1952 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00001953 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301954#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001955 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001956#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301957#ifdef ECM_INTERFACE_PPTP_ENABLE
1958 int protocol = IPPROTO_IP;
1959 struct pptp_opt opt;
1960 struct iphdr *v4_hdr = NULL;
1961 if (skb) {
1962 v4_hdr = ip_hdr(skb);
1963 protocol = v4_hdr->protocol;
1964 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301965#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301966#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001967 /*
1968 * Get basic information about the given device
1969 */
1970 dev_interface_num = dev->ifindex;
1971 dev_name = dev->name;
1972 dev_type = dev->type;
1973 dev_mtu = dev->mtu;
1974
1975 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07001976 * Does the accel engine recognise this interface?
Ben Menchaca84f36632014-02-28 20:57:38 +00001977 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001978 ae_interface_num = feci->ae_interface_number_by_dev_get(dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00001979
Murat Sezgin91c5d712015-06-12 15:16:22 -07001980 DEBUG_TRACE("Establish interface instance for device: %p is type: %d, name: %s, ifindex: %d, ae_if: %d, mtu: %d\n",
1981 dev, dev_type, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00001982
1983 /*
1984 * Extract from the device more type-specific information
1985 */
1986 if (dev_type == ARPHRD_ETHER) {
Shyam Sunder39e25672015-09-03 14:28:09 +05301987
Ben Menchaca84f36632014-02-28 20:57:38 +00001988 /*
1989 * Ethernet - but what sub type?
1990 */
1991
Gareth Williams141d2382014-11-25 11:35:19 -08001992#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001993 /*
1994 * VLAN?
1995 */
1996 if (is_vlan_dev(dev)) {
1997 /*
1998 * VLAN master
1999 * GGG No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
2000 */
2001 memcpy(type_info.vlan.address, dev->dev_addr, 6);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05302002 type_info.vlan.vlan_tag = vlan_dev_vlan_id(dev);
Murat Sezginb2676062015-06-12 17:05:31 -07002003 type_info.vlan.vlan_tpid = ETH_P_8021Q;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05302004 DEBUG_TRACE("Net device: %p is VLAN, mac: %pM, vlan_id: %x vlan_tpid: %x\n",
2005 dev, type_info.vlan.address, type_info.vlan.vlan_tag, type_info.vlan.vlan_tpid);
Ben Menchaca84f36632014-02-28 20:57:38 +00002006
2007 /*
2008 * Establish this type of interface
2009 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002010 ii = ecm_interface_vlan_interface_establish(&type_info.vlan, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder39e25672015-09-03 14:28:09 +05302011 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00002012 }
Gareth Williams141d2382014-11-25 11:35:19 -08002013#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002014
2015 /*
2016 * BRIDGE?
2017 */
2018 if (ecm_front_end_is_bridge_device(dev)) {
2019 /*
2020 * Bridge
2021 */
2022 memcpy(type_info.bridge.address, dev->dev_addr, 6);
2023
2024 DEBUG_TRACE("Net device: %p is BRIDGE, mac: %pM\n",
2025 dev, type_info.bridge.address);
2026
2027 /*
2028 * Establish this type of interface
2029 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002030 ii = ecm_interface_bridge_interface_establish(&type_info.bridge, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder39e25672015-09-03 14:28:09 +05302031 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00002032 }
2033
Murat Sezgin910c9662015-03-11 16:15:06 -07002034#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002035 /*
2036 * LAG?
2037 */
2038 if (ecm_front_end_is_lag_master(dev)) {
2039 /*
2040 * Link aggregation
2041 */
2042 memcpy(type_info.lag.address, dev->dev_addr, 6);
2043
2044 DEBUG_TRACE("Net device: %p is LAG, mac: %pM\n",
2045 dev, type_info.lag.address);
2046
2047 /*
2048 * Establish this type of interface
2049 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002050 ii = ecm_interface_lag_interface_establish(&type_info.lag, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder39e25672015-09-03 14:28:09 +05302051 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00002052 }
Murat Sezgin910c9662015-03-11 16:15:06 -07002053#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002054
2055 /*
2056 * ETHERNET!
2057 * Just plain ethernet it seems
2058 */
2059 memcpy(type_info.ethernet.address, dev->dev_addr, 6);
2060 DEBUG_TRACE("Net device: %p is ETHERNET, mac: %pM\n",
2061 dev, type_info.ethernet.address);
2062
2063 /*
2064 * Establish this type of interface
2065 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002066 ii = ecm_interface_ethernet_interface_establish(&type_info.ethernet, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder39e25672015-09-03 14:28:09 +05302067
2068identifier_update:
2069 if (ii) {
2070 /*
2071 * An interface identifier/ifindex can be change after network restart. Below
2072 * functtion will check interface_identifier present in 'ii' with new dev_interface_num.
2073 * If differ then update new ifindex and update the interface identifier hash table.
2074 */
2075 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2076 }
2077
Ben Menchaca84f36632014-02-28 20:57:38 +00002078 return ii;
2079 }
2080
2081 /*
2082 * LOOPBACK?
2083 */
2084 if (dev_type == ARPHRD_LOOPBACK) {
2085 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dev, dev_type);
2086 type_info.loopback.os_specific_ident = dev_interface_num;
Murat Sezgin91c5d712015-06-12 15:16:22 -07002087 ii = ecm_interface_loopback_interface_establish(&type_info.loopback, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002088 return ii;
2089 }
2090
Murat Sezgin69a27532015-03-12 14:09:40 -07002091#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002092 /*
2093 * IPSEC?
2094 */
2095 if (dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2096 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dev, dev_type);
2097 type_info.ipsec_tunnel.os_specific_ident = dev_interface_num;
Ankit Dhanuka6d5014a2014-06-22 17:21:44 +05302098
Ben Menchaca84f36632014-02-28 20:57:38 +00002099 // GGG TODO Flesh this out with tunnel endpoint addressing detail
Murat Sezgin91c5d712015-06-12 15:16:22 -07002100 ii = ecm_interface_ipsec_tunnel_interface_establish(&type_info.ipsec_tunnel, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002101 return ii;
2102 }
Murat Sezgin69a27532015-03-12 14:09:40 -07002103#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002104
ratheesh kannothcfdcb332015-12-24 07:19:18 +05302105#ifdef ECM_INTERFACE_MAP_T_ENABLE
2106 if (dev_type == ARPHRD_NONE) {
2107 if (is_map_t_dev(dev)) {
2108 type_info.map_t.if_index = dev_interface_num;
2109 ii = ecm_interface_map_t_interface_establish(&type_info.map_t, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2110 return ii;
2111 }
2112
2113 }
2114#endif
2115
Murat Sezginb3731e82014-11-26 12:20:59 -08002116#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07002117#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00002118 /*
2119 * SIT (6-in-4)?
2120 */
2121 if (dev_type == ARPHRD_SIT) {
2122 struct ip_tunnel *tunnel;
2123 struct ip_tunnel_6rd_parm *ip6rd;
2124 const struct iphdr *tiph;
2125
2126 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dev, dev_type);
2127
2128 tunnel = (struct ip_tunnel*)netdev_priv(dev);
2129 ip6rd = &tunnel->ip6rd;
2130
2131 /*
2132 * Get the Tunnel device IP header info
2133 */
2134 tiph = &tunnel->parms.iph ;
2135
2136 type_info.sit.prefixlen = ip6rd->prefixlen;
2137 type_info.sit.relay_prefix = ip6rd->relay_prefix;
2138 type_info.sit.relay_prefixlen = ip6rd->relay_prefixlen;
2139 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.saddr, tiph->saddr);
2140 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.daddr, tiph->daddr);
2141 type_info.sit.prefix[0] = ntohl(ip6rd->prefix.s6_addr32[0]);
2142 type_info.sit.prefix[1] = ntohl(ip6rd->prefix.s6_addr32[1]);
2143 type_info.sit.prefix[2] = ntohl(ip6rd->prefix.s6_addr32[2]);
2144 type_info.sit.prefix[3] = ntohl(ip6rd->prefix.s6_addr32[3]);
2145 type_info.sit.ttl = tiph->ttl;
2146 type_info.sit.tos = tiph->tos;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05302147
Murat Sezgin91c5d712015-06-12 15:16:22 -07002148 ii = ecm_interface_sit_interface_establish(&type_info.sit, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002149 return ii;
2150 }
Murat Sezgincc6eedf2014-05-09 23:59:19 -07002151#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08002152#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002153
Murat Sezginc1402562015-03-12 12:32:20 -07002154#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00002155#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002156 /*
2157 * IPIP6 Tunnel?
2158 */
2159 if (dev_type == ARPHRD_TUNNEL6) {
2160 struct ip6_tnl *tunnel;
2161 struct flowi6 *fl6;
2162
2163 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dev, dev_type);
2164
2165 /*
2166 * Get the tunnel device flow information (discover the output path of the tunnel)
2167 */
2168 tunnel = (struct ip6_tnl *)netdev_priv(dev);
2169 fl6 = &tunnel->fl.u.ip6;
2170
2171 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.saddr, fl6->saddr);
2172 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.daddr, fl6->daddr);
2173 type_info.tunipip6.hop_limit = tunnel->parms.hop_limit;
2174 type_info.tunipip6.flags = ntohl(tunnel->parms.flags);
2175 type_info.tunipip6.flowlabel = fl6->flowlabel; /* flow Label In kernel is stored in big endian format */
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05302176
Murat Sezgin91c5d712015-06-12 15:16:22 -07002177 ii = ecm_interface_tunipip6_interface_establish(&type_info.tunipip6, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002178 return ii;
2179 }
Murat Sezginc1402562015-03-12 12:32:20 -07002180#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00002181#endif
2182
Ben Menchaca84f36632014-02-28 20:57:38 +00002183 /*
2184 * If this is NOT PPP then it is unknown to the ecm
2185 */
2186 if (dev_type != ARPHRD_PPP) {
2187 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dev, dev_type);
2188 type_info.unknown.os_specific_ident = dev_interface_num;
2189
2190 /*
2191 * Establish this type of interface
2192 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002193 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002194 return ii;
2195 }
2196
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08002197#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002198 /*
2199 * PPP support is NOT provided for.
2200 * Interface is therefore unknown
2201 */
2202 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dev, dev_type);
2203 type_info.unknown.os_specific_ident = dev_interface_num;
2204
2205 /*
2206 * Establish this type of interface
2207 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002208 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002209 return ii;
2210#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302211
2212#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2213 /*
2214 * ppp_xmit lock is held by linux kernel for l2tp packet in transmit
2215 * direction. we need to check for l2tp packet and avoid calls to
2216 * ppp_is_multilink() and ppp_hold_channels() which acquire same lock
2217 */
2218 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP)
2219 && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
ratheesh kannothed721852015-09-28 12:39:52 +05302220 if (skb->skb_iif == dev->ifindex) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302221 struct pppol2tp_common_addr info;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302222
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302223 if (__ppp_is_multilink(dev) > 0) {
2224 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
2225 type_info.unknown.os_specific_ident = dev_interface_num;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302226
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302227 /*
2228 * Establish this type of interface
2229 */
2230 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2231 return ii;
2232 }
2233 channel_count = __ppp_hold_channels(dev, ppp_chan, 1);
2234 if (channel_count != 1) {
2235 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
2236 dev, channel_count);
2237 type_info.unknown.os_specific_ident = dev_interface_num;
2238
2239 /*
2240 * Establish this type of interface
2241 */
2242 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2243 return ii;
2244 }
2245
2246 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
2247 ppp_release_channels(ppp_chan, 1);
ratheesh kannothed721852015-09-28 12:39:52 +05302248 return NULL;
2249 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302250
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302251 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = info.local_tunnel_id;
2252 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = info.remote_tunnel_id;
2253 type_info.pppol2tpv2.l2tp.session.session_id = info.local_session_id;
2254 type_info.pppol2tpv2.l2tp.session.peer_session_id = info.remote_session_id;
2255 type_info.pppol2tpv2.udp.sport = ntohs(info.local_addr.sin_port);
2256 type_info.pppol2tpv2.udp.dport = ntohs(info.remote_addr.sin_port);
2257 type_info.pppol2tpv2.ip.saddr = ntohl(info.local_addr.sin_addr.s_addr);
2258 type_info.pppol2tpv2.ip.daddr = ntohl(info.remote_addr.sin_addr.s_addr);
ratheesh kannothed721852015-09-28 12:39:52 +05302259
2260 /*
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302261 * Release the channel. Note that next_dev is still (correctly) held.
ratheesh kannothed721852015-09-28 12:39:52 +05302262 */
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302263 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302264
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302265 DEBUG_TRACE("Net device: %p PPPo2L2TP session: %d,n", dev, type_info.pppol2tpv2.l2tp.session.peer_session_id);
ratheesh kannothed721852015-09-28 12:39:52 +05302266
2267 /*
2268 * Establish this type of interface
2269 */
2270 ii = ecm_interface_pppol2tpv2_interface_establish(&type_info.pppol2tpv2, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2271 return ii;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302272 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302273 }
2274#endif
2275
Shyam Sunder23f2e542015-09-28 14:56:49 +05302276#ifdef ECM_INTERFACE_PPTP_ENABLE
2277 if ((protocol == IPPROTO_GRE) && skb && v4_hdr) {
2278 struct gre_hdr_pptp *gre_hdr;
2279 uint16_t proto;
2280 int ret;
2281
2282 skb_pull(skb, sizeof(struct iphdr));
2283 gre_hdr = (struct gre_hdr_pptp *)(skb->data);
2284 proto = ntohs(gre_hdr->protocol);
2285 if ((gre_hdr->version == GRE_VERSION_PPTP) && (proto == GRE_PROTOCOL_PPTP)) {
2286 ret = pptp_session_find(&opt, gre_hdr->call_id, v4_hdr->daddr);
2287 if (ret < 0) {
2288 skb_push(skb, sizeof(struct iphdr));
2289 DEBUG_WARN("PPTP session info not found\n");
2290 return NULL;
2291 }
2292
2293 /*
2294 * Get PPTP session info
2295 */
2296 type_info.pptp.src_call_id = ntohs(opt.src_addr.call_id);
2297 type_info.pptp.dst_call_id = ntohs(opt.dst_addr.call_id);
2298 type_info.pptp.src_ip = ntohl(opt.src_addr.sin_addr.s_addr);
2299 type_info.pptp.dst_ip = ntohl(opt.dst_addr.sin_addr.s_addr);
2300
2301 skb_push(skb, sizeof(struct iphdr));
2302
2303 /*
2304 * Establish this type of interface
2305 */
2306 ii = ecm_interface_pptp_interface_establish(&type_info.pptp, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder65f013e2015-12-14 18:04:54 +05302307 if (ii) {
2308 /*
2309 * The ifindex of a virtual netdevice like a PPTP session can change if it is destroyed
2310 * and comes up again. Detect if the ifindex has changed and update it if required
2311 */
2312 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2313 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05302314 return ii;
2315 }
2316
2317 skb_push(skb, sizeof(struct iphdr));
2318
2319 DEBUG_TRACE("Unknown GRE protocol \n");
2320 type_info.unknown.os_specific_ident = dev_interface_num;
2321
2322 /*
2323 * Establish this type of interface
2324 */
2325 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2326 return ii;
2327 }
2328#endif
2329
Ben Menchaca84f36632014-02-28 20:57:38 +00002330 /*
2331 * PPP - but what is the channel type?
2332 * First: If this is multi-link then we do not support it
2333 */
2334 if (ppp_is_multilink(dev) > 0) {
2335 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
2336 type_info.unknown.os_specific_ident = dev_interface_num;
2337
2338 /*
2339 * Establish this type of interface
2340 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002341 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002342 return ii;
2343 }
2344
2345 DEBUG_TRACE("Net device: %p is PPP\n", dev);
2346
2347 /*
2348 * Get the PPP channel and then enquire what kind of channel it is
2349 * NOTE: Not multilink so only one channel to get.
2350 */
2351 channel_count = ppp_hold_channels(dev, ppp_chan, 1);
2352 if (channel_count != 1) {
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002353 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
2354 dev, channel_count);
Ben Menchaca84f36632014-02-28 20:57:38 +00002355 type_info.unknown.os_specific_ident = dev_interface_num;
2356
2357 /*
2358 * Establish this type of interface
2359 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002360 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002361 return ii;
2362 }
2363
2364 /*
2365 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002366 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00002367 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002368 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302369
2370#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2371 if (channel_protocol == PX_PROTO_OL2TP) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302372 struct pppol2tp_common_addr info;
Ben Menchaca84f36632014-02-28 20:57:38 +00002373
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302374 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302375 ppp_release_channels(ppp_chan, 1);
2376 return NULL;
2377 }
2378
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302379 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = info.local_tunnel_id;
2380 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = info.remote_tunnel_id;
2381 type_info.pppol2tpv2.l2tp.session.session_id = info.local_session_id;
2382 type_info.pppol2tpv2.l2tp.session.peer_session_id = info.remote_session_id;
2383 type_info.pppol2tpv2.udp.sport = ntohs(info.local_addr.sin_port);
2384 type_info.pppol2tpv2.udp.dport = ntohs(info.remote_addr.sin_port);
2385 type_info.pppol2tpv2.ip.saddr = ntohl(info.local_addr.sin_addr.s_addr);
2386 type_info.pppol2tpv2.ip.daddr = ntohl(info.remote_addr.sin_addr.s_addr);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302387
2388 /*
2389 * Release the channel. Note that next_dev is still (correctly) held.
Ben Menchaca84f36632014-02-28 20:57:38 +00002390 */
2391 ppp_release_channels(ppp_chan, 1);
2392
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302393 DEBUG_TRACE("Net device: %p PPPo2L2TP session: %d,n", dev, type_info.pppol2tpv2.l2tp.session.peer_session_id);
2394
Ben Menchaca84f36632014-02-28 20:57:38 +00002395 /*
2396 * Establish this type of interface
2397 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302398 ii = ecm_interface_pppol2tpv2_interface_establish(&type_info.pppol2tpv2, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002399 return ii;
2400 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302401#endif
2402#ifdef ECM_INTERFACE_PPPOE_ENABLE
2403 if (channel_protocol == PX_PROTO_OE) {
2404
2405 /*
2406 * PPPoE channel
2407 */
2408 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dev);
2409
2410 /*
2411 * Get PPPoE session information and the underlying device it is using.
2412 */
2413 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2414 type_info.pppoe.pppoe_session_id = (uint16_t)ntohs((uint16_t)addressing.pa.sid);
2415 memcpy(type_info.pppoe.remote_mac, addressing.pa.remote, ETH_ALEN);
2416 dev_put(addressing.dev);
2417
2418 /*
2419 * Release the channel. Note that next_dev is still (correctly) held.
2420 */
2421 ppp_release_channels(ppp_chan, 1);
2422
2423 DEBUG_TRACE("Net device: %p PPPoE session: %x, remote mac: %pM\n",
2424 dev, type_info.pppoe.pppoe_session_id, type_info.pppoe.remote_mac);
2425
2426 /*
2427 * Establish this type of interface
2428 */
2429 ii = ecm_interface_pppoe_interface_establish(&type_info.pppoe, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2430 return ii;
2431 }
2432#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05302433
2434#ifdef ECM_INTERFACE_PPTP_ENABLE
2435 if (channel_protocol == PX_PROTO_PPTP) {
2436 pptp_channel_addressing_get(&opt, ppp_chan[0]);
2437
2438 /*
2439 * Get PPTP session info
2440 */
2441 type_info.pptp.src_call_id = ntohs(opt.src_addr.call_id);
2442 type_info.pptp.dst_call_id = ntohs(opt.dst_addr.call_id);
2443 type_info.pptp.src_ip = ntohl(opt.src_addr.sin_addr.s_addr);
2444 type_info.pptp.dst_ip = ntohl(opt.dst_addr.sin_addr.s_addr);
2445
2446 DEBUG_TRACE("Net device: %p PPTP source call id: %d,n", dev, type_info.pptp.src_call_id);
2447 ppp_release_channels(ppp_chan, 1);
2448
2449 /*
2450 * Establish this type of interface
2451 */
2452 ii = ecm_interface_pptp_interface_establish(&type_info.pptp, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder65f013e2015-12-14 18:04:54 +05302453 if (ii) {
2454 /*
2455 * The ifindex of a virtual netdevice like a PPTP session can change if it is destroyed
2456 * and comes up again. Detect if the ifindex has changed and update it if required
2457 */
2458 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2459 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05302460 return ii;
2461 }
2462#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302463 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n", dev, channel_protocol);
2464 type_info.unknown.os_specific_ident = dev_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00002465
2466 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302467 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00002468 */
2469 ppp_release_channels(ppp_chan, 1);
2470
Ben Menchaca84f36632014-02-28 20:57:38 +00002471 /*
2472 * Establish this type of interface
2473 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302474 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002475 return ii;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002476#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002477}
2478EXPORT_SYMBOL(ecm_interface_establish_and_ref);
2479
Shyam Sunder6358b862015-05-04 15:06:24 +05302480#ifdef ECM_MULTICAST_ENABLE
2481/*
2482 * ecm_interface_multicast_heirarchy_construct_single()
2483 * Create and return an interface heirarchy for a single interface for a multicast connection
2484 *
2485 * src_addr IP source address
2486 * dest_addr IP Destination address/Group Address
2487 * interface Pointer to a single multicast interface heirarchy
2488 * given_dest_dev Netdev pointer for destination interface
2489 * br_slave_dev Netdev pointer to a bridge slave device. It could be NULL in case of pure
2490 * routed flow without any bridge interface in destination dev list.
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302491 * skb sk_buff
Shyam Sunder6358b862015-05-04 15:06:24 +05302492 */
Shyam Sunder81836832015-07-09 19:18:25 +05302493static uint32_t ecm_interface_multicast_heirarchy_construct_single(struct ecm_front_end_connection_instance *feci, ip_addr_t src_addr,
2494 ip_addr_t dest_addr, struct ecm_db_iface_instance *interface,
2495 struct net_device *given_dest_dev, struct net_device *br_slave_dev,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302496 uint8_t *src_node_addr, bool is_routed, __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302497{
2498 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2499 struct ecm_db_iface_instance **ifaces;
2500 struct ecm_db_iface_instance *ii_temp;
2501 struct net_device *dest_dev;
2502 int32_t current_interface_index;
2503 int32_t interfaces_cnt = 0;
2504 int32_t dest_dev_type;
2505
2506 dest_dev = given_dest_dev;
2507 dev_hold(dest_dev);
2508 dest_dev_type = dest_dev->type;
2509 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
2510
2511 while (current_interface_index > 0) {
2512 struct ecm_db_iface_instance *ii;
2513 struct net_device *next_dev;
2514
2515 /*
2516 * Get the ecm db interface instance for the device at hand
2517 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302518 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Shyam Sunder6358b862015-05-04 15:06:24 +05302519 interfaces_cnt++;
2520
2521 /*
2522 * If the interface could not be established then we abort
2523 */
2524 if (!ii) {
2525 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev->name);
2526 dev_put(dest_dev);
2527
2528 /*
2529 * Release the interfaces heirarchy we constructed to this point.
2530 */
2531 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2532 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2533 return ECM_DB_IFACE_HEIRARCHY_MAX;
2534 }
2535
2536 /*
2537 * Record the interface instance into the *ifaces
2538 */
2539 current_interface_index--;
2540 ii_temp = ecm_db_multicast_if_instance_get_at_index(interface, current_interface_index);
2541 ifaces = (struct ecm_db_iface_instance **)ii_temp;
2542 *ifaces = ii;
2543
2544 /*
2545 * Now we have to figure out what the next device will be (in the transmission path)
2546 */
2547 do {
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302548#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302549 int channel_count;
2550 struct ppp_channel *ppp_chan[1];
2551 int channel_protocol;
2552 struct pppoe_opt addressing;
2553#endif
2554 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev->name);
2555 next_dev = NULL;
2556
2557 if (dest_dev_type == ARPHRD_ETHER) {
2558 /*
2559 * Ethernet - but what sub type?
2560 */
2561
2562 /*
2563 * VLAN?
2564 */
2565 if (is_vlan_dev(dest_dev)) {
2566 /*
2567 * VLAN master
2568 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
2569 */
Shyam Sunder9db20852016-03-09 19:04:49 +05302570 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Shyam Sunder6358b862015-05-04 15:06:24 +05302571 dev_hold(next_dev);
2572 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
2573 dest_dev, next_dev, next_dev->name);
2574 break;
2575 }
2576
2577 /*
2578 * BRIDGE?
2579 */
2580 if (ecm_front_end_is_bridge_device(dest_dev)) {
2581 if (!ecm_front_end_is_bridge_port(br_slave_dev)) {
2582 DEBUG_ASSERT(NULL, "%p: expected only bridge slave here\n", interface);
2583
2584 /*
2585 * Release the interfaces heirarchy we constructed to this point.
2586 */
2587 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2588 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2589 dev_put(dest_dev);
2590 return ECM_DB_IFACE_HEIRARCHY_MAX;
2591 }
2592
2593 next_dev = br_slave_dev;
2594 if (!next_dev) {
2595 DEBUG_WARN("Unable to obtain output port \n");
2596
2597 /*
2598 * Release the interfaces heirarchy we constructed to this point.
2599 */
2600 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2601 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2602 dev_put(dest_dev);
2603 return ECM_DB_IFACE_HEIRARCHY_MAX;
2604 }
2605 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2606 dev_hold(next_dev);
2607 break;
2608 }
2609
Shyam Sunder81836832015-07-09 19:18:25 +05302610#ifdef ECM_INTERFACE_BOND_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302611 /*
2612 * LAG?
2613 */
2614 if (ecm_front_end_is_lag_master(dest_dev)) {
2615 /*
2616 * Link aggregation
2617 * Figure out which slave device of the link aggregation will be used to reach the destination.
2618 */
2619 uint32_t src_addr_32 = 0;
2620 uint32_t dest_addr_32 = 0;
Suman Ghoshf14d2172015-07-31 14:38:10 +05302621 struct in6_addr src_addr6;
2622 struct in6_addr dest_addr6;
Shyam Sunder6358b862015-05-04 15:06:24 +05302623 uint8_t src_mac_addr[ETH_ALEN];
2624 uint8_t dest_mac_addr[ETH_ALEN];
2625
2626 memset(src_mac_addr, 0, ETH_ALEN);
2627 memset(dest_mac_addr, 0, ETH_ALEN);
2628
Shyam Sunder81836832015-07-09 19:18:25 +05302629 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2630 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
2631 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
2632 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302633
Shyam Sunder81836832015-07-09 19:18:25 +05302634 if (!is_routed) {
2635 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
Shyam Sunder6358b862015-05-04 15:06:24 +05302636 } else {
Shyam Sunder81836832015-07-09 19:18:25 +05302637 struct net_device *dest_dev_master;
2638
2639 /*
2640 * Use appropriate source MAC address for routed packets
2641 */
2642 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
2643 if (dest_dev_master) {
2644 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
2645 dev_put(dest_dev_master);
2646 } else {
2647 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
2648 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302649 }
2650
2651 /*
2652 * Create Destination MAC address using IP multicast destination address
2653 */
2654 ecm_translate_multicast_mac(dest_addr, dest_mac_addr);
2655
Shyam Sunder81836832015-07-09 19:18:25 +05302656 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2657 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
2658 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302659 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302660 } else {
Suman Ghoshf14d2172015-07-31 14:38:10 +05302661 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
2662 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, dest_addr);
Shyam Sunder81836832015-07-09 19:18:25 +05302663 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
Suman Ghoshf14d2172015-07-31 14:38:10 +05302664 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05302665 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302666 }
2667
Shyam Sunder6358b862015-05-04 15:06:24 +05302668 if (!(next_dev && netif_carrier_ok(next_dev))) {
2669 DEBUG_WARN("Unable to obtain LAG output slave device\n");
2670 dev_put(dest_dev);
2671
2672 /*
2673 * Release the interfaces heirarchy we constructed to this point.
2674 */
2675 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2676 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2677 return ECM_DB_IFACE_HEIRARCHY_MAX;
2678 }
2679
2680 dev_hold(next_dev);
2681 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2682 break;
2683 }
2684#endif
2685
2686 /*
2687 * ETHERNET!
2688 * Just plain ethernet it seems.
2689 */
2690 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
2691 break;
2692 }
2693
2694 /*
2695 * LOOPBACK?
2696 */
2697 if (dest_dev_type == ARPHRD_LOOPBACK) {
2698 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
2699 break;
2700 }
2701
2702 /*
2703 * IPSEC?
2704 */
2705 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2706 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
2707 /*
2708 * TODO Figure out the next device the tunnel is using...
2709 */
2710 break;
2711 }
2712
2713 /*
2714 * SIT (6-in-4)?
2715 */
2716 if (dest_dev_type == ARPHRD_SIT) {
2717 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
2718 /*
2719 * TODO Figure out the next device the tunnel is using...
2720 */
2721 break;
2722 }
2723
2724 /*
2725 * IPIP6 Tunnel?
2726 */
2727 if (dest_dev_type == ARPHRD_TUNNEL6) {
2728 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
2729 /*
2730 * TODO Figure out the next device the tunnel is using...
2731 */
2732 break;
2733 }
2734
2735 /*
2736 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
2737 */
2738 if (dest_dev_type != ARPHRD_PPP) {
2739 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
2740 break;
2741 }
2742
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302743#ifndef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302744 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
2745#else
2746 /*
2747 * PPP - but what is the channel type?
2748 * First: If this is multi-link then we do not support it
2749 */
2750 if (ppp_is_multilink(dest_dev) > 0) {
2751 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
2752 break;
2753 }
2754
2755 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
2756
2757 /*
2758 * Get the PPP channel and then enquire what kind of channel it is
2759 * NOTE: Not multilink so only one channel to get.
2760 */
2761 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
2762 if (channel_count != 1) {
2763 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
2764 dest_dev, channel_count);
2765 break;
2766 }
2767
2768 /*
2769 * Get channel protocol type
2770 * NOTE: Not all PPP channels support channel specific methods.
2771 */
2772 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
2773 if (channel_protocol != PX_PROTO_OE) {
2774 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
2775 dest_dev, channel_protocol);
2776
2777 /*
2778 * Release the channel
2779 */
2780 ppp_release_channels(ppp_chan, 1);
2781
2782 break;
2783 }
2784
2785 /*
2786 * PPPoE channel
2787 */
2788 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
2789
2790 /*
2791 * Get PPPoE session information and the underlying device it is using.
2792 */
2793 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2794
2795 /*
2796 * Copy the dev hold into this, we will release the hold later
2797 */
2798 next_dev = addressing.dev;
2799
Shyam Sunder6358b862015-05-04 15:06:24 +05302800 /*
2801 * Release the channel. Note that next_dev is still (correctly) held.
2802 */
2803 ppp_release_channels(ppp_chan, 1);
2804#endif
2805 } while (false);
2806
2807 /*
2808 * No longer need dest_dev as it may become next_dev
2809 */
2810 dev_put(dest_dev);
2811
2812 /*
2813 * Check out the next_dev, if any
2814 */
2815 if (!next_dev) {
2816 int32_t i __attribute__((unused));
2817 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
2818#if DEBUG_LEVEL > 1
2819 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2820 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
2821 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n", \
2822 i, to_list_single[i], ecm_db_connection_iface_type_get(to_list_single[i]), \
2823 ecm_db_interface_type_to_string(ecm_db_connection_iface_type_get(to_list_single[i])));
2824 }
2825#endif
2826 return current_interface_index;
2827 }
2828
2829 /*
2830 * dest_dev becomes next_dev
2831 */
2832 dest_dev = next_dev;
2833 dest_dev_type = dest_dev->type;
2834 }
2835
2836 dev_put(dest_dev);
2837
2838 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2839 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2840 return ECM_DB_IFACE_HEIRARCHY_MAX;
2841}
2842
2843/*
2844 * ecm_interface_multicast_heirarchy_construct_routed()
2845 * Create destination interface heirarchy for a routed multicast connectiona
2846 *
2847 * interfaces Pointer to the 2-D array of multicast interface heirarchies
2848 * in_dev Pointer to the source netdev
2849 * packet_src_addr Source IP of the multicast flow
2850 * packet_dest_addr Group(dest) IP of the multicast flow
2851 * max_dst Maximum number of netdev joined the multicast group
2852 * dst_if_index_base An array of if index joined the multicast group
2853 * interface_first_base An array of the index of the first interface in the list
2854 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002855int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_connection_instance *feci,
2856 struct ecm_db_iface_instance *interfaces,
2857 struct net_device *in_dev,
2858 ip_addr_t packet_src_addr,
2859 ip_addr_t packet_dest_addr, uint8_t max_if,
2860 uint32_t *dst_if_index_base,
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302861 uint32_t *interface_first_base, bool mfc_update,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302862 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302863{
2864 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2865 struct ecm_db_iface_instance *ifaces;
2866 struct net_device *dest_dev = NULL;
2867 struct net_device *br_dev_src = NULL;
2868 uint32_t *dst_if_index;
2869 uint32_t *interface_first;
2870 uint32_t br_if;
2871 uint32_t valid_if;
Shyam Sunder41637872015-06-11 21:19:05 +05302872 int32_t if_num;
Shyam Sunder6358b862015-05-04 15:06:24 +05302873 int32_t dest_dev_type;
2874 int if_index;
2875 int ii_cnt;
2876 int total_ii_count = 0;
2877 bool src_dev_is_bridge = false;
2878
2879 DEBUG_TRACE("Construct interface heirarchy for dest_addr: " ECM_IP_ADDR_DOT_FMT " src_addr: " ECM_IP_ADDR_DOT_FMT "total destination ifs %d\n",
2880 ECM_IP_ADDR_TO_DOT(packet_dest_addr), ECM_IP_ADDR_TO_DOT(packet_src_addr), max_if);
2881
2882 /*
2883 * Check if the source net_dev is a bridge slave.
2884 */
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302885 if (in_dev && !mfc_update) {
Shyam Sunder6358b862015-05-04 15:06:24 +05302886 if (ecm_front_end_is_bridge_port(in_dev)) {
2887 src_dev_is_bridge = true;
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302888 br_dev_src = ecm_interface_get_and_hold_dev_master(in_dev);
2889 DEBUG_ASSERT(br_dev_src, "Expected a master\n");
Shyam Sunder6358b862015-05-04 15:06:24 +05302890
2891 /*
2892 * The source net_dev found as bridge slave. In case of routed interface
2893 * heirarchy MFC is not aware of any other bridge slave has joined the same
2894 * multicast group as a destination interface. Therfore we assume there
2895 * are bridge slaves present in multicast destination interface list
2896 * and increase the max_if by one.
2897 */
2898 max_if++;
2899 }
2900 }
2901
2902 ii_cnt = 0;
2903 br_if = if_num = 0;
2904
2905 /*
2906 * This loop is for creating the destination interface hierarchy list.
2907 * We take the destination interface array we got from MFC (in form of ifindex array)
2908 * as input for this.
2909 */
2910 for (if_index = 0, valid_if = 0; if_index < max_if; if_index++) {
2911 dst_if_index = ecm_db_multicast_if_first_get_at_index(dst_if_index_base, if_index);
2912
2913 if (*dst_if_index == ECM_INTERFACE_LOOPBACK_DEV_INDEX) {
2914 continue;
2915 }
2916
2917 dest_dev = dev_get_by_index(&init_net, *dst_if_index);
2918 if (!dest_dev) {
2919 if (!src_dev_is_bridge) {
2920 int i;
2921
2922 /*
2923 * If already constructed any interface heirarchies before hitting
2924 * this error condition then Deref all interface heirarchies.
2925 */
2926 if (valid_if > 0) {
2927 for (i = 0; i < valid_if; i++) {
2928 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2929 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2930 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2931 }
2932 }
2933
2934 /*
2935 * If valid netdev not found, Return 0
2936 */
2937 return 0;
2938 }
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302939
Shyam Sunder6358b862015-05-04 15:06:24 +05302940 dest_dev = br_dev_src;
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302941
Shyam Sunder6358b862015-05-04 15:06:24 +05302942 }
2943
2944 dest_dev_type = dest_dev->type;
2945
2946 if (ecm_front_end_is_bridge_device(dest_dev)) {
2947 struct net_device *mc_br_slave_dev = NULL;
2948 uint32_t mc_max_dst = ECM_DB_MULTICAST_IF_MAX;
2949 uint32_t mc_dst_if_index[ECM_DB_MULTICAST_IF_MAX];
2950
2951 if (ECM_IP_ADDR_IS_V4(packet_src_addr)) {
2952 if_num = mc_bridge_ipv4_get_if(dest_dev, htonl((packet_src_addr[0])), htonl(packet_dest_addr[0]), mc_max_dst, mc_dst_if_index);
2953 } else {
2954 struct in6_addr origin6;
2955 struct in6_addr group6;
2956 ECM_IP_ADDR_TO_NIN6_ADDR(origin6, packet_src_addr);
2957 ECM_IP_ADDR_TO_NIN6_ADDR(group6, packet_dest_addr);
2958 if_num = mc_bridge_ipv6_get_if(dest_dev, &origin6, &group6, mc_max_dst, mc_dst_if_index);
2959 }
2960
Shyam Sunder81836832015-07-09 19:18:25 +05302961 if ((if_num < 0) || (if_num > ECM_DB_MULTICAST_IF_MAX)) {
2962 int i;
2963 DEBUG_WARN("MCS is not ready\n");
2964
2965 /*
2966 * If already constructed any interface heirarchies before hitting
2967 * this error condition then Deref all interface heirarchies.
2968 */
2969 if (valid_if > 0) {
2970 for (i = 0; i < valid_if; i++) {
2971 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2972 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2973 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2974 }
2975 }
2976
Shyam Sunder41637872015-06-11 21:19:05 +05302977 dev_put(dest_dev);
2978 return 0;
2979 }
2980
Shyam Sundera450b582016-07-22 14:44:14 +05302981 if (in_dev && !mfc_update) {
Shyam Sunder06588292016-04-18 19:57:39 +05302982 if_num = ecm_interface_multicast_check_for_src_ifindex(mc_dst_if_index, if_num, in_dev->ifindex);
2983 }
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302984
Shyam Sunder6358b862015-05-04 15:06:24 +05302985 for (br_if = 0; br_if < if_num; br_if++) {
2986 mc_br_slave_dev = dev_get_by_index(&init_net, mc_dst_if_index[br_if]);
2987 if (!mc_br_slave_dev) {
2988 continue;
2989 }
2990
2991 if ((valid_if + br_if) > ECM_DB_MULTICAST_IF_MAX) {
2992 int i;
2993
2994 /*
2995 * If already constructed any interface heirarchies before hitting
2996 * this error condition then Deref all interface heirarchies.
2997 */
2998 for (i = 0; i < (valid_if + br_if); i++) {
2999 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3000 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3001 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3002 }
3003
3004 dev_put(dest_dev);
3005 dev_put(mc_br_slave_dev);
3006 return 0;
3007 }
3008
3009 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if + br_if);
3010 /*
3011 * Construct a single interface heirarchy of a multicast dev.
3012 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303013 ii_cnt = ecm_interface_multicast_heirarchy_construct_single(feci, packet_src_addr, packet_dest_addr, ifaces, dest_dev, mc_br_slave_dev, NULL, true, layer4hdr, skb);
Shyam Sunder6358b862015-05-04 15:06:24 +05303014 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3015
3016 /*
3017 * If already constructed any interface heirarchies before hitting
3018 * this error condition then Deref all interface heirarchies.
3019 */
3020 if ((valid_if + br_if) > 0) {
3021 int i;
3022 for (i = 0; i < (valid_if + br_if); i++) {
3023 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3024 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3025 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3026 }
3027 }
3028
3029 dev_put(dest_dev);
3030 dev_put(mc_br_slave_dev);
3031 return 0;
3032 }
3033
3034 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, (valid_if + br_if));
3035 *interface_first = ii_cnt;
3036 total_ii_count += ii_cnt;
3037 dev_put(mc_br_slave_dev);
3038 }
3039
3040 valid_if += br_if;
3041
3042 } else {
3043
3044 DEBUG_ASSERT(valid_if < ECM_DB_MULTICAST_IF_MAX, "Bad array index size %d\n", valid_if);
3045 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
3046 /*
3047 * Construct a single interface heirarchy of a multicast dev.
3048 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303049 ii_cnt = ecm_interface_multicast_heirarchy_construct_single(feci, packet_src_addr, packet_dest_addr, ifaces, dest_dev, NULL, NULL, true, layer4hdr, skb);
Shyam Sunder6358b862015-05-04 15:06:24 +05303050 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3051
3052 /*
3053 * If already constructed any interface heirarchies before hitting
3054 * this error condition then Deref all interface heirarchies.
3055 */
3056 if (valid_if > 0) {
3057 int i;
3058 for (i = 0; i < valid_if; i++) {
3059 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3060 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3061 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3062 }
3063 }
3064
3065 dev_put(dest_dev);
3066 return 0;
3067 }
3068
3069 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
3070 *interface_first = ii_cnt;
3071 total_ii_count += ii_cnt;
3072 valid_if++;
3073 }
3074
3075 dev_put(dest_dev);
3076 }
3077 return total_ii_count;
3078}
3079EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed);
3080
3081/*
3082 * ecm_interface_multicast_heirarchy_construct_bridged()
3083 * This function called when the Hyfi bridge snooper has IGMP/IMLD updates, this function
3084 * creates destination interface heirarchy for a bridged multicast connection.
3085 *
3086 * interfaces Pointer to the 2-D array of multicast interface heirarchies
3087 * dest_dev Pointer to the destination dev, here dest_dev is always a bridge type
3088 * packet_src_addr Source IP of the multicast flow
3089 * packet_dest_addr Group(dest) IP of the multicast flow
3090 * mc_max_dst Maximum number of bridge slaves joined the multicast group
3091 * mc_dst_if_index_base An array of if index joined the multicast group
3092 * interface_first_base An array of the index of the first interface in the list
3093 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003094int32_t ecm_interface_multicast_heirarchy_construct_bridged(struct ecm_front_end_connection_instance *feci,
Shyam Sunder81836832015-07-09 19:18:25 +05303095 struct ecm_db_iface_instance *interfaces, struct net_device *dest_dev,
3096 ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, uint8_t mc_max_dst,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05303097 int *mc_dst_if_index_base, uint32_t *interface_first_base, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303098 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05303099{
3100 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
3101 struct ecm_db_iface_instance *ifaces;
3102 struct net_device *mc_br_slave_dev = NULL;
3103 uint32_t *interface_first;
3104 int *mc_dst_if_index;
3105 int valid_if;
3106 int ii_cnt = 0;
3107 int br_if;
3108 int total_ii_cnt = 0;
3109
3110 /*
3111 * Go through the newly joined interface index one by one and
3112 * create an interface heirarchy for each valid interface.
3113 */
3114 for (br_if = 0, valid_if = 0; br_if < mc_max_dst; br_if++) {
3115 mc_dst_if_index = (int *)ecm_db_multicast_if_num_get_at_index(mc_dst_if_index_base, br_if);
3116 mc_br_slave_dev = dev_get_by_index(&init_net, *mc_dst_if_index);
3117 if (!mc_br_slave_dev) {
3118
3119 /*
3120 * If already constructed any interface heirarchies before hitting
3121 * this error condition then Deref all interface heirarchies.
3122 */
3123 if (valid_if > 0) {
3124 int i;
3125 for (i = 0; i < valid_if; i++) {
3126 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3127 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3128 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3129 }
3130 }
3131
3132 /*
3133 * If valid netdev not found, Return 0
3134 */
3135 return 0;
3136 }
3137
3138 if (valid_if > ECM_DB_MULTICAST_IF_MAX) {
3139 int i;
3140
3141 /*
3142 * If already constructed any interface heirarchies before hitting
3143 * this error condition then Deref all interface heirarchies.
3144 */
3145 for (i = 0; i < valid_if; i++) {
3146 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3147 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3148 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3149 }
3150
3151 dev_put(mc_br_slave_dev);
3152 return 0;
3153 }
3154
3155 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
3156
3157 /*
3158 * Construct a single interface heirarchy of a multicast dev.
3159 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303160 ii_cnt = ecm_interface_multicast_heirarchy_construct_single(feci, packet_src_addr, packet_dest_addr, ifaces, dest_dev, mc_br_slave_dev, src_node_addr, false, layer4hdr, skb);
Shyam Sunder6358b862015-05-04 15:06:24 +05303161 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3162
3163 /*
3164 * If already constructed any interface heirarchies before hitting
3165 * this error condition then Deref all interface heirarchies.
3166 */
3167 if (valid_if > 0) {
3168 int i;
3169 for (i = 0; i < valid_if; i++) {
3170 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3171 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3172 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3173 }
3174 }
3175
3176 dev_put(mc_br_slave_dev);
3177 return 0;
3178 }
3179
3180 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
3181 *interface_first = ii_cnt;
3182 total_ii_cnt += ii_cnt;
3183 valid_if++;
3184 dev_put(mc_br_slave_dev);
3185 }
3186
Shyam Sunder280b34a2016-06-22 19:30:22 +05303187 return valid_if;
Shyam Sunder6358b862015-05-04 15:06:24 +05303188}
3189EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_bridged);
Shyam Sunder6358b862015-05-04 15:06:24 +05303190
Ben Menchaca84f36632014-02-28 20:57:38 +00003191/*
Murat Sezgin5dae8832015-12-03 14:23:19 -08003192 * ecm_interface_multicast_get_next_node_mac_address()
3193 * Get the MAC address of the next node for multicast flows
3194 *
3195 * TODO: This function will be removed when the multicast flow code
3196 * is fixed to use the new interface hierarchy construction model.
3197 *
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003198 */
Murat Sezgin5dae8832015-12-03 14:23:19 -08003199static bool ecm_interface_multicast_get_next_node_mac_address(
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003200 ip_addr_t dest_addr, struct net_device *dest_dev, int ip_version,
3201 uint8_t *mac_addr)
3202{
3203 bool on_link;
3204 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3205
3206 if (!ecm_interface_mac_addr_get(dest_addr, mac_addr, &on_link, gw_addr)) {
3207 if (ip_version == 4) {
3208 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n",
3209 ECM_IP_ADDR_TO_DOT(dest_addr));
3210 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
3211 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003212#ifdef ECM_IPV6_ENABLE
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003213 if (ip_version == 6) {
3214 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n",
3215 ECM_IP_ADDR_TO_OCTAL(dest_addr));
3216 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
3217 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003218#endif
3219 return false;
3220 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003221
Murat Sezgin5dae8832015-12-03 14:23:19 -08003222 return true;
3223}
Murat Sezgin8f70b312016-02-02 23:33:10 -08003224#endif
Murat Sezgin5dae8832015-12-03 14:23:19 -08003225
3226/*
3227 * ecm_interface_get_next_node_mac_address()
3228 * Get the MAC address of the next node
3229 */
3230static bool ecm_interface_get_next_node_mac_address(
3231 ip_addr_t dest_addr, struct net_device *dest_dev, int ip_version,
3232 uint8_t *mac_addr)
3233{
3234 if (!ecm_interface_mac_addr_get_no_route(dest_dev, dest_addr, mac_addr)) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003235 /*
3236 * MAC address look up failed. The host IP address may not be in the
3237 * neighbour table. So, let's send an ARP or neighbour solicitation
3238 * request to this host IP address, so in the subsequent lookups it can be
3239 * found.
3240 */
Murat Sezgin5dae8832015-12-03 14:23:19 -08003241 if (ip_version == 4) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003242 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3243 bool on_link = true;
3244
3245 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT " send ARP request\n",
Murat Sezgin5dae8832015-12-03 14:23:19 -08003246 ECM_IP_ADDR_TO_DOT(dest_addr));
Murat Sezgin00627c12016-02-05 16:53:21 -08003247
3248 if (ecm_interface_find_gateway(dest_addr, gw_addr)) {
3249 on_link = false;
3250 }
3251 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003252 }
3253#ifdef ECM_IPV6_ENABLE
3254 if (ip_version == 6) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003255 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT " send neighbour solicitation request\n",
Murat Sezgin5dae8832015-12-03 14:23:19 -08003256 ECM_IP_ADDR_TO_OCTAL(dest_addr));
Murat Sezgin00627c12016-02-05 16:53:21 -08003257 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003258 }
3259#endif
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003260 return false;
3261 }
3262
3263 return true;
3264}
3265
3266/*
3267 * ecm_interface_should_update_egress_device_bridged()
3268 * Determine if the egress port should be re-evaluated in the bridged case
3269 *
3270 * This will be done if:
3271 * - The egress port is the one provided from the front-end
3272 * - The egress port is not a bridge, but is a slave of the bridge
3273 * - Not routed
3274 *
3275 * If these conditions hold, this function will hold a reference to the bridge
3276 * port and return it to the caller. Otherwise no reference will be held and
3277 * it will return NULL.
3278 */
3279static struct net_device *ecm_interface_should_update_egress_device_bridged(
3280 struct net_device *given_dest_dev, struct net_device *dest_dev,
3281 bool is_routed)
3282{
3283 struct net_device *bridge;
3284
3285 /*
3286 * Determine if we should attempt to fetch the bridge device
3287 */
3288 if (!given_dest_dev || is_routed || (dest_dev != given_dest_dev) ||
3289 ecm_front_end_is_bridge_device(given_dest_dev))
3290 return NULL;
3291
3292 bridge = ecm_interface_get_and_hold_dev_master(given_dest_dev);
3293
3294 if (!bridge)
3295 return NULL;
3296
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003297 if (!ecm_front_end_is_bridge_device(bridge)) {
3298 /*
3299 * Master is not a bridge - free the reference and return
3300 */
3301 dev_put(bridge);
3302 return NULL;
3303 }
3304
3305 /*
3306 * Reference is held to bridge and must be freed by caller
3307 */
3308 return bridge;
3309}
3310
3311/*
Ben Menchaca84f36632014-02-28 20:57:38 +00003312 * ecm_interface_heirarchy_construct()
3313 * Construct an interface heirarchy.
3314 *
3315 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
3316 * This is the heirarchy of interfaces a packet would transit to emit from the device.
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003317 *
3318 * We will use the given src/dest devices when is_routed is false.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003319 * When is_routed is true we will use the construct and the other devices (which is the src device of the
3320 * construct device) whcih were obtained from the skb's route field and passed to this function..
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003321 *
Ben Menchaca84f36632014-02-28 20:57:38 +00003322 * For example, with this network arrangement:
3323 *
3324 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
3325 *
Gareth Williams43fc0852014-05-26 19:10:00 +01003326 * Given the packet_dest_addr IP address 10.22.33.11 this will create an interface heirarchy (in interracfes[]) of:
Ben Menchaca84f36632014-02-28 20:57:38 +00003327 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
3328 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
3329 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
3330 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
3331 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
3332 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
3333 *
3334 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
3335 * they will be created and added automatically to the database.
Ben Menchaca84f36632014-02-28 20:57:38 +00003336 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003337int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
3338 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin5dae8832015-12-03 14:23:19 -08003339 struct net_device *const_if, struct net_device *other_if,
Murat Sezginf92db492016-07-15 11:33:15 -07003340 ip_addr_t lookup_src_addr,
3341 ip_addr_t lookup_dest_addr,
3342 ip_addr_t real_dest_addr,
Murat Sezgin5dae8832015-12-03 14:23:19 -08003343 int ip_version, int packet_protocol,
3344 struct net_device *given_dest_dev,
3345 bool is_routed, struct net_device *given_src_dev,
3346 uint8_t *dest_node_addr, uint8_t *src_node_addr,
3347 __be16 *layer4hdr, struct sk_buff *skb)
3348{
3349 int protocol;
3350 ip_addr_t src_addr;
3351 ip_addr_t dest_addr;
3352 struct net_device *dest_dev;
3353 char *dest_dev_name;
3354 int32_t dest_dev_type;
3355 struct net_device *src_dev;
3356 char *src_dev_name;
3357 int32_t src_dev_type;
3358 int32_t current_interface_index;
3359 bool from_local_addr;
3360 bool next_dest_addr_valid;
3361 bool next_dest_node_addr_valid = false;
3362 ip_addr_t next_dest_addr;
3363 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003364 struct net_device *bridge;
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303365 struct net_device *top_dev_vlan = NULL;
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003366 uint32_t serial = ecm_db_connection_serial_get(feci->ci);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003367
3368 /*
3369 * Get a big endian of the IPv4 address we have been given as our starting point.
3370 */
3371 protocol = packet_protocol;
Murat Sezginf92db492016-07-15 11:33:15 -07003372 ECM_IP_ADDR_COPY(src_addr, lookup_src_addr);
3373 ECM_IP_ADDR_COPY(dest_addr, lookup_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003374
3375 if (ip_version == 4) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003376 DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_DOT_FMT " to dest_addr: " ECM_IP_ADDR_DOT_FMT ", protocol: %d (serial %u)\n",
3377 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol,
3378 serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003379#ifdef ECM_IPV6_ENABLE
3380 } else if (ip_version == 6) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003381 DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_OCTAL_FMT " to dest_addr: " ECM_IP_ADDR_OCTAL_FMT ", protocol: %d (serial %u)\n",
3382 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol,
3383 serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003384#endif
3385 } else {
3386 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
3387 return ECM_DB_IFACE_HEIRARCHY_MAX;
3388 }
3389
3390 /*
3391 * Get device to reach the given destination address.
3392 * If the heirarchy is for a routed connection we must use the devices obtained from the skb's route information..
3393 * If the heirarchy is NOT for a routed connection we try the given_dest_dev.
3394 */
3395 from_local_addr = false;
3396 if (!is_routed) {
3397 dest_dev = given_dest_dev;
3398 dev_hold(dest_dev);
3399 } else {
3400 dest_dev = ecm_interface_dev_find_by_local_addr(dest_addr);
3401 if (dest_dev) {
3402 from_local_addr = true;
3403 } else {
3404 dest_dev = const_if;
3405 dev_hold(dest_dev);
3406 }
3407 }
3408
3409 /*
3410 * If the address is a local address and protocol is an IP tunnel
3411 * then this connection is a tunnel endpoint made to this device.
3412 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
3413 *
3414 * TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
3415 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
3416 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
3417 */
3418 if (dest_dev && from_local_addr) {
3419 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
3420 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
3421 dev_put(dest_dev);
3422 dest_dev = given_dest_dev;
3423 if (dest_dev) {
3424 dev_hold(dest_dev);
3425 if (ip_version == 4) {
3426 DEBUG_TRACE("HACK: %s tunnel packet with dest_addr: " ECM_IP_ADDR_DOT_FMT " uses dev: %p(%s)\n", "IPV6", ECM_IP_ADDR_TO_DOT(dest_addr), dest_dev, dest_dev->name);
3427 } else {
3428 DEBUG_TRACE("HACK: %s tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", "IPIP", ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
3429 }
3430 }
3431 }
3432 }
3433
3434#ifdef ECM_INTERFACE_L2TPV2_ENABLE
3435 /*
3436 * if the address is a local address and indev=l2tp.
3437 */
3438 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
3439 dev_put(dest_dev);
3440 dest_dev = given_dest_dev;
3441 if (dest_dev) {
3442 dev_hold(dest_dev);
3443 DEBUG_TRACE("l2tp packet tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
3444 }
3445 }
3446#endif
3447
3448#ifdef ECM_INTERFACE_PPTP_ENABLE
3449 /*
3450 * if the address is a local address and indev=PPTP.
3451 */
3452 if (protocol == IPPROTO_GRE && given_dest_dev && given_dest_dev->type == ARPHRD_PPP) {
3453 dev_put(dest_dev);
3454 dest_dev = given_dest_dev;
3455 if (dest_dev) {
3456 dev_hold(dest_dev);
3457 DEBUG_TRACE("PPTP packet tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
3458 }
3459 }
3460#endif
3461
3462 if (!dest_dev) {
3463 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
3464 return ECM_DB_IFACE_HEIRARCHY_MAX;
3465 }
3466 dest_dev_name = dest_dev->name;
3467 dest_dev_type = dest_dev->type;
3468
3469 /*
3470 * Get device to reach the given source address.
3471 * If the heirarchy is for a routed connection we must use the devices obtained from the skb's route information..
3472 * If the heirarchy is NOT for a routed connection we try the given_src_dev.
3473 */
3474 from_local_addr = false;
3475 if (!is_routed) {
3476 src_dev = given_src_dev;
3477 dev_hold(src_dev);
3478 } else {
3479 src_dev = ecm_interface_dev_find_by_local_addr(src_addr);
3480 if (src_dev) {
3481 from_local_addr = true;
3482 } else {
3483 src_dev = other_if;
3484 dev_hold(src_dev);
3485 }
3486 }
3487
3488 /*
3489 * If the address is a local address and protocol is an IP tunnel
3490 * then this connection is a tunnel endpoint made to this device.
3491 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
3492 *
3493 * TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
3494 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
3495 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
3496 */
3497 if (src_dev && from_local_addr) {
3498 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
3499 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
3500 dev_put(src_dev);
3501 src_dev = given_src_dev;
3502 if (src_dev) {
3503 dev_hold(src_dev);
3504 if (ip_version == 4) {
3505 DEBUG_TRACE("HACK: %s tunnel packet with src_addr: " ECM_IP_ADDR_DOT_FMT " uses dev: %p(%s)\n", "IPV6", ECM_IP_ADDR_TO_DOT(src_addr), src_dev, src_dev->name);
3506 } else {
3507 DEBUG_TRACE("HACK: %s tunnel packet with src_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", "IPIP", ECM_IP_ADDR_TO_OCTAL(src_addr), src_dev, src_dev->name);
3508 }
3509 }
3510 }
3511 }
3512
3513 if (!src_dev) {
3514 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
3515 dev_put(dest_dev);
3516 return ECM_DB_IFACE_HEIRARCHY_MAX;
3517 }
3518 src_dev_name = src_dev->name;
3519 src_dev_type = src_dev->type;
3520
3521 /*
3522 * Check if source and dest dev are same.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003523 */
3524 if (src_dev == dest_dev) {
ratheesh kannotha6d25952016-04-11 12:23:26 +05303525 bool skip = false;
3526
Murat Sezgin5dae8832015-12-03 14:23:19 -08003527 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
ratheesh kannotha6d25952016-04-11 12:23:26 +05303528
3529 switch (ip_version) {
3530 case 4:
3531 if ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)) {
3532 skip = true;
3533 break;
3534 }
3535
3536 if ((protocol == IPPROTO_UDP) && (udp_hdr(skb)->dest == htons(4500))) {
3537 skip = true;
3538 break;
3539 }
3540
3541 break;
3542
3543 case 6:
ratheesh kannotha6d25952016-04-11 12:23:26 +05303544 if ((protocol == IPPROTO_IPIP) || (protocol == IPPROTO_ESP)) {
3545 skip = true;
3546 break;
3547 }
3548
3549 break;
3550
3551 default:
3552 DEBUG_WARN("IP version = %d, Protocol = %d: Corrupted packet entered ecm\n", ip_version, protocol);
3553 skip = true;
3554 break;
3555 }
3556
3557 if (skip) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003558 /*
3559 * This happens from the input hook
3560 * We do not want to create a connection entry for this
3561 * TODO YES WE DO.
3562 * TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
3563 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
3564 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
3565 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
3566 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
3567 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
3568 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
3569 */
3570 dev_put(src_dev);
3571 dev_put(dest_dev);
3572 return ECM_DB_IFACE_HEIRARCHY_MAX;
3573 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003574 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003575
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003576 bridge = ecm_interface_should_update_egress_device_bridged(
3577 given_dest_dev, dest_dev, is_routed);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003578
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003579 if (bridge) {
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003580 struct net_device *new_dest_dev;
Murat Sezginb9bd5e02016-08-05 14:55:07 -07003581 new_dest_dev = br_port_dev_get(bridge, dest_node_addr, skb, serial);
3582 if (new_dest_dev) {
3583 dev_put(dest_dev);
3584 if (new_dest_dev != given_dest_dev) {
3585 DEBUG_INFO("Adjusted port for %pM is %s (given was %s)\n",
3586 dest_node_addr, new_dest_dev->name,
3587 given_dest_dev->name);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003588
Murat Sezginb9bd5e02016-08-05 14:55:07 -07003589 dest_dev = new_dest_dev;
3590 dest_dev_name = dest_dev->name;
3591 dest_dev_type = dest_dev->type;
Murat Sezgin5dae8832015-12-03 14:23:19 -08003592 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003593 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003594 dev_put(bridge);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003595 }
3596
3597 next_dest_addr_valid = true;
3598 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
3599
3600 /*
3601 * Iterate until we are done or get to the max number of interfaces we can record.
3602 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
3603 * because we add from the end first_interface grows downwards.
3604 */
3605 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
3606 while (current_interface_index > 0) {
3607 struct ecm_db_iface_instance *ii;
3608 struct net_device *next_dev;
3609 /*
3610 * Get the ecm db interface instance for the device at hand
3611 */
3612 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
3613
3614 /*
3615 * If the interface could not be established then we abort
3616 */
3617 if (!ii) {
3618 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
3619 dev_put(src_dev);
3620 dev_put(dest_dev);
3621
3622 /*
3623 * Release the interfaces heirarchy we constructed to this point.
3624 */
3625 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3626 return ECM_DB_IFACE_HEIRARCHY_MAX;
3627 }
3628
3629 /*
3630 * Record the interface instance into the interfaces[]
3631 */
3632 current_interface_index--;
3633 interfaces[current_interface_index] = ii;
3634
3635 /*
3636 * Now we have to figure out what the next device will be (in the transmission path) the skb
3637 * will use to emit to the destination address.
3638 */
3639 do {
3640#ifdef ECM_INTERFACE_PPP_ENABLE
3641 int channel_count;
3642 struct ppp_channel *ppp_chan[1];
3643 int channel_protocol;
3644#ifdef ECM_INTERFACE_PPPOE_ENABLE
3645 struct pppoe_opt addressing;
3646#endif
3647#endif
3648
3649 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
3650 next_dev = NULL;
3651
3652 if (dest_dev_type == ARPHRD_ETHER) {
3653 /*
3654 * Ethernet - but what sub type?
3655 */
3656
3657#ifdef ECM_INTERFACE_VLAN_ENABLE
3658 /*
3659 * VLAN?
3660 */
3661 if (is_vlan_dev(dest_dev)) {
3662 /*
3663 * VLAN master
3664 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
3665 */
Shyam Sunder9db20852016-03-09 19:04:49 +05303666 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003667 dev_hold(next_dev);
3668 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
3669 dest_dev, next_dev, next_dev->name);
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303670 if (current_interface_index == (ECM_DB_IFACE_HEIRARCHY_MAX - 1)) {
3671 top_dev_vlan = dest_dev;
3672 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003673 break;
3674 }
3675#endif
3676
3677 /*
3678 * BRIDGE?
3679 */
3680 if (ecm_front_end_is_bridge_device(dest_dev)) {
3681 /*
3682 * Bridge
3683 * Figure out which port device the skb will go to using the dest_addr.
3684 */
3685 uint8_t mac_addr[ETH_ALEN];
3686
3687 if (next_dest_node_addr_valid) {
3688 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
3689 } else if (!next_dest_addr_valid) {
3690 dev_put(src_dev);
3691 dev_put(dest_dev);
3692
3693 /*
3694 * Release the interfaces heirarchy we constructed to this point.
3695 */
3696 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3697 return ECM_DB_IFACE_HEIRARCHY_MAX;
3698 } else {
3699 if (!ecm_interface_get_next_node_mac_address(dest_addr, dest_dev, ip_version, mac_addr)) {
3700 dev_put(src_dev);
3701 dev_put(dest_dev);
3702
3703 /*
3704 * Release the interfaces heirarchy we constructed to this point.
3705 */
3706 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3707 return ECM_DB_IFACE_HEIRARCHY_MAX;
3708 }
3709 }
3710
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003711 next_dev = br_port_dev_get(dest_dev,
3712 mac_addr, skb, serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003713
3714 if (!next_dev) {
3715 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
3716 dev_put(src_dev);
3717 dev_put(dest_dev);
3718
3719 /*
3720 * Release the interfaces heirarchy we constructed to this point.
3721 */
3722 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3723 return ECM_DB_IFACE_HEIRARCHY_MAX;
3724 }
3725 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3726 break;
3727 }
3728
3729#ifdef ECM_INTERFACE_BOND_ENABLE
3730 /*
3731 * LAG?
3732 */
3733 if (ecm_front_end_is_lag_master(dest_dev)) {
3734 /*
3735 * Link aggregation
3736 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
3737 */
3738 uint32_t src_addr_32 = 0;
3739 uint32_t dest_addr_32 = 0;
3740 struct in6_addr src_addr6;
3741 struct in6_addr dest_addr6;
3742 uint8_t src_mac_addr[ETH_ALEN];
3743 uint8_t dest_mac_addr[ETH_ALEN];
3744
3745 memset(src_mac_addr, 0, ETH_ALEN);
3746 memset(dest_mac_addr, 0, ETH_ALEN);
3747
3748 if (ip_version == 4) {
3749 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
Murat Sezginf92db492016-07-15 11:33:15 -07003750 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, real_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003751 }
3752
3753 if (!is_routed) {
3754 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
3755 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
3756 } else {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003757 struct net_device *master_dev;
Murat Sezgin5dae8832015-12-03 14:23:19 -08003758
3759 /*
Murat Sezgin7be87d22016-01-29 17:41:37 -08003760 * Use appropriate source MAC address for routed packets and
3761 * find proper interface to find the destination mac address and
3762 * from which to issue ARP or neighbour solicitation packet.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003763 */
Murat Sezgin7be87d22016-01-29 17:41:37 -08003764 master_dev = ecm_interface_get_and_hold_dev_master(dest_dev);
3765 if (master_dev) {
3766 memcpy(src_mac_addr, master_dev->dev_addr, ETH_ALEN);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003767 } else {
3768 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003769 master_dev = dest_dev;
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303770 if (top_dev_vlan) {
3771 master_dev = top_dev_vlan;
3772 }
Murat Sezgin7be87d22016-01-29 17:41:37 -08003773 dev_hold(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003774 }
3775
3776 /*
3777 * Determine destination MAC address for this routed packet
3778 */
3779 if (next_dest_node_addr_valid) {
3780 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
3781 } else if (!next_dest_addr_valid) {
3782 dev_put(src_dev);
3783 dev_put(dest_dev);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003784 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003785 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3786 return ECM_DB_IFACE_HEIRARCHY_MAX;
3787 } else {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003788 if (!ecm_interface_mac_addr_get_no_route(master_dev, dest_addr, dest_mac_addr)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003789 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3790 /*
3791 * Try one more time with gateway ip address if it exists.
3792 */
3793 if (!ecm_interface_find_gateway(dest_addr, gw_addr)) {
3794 goto lag_fail;
3795 }
3796
3797 if (ip_version == 4) {
3798 DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(gw_addr));
3799 }
3800#ifdef ECM_IPV6_ENABLE
3801
3802 if (ip_version == 6) {
3803 DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr));
3804 }
3805#endif
Murat Sezgin7be87d22016-01-29 17:41:37 -08003806 if (ecm_interface_mac_addr_get_no_route(master_dev, gw_addr, dest_mac_addr)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003807 DEBUG_TRACE("Found the mac address for gateway\n");
Murat Sezgin7be87d22016-01-29 17:41:37 -08003808 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003809 goto lag_success;
3810 }
3811
3812 if (ip_version == 4) {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003813 ecm_interface_send_arp_request(master_dev, dest_addr, false, gw_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003814
3815 DEBUG_WARN("Unable to obtain any MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
3816 }
3817#ifdef ECM_IPV6_ENABLE
3818 if (ip_version == 6) {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003819 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003820
3821 DEBUG_WARN("Unable to obtain any MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
3822 }
3823#endif
3824lag_fail:
3825 dev_put(src_dev);
3826 dev_put(dest_dev);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003827 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003828
3829 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3830 return ECM_DB_IFACE_HEIRARCHY_MAX;
3831 }
Murat Sezgin7be87d22016-01-29 17:41:37 -08003832 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003833 }
3834 }
3835lag_success:
3836 if (ip_version == 4) {
3837 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3838 &src_addr_32, &dest_addr_32,
3839 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
3840 } else if (ip_version == 6) {
3841 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
Murat Sezginf92db492016-07-15 11:33:15 -07003842 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, real_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003843 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3844 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05303845 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003846 }
3847
3848 if (next_dev && netif_carrier_ok(next_dev)) {
3849 dev_hold(next_dev);
3850 } else {
3851 DEBUG_WARN("Unable to obtain LAG output slave device\n");
3852 dev_put(src_dev);
3853 dev_put(dest_dev);
3854
3855 /*
3856 * Release the interfaces heirarchy we constructed to this point.
3857 */
3858 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3859 return ECM_DB_IFACE_HEIRARCHY_MAX;
3860 }
3861
3862 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3863 break;
3864 }
3865#endif
3866
3867 /*
3868 * ETHERNET!
3869 * Just plain ethernet it seems.
3870 */
3871 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
3872 break;
3873 }
3874
3875 /*
3876 * LOOPBACK?
3877 */
3878 if (dest_dev_type == ARPHRD_LOOPBACK) {
3879 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
3880 break;
3881 }
3882
3883 /*
3884 * IPSEC?
3885 */
3886 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
3887 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
3888 /* TODO Figure out the next device the tunnel is using... */
3889 break;
3890 }
3891
3892 /*
3893 * SIT (6-in-4)?
3894 */
3895 if (dest_dev_type == ARPHRD_SIT) {
3896 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
3897 /* TODO Figure out the next device the tunnel is using... */
3898 break;
3899 }
3900
3901 /*
3902 * IPIP6 Tunnel?
3903 */
3904 if (dest_dev_type == ARPHRD_TUNNEL6) {
3905 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
3906 /* TODO Figure out the next device the tunnel is using... */
3907 break;
3908 }
3909
ratheesh kannothcfdcb332015-12-24 07:19:18 +05303910#ifdef ECM_INTERFACE_MAP_T_ENABLE
3911 /*
3912 * MAP-T xlate ?
3913 */
3914 if (dest_dev_type == ARPHRD_NONE) {
3915 if (is_map_t_dev(dest_dev)) {
3916 DEBUG_TRACE("Net device: %p is MAP-T type: %d\n", dest_dev, dest_dev_type);
3917 break;
3918 }
3919 }
3920#endif
3921
Murat Sezgin5dae8832015-12-03 14:23:19 -08003922 /*
3923 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
3924 */
3925 if (dest_dev_type != ARPHRD_PPP) {
3926 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
3927 break;
3928 }
3929
3930#ifndef ECM_INTERFACE_PPP_ENABLE
3931 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
3932#else
3933 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
3934
3935#ifdef ECM_INTERFACE_L2TPV2_ENABLE
3936 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
3937 if (skb->skb_iif == dest_dev->ifindex) {
3938 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
3939 break;
3940 }
3941 }
3942#endif
3943
3944#ifdef ECM_INTERFACE_PPTP_ENABLE
3945 if (protocol == IPPROTO_GRE && dest_dev && dest_dev->type == ARPHRD_PPP) {
3946 DEBUG_TRACE("Net device: %p PPP channel is PPTP\n", dest_dev);
3947 break;
3948 }
3949#endif
3950 /*
3951 * PPP - but what is the channel type?
3952 * First: If this is multi-link then we do not support it
3953 */
3954 if (ppp_is_multilink(dest_dev) > 0) {
3955 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
3956 break;
3957 }
3958
3959 /*
3960 * Get the PPP channel and then enquire what kind of channel it is
3961 * NOTE: Not multilink so only one channel to get.
3962 */
3963 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
3964 if (channel_count != 1) {
3965 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
3966 dest_dev, channel_count);
3967 break;
3968 }
3969
3970 /*
3971 * Get channel protocol type
3972 * NOTE: Not all PPP channels support channel specific methods.
3973 */
3974 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
3975
3976#ifdef ECM_INTERFACE_L2TPV2_ENABLE
3977 if (channel_protocol == PX_PROTO_OL2TP) {
3978
3979 /*
3980 * PPPoL2TPV2 channel
3981 */
3982 ppp_release_channels(ppp_chan, 1);
3983 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
3984
3985 /*
3986 * Release the channel. Note that next_dev not held.
3987 */
3988 break;
3989 }
3990#endif
3991#ifdef ECM_INTERFACE_PPPOE_ENABLE
3992 if (channel_protocol == PX_PROTO_OE) {
3993 /*
3994 * PPPoE channel
3995 */
3996 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
3997
3998 /*
3999 * Get PPPoE session information and the underlying device it is using.
4000 */
4001 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
4002
4003 /*
4004 * Copy the dev hold into this, we will release the hold later
4005 */
4006 next_dev = addressing.dev;
4007 next_dest_addr_valid = false;
4008 next_dest_node_addr_valid = true;
4009 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
4010
4011 /*
4012 * Release the channel. Note that next_dev is still (correctly) held.
4013 */
4014 ppp_release_channels(ppp_chan, 1);
4015 break;
4016 }
4017#endif
4018
4019 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
4020 dest_dev, channel_protocol);
4021
4022 /*
4023 * Release the channel
4024 */
4025 ppp_release_channels(ppp_chan, 1);
4026
4027#endif
4028 } while (false);
4029
4030 /*
4031 * No longer need dest_dev as it may become next_dev
4032 */
4033 dev_put(dest_dev);
4034
4035 /*
4036 * Check out the next_dev, if any
4037 */
4038 if (!next_dev) {
4039 int32_t i __attribute__((unused));
4040 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
4041#if DEBUG_LEVEL > 1
4042 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
4043 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
4044 i, interfaces[i], ecm_db_connection_iface_type_get(interfaces[i]), ecm_db_interface_type_to_string(ecm_db_connection_iface_type_get(interfaces[i])));
4045
4046 }
4047#endif
4048
4049 /*
4050 * Release src_dev now
4051 */
4052 dev_put(src_dev);
4053 return current_interface_index;
4054 }
4055
4056 /*
4057 * dest_dev becomes next_dev
4058 */
4059 dest_dev = next_dev;
4060 dest_dev_name = dest_dev->name;
4061 dest_dev_type = dest_dev->type;
4062 }
4063
4064 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
4065 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
4066 dev_put(src_dev);
4067 dev_put(dest_dev);
4068
4069 /*
4070 * Release the interfaces heirarchy we constructed to this point.
4071 */
4072 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4073 return ECM_DB_IFACE_HEIRARCHY_MAX;
4074}
4075EXPORT_SYMBOL(ecm_interface_heirarchy_construct);
4076
4077#ifdef ECM_MULTICAST_ENABLE
4078/*
4079 * ecm_interface_multicast_from_heirarchy_construct()
4080 * Construct an interface heirarchy.
4081 *
4082 * TODO: This function will be removed later and ecm_interface_heirarchy_construct() function
4083 * will be used when the multicast code is fixed to use the new interface hierarchy
4084 * construction model which uses the skb's route information instead of doing
4085 * the route lookup based on the IP addresses.
4086 *
4087 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
4088 * This is the heirarchy of interfaces a packet would transit to emit from the device.
4089 *
4090 * We will use the given src/dest devices when is_routed is false.
4091 * When is_routed is true we will try routing tables first, failing back to any given.
4092 *
4093 * For example, with this network arrangement:
4094 *
4095 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
4096 *
4097 * Given the packet_dest_addr IP address 10.22.33.11 this will create an interface heirarchy (in interracfes[]) of:
4098 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
4099 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
4100 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
4101 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
4102 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
4103 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
4104 *
4105 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
4106 * they will be created and added automatically to the database.
4107 */
4108int32_t ecm_interface_multicast_from_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
4109 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin188b4a32015-06-03 10:58:59 -07004110 ip_addr_t packet_src_addr,
4111 ip_addr_t packet_dest_addr,
4112 int ip_version, int packet_protocol,
4113 struct net_device *given_dest_dev,
4114 bool is_routed, struct net_device *given_src_dev,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05304115 uint8_t *dest_node_addr, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304116 __be16 *layer4hdr, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00004117{
Ben Menchaca84f36632014-02-28 20:57:38 +00004118 int protocol;
4119 ip_addr_t src_addr;
4120 ip_addr_t dest_addr;
Ben Menchaca84f36632014-02-28 20:57:38 +00004121 struct net_device *dest_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00004122 char *dest_dev_name;
Ben Menchaca84f36632014-02-28 20:57:38 +00004123 int32_t dest_dev_type;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004124 struct net_device *src_dev;
4125 char *src_dev_name;
4126 int32_t src_dev_type;
Ben Menchaca84f36632014-02-28 20:57:38 +00004127 int32_t current_interface_index;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004128 bool from_local_addr;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004129 bool next_dest_addr_valid;
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004130 bool next_dest_node_addr_valid = false;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004131 ip_addr_t next_dest_addr;
4132 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004133 struct net_device *bridge;
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004134 uint32_t serial = ecm_db_connection_serial_get(feci->ci);
Ben Menchaca84f36632014-02-28 20:57:38 +00004135
4136 /*
4137 * Get a big endian of the IPv4 address we have been given as our starting point.
4138 */
4139 protocol = packet_protocol;
4140 ECM_IP_ADDR_COPY(src_addr, packet_src_addr);
4141 ECM_IP_ADDR_COPY(dest_addr, packet_dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004142
4143 if (ip_version == 4) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004144 DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_DOT_FMT " to dest_addr: " ECM_IP_ADDR_DOT_FMT ", protocol: %d (serial %u)\n",
4145 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol,
4146 serial);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004147#ifdef ECM_IPV6_ENABLE
4148 } else if (ip_version == 6) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004149 DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_OCTAL_FMT " to dest_addr: " ECM_IP_ADDR_OCTAL_FMT ", protocol: %d (serial %u)\n",
4150 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol,
4151 serial);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004152#endif
4153 } else {
4154 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
4155 return ECM_DB_IFACE_HEIRARCHY_MAX;
4156 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004157
4158 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004159 * Get device to reach the given destination address.
4160 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_dest_dev.
4161 * If the heirarchy is NOT for a routed connection we try the given_dest_dev first, followed by routed lookup.
Ben Menchaca84f36632014-02-28 20:57:38 +00004162 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004163 from_local_addr = false;
4164 if (is_routed) {
4165 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
4166 if (!dest_dev && given_dest_dev) {
4167 /*
4168 * Fall back to any given
4169 */
4170 dest_dev = given_dest_dev;
4171 dev_hold(dest_dev);
Gareth Williams43fc0852014-05-26 19:10:00 +01004172 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004173 } else if (given_dest_dev) {
4174 dest_dev = given_dest_dev;
4175 dev_hold(dest_dev);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304176 } else {
4177 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004178 * Fall back to routed look up
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304179 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004180 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
Gareth Williams43fc0852014-05-26 19:10:00 +01004181 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304182
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004183 /*
4184 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
4185 * then this connection is a tunnel endpoint made to this device.
4186 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
4187 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
4188 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
4189 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
4190 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07004191 if (dest_dev && from_local_addr) {
4192 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
4193 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
4194 dev_put(dest_dev);
4195 dest_dev = given_dest_dev;
4196 if (dest_dev) {
4197 dev_hold(dest_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05304198 if (ip_version == 4) {
4199 DEBUG_TRACE("HACK: %s tunnel packet with dest_addr: " ECM_IP_ADDR_DOT_FMT " uses dev: %p(%s)\n", "IPV6", ECM_IP_ADDR_TO_DOT(dest_addr), dest_dev, dest_dev->name);
4200 } else {
4201 DEBUG_TRACE("HACK: %s tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", "IPIP", ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
4202 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004203 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304204 }
Gareth Williams43fc0852014-05-26 19:10:00 +01004205 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304206
4207#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4208 /*
4209 * if the address is a local address and indev=l2tp.
4210 */
4211 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
4212 dev_put(dest_dev);
4213 dest_dev = given_dest_dev;
4214 if (dest_dev) {
4215 dev_hold(dest_dev);
4216 DEBUG_TRACE("l2tp packet tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
4217 }
4218 }
4219#endif
4220
Shyam Sunder23f2e542015-09-28 14:56:49 +05304221#ifdef ECM_INTERFACE_PPTP_ENABLE
4222 /*
4223 * if the address is a local address and indev=PPTP.
4224 */
4225 if (protocol == IPPROTO_GRE && given_dest_dev && given_dest_dev->type == ARPHRD_PPP) {
4226 dev_put(dest_dev);
4227 dest_dev = given_dest_dev;
4228 if (dest_dev) {
4229 dev_hold(dest_dev);
4230 DEBUG_TRACE("PPTP packet tunnel packet with dest_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(dest_addr), dest_dev, dest_dev->name);
4231 }
4232 }
4233#endif
4234
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004235 if (!dest_dev) {
4236 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
4237 return ECM_DB_IFACE_HEIRARCHY_MAX;
4238 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004239 dest_dev_name = dest_dev->name;
4240 dest_dev_type = dest_dev->type;
4241
4242 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004243 * Get device to reach the given source address.
4244 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_src_dev.
4245 * If the heirarchy is NOT for a routed connection we try the given_src_dev first, followed by routed lookup.
4246 */
4247 from_local_addr = false;
4248 if (is_routed) {
4249 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
4250 if (!src_dev && given_src_dev) {
4251 /*
4252 * Fall back to any given
4253 */
4254 src_dev = given_src_dev;
4255 dev_hold(src_dev);
4256 }
4257 } else if (given_src_dev) {
4258 src_dev = given_src_dev;
4259 dev_hold(src_dev);
4260 } else {
4261 /*
4262 * Fall back to routed look up
4263 */
4264 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
4265 }
4266
4267 /*
4268 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
4269 * then this connection is a tunnel endpoint made to this device.
4270 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
4271 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
4272 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
4273 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
4274 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07004275 if (src_dev && from_local_addr) {
4276 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
4277 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
4278 dev_put(src_dev);
4279 src_dev = given_src_dev;
4280 if (src_dev) {
4281 dev_hold(src_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05304282 if (ip_version == 4) {
4283 DEBUG_TRACE("HACK: %s tunnel packet with src_addr: " ECM_IP_ADDR_DOT_FMT " uses dev: %p(%s)\n", "IPV6", ECM_IP_ADDR_TO_DOT(src_addr), src_dev, src_dev->name);
4284 } else {
4285 DEBUG_TRACE("HACK: %s tunnel packet with src_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", "IPIP", ECM_IP_ADDR_TO_OCTAL(src_addr), src_dev, src_dev->name);
4286 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004287 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004288 }
4289 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004290
ratheesh kannothed721852015-09-28 12:39:52 +05304291#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4292 /*
4293 * if the address is a local address and indev=l2tp.
4294 */
4295 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
4296 if (dest_dev != given_src_dev) {
4297 dev_put(src_dev);
4298 src_dev = given_src_dev;
4299 if (src_dev) {
4300 dev_hold(src_dev);
4301 DEBUG_TRACE("l2tp tunnel packet with src_addr: " ECM_IP_ADDR_OCTAL_FMT " uses dev: %p(%s)\n", ECM_IP_ADDR_TO_OCTAL(src_addr), src_dev, src_dev->name);
4302 }
4303 }
4304 }
4305#endif
4306
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004307 if (!src_dev) {
4308 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
4309 dev_put(dest_dev);
4310 return ECM_DB_IFACE_HEIRARCHY_MAX;
4311 }
4312 src_dev_name = src_dev->name;
4313 src_dev_type = src_dev->type;
4314
4315 /*
4316 * Check if source and dest dev are same.
4317 * For the forwarded flows which involve tunnels this will happen when called from input hook.
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304318 */
4319 if (src_dev == dest_dev) {
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004320 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004321 if (((ip_version == 4) && ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)))
4322 || ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304323 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004324 * This happens from the input hook
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304325 * We do not want to create a connection entry for this
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004326 * GGG TODO YES WE DO.
4327 * GGG TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
4328 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
4329 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
4330 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
4331 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
4332 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
4333 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304334 */
4335 dev_put(src_dev);
4336 dev_put(dest_dev);
4337 return ECM_DB_IFACE_HEIRARCHY_MAX;
4338 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004339 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004340
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004341 bridge = ecm_interface_should_update_egress_device_bridged(
4342 given_dest_dev, dest_dev, is_routed);
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004343
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004344 if (bridge) {
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004345 struct net_device *new_dest_dev;
Murat Sezginb9bd5e02016-08-05 14:55:07 -07004346 new_dest_dev = br_port_dev_get(bridge, dest_node_addr, skb, serial);
4347 if (new_dest_dev) {
4348 dev_put(dest_dev);
4349 if (new_dest_dev != given_dest_dev) {
4350 DEBUG_INFO("Adjusted port for %pM is %s (given was %s)\n",
4351 dest_node_addr, new_dest_dev->name,
4352 given_dest_dev->name);
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004353
Murat Sezginb9bd5e02016-08-05 14:55:07 -07004354 dest_dev = new_dest_dev;
4355 dest_dev_name = dest_dev->name;
4356 dest_dev_type = dest_dev->type;
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004357 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004358 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004359 dev_put(bridge);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304360 }
4361
Murat Sezgin7ef29962015-08-14 10:53:24 -07004362 next_dest_addr_valid = true;
Murat Sezgin5dae8832015-12-03 14:23:19 -08004363 next_dest_node_addr_valid = false;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004364 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
4365
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304366 /*
Ben Menchaca84f36632014-02-28 20:57:38 +00004367 * Iterate until we are done or get to the max number of interfaces we can record.
4368 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
4369 * because we add from the end first_interface grows downwards.
4370 */
4371 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
4372 while (current_interface_index > 0) {
4373 struct ecm_db_iface_instance *ii;
4374 struct net_device *next_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00004375 /*
4376 * Get the ecm db interface instance for the device at hand
4377 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304378 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Ben Menchaca84f36632014-02-28 20:57:38 +00004379
4380 /*
4381 * If the interface could not be established then we abort
4382 */
4383 if (!ii) {
4384 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
4385 dev_put(src_dev);
4386 dev_put(dest_dev);
4387
4388 /*
4389 * Release the interfaces heirarchy we constructed to this point.
4390 */
4391 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4392 return ECM_DB_IFACE_HEIRARCHY_MAX;
4393 }
4394
4395 /*
4396 * Record the interface instance into the interfaces[]
4397 */
4398 current_interface_index--;
4399 interfaces[current_interface_index] = ii;
4400
4401 /*
4402 * Now we have to figure out what the next device will be (in the transmission path) the skb
4403 * will use to emit to the destination address.
4404 */
4405 do {
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08004406#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004407 int channel_count;
4408 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00004409 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304410#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004411 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004412#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304413#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004414
4415 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
4416 next_dev = NULL;
4417
4418 if (dest_dev_type == ARPHRD_ETHER) {
4419 /*
4420 * Ethernet - but what sub type?
4421 */
4422
Gareth Williams141d2382014-11-25 11:35:19 -08004423#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004424 /*
4425 * VLAN?
4426 */
4427 if (is_vlan_dev(dest_dev)) {
4428 /*
4429 * VLAN master
4430 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
4431 */
Shyam Sunder9db20852016-03-09 19:04:49 +05304432 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004433 dev_hold(next_dev);
4434 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
4435 dest_dev, next_dev, next_dev->name);
4436 break;
4437 }
Gareth Williams141d2382014-11-25 11:35:19 -08004438#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004439
4440 /*
4441 * BRIDGE?
4442 */
4443 if (ecm_front_end_is_bridge_device(dest_dev)) {
4444 /*
4445 * Bridge
4446 * Figure out which port device the skb will go to using the dest_addr.
4447 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004448 uint8_t mac_addr[ETH_ALEN];
Murat Sezgin7ef29962015-08-14 10:53:24 -07004449
4450 if (next_dest_node_addr_valid) {
4451 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
4452 } else if (!next_dest_addr_valid) {
Ben Menchaca84f36632014-02-28 20:57:38 +00004453 dev_put(src_dev);
4454 dev_put(dest_dev);
4455
4456 /*
4457 * Release the interfaces heirarchy we constructed to this point.
4458 */
4459 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4460 return ECM_DB_IFACE_HEIRARCHY_MAX;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004461 } else {
Murat Sezgin5dae8832015-12-03 14:23:19 -08004462 if (!ecm_interface_multicast_get_next_node_mac_address(next_dest_addr, dest_dev, ip_version, mac_addr)) {
Murat Sezgin7ef29962015-08-14 10:53:24 -07004463 dev_put(src_dev);
4464 dev_put(dest_dev);
4465
4466 /*
4467 * Release the interfaces heirarchy we constructed to this point.
4468 */
4469 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4470 return ECM_DB_IFACE_HEIRARCHY_MAX;
4471 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004472 }
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004473 next_dev = br_port_dev_get(dest_dev,
4474 mac_addr, skb, serial);
Ben Menchaca84f36632014-02-28 20:57:38 +00004475 if (!next_dev) {
4476 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
4477 dev_put(src_dev);
4478 dev_put(dest_dev);
4479
4480 /*
4481 * Release the interfaces heirarchy we constructed to this point.
4482 */
4483 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4484 return ECM_DB_IFACE_HEIRARCHY_MAX;
4485 }
4486 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
4487 break;
4488 }
Gareth Williams8ac34292015-03-17 14:06:58 +00004489
Murat Sezginb3731e82014-11-26 12:20:59 -08004490#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004491 /*
4492 * LAG?
4493 */
4494 if (ecm_front_end_is_lag_master(dest_dev)) {
4495 /*
4496 * Link aggregation
Murat Sezginb3731e82014-11-26 12:20:59 -08004497 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
Ben Menchaca84f36632014-02-28 20:57:38 +00004498 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304499 bool dest_on_link = false;
4500 ip_addr_t dest_gw_addr = ECM_IP_ADDR_NULL;
4501 uint32_t src_addr_32 = 0;
4502 uint32_t dest_addr_32 = 0;
Suman Ghoshf14d2172015-07-31 14:38:10 +05304503 struct in6_addr src_addr6;
4504 struct in6_addr dest_addr6;
Ben Menchaca84f36632014-02-28 20:57:38 +00004505 uint8_t src_mac_addr[ETH_ALEN];
4506 uint8_t dest_mac_addr[ETH_ALEN];
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304507 struct net_device *master_dev = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00004508
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304509 memset(src_mac_addr, 0, ETH_ALEN);
4510 memset(dest_mac_addr, 0, ETH_ALEN);
Ben Menchaca84f36632014-02-28 20:57:38 +00004511
Gareth Williams341df382015-07-20 16:44:17 +01004512 if (ip_version == 4) {
4513 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
4514 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
4515 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304516
4517 if (!is_routed) {
4518 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
4519 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
4520 } else {
Murat Sezginb3731e82014-11-26 12:20:59 -08004521 struct net_device *dest_dev_master;
4522
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304523 /*
4524 * Use appropriate source MAC address for routed packets
4525 */
Murat Sezginb3731e82014-11-26 12:20:59 -08004526 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
4527 if (dest_dev_master) {
4528 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304529 } else {
4530 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
4531 }
4532
4533 /*
4534 * Determine destination MAC address for this routed packet
4535 */
Tushar Mathur78b5f432015-09-18 20:13:31 +05304536 if (next_dest_node_addr_valid) {
4537 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
4538 } else if (!next_dest_addr_valid) {
4539 dev_put(src_dev);
4540 dev_put(dest_dev);
Murat Sezginb3731e82014-11-26 12:20:59 -08004541 if (dest_dev_master) {
4542 dev_put(dest_dev_master);
4543 }
4544
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304545 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4546 return ECM_DB_IFACE_HEIRARCHY_MAX;
Tushar Mathur78b5f432015-09-18 20:13:31 +05304547 } else {
4548 if (!ecm_interface_mac_addr_get(dest_addr, dest_mac_addr,
4549 &dest_on_link, dest_gw_addr)) {
4550
4551 /*
4552 * Find proper interfce from which to issue ARP
4553 * or neighbour solicitation packet.
4554 */
4555 if (dest_dev_master) {
4556 master_dev = dest_dev_master;
4557 } else {
4558 master_dev = dest_dev;
4559 }
4560
4561 dev_hold(master_dev);
4562
4563 if (dest_dev_master) {
4564 dev_put(dest_dev_master);
4565 }
4566
4567 if (ip_version == 4) {
4568 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
4569 ecm_interface_send_arp_request(dest_dev, dest_addr, dest_on_link, dest_gw_addr);
4570 }
4571#ifdef ECM_IPV6_ENABLE
4572 if (ip_version == 6) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08004573 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
Tushar Mathur78b5f432015-09-18 20:13:31 +05304574 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
4575 }
4576#endif
4577 dev_put(src_dev);
4578 dev_put(dest_dev);
4579 dev_put(master_dev);
4580 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4581 return ECM_DB_IFACE_HEIRARCHY_MAX;
4582 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304583 }
Murat Sezginb3731e82014-11-26 12:20:59 -08004584
4585 if (dest_dev_master) {
4586 dev_put(dest_dev_master);
4587 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304588 }
4589
Murat Sezgin188b4a32015-06-03 10:58:59 -07004590 if (ip_version == 4) {
4591 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
4592 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05304593 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004594 } else if (ip_version == 6) {
Suman Ghoshf14d2172015-07-31 14:38:10 +05304595 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
4596 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004597 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
Suman Ghoshf14d2172015-07-31 14:38:10 +05304598 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05304599 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004600 }
4601
Tushar Mathur933907c2014-06-24 17:06:14 +05304602 if (next_dev && netif_carrier_ok(next_dev)) {
Ben Menchaca84f36632014-02-28 20:57:38 +00004603 dev_hold(next_dev);
4604 } else {
4605 DEBUG_WARN("Unable to obtain LAG output slave device\n");
4606 dev_put(src_dev);
4607 dev_put(dest_dev);
4608
4609 /*
4610 * Release the interfaces heirarchy we constructed to this point.
4611 */
4612 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4613 return ECM_DB_IFACE_HEIRARCHY_MAX;
4614 }
4615
4616 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
Ben Menchaca84f36632014-02-28 20:57:38 +00004617 break;
4618 }
Murat Sezginb3731e82014-11-26 12:20:59 -08004619#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004620
4621 /*
4622 * ETHERNET!
4623 * Just plain ethernet it seems.
4624 */
4625 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
4626 break;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05304627 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004628
4629 /*
4630 * LOOPBACK?
4631 */
4632 if (dest_dev_type == ARPHRD_LOOPBACK) {
4633 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
4634 break;
4635 }
4636
4637 /*
4638 * IPSEC?
4639 */
4640 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
4641 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004642 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004643 break;
4644 }
4645
4646 /*
4647 * SIT (6-in-4)?
4648 */
4649 if (dest_dev_type == ARPHRD_SIT) {
4650 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004651 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004652 break;
4653 }
4654
4655 /*
4656 * IPIP6 Tunnel?
4657 */
4658 if (dest_dev_type == ARPHRD_TUNNEL6) {
4659 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004660 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004661 break;
4662 }
4663
4664 /*
4665 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
4666 */
4667 if (dest_dev_type != ARPHRD_PPP) {
4668 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
4669 break;
4670 }
4671
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08004672#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004673 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
4674#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304675 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
4676
4677#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4678 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
ratheesh kannothed721852015-09-28 12:39:52 +05304679 if (skb->skb_iif == dest_dev->ifindex) {
4680 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
4681 break;
4682 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304683 }
4684#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05304685
4686#ifdef ECM_INTERFACE_PPTP_ENABLE
4687 if (protocol == IPPROTO_GRE && dest_dev && dest_dev->type == ARPHRD_PPP) {
4688 DEBUG_TRACE("Net device: %p PPP channel is PPTP\n", dest_dev);
4689 break;
4690 }
4691#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004692 /*
4693 * PPP - but what is the channel type?
4694 * First: If this is multi-link then we do not support it
4695 */
4696 if (ppp_is_multilink(dest_dev) > 0) {
4697 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
4698 break;
4699 }
4700
Ben Menchaca84f36632014-02-28 20:57:38 +00004701 /*
4702 * Get the PPP channel and then enquire what kind of channel it is
4703 * NOTE: Not multilink so only one channel to get.
4704 */
4705 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
4706 if (channel_count != 1) {
4707 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
4708 dest_dev, channel_count);
4709 break;
4710 }
4711
4712 /*
4713 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01004714 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00004715 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01004716 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304717
4718#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4719 if (channel_protocol == PX_PROTO_OL2TP) {
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05304720
Ben Menchaca84f36632014-02-28 20:57:38 +00004721 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304722 * PPPoL2TPV2 channel
Ben Menchaca84f36632014-02-28 20:57:38 +00004723 */
4724 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304725 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004726
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304727 /*
4728 * Release the channel. Note that next_dev not held.
4729 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004730 break;
4731 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304732#endif
4733#ifdef ECM_INTERFACE_PPPOE_ENABLE
4734 if (channel_protocol == PX_PROTO_OE) {
4735 /*
4736 * PPPoE channel
4737 */
4738 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
4739
4740 /*
4741 * Get PPPoE session information and the underlying device it is using.
4742 */
4743 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
4744
4745 /*
4746 * Copy the dev hold into this, we will release the hold later
4747 */
4748 next_dev = addressing.dev;
4749 next_dest_addr_valid = false;
4750 next_dest_node_addr_valid = true;
4751 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
4752
4753 /*
4754 * Release the channel. Note that next_dev is still (correctly) held.
4755 */
4756 ppp_release_channels(ppp_chan, 1);
4757 break;
4758 }
4759#endif
4760
4761 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
4762 dest_dev, channel_protocol);
Ben Menchaca84f36632014-02-28 20:57:38 +00004763
4764 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304765 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00004766 */
4767 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304768
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004769#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004770 } while (false);
4771
4772 /*
Gareth Williamsa11d4352014-05-14 18:25:49 +01004773 * No longer need dest_dev as it may become next_dev
Ben Menchaca84f36632014-02-28 20:57:38 +00004774 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004775 dev_put(dest_dev);
4776
4777 /*
4778 * Check out the next_dev, if any
4779 */
4780 if (!next_dev) {
4781 int32_t i __attribute__((unused));
4782 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
4783#if DEBUG_LEVEL > 1
4784 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
4785 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
4786 i, interfaces[i], ecm_db_connection_iface_type_get(interfaces[i]), ecm_db_interface_type_to_string(ecm_db_connection_iface_type_get(interfaces[i])));
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304787
Ben Menchaca84f36632014-02-28 20:57:38 +00004788 }
4789#endif
Gareth Williamsa11d4352014-05-14 18:25:49 +01004790
4791 /*
4792 * Release src_dev now
4793 */
4794 dev_put(src_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004795 return current_interface_index;
4796 }
4797
Gareth Williamsa11d4352014-05-14 18:25:49 +01004798 /*
4799 * dest_dev becomes next_dev
4800 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004801 dest_dev = next_dev;
4802 dest_dev_name = dest_dev->name;
4803 dest_dev_type = dest_dev->type;
4804 }
4805
4806 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
4807 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
4808 dev_put(src_dev);
4809 dev_put(dest_dev);
4810
4811 /*
4812 * Release the interfaces heirarchy we constructed to this point.
4813 */
4814 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4815 return ECM_DB_IFACE_HEIRARCHY_MAX;
4816}
Murat Sezgin5dae8832015-12-03 14:23:19 -08004817EXPORT_SYMBOL(ecm_interface_multicast_from_heirarchy_construct);
4818#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004819
4820/*
Gareth Williamsadf425f2014-05-26 19:29:02 +01004821 * ecm_interface_list_stats_update()
4822 * Given an interface list, walk the interfaces and update the stats for certain types.
4823 */
4824static void ecm_interface_list_stats_update(int iface_list_first, struct ecm_db_iface_instance *iface_list[], uint8_t *mac_addr,
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304825 bool is_mcast_flow, uint32_t tx_packets, uint32_t tx_bytes, uint32_t rx_packets, uint32_t rx_bytes)
Gareth Williamsadf425f2014-05-26 19:29:02 +01004826{
4827 int list_index;
4828
4829 for (list_index = iface_list_first; (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) {
4830 struct ecm_db_iface_instance *ii;
4831 ecm_db_iface_type_t ii_type;
4832 char *ii_name;
4833 struct net_device *dev;
4834
4835 ii = iface_list[list_index];
4836 ii_type = ecm_db_connection_iface_type_get(ii);
4837 ii_name = ecm_db_interface_type_to_string(ii_type);
4838 DEBUG_TRACE("list_index: %d, ii: %p, type: %d (%s)\n", list_index, ii, ii_type, ii_name);
4839
4840 /*
4841 * Locate real device in system
4842 */
4843 dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii));
4844 if (!dev) {
4845 DEBUG_WARN("Could not locate interface\n");
4846 continue;
4847 }
4848 DEBUG_TRACE("found dev: %p (%s)\n", dev, dev->name);
4849
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304850 if (likely(!is_mcast_flow)) {
4851 /*
4852 * Refresh the bridge forward table entry if the port is a bridge port
4853 * Note: A bridge port can be of different interface type, e.g VLAN, ethernet.
4854 * This check, therefore, should be performed for all interface types.
4855 */
4856 if (is_valid_ether_addr(mac_addr) && ecm_front_end_is_bridge_port(dev) && rx_packets) {
4857 DEBUG_TRACE("Update bridge fdb entry for mac: %pM\n", mac_addr);
4858 br_refresh_fdb_entry(dev, mac_addr);
4859 }
Selin Dag1af781a2014-06-10 10:37:54 -07004860 }
4861
Gareth Williamsadf425f2014-05-26 19:29:02 +01004862 switch (ii_type) {
4863 struct rtnl_link_stats64 stats;
4864
Gareth Williams141d2382014-11-25 11:35:19 -08004865#ifdef ECM_INTERFACE_VLAN_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +01004866 case ECM_DB_IFACE_TYPE_VLAN:
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304867 DEBUG_INFO("VLAN\n");
Gareth Williamsadf425f2014-05-26 19:29:02 +01004868 stats.rx_packets = rx_packets;
4869 stats.rx_bytes = rx_bytes;
4870 stats.tx_packets = tx_packets;
4871 stats.tx_bytes = tx_bytes;
4872 __vlan_dev_update_accel_stats(dev, &stats);
4873 break;
Gareth Williams141d2382014-11-25 11:35:19 -08004874#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01004875 case ECM_DB_IFACE_TYPE_BRIDGE:
4876 DEBUG_INFO("BRIDGE\n");
4877 stats.rx_packets = rx_packets;
4878 stats.rx_bytes = rx_bytes;
4879 stats.tx_packets = tx_packets;
4880 stats.tx_bytes = tx_bytes;
4881 br_dev_update_stats(dev, &stats);
Gareth Williamsadf425f2014-05-26 19:29:02 +01004882 break;
Murat Sezgina683edd2015-01-20 10:48:30 -08004883
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304884#ifdef ECM_INTERFACE_PPPOE_ENABLE
Murat Sezgina683edd2015-01-20 10:48:30 -08004885 case ECM_DB_IFACE_TYPE_PPPOE:
4886 DEBUG_INFO("PPPOE\n");
ratheesh kannothb1b753a2015-09-28 11:17:35 +05304887 ppp_update_stats(dev, rx_packets, rx_bytes, tx_packets, tx_bytes, 0, 0, 0, 0);
Murat Sezgina683edd2015-01-20 10:48:30 -08004888 break;
4889#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01004890 default:
4891 /*
4892 * TODO: Extend it accordingly
4893 */
4894 break;
4895 }
4896
4897 dev_put(dev);
4898 }
4899}
4900
4901/*
4902 * ecm_interface_stats_update()
4903 * Using the interface lists for the given connection, update the interface statistics for each.
4904 *
4905 * 'from' here is wrt the connection 'from' side. Likewise with 'to'.
4906 * TX is wrt what the interface has transmitted. RX is what the interface has received.
4907 */
4908void ecm_interface_stats_update(struct ecm_db_connection_instance *ci,
4909 uint32_t from_tx_packets, uint32_t from_tx_bytes, uint32_t from_rx_packets, uint32_t from_rx_bytes,
4910 uint32_t to_tx_packets, uint32_t to_tx_bytes, uint32_t to_rx_packets, uint32_t to_rx_bytes)
4911{
4912 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
4913 struct ecm_db_iface_instance *to_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
4914 int from_ifaces_first;
4915 int to_ifaces_first;
4916 uint8_t mac_addr[ETH_ALEN];
4917
4918 /*
4919 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
4920 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
4921 * from_rx_packets / bytes: the amount received by the 'from' interface
4922 */
4923 DEBUG_INFO("%p: Update from interface stats\n", ci);
4924 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
4925 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304926 ecm_interface_list_stats_update(from_ifaces_first, from_ifaces, mac_addr, false, from_tx_packets, from_tx_bytes, from_rx_packets, from_rx_bytes);
Gareth Williamsadf425f2014-05-26 19:29:02 +01004927 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
4928
4929 /*
4930 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
4931 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
4932 * to_rx_packets / bytes: the amount received by the 'to' interface
4933 */
4934 DEBUG_INFO("%p: Update to interface stats\n", ci);
4935 to_ifaces_first = ecm_db_connection_to_interfaces_get_and_ref(ci, to_ifaces);
4936 ecm_db_connection_to_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304937 ecm_interface_list_stats_update(to_ifaces_first, to_ifaces, mac_addr, false, to_tx_packets, to_tx_bytes, to_rx_packets, to_rx_bytes);
Gareth Williamsadf425f2014-05-26 19:29:02 +01004938 ecm_db_connection_interfaces_deref(to_ifaces, to_ifaces_first);
4939}
4940EXPORT_SYMBOL(ecm_interface_stats_update);
4941
Shyam Sunder6358b862015-05-04 15:06:24 +05304942#ifdef ECM_MULTICAST_ENABLE
4943/*
Shyam Sunder6358b862015-05-04 15:06:24 +05304944 * ecm_interface_multicast_stats_update()
4945 * Using the interface lists for the given connection, update the interface statistics for each.
4946 *
4947 * 'from interface' here is the connection 'from' side. Likewise with 'to interface'.
4948 * TX is wrt what the interface has transmitted. RX is what the interface has received.
4949 */
4950void ecm_interface_multicast_stats_update(struct ecm_db_connection_instance *ci, uint32_t from_tx_packets, uint32_t from_tx_bytes,
4951 uint32_t from_rx_packets, uint32_t from_rx_bytes, uint32_t to_tx_packets, uint32_t to_tx_bytes,
4952 uint32_t to_rx_packets, uint32_t to_rx_bytes)
4953{
4954 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304955 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunder6358b862015-05-04 15:06:24 +05304956 struct ecm_db_iface_instance *to_ifaces;
4957 struct ecm_db_iface_instance *ii_temp;
4958 int from_ifaces_first;
4959 int *to_ifaces_first;
4960 int if_index;
4961 int ret;
4962 uint8_t mac_addr[ETH_ALEN];
4963
4964 /*
4965 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
4966 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
4967 * from_rx_packets / bytes: the amount received by the 'from' interface
4968 */
4969 DEBUG_INFO("%p: Update from interface stats\n", ci);
4970 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
4971 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304972 ecm_interface_list_stats_update(from_ifaces_first, from_ifaces, mac_addr, false, from_tx_packets, from_tx_bytes, from_rx_packets, from_rx_bytes);
Shyam Sunder6358b862015-05-04 15:06:24 +05304973 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
4974
4975 /*
4976 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
4977 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
4978 * to_rx_packets / bytes: the amount received by the 'to' interface
4979 */
4980 DEBUG_INFO("%p: Update to interface stats\n", ci);
4981
4982 /*
4983 * This function allocates the memory for temporary destination interface heirarchies.
4984 * This memory needs to be free at the end.
4985 */
4986 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &to_ifaces, &to_ifaces_first);
4987 if (ret == 0) {
4988 DEBUG_WARN("%p: Get and ref to all multicast detination interface heirarchies failed\n", ci);
4989 return;
4990 }
4991
4992 for (if_index = 0; if_index < ECM_DB_MULTICAST_IF_MAX; if_index++) {
4993 if (to_ifaces_first[if_index] < ECM_DB_IFACE_HEIRARCHY_MAX) {
4994 ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, if_index);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304995 ecm_db_multicast_copy_if_heirarchy(to_list_single, ii_temp);
4996 ecm_interface_list_stats_update(to_ifaces_first[if_index], to_list_single, mac_addr, true, to_tx_packets, to_tx_bytes, to_rx_packets, to_rx_bytes);
Shyam Sunder6358b862015-05-04 15:06:24 +05304997 }
4998 }
4999
5000 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
5001}
5002EXPORT_SYMBOL(ecm_interface_multicast_stats_update);
5003#endif
5004
Gareth Williamsadf425f2014-05-26 19:29:02 +01005005/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005006 * ecm_interface_regenerate_connections()
5007 * Cause regeneration of all connections that are using the specified interface.
5008 */
5009static void ecm_interface_regenerate_connections(struct ecm_db_iface_instance *ii)
5010{
Gareth Williamsb5903892015-03-20 15:13:07 +00005011#ifdef ECM_DB_XREF_ENABLE
Gareth Williamsa4390962015-08-26 12:51:31 +01005012 struct ecm_db_connection_instance *ci_from;
5013 struct ecm_db_connection_instance *ci_to;
5014 struct ecm_db_connection_instance *ci_from_nat;
5015 struct ecm_db_connection_instance *ci_to_nat;
5016 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
Gareth Williamsb5903892015-03-20 15:13:07 +00005017#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005018
5019 DEBUG_TRACE("Regenerate connections using interface: %p\n", ii);
5020
Gareth Williamsb5903892015-03-20 15:13:07 +00005021#ifndef ECM_DB_XREF_ENABLE
5022 /*
5023 * An interface has changed, re-generate the connections to ensure all state is updated.
5024 */
Tushar Mathurd38cacd2015-07-28 12:19:10 +05305025 ecm_db_regeneration_needed();
Gareth Williamsb5903892015-03-20 15:13:07 +00005026#else
Ben Menchaca84f36632014-02-28 20:57:38 +00005027 /*
Gareth Williamsa4390962015-08-26 12:51:31 +01005028 * If the interface has NO connections then we re-generate all.
5029 */
5030 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
5031 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
5032 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
5033 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
5034 if (!ci_from && !ci_to && !ci_from_nat && !ci_to_nat) {
5035 ecm_db_regeneration_needed();
5036 DEBUG_TRACE("%p: Regenerate (ALL) COMPLETE\n", ii);
5037 return;
5038 }
5039
5040 /*
5041 * Re-generate all connections associated with this interface
Ben Menchaca84f36632014-02-28 20:57:38 +00005042 */
5043 DEBUG_TRACE("%p: Regenerate 'from' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005044 while (ci_from) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005045 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005046 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
Ben Menchaca84f36632014-02-28 20:57:38 +00005047
Gareth Williamsa4390962015-08-26 12:51:31 +01005048 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005049 ecm_db_connection_regenerate(ci_from);
Gareth Williamsa4390962015-08-26 12:51:31 +01005050 ecm_db_connection_deref(ci_from);
5051 ci_from = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005052 }
5053
5054 DEBUG_TRACE("%p: Regenerate 'to' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005055 while (ci_to) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005056 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005057 cin = ecm_db_connection_iface_to_get_and_ref_next(ci_to);
Ben Menchaca84f36632014-02-28 20:57:38 +00005058
Gareth Williamsa4390962015-08-26 12:51:31 +01005059 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005060 ecm_db_connection_regenerate(ci_to);
Gareth Williamsa4390962015-08-26 12:51:31 +01005061 ecm_db_connection_deref(ci_to);
5062 ci_to = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005063 }
5064
Gareth Williamsa4390962015-08-26 12:51:31 +01005065 /*
5066 * GGG TODO These deprecated lists _nat_ lists will eventually be removed
5067 */
Ben Menchaca84f36632014-02-28 20:57:38 +00005068 DEBUG_TRACE("%p: Regenerate 'from_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005069 while (ci_from_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005070 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005071 cin = ecm_db_connection_iface_nat_from_get_and_ref_next(ci_from_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00005072
Gareth Williamsa4390962015-08-26 12:51:31 +01005073 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005074 ecm_db_connection_regenerate(ci_from_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01005075 ecm_db_connection_deref(ci_from_nat);
5076 ci_from_nat = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005077 }
5078
5079 DEBUG_TRACE("%p: Regenerate 'to_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005080 while (ci_to_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005081 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005082 cin = ecm_db_connection_iface_nat_to_get_and_ref_next(ci_to_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00005083
Gareth Williamsa4390962015-08-26 12:51:31 +01005084 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005085 ecm_db_connection_regenerate(ci_to_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01005086 ecm_db_connection_deref(ci_to_nat);
5087 ci_to_nat = cin;
5088 }
5089
5090#ifdef ECM_MULTICAST_ENABLE
5091 /*
5092 * Multicasts would not have recorded in the lists above.
5093 * Our only way to re-gen those is to iterate all multicasts.
5094 * GGG TODO This will be optimised in a future release.
5095 */
5096 ci_mcast = ecm_db_connections_get_and_ref_first();
5097 while (ci_mcast) {
5098 struct ecm_db_connection_instance *cin;
5099
5100 /*
5101 * Multicast and NOT flagged for re-gen?
5102 */
5103 if (ecm_db_multicast_connection_to_interfaces_set_check(ci_mcast)
5104 && ecm_db_connection_regeneration_required_peek(ci_mcast)) {
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005105 ecm_db_connection_regenerate(ci_mcast);
Gareth Williamsa4390962015-08-26 12:51:31 +01005106 }
5107
5108 cin = ecm_db_connection_get_and_ref_next(ci_mcast);
5109 ecm_db_connection_deref(ci_mcast);
5110 ci_mcast = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005111 }
Gareth Williamsb5903892015-03-20 15:13:07 +00005112#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005113
Gareth Williamsa4390962015-08-26 12:51:31 +01005114#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005115 DEBUG_TRACE("%p: Regenerate COMPLETE\n", ii);
5116}
5117
5118/*
5119 * ecm_interface_dev_regenerate_connections()
5120 * Cause regeneration of all connections that are using the specified interface.
5121 */
Tushar Mathurcccbf282015-01-13 01:22:44 +05305122void ecm_interface_dev_regenerate_connections(struct net_device *dev)
Ben Menchaca84f36632014-02-28 20:57:38 +00005123{
5124 struct ecm_db_iface_instance *ii;
5125
5126 DEBUG_INFO("Regenerate connections for: %p (%s)\n", dev, dev->name);
5127
5128 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07005129 * If the interface is known to us then we will get it returned by this
5130 * function and process it accordingly.
Ben Menchaca84f36632014-02-28 20:57:38 +00005131 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07005132 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00005133 if (!ii) {
5134 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5135 return;
5136 }
5137 ecm_interface_regenerate_connections(ii);
5138 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
5139 ecm_db_iface_deref(ii);
5140}
5141
5142/*
Suman Ghosh7a261712016-01-12 21:42:55 +05305143 * ecm_interface_defunct_connections()
5144 * Cause defunct of all connections that are using the specified interface.
5145 */
5146static void ecm_interface_defunct_connections(struct ecm_db_iface_instance *ii)
5147{
5148#ifndef ECM_DB_XREF_ENABLE
5149 ecm_db_connection_defunct_all();
5150#else
5151 struct ecm_db_connection_instance *ci_from;
5152 struct ecm_db_connection_instance *ci_to;
5153 struct ecm_db_connection_instance *ci_from_nat;
5154 struct ecm_db_connection_instance *ci_to_nat;
5155 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
5156
5157 DEBUG_TRACE("defunct connections using interface: %p\n", ii);
5158
5159 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
5160 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
5161 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
5162 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
5163
5164 /*
5165 * Defunct all connections associated with this interface
5166 */
5167 DEBUG_TRACE("%p: Defunct 'from' connections\n", ii);
5168 while (ci_from) {
5169 struct ecm_db_connection_instance *cin;
5170 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
5171
5172 DEBUG_TRACE("%p: Defunct: %p", ii, ci_from);
5173 ecm_db_connection_make_defunct(ci_from);
5174 ecm_db_connection_deref(ci_from);
5175 ci_from = cin;
5176 }
5177
5178 DEBUG_TRACE("%p: Defunct 'to' connections\n", ii);
5179 while (ci_to) {
5180 struct ecm_db_connection_instance *cin;
5181 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to);
5182
5183 DEBUG_TRACE("%p: Defunct: %p", ii, ci_to);
5184 ecm_db_connection_make_defunct(ci_to);
5185 ecm_db_connection_deref(ci_to);
5186 ci_to = cin;
5187 }
5188
5189 DEBUG_TRACE("%p: Defunct 'from_nat' connections\n", ii);
5190 while (ci_from_nat) {
5191 struct ecm_db_connection_instance *cin;
5192 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from_nat);
5193
5194 DEBUG_TRACE("%p: Defunct: %p", ii, ci_from_nat);
5195 ecm_db_connection_make_defunct(ci_from_nat);
5196 ecm_db_connection_deref(ci_from_nat);
5197 ci_from_nat = cin;
5198 }
5199
5200 DEBUG_TRACE("%p: Defunct 'to_nat' connections\n", ii);
5201 while (ci_to_nat) {
5202 struct ecm_db_connection_instance *cin;
5203 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to_nat);
5204
5205 DEBUG_TRACE("%p: Defunct: %p", ii, ci_to_nat);
5206 ecm_db_connection_make_defunct(ci_to_nat);
5207 ecm_db_connection_deref(ci_to_nat);
5208 ci_to_nat = cin;
5209 }
5210#endif
5211 DEBUG_TRACE("%p: Defunct COMPLETE\n", ii);
5212}
5213
5214/*
5215 * ecm_interface_dev_defunct_connections()
5216 * Cause defunct of all connections that are using the specified interface.
5217 */
5218void ecm_interface_dev_defunct_connections(struct net_device *dev)
5219{
5220 struct ecm_db_iface_instance *ii;
5221
5222 DEBUG_INFO("defunct connections for: %p (%s)\n", dev, dev->name);
5223
5224 /*
5225 * If the interface is known to us then we will get it returned by this
5226 * function and process it accordingly.
5227 */
5228 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
5229 if (!ii) {
5230 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5231 return;
5232 }
5233 ecm_interface_defunct_connections(ii);
5234 DEBUG_TRACE("%p: defunct for %p: COMPLETE\n", dev, ii);
5235 ecm_db_iface_deref(ii);
5236}
5237
5238/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005239 * ecm_interface_mtu_change()
5240 * MTU of interface has changed
5241 */
5242static void ecm_interface_mtu_change(struct net_device *dev)
5243{
5244 int mtu;
5245 struct ecm_db_iface_instance *ii;
5246
5247 mtu = dev->mtu;
5248 DEBUG_INFO("%p (%s): MTU Change to: %d\n", dev, dev->name, mtu);
5249
5250 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07005251 * Find the interface for the given device.
Ben Menchaca84f36632014-02-28 20:57:38 +00005252 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07005253 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00005254 if (!ii) {
5255 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5256 return;
5257 }
5258
5259 /*
5260 * Change the mtu
5261 */
5262 ecm_db_iface_mtu_reset(ii, mtu);
5263 DEBUG_TRACE("%p (%s): MTU Changed to: %d\n", dev, dev->name, mtu);
Tushar Mathurad534d62015-06-10 18:37:52 +05305264 if (netif_is_bond_slave(dev)) {
5265 struct net_device *master = NULL;
5266 master = ecm_interface_get_and_hold_dev_master(dev);
5267 DEBUG_ASSERT(master, "Expected a master\n");
5268 ecm_interface_dev_regenerate_connections(master);
5269 dev_put(master);
5270 } else {
5271 ecm_interface_regenerate_connections(ii);
5272 }
5273
Ben Menchaca84f36632014-02-28 20:57:38 +00005274 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
5275 ecm_db_iface_deref(ii);
5276}
5277
5278/*
5279 * ecm_interface_netdev_notifier_callback()
5280 * Netdevice notifier callback to inform us of change of state of a netdevice
5281 */
5282static int ecm_interface_netdev_notifier_callback(struct notifier_block *this, unsigned long event, void *ptr)
5283{
Stephen Wang69379c32015-02-04 18:37:13 -08005284#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0))
Ben Menchaca84f36632014-02-28 20:57:38 +00005285 struct net_device *dev __attribute__ ((unused)) = (struct net_device *)ptr;
Stephen Wang69379c32015-02-04 18:37:13 -08005286#else
5287 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
5288#endif
Tushar Mathurad534d62015-06-10 18:37:52 +05305289 struct net_device *master = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00005290
5291 DEBUG_INFO("Net device notifier for: %p, name: %s, event: %lx\n", dev, dev->name, event);
5292
5293 switch (event) {
5294 case NETDEV_DOWN:
5295 DEBUG_INFO("Net device: %p, DOWN\n", dev);
Tushar Mathurad534d62015-06-10 18:37:52 +05305296 if (netif_is_bond_slave(dev)) {
5297 master = ecm_interface_get_and_hold_dev_master(dev);
5298 DEBUG_ASSERT(master, "Expected a master\n");
5299 ecm_interface_dev_regenerate_connections(master);
5300 dev_put(master);
5301 } else {
5302 ecm_interface_dev_regenerate_connections(dev);
5303 }
Ben Menchaca84f36632014-02-28 20:57:38 +00005304 break;
5305
5306 case NETDEV_CHANGE:
5307 DEBUG_INFO("Net device: %p, CHANGE\n", dev);
5308 if (!netif_carrier_ok(dev)) {
5309 DEBUG_INFO("Net device: %p, CARRIER BAD\n", dev);
Tushar Mathur933907c2014-06-24 17:06:14 +05305310 if (netif_is_bond_slave(dev)) {
Murat Sezginb3731e82014-11-26 12:20:59 -08005311 master = ecm_interface_get_and_hold_dev_master(dev);
5312 DEBUG_ASSERT(master, "Expected a master\n");
5313 ecm_interface_dev_regenerate_connections(master);
5314 dev_put(master);
Tushar Mathur933907c2014-06-24 17:06:14 +05305315 } else {
5316 ecm_interface_dev_regenerate_connections(dev);
5317 }
Ben Menchaca84f36632014-02-28 20:57:38 +00005318 }
5319 break;
5320
5321 case NETDEV_CHANGEMTU:
5322 DEBUG_INFO("Net device: %p, MTU CHANGE\n", dev);
5323 ecm_interface_mtu_change(dev);
5324 break;
5325
5326 default:
5327 DEBUG_TRACE("Net device: %p, UNHANDLED: %lx\n", dev, event);
5328 break;
5329 }
5330
5331 return NOTIFY_DONE;
5332}
5333
5334/*
Murat Sezgina205b042016-07-19 14:18:14 -07005335 * ecm_interface_node_connections_decelerate()
5336 * Decelerate the connections on this node.
5337 */
Murat Sezgina5f3de12016-08-02 17:29:30 -07005338void ecm_interface_node_connections_decelerate(uint8_t *mac)
Murat Sezgina205b042016-07-19 14:18:14 -07005339{
Murat Sezgina5f3de12016-08-02 17:29:30 -07005340 struct ecm_db_node_instance *ni = NULL;
Murat Sezgina205b042016-07-19 14:18:14 -07005341
5342 if (unlikely(!mac)) {
5343 DEBUG_WARN("mac address is null\n");
5344 return;
5345 }
5346
Murat Sezgina5f3de12016-08-02 17:29:30 -07005347 ni = ecm_db_node_chain_get_and_ref_first(mac);
5348 while (ni) {
5349 struct ecm_db_node_instance *nin;
Murat Sezgina205b042016-07-19 14:18:14 -07005350
Murat Sezgina5f3de12016-08-02 17:29:30 -07005351 if (ecm_db_node_is_mac_addr_equal(ni, mac)) {
5352 ecm_db_traverse_node_from_connection_list_and_decelerate(ni);
5353 ecm_db_traverse_node_to_connection_list_and_decelerate(ni);
5354 ecm_db_traverse_node_from_nat_connection_list_and_decelerate(ni);
5355 ecm_db_traverse_node_to_nat_connection_list_and_decelerate(ni);
5356 }
5357
5358 /*
5359 * Get next node in the chain
5360 */
5361 nin = ecm_db_node_chain_get_and_ref_next(ni);
5362 ecm_db_node_deref(ni);
5363 ni = nin;
Murat Sezgina205b042016-07-19 14:18:14 -07005364 }
Murat Sezgina205b042016-07-19 14:18:14 -07005365}
Murat Sezgina5f3de12016-08-02 17:29:30 -07005366EXPORT_SYMBOL(ecm_interface_node_connections_decelerate);
Murat Sezgina205b042016-07-19 14:18:14 -07005367
5368/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005369 * struct notifier_block ecm_interface_netdev_notifier
5370 * Registration for net device changes of state.
5371 */
5372static struct notifier_block ecm_interface_netdev_notifier __read_mostly = {
5373 .notifier_call = ecm_interface_netdev_notifier_callback,
5374};
Murat Sezgina205b042016-07-19 14:18:14 -07005375
Murat Sezgin8c345822015-05-27 15:35:38 -07005376#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
Ben Menchaca84f36632014-02-28 20:57:38 +00005377/*
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305378 * ecm_interfae_node_br_fdb_notify_event()
5379 * This is a call back for "bridge fdb update event/ageing timer expire
5380 * event".
5381 */
5382static int ecm_interface_node_br_fdb_notify_event(struct notifier_block *nb,
5383 unsigned long val,
5384 void *data)
5385{
5386 uint8_t *mac = (uint8_t *)data;
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305387
Murat Sezgine34b0172015-11-05 21:58:14 -08005388 DEBUG_INFO("FDB updated for node %pM\n", mac);
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305389
Murat Sezgina205b042016-07-19 14:18:14 -07005390 ecm_interface_node_connections_decelerate(mac);
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305391
5392 return NOTIFY_DONE;
5393}
5394
5395static struct notifier_block ecm_interface_node_br_fdb_update_nb = {
5396 .notifier_call = ecm_interface_node_br_fdb_notify_event,
5397};
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07005398
5399static int ecm_interface_node_br_fdb_delete_event(struct notifier_block *nb,
5400 unsigned long event,
5401 void *ctx)
5402{
5403 struct br_fdb_event *fe = (struct br_fdb_event *)ctx;
5404
5405 if ((event != BR_FDB_EVENT_DEL) || fe->is_local) {
5406 DEBUG_WARN("local fdb or not deleting event, ignore\n");
5407 return NOTIFY_DONE;
5408 }
5409
5410 return ecm_interface_node_br_fdb_notify_event(nb, event, fe->addr);
5411}
5412
5413static struct notifier_block ecm_interface_node_br_fdb_delete_nb = {
5414 .notifier_call = ecm_interface_node_br_fdb_delete_event,
5415};
Murat Sezgin8c345822015-05-27 15:35:38 -07005416#endif
Shyam Sunder6358b862015-05-04 15:06:24 +05305417
5418#ifdef ECM_MULTICAST_ENABLE
5419/*
5420 * ecm_interface_multicast_find_outdated_iface_instances()
5421 *
5422 * Called in the case of Routing/Bridging Multicast update events.
5423 *
5424 * This function takes a list of ifindex for the connection which was received
5425 * from MFC or bridge snooper, compares it against the existing list of interfaces
5426 * in the DB connection, and extracts the list of those interfaces that have left
5427 * the multicast group.
5428 *
5429 * ci A DB connection instance.
5430 * mc_updates Part of return Information. The function will mark the index of those
5431 * interfaces in the DB connection 'to_mcast_interfaces' array that have
5432 * left the group, in the mc_updates->if_leave_idx array. The caller uses this
5433 * information to delete those outdated interface heirarchies from the
5434 * connection.
5435 * is_bridged True if the function called due to bridge multicast snooper update event.
5436 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
5437 * by the update from MFC or Bridge snooper.
5438 * max_to_dev Size of the array 'dst_dev'
5439 *
5440 * Return true if outdated interfaces found
5441 */
5442static bool ecm_interface_multicast_find_outdated_iface_instances(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
5443 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5444{
5445 struct ecm_db_iface_instance *mc_ifaces;
5446 struct ecm_db_iface_instance *ii_temp;
5447 struct ecm_db_iface_instance *ii_single;
5448 struct ecm_db_iface_instance **ifaces;
5449 struct ecm_db_iface_instance *to_iface;
5450 int32_t *to_iface_first;
5451 int32_t *mc_ifaces_first;
5452 uint32_t *dst_if_index;
5453 ecm_db_iface_type_t ii_type;
5454 int32_t heirarchy_index;
5455 int32_t if_index;
5456 int32_t if_cnt = 0;
5457 int found = 0;
5458 int ii;
5459 int ret;
5460 int32_t ifaces_identifier;
5461
5462 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
5463 if (ret == 0) {
5464 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
5465 return false;
5466 }
5467
5468 /*
5469 * Loop through the current interface list in the DB
5470 * connection 'to_mcast_interfaces' array
5471 */
5472 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX; heirarchy_index++) {
5473 found = 0;
5474 to_iface_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5475
5476 /*
5477 * Invalid interface entry, skip
5478 */
5479 if (*to_iface_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5480 continue;
5481 }
5482
5483 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
5484 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ECM_DB_IFACE_HEIRARCHY_MAX - 1);
5485 ifaces = (struct ecm_db_iface_instance **)ii_single;
5486 to_iface = *ifaces;
5487 ii_type = ecm_db_connection_iface_type_get(to_iface);
5488
5489 /*
5490 * If the update was received from bridge snooper, do not consider entries in the
5491 * interface list that are not part of a bridge.
5492 */
5493 if (is_br_snooper && (ii_type != ECM_DB_IFACE_TYPE_BRIDGE)) {
5494 continue;
5495 }
5496
5497 /*
5498 * If the update was received from MFC, do not consider entries in the
5499 * interface list that are part of a bridge. The bridge entries will be
5500 * taken care by the Bridge Snooper Callback
5501 */
5502 if (ii_type == ECM_DB_IFACE_TYPE_BRIDGE) {
5503 if (!is_br_snooper && !(flags & ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG)) {
5504 continue;
5505 }
5506 }
5507
5508 /*
5509 * Try to find a match in the newly received interface list, for any of
5510 * the interface instance in the heirarchy. If found, it means that this
5511 * interface has not left the group. If not found, it means that this
5512 * interface has left the group.
5513 */
5514 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_iface_first; ii--) {
5515 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
5516 ifaces = (struct ecm_db_iface_instance **)ii_single;
5517 to_iface = *ifaces;
5518
5519 ii_type = ecm_db_connection_iface_type_get(to_iface);
5520 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_iface);
5521 for (if_index = 0; if_index < max_to_dev; if_index++) {
5522 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
5523 if (*dst_if_index == ifaces_identifier) {
5524 found = 1;
5525 break;
5526 }
5527 }
5528 if (found) {
5529 break;
5530 }
5531 }
5532
5533 /*
5534 * We did not find a match for the interface in the present list. So mark
5535 * if as one that has left the group.
5536 */
5537 if (!found) {
5538 if_cnt++;
5539 mc_updates->if_leave_idx[heirarchy_index] = 1;
5540 }
5541 }
5542
5543 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
5544 mc_updates->if_leave_cnt = if_cnt;
5545 return (if_cnt > 0);
5546}
5547
5548/*
5549 * ecm_interface_multicast_find_new_iface_instances()
5550 *
5551 * Called in the case of Routing/Bridging Multicast update events.
5552 *
5553 * This function takes a list of ifindex for the connection which was received
5554 * from MFC or bridge snooper, compares it against the existing list of interfaces
5555 * in the DB connection, and extracts the list of the new joinees for the multicast
5556 * group.
5557 *
5558 * ci A DB connection instance.
5559 * mc_updates Part of return Information. The function will mark the index of those
5560 * interfaces in the 'dst_dev' array that have joined the group, in the
5561 * mc_updates->if_join_idx array. The caller uses this information to add the new
5562 * interface heirarchies into the connection.
5563 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
5564 * by the update from MFC or Bridge snooper.
5565 * max_to_dev Size of the array 'dst_dev'
5566 *
5567 * Return true if new joinees found
5568 */
5569static bool ecm_interface_multicast_find_new_iface_instances(struct ecm_db_connection_instance *ci,
5570 struct ecm_multicast_if_update *mc_updates, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5571{
5572 struct ecm_db_iface_instance *mc_ifaces;
5573 struct ecm_db_iface_instance *ii_temp;
5574 struct ecm_db_iface_instance *ii_single;
5575 struct ecm_db_iface_instance **ifaces;
5576 int32_t *mc_ifaces_first;
5577 int32_t *to_list_first;
5578 int32_t heirarchy_index;
5579 int32_t if_index;
5580 int32_t if_cnt = 0;
5581 int found = 0;
5582 int ii;
5583 int ret;
5584 uint32_t *dst_if_index;
5585 int32_t ifaces_identifier;
5586 struct ecm_db_iface_instance *to_list;
5587
5588 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
5589 if (ret == 0) {
5590 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
5591 return false;
5592 }
5593
5594 /*
5595 * Loop through the new interface list 'dst_dev'
5596 */
5597 for (if_index = 0; if_index < max_to_dev; if_index++) {
5598 found = 0;
5599 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
5600 if (*dst_if_index == 0) {
5601 continue;
5602 }
5603
5604 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
5605 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5606
5607 /*
5608 * Invalid interface entry, skip
5609 */
5610 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5611 continue;
5612 }
5613
5614 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
5615
5616 /*
5617 * Try to find a match for this ifindex (dst_dev[if_index]), in any of the
5618 * interface instance in the heirarchy. If not found, it means that this
5619 * ifindex has joined the group. If found, it means that this ifindex was
5620 * already part of the list of destination interfaces.
5621 */
5622 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_list_first; ii--) {
5623 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
5624 ifaces = (struct ecm_db_iface_instance **)ii_single;
5625 to_list = *ifaces;
5626 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_list);
5627 if (*dst_if_index == ifaces_identifier) {
5628 found = 1;
5629 break;
5630 }
5631 }
5632
5633 if (found) {
5634 break;
5635 }
5636 }
5637
5638 /*
5639 * We did not find a match for the interface in the present list. So mark
5640 * it as one that has joined the group.
5641 */
5642 if (!found) {
5643
5644 /*
5645 * Store the if index of the new joinee
5646 */
5647 mc_updates->join_dev[if_cnt] = *dst_if_index;
5648
5649 /*
5650 * Identify a new vacant slot in the 'to_mcast_interfaces' to place
5651 * the new interface
5652 */
5653 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
5654 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5655 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5656 mc_updates->if_join_idx[heirarchy_index] = 1;
5657 break;
5658 }
5659 }
5660
5661 if_cnt++;
5662 }
5663 }
5664
5665 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
5666 mc_updates->if_join_cnt = if_cnt;
5667
5668 return (if_cnt > 0);
5669}
5670
5671/*
5672 * ecm_interface_multicast_find_updates_to_iface_list()
5673 * Process IGMP/MLD updates either from MFC or bridge snooper. Identity the interfaces
5674 * that have left the group and new interfaces that have joined the group.
5675 *
5676 * The function returns true if there was any update necessary to the current destination
5677 * interface list
5678 */
5679bool ecm_interface_multicast_find_updates_to_iface_list(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
5680 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5681{
5682 bool join;
5683 bool leave;
5684 /*
5685 * Find destination interfaces that have left the group
5686 */
5687 leave = ecm_interface_multicast_find_outdated_iface_instances(ci, mc_updates, flags, is_br_snooper, mc_dst_if_index, max_to_dev);
5688 /*
5689 * Find new destination interfaces that have joined the group
5690 */
5691 join = ecm_interface_multicast_find_new_iface_instances(ci, mc_updates, mc_dst_if_index, max_to_dev);
5692
5693 return (leave || join);
5694}
5695EXPORT_SYMBOL(ecm_interface_multicast_find_updates_to_iface_list);
5696#endif
5697
Murat Sezgin42a44c22016-05-05 14:06:39 -07005698#ifdef ECM_DB_XREF_ENABLE
5699/*
5700 * ecm_interface_neigh_mac_update_notify_event()
5701 * Neighbour mac address change handler.
5702 */
5703static int ecm_interface_neigh_mac_update_notify_event(struct notifier_block *nb,
5704 unsigned long val,
5705 void *data)
5706{
Murat Sezgin42a44c22016-05-05 14:06:39 -07005707 struct neigh_mac_update *nmu = (struct neigh_mac_update *)data;
5708
5709 /*
5710 * If the old and new mac addresses are equal, do nothing.
5711 * This case shouldn't happen.
5712 */
5713 if (!ecm_mac_addr_equal(nmu->old_mac, nmu->update_mac)) {
5714 DEBUG_TRACE("old and new mac addresses are equal: %pM\n", nmu->old_mac);
5715 return NOTIFY_DONE;
5716 }
5717
5718 /*
5719 * If the old mac is zero, do nothing. When a host joins the arp table first
5720 * time, its old mac comes as zero. We shouldn't handle this case, because
5721 * there is not any connection in ECM db with zero mac.
5722 */
5723 if (is_zero_ether_addr(nmu->old_mac)) {
5724 DEBUG_WARN("old mac is zero\n");
5725 return NOTIFY_DONE;
5726 }
5727
5728 DEBUG_TRACE("old mac: %pM new mac: %pM\n", nmu->old_mac, nmu->update_mac);
5729
Murat Sezgina205b042016-07-19 14:18:14 -07005730 DEBUG_INFO("neigh mac update notify for node %pM\n", nmu->old_mac);
5731 ecm_interface_node_connections_decelerate((uint8_t *)nmu->old_mac);
Murat Sezgin42a44c22016-05-05 14:06:39 -07005732
5733 return NOTIFY_DONE;
5734}
5735
5736/*
5737 * struct notifier_block ecm_interface_neigh_mac_update_nb
5738 * Registration for neighbour mac address update.
5739 */
5740static struct notifier_block ecm_interface_neigh_mac_update_nb = {
5741 .notifier_call = ecm_interface_neigh_mac_update_notify_event,
5742};
5743#endif
5744
Murat Sezgin1f381852014-11-20 09:51:07 -08005745/*
Murat Sezgina205b042016-07-19 14:18:14 -07005746 * ecm_interface_wifi_event_iwevent
5747 * wireless event handler
5748 */
5749static int ecm_interface_wifi_event_iwevent(int ifindex, unsigned char *buf, size_t len)
5750{
5751 struct iw_event iwe_buf, *iwe = &iwe_buf;
5752 char *pos, *end;
5753
5754 pos = buf;
5755 end = buf + len;
5756 while (pos + IW_EV_LCP_LEN <= end) {
5757
5758 /*
5759 * Copy the base data structure to get iwe->len
5760 */
5761 memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
5762
5763 /*
5764 * Check that len is valid and that we have that much in the buffer.
5765 *
5766 */
5767 if (iwe->len < IW_EV_LCP_LEN) {
5768 return -1;
5769 }
5770
5771 if ((iwe->len > sizeof (struct iw_event)) || (iwe->len + pos) > end) {
5772 return -1;
5773 }
5774
5775 /*
5776 * Do the copy again with the full length.
5777 */
5778 memcpy(&iwe_buf, pos, iwe->len);
5779
5780 if (iwe->cmd == IWEVREGISTERED) {
5781 DEBUG_INFO("STA %pM joining\n", (uint8_t *)iwe->u.addr.sa_data);
5782 } else if (iwe->cmd == IWEVEXPIRED) {
5783 DEBUG_INFO("STA %pM leaving\n", (uint8_t *)iwe->u.addr.sa_data);
5784 ecm_interface_node_connections_decelerate((uint8_t *)iwe->u.addr.sa_data);
5785 } else {
5786 DEBUG_INFO("iwe->cmd is %d for STA %pM\n", iwe->cmd, (unsigned char *) iwe->u.addr.sa_data);
5787 }
5788
5789 pos += iwe->len;
5790 }
5791
5792 return 0;
5793}
5794
5795/*
5796 * ecm_interface_wifi_event_newlink
5797 * Link event handler
5798 */
5799static int ecm_interface_wifi_event_newlink(struct ifinfomsg *ifi, unsigned char *buf, size_t len)
5800{
5801 struct rtattr *attr;
5802 int attrlen, rta_len;
5803
5804 DEBUG_TRACE("Event from interface %d\n", ifi->ifi_index);
5805
5806 attrlen = len;
5807 attr = (struct rtattr *) buf;
5808 rta_len = RTA_ALIGN(sizeof(struct rtattr));
5809
5810 while (RTA_OK(attr, attrlen)) {
5811 if (attr->rta_type == IFLA_WIRELESS) {
5812 ecm_interface_wifi_event_iwevent(ifi->ifi_index, ((char *) attr) + rta_len, attr->rta_len - rta_len);
5813 }
5814 attr = RTA_NEXT(attr, attrlen);
5815 }
5816
5817 return 0;
5818}
5819
5820/*
5821 * ecm_interface_wifi_event_handler
5822 * Netlink event handler
5823 */
5824static int ecm_interface_wifi_event_handler(unsigned char *buf, int len)
5825{
5826 struct nlmsghdr *nlh;
5827 struct ifinfomsg *ifi;
5828 int left;
5829
5830 nlh = (struct nlmsghdr *) buf;
5831 left = len;
5832
5833 while (NLMSG_OK(nlh, left)) {
5834 switch (nlh->nlmsg_type) {
5835 case RTM_NEWLINK:
5836 case RTM_DELLINK:
5837 if (NLMSG_PAYLOAD(nlh, 0) < sizeof(struct ifinfomsg)) {
5838 DEBUG_INFO("invalid netlink message\n");
5839 break;
5840 }
5841
5842 ifi = NLMSG_DATA(nlh);
5843 DEBUG_INFO("ifi->ifi_family: %d\n", ifi->ifi_family);
5844 if (ifi->ifi_family != AF_BRIDGE) {
5845 ecm_interface_wifi_event_newlink(ifi, (u8 *)ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
5846 NLMSG_PAYLOAD(nlh, sizeof(struct ifinfomsg)));
5847 }
5848 break;
5849 }
5850
5851 nlh = NLMSG_NEXT(nlh, left);
5852 }
5853
5854 return 0;
5855}
5856
5857/*
5858 * ecm_interface_wifi_event_rx
5859 * Receive netlink message from socket
5860 */
5861static int ecm_interface_wifi_event_rx(struct socket *sock, struct sockaddr_nl *addr, unsigned char *buf, int len)
5862{
5863 struct msghdr msg;
5864 struct iovec iov;
5865 mm_segment_t oldfs;
5866 int size;
5867
5868 iov.iov_base = buf;
5869 iov.iov_len = len;
5870
5871 msg.msg_flags = 0;
5872 msg.msg_name = addr;
5873 msg.msg_namelen = sizeof(struct sockaddr_nl);
5874 msg.msg_control = NULL;
5875 msg.msg_controllen = 0;
5876#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
5877 msg.msg_iov = &iov;
5878 msg.msg_iovlen = 1;
5879#else
5880 iov_iter_init(&msg.msg_iter, READ, &iov, 1, 1);
5881#endif
5882 oldfs = get_fs();
5883 set_fs(KERNEL_DS);
5884 size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
5885 set_fs(oldfs);
5886
5887 return size;
5888}
5889
5890/*
5891 * ecm_interface_wifi_event_thread
5892 */
5893static void ecm_interface_wifi_event_thread(void)
5894{
5895 int err;
5896 int size;
5897 struct sockaddr_nl saddr;
5898 unsigned char buf[512];
5899 int len = sizeof(buf);
5900
5901 allow_signal(SIGKILL|SIGSTOP);
5902 err = sock_create(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, &__ewn.sock);
5903 if (err < 0) {
5904 DEBUG_ERROR("failed to create sock\n");
5905 goto exit1;
5906 }
5907
5908 memset(&saddr, 0, sizeof(struct sockaddr));
5909 saddr.nl_family = AF_NETLINK;
5910 saddr.nl_groups = RTNLGRP_LINK;
5911 saddr.nl_pid = current->pid;
5912
5913 err = __ewn.sock->ops->bind(__ewn.sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr));
5914 if (err < 0) {
5915 DEBUG_ERROR("failed to bind sock\n");
5916 goto exit2;
5917 }
5918
5919 DEBUG_INFO("ecm_interface_wifi_event thread started\n");
5920 while (!kthread_should_stop()) {
5921 size = ecm_interface_wifi_event_rx(__ewn.sock, &saddr, buf, len);
5922 DEBUG_TRACE("got a netlink msg with len %d\n", size);
5923
5924 if (signal_pending(current))
5925 break;
5926
5927 if (size < 0) {
5928 DEBUG_WARN("netlink rx error\n");
5929 } else {
5930 ecm_interface_wifi_event_handler(buf, size);
5931 }
5932 }
5933
5934 DEBUG_INFO("ecm_interface_wifi_event thread stopped\n");
5935exit2:
5936 sock_release(__ewn.sock);
5937exit1:
5938 __ewn.sock = NULL;
5939
5940 return;
5941}
5942
5943/*
5944 * ecm_interface_wifi_event_start()
5945 */
5946int ecm_interface_wifi_event_start(void)
5947{
5948 if (__ewn.thread) {
5949 return 0;
5950 }
5951
5952 __ewn.thread = kthread_run((void *)ecm_interface_wifi_event_thread, NULL, "ECM_wifi_event");
5953 if (IS_ERR(__ewn.thread)) {
5954 DEBUG_ERROR("Unable to start kernel thread\n");
5955 return -ENOMEM;
5956 }
5957
5958 return 0;
5959}
5960
5961/*
5962 * ecm_interface_wifi_event_stop()
5963 */
5964int ecm_interface_wifi_event_stop(void)
5965{
5966 int err;
5967
5968 if (__ewn.thread == NULL) {
5969 return 0;
5970 }
5971
5972 DEBUG_INFO("kill ecm_interface_wifi_event thread\n");
5973 force_sig(SIGKILL, __ewn.thread);
5974 err = kthread_stop(__ewn.thread);
5975 __ewn.thread = NULL;
5976
5977 return err;
5978}
5979
5980/*
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005981 * ecm_interface_init()
Ben Menchaca84f36632014-02-28 20:57:38 +00005982 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005983int ecm_interface_init(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00005984{
5985 int result;
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005986 DEBUG_INFO("ECM Interface init\n");
Ben Menchaca84f36632014-02-28 20:57:38 +00005987
Ben Menchaca84f36632014-02-28 20:57:38 +00005988 result = register_netdevice_notifier(&ecm_interface_netdev_notifier);
5989 if (result != 0) {
5990 DEBUG_ERROR("Failed to register netdevice notifier %d\n", result);
Murat Sezgin908ecb32015-05-10 20:54:36 -07005991 return result;
Ben Menchaca84f36632014-02-28 20:57:38 +00005992 }
Murat Sezgin8c345822015-05-27 15:35:38 -07005993#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305994 /*
5995 * register for bridge fdb database modificationevents
5996 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05305997 br_fdb_update_register_notify(&ecm_interface_node_br_fdb_update_nb);
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07005998 br_fdb_register_notify(&ecm_interface_node_br_fdb_delete_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07005999#endif
Murat Sezgin42a44c22016-05-05 14:06:39 -07006000#ifdef ECM_DB_XREF_ENABLE
6001 neigh_mac_update_register_notify(&ecm_interface_neigh_mac_update_nb);
6002#endif
Murat Sezgina205b042016-07-19 14:18:14 -07006003 ecm_interface_wifi_event_start();
6004
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006005 return 0;
Ben Menchaca84f36632014-02-28 20:57:38 +00006006}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006007EXPORT_SYMBOL(ecm_interface_init);
Ben Menchaca84f36632014-02-28 20:57:38 +00006008
6009/*
6010 * ecm_interface_exit()
6011 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006012void ecm_interface_exit(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00006013{
6014 DEBUG_INFO("ECM Interface exit\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006015
6016 spin_lock_bh(&ecm_interface_lock);
6017 ecm_interface_terminate_pending = true;
6018 spin_unlock_bh(&ecm_interface_lock);
6019
6020 unregister_netdevice_notifier(&ecm_interface_netdev_notifier);
Murat Sezgin42a44c22016-05-05 14:06:39 -07006021#ifdef ECM_DB_XREF_ENABLE
6022 neigh_mac_update_unregister_notify(&ecm_interface_neigh_mac_update_nb);
6023#endif
6024
Murat Sezgin8c345822015-05-27 15:35:38 -07006025#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05306026 /*
6027 * unregister for bridge fdb update events
6028 */
6029 br_fdb_update_unregister_notify(&ecm_interface_node_br_fdb_update_nb);
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07006030 br_fdb_unregister_notify(&ecm_interface_node_br_fdb_delete_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07006031#endif
Murat Sezgina205b042016-07-19 14:18:14 -07006032 ecm_interface_wifi_event_stop();
Ben Menchaca84f36632014-02-28 20:57:38 +00006033}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006034EXPORT_SYMBOL(ecm_interface_exit);