blob: 0824160f78483a9145ecf3af3c16ba85a1e5dc82 [file] [log] [blame]
Ben Menchaca84f36632014-02-28 20:57:38 +00001/*
2 **************************************************************************
Murat Sezgindb0c5d82017-02-22 11:43:03 -08003 * Copyright (c) 2014-2017 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)) {
Murat Sezgin313f2222016-08-11 12:22:10 -0700403 ecm_interface_route_release(&ecm_rt);
Murat Sezgin5dae8832015-12-03 14:23:19 -0800404 return false;
405 }
406
407 ECM_NIN6_ADDR_TO_IP_ADDR(gw_addr, rt->rt6i_gateway)
Murat Sezgin313f2222016-08-11 12:22:10 -0700408 ecm_interface_route_release(&ecm_rt);
Murat Sezgin5dae8832015-12-03 14:23:19 -0800409 return true;
410}
Murat Sezgin49465a42014-11-24 15:37:48 -0800411#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000412
413/*
Murat Sezgin5dae8832015-12-03 14:23:19 -0800414 * ecm_interface_find_gateway_ipv4()
415 * Finds the ipv4 gateway address of a given ipv4 address.
416 */
417static bool ecm_interface_find_gateway_ipv4(ip_addr_t addr, ip_addr_t gw_addr)
418{
419 struct ecm_interface_route ecm_rt;
420 struct rtable *rt;
421
422 /*
423 * Find the ipv4 route of the given ip address to look up
424 * whether we have a gateway to reach to that ip address or not.
425 */
426 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
427 return false;
428 }
429 DEBUG_ASSERT(ecm_rt.v4_route, "Did not locate a v4 route!\n");
430 DEBUG_TRACE("Found route\n");
431
432 /*
433 * Is this destination reachable via a gateway?
434 */
435 rt = ecm_rt.rt.rtv4;
436#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
437 if (!(rt->rt_dst != rt->rt_gateway) && !(rt->rt_flags & RTF_GATEWAY)) {
438#else
439 if (!rt->rt_uses_gateway && !(rt->rt_flags & RTF_GATEWAY)) {
440#endif
Murat Sezgin313f2222016-08-11 12:22:10 -0700441 ecm_interface_route_release(&ecm_rt);
Murat Sezgin5dae8832015-12-03 14:23:19 -0800442 return false;
443 }
444
445 ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway)
Murat Sezgin313f2222016-08-11 12:22:10 -0700446 ecm_interface_route_release(&ecm_rt);
Murat Sezgin5dae8832015-12-03 14:23:19 -0800447 return true;
448}
449
450/*
451 * ecm_interface_find_gateway()
452 * Finds the gateway ip address of a given ECM ip address type.
453 */
454bool ecm_interface_find_gateway(ip_addr_t addr, ip_addr_t gw_addr)
455{
456 if (ECM_IP_ADDR_IS_V4(addr)) {
457 return ecm_interface_find_gateway_ipv4(addr, gw_addr);
458 }
459
460#ifdef ECM_IPV6_ENABLE
461 return ecm_interface_find_gateway_ipv6(addr, gw_addr);
462#else
463 return false;
464#endif
465}
466EXPORT_SYMBOL(ecm_interface_find_gateway);
467
468/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000469 * ecm_interface_mac_addr_get_ipv4()
470 * Return mac for an IPv4 address
471 */
472static bool ecm_interface_mac_addr_get_ipv4(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
473{
474 struct neighbour *neigh;
475 struct ecm_interface_route ecm_rt;
476 struct rtable *rt;
477 struct dst_entry *dst;
478 __be32 ipv4_addr;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530479
Ben Menchaca84f36632014-02-28 20:57:38 +0000480 /*
481 * Get the MAC address that corresponds to IP address given.
482 * We look up the rtable entries and, from its neighbour structure, obtain the hardware address.
483 * This means we will also work if the neighbours are routers too.
484 * We also locate the MAC if the address is a local host address.
485 */
486 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
487 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
Kiran Kumar C. S. K7d178222014-06-27 18:47:29 +0530488 *on_link = false;
Ben Menchaca84f36632014-02-28 20:57:38 +0000489 return false;
490 }
491 DEBUG_ASSERT(ecm_rt.v4_route, "Did not locate a v4 route!\n");
Murat Sezginb3731e82014-11-26 12:20:59 -0800492 DEBUG_TRACE("Found route\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000493
494 /*
495 * Is this destination on link or off-link via a gateway?
496 */
497 rt = ecm_rt.rt.rtv4;
Murat Sezginb3731e82014-11-26 12:20:59 -0800498#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000499 if ((rt->rt_dst != rt->rt_gateway) || (rt->rt_flags & RTF_GATEWAY)) {
Murat Sezginb3731e82014-11-26 12:20:59 -0800500#else
501 if (rt->rt_uses_gateway || (rt->rt_flags & RTF_GATEWAY)) {
502#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000503 *on_link = false;
504 ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway)
505 } else {
506 *on_link = true;
507 }
508
509 /*
510 * Get the neighbour entry for the address
511 */
512 rcu_read_lock();
513 dst = ecm_rt.dst;
Murat Sezginb3731e82014-11-26 12:20:59 -0800514#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000515 neigh = dst_get_neighbour_noref(dst);
516 if (neigh) {
517 neigh_hold(neigh);
Murat Sezginb3731e82014-11-26 12:20:59 -0800518 }
519#else
520 neigh = dst_neigh_lookup(dst, &ipv4_addr);
521#endif
522 if (!neigh) {
Ben Menchaca84f36632014-02-28 20:57:38 +0000523 neigh = neigh_lookup(&arp_tbl, &ipv4_addr, dst->dev);
524 }
525 if (!neigh) {
526 rcu_read_unlock();
527 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800528 DEBUG_WARN("no neigh\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000529 return false;
530 }
531 if (!(neigh->nud_state & NUD_VALID)) {
532 rcu_read_unlock();
533 neigh_release(neigh);
534 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800535 DEBUG_WARN("neigh nud state is not valid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000536 return false;
537 }
538 if (!neigh->dev) {
539 rcu_read_unlock();
540 neigh_release(neigh);
541 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800542 DEBUG_WARN("neigh has no device\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000543 return false;
544 }
545
546 /*
547 * If the device is loopback this will be because the address is a local address
548 * In this case locate the device that has this local address and get its mac.
549 */
550 if (neigh->dev->type == ARPHRD_LOOPBACK) {
551 struct net_device *dev;
552
553 DEBUG_TRACE("%pI4 finds loopback device, dev: %p (%s)\n", &ipv4_addr, neigh->dev, neigh->dev->name);
554 rcu_read_unlock();
555 neigh_release(neigh);
556 ecm_interface_route_release(&ecm_rt);
557
558 /*
559 * Lookup the device that has this IP address assigned
560 */
561 dev = ip_dev_find(&init_net, ipv4_addr);
562 if (!dev) {
563 DEBUG_WARN("Unable to locate dev for: %pI4\n", &ipv4_addr);
564 return false;
565 }
566 memcpy(mac_addr, dev->dev_addr, (size_t)dev->addr_len);
567 DEBUG_TRACE("is local addr: %pI4, mac: %pM, dev ifindex: %d, dev: %p (%s), dev_type: %d\n",
568 &ipv4_addr, mac_addr, dev->ifindex, dev, dev->name, dev->type);
569 dev_put(dev);
570 return true;
571 }
572
573 if (!(neigh->dev->flags & IFF_NOARP)) {
574 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
575 } else {
576 DEBUG_TRACE("non-arp device: %p (%s, type: %d) to reach %pI4\n", neigh->dev, neigh->dev->name, neigh->dev->type, &ipv4_addr);
577 memset(mac_addr, 0, 6);
578 }
579 DEBUG_TRACE("addr: %pI4, mac: %pM, iif: %d, neigh dev ifindex: %d, dev: %p (%s), dev_type: %d\n",
580 &ipv4_addr, mac_addr, rt->rt_iif, neigh->dev->ifindex, neigh->dev, neigh->dev->name, neigh->dev->type);
581
582 rcu_read_unlock();
583 neigh_release(neigh);
584 ecm_interface_route_release(&ecm_rt);
585 return true;
586}
587
588/*
589 * ecm_interface_mac_addr_get()
590 * Return the mac address for the given IP address. Returns false on failure.
Ben Menchaca84f36632014-02-28 20:57:38 +0000591 */
592bool ecm_interface_mac_addr_get(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
593{
594 if (ECM_IP_ADDR_IS_V4(addr)) {
595 return ecm_interface_mac_addr_get_ipv4(addr, mac_addr, on_link, gw_addr);
596 }
597
Gareth Williams8ac34292015-03-17 14:06:58 +0000598#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000599 return ecm_interface_mac_addr_get_ipv6(addr, mac_addr, on_link, gw_addr);
Murat Sezgin49465a42014-11-24 15:37:48 -0800600#else
601 return false;
602#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000603}
604EXPORT_SYMBOL(ecm_interface_mac_addr_get);
605
Murat Sezgin5dae8832015-12-03 14:23:19 -0800606#ifdef ECM_IPV6_ENABLE
607/*
608 * ecm_interface_mac_addr_get_ipv6_no_route()
609 * Finds the mac address of a node from its ip address reachable via
610 * the given device. It looks up the mac address in the neighbour entries.
611 * It doesn't do any route lookup to find the dst entry.
612 */
613static bool ecm_interface_mac_addr_get_ipv6_no_route(struct net_device *dev, ip_addr_t addr, uint8_t *mac_addr)
614{
615 struct in6_addr daddr;
616 struct neighbour *neigh;
617 struct net_device *local_dev;
618
619 memset(mac_addr, 0, ETH_ALEN);
620
621 /*
622 * Get the MAC address that corresponds to IP address given.
623 */
624 ECM_IP_ADDR_TO_NIN6_ADDR(daddr, addr);
625 local_dev = ipv6_dev_find(&init_net, &daddr, 1);
626 if (local_dev) {
627 DEBUG_TRACE("%pi6 is a local address\n", &daddr);
628 memcpy(mac_addr, dev->dev_addr, ETH_ALEN);
629 dev_put(local_dev);
630 return true;
631 }
632
633 rcu_read_lock();
634 neigh = neigh_lookup(&nd_tbl, &daddr, dev);
635 if (!neigh) {
636 rcu_read_unlock();
637 DEBUG_WARN("No neigh reference\n");
638 return false;
639 }
640 if (!(neigh->nud_state & NUD_VALID)) {
641 neigh_release(neigh);
642 rcu_read_unlock();
643 DEBUG_WARN("NUD invalid\n");
644 return false;
645 }
646 if (!neigh->dev) {
647 neigh_release(neigh);
648 rcu_read_unlock();
649 DEBUG_WARN("Neigh dev invalid\n");
650 return false;
651 }
652
653 if (neigh->dev->flags & IFF_NOARP) {
654 neigh_release(neigh);
655 rcu_read_unlock();
656 DEBUG_TRACE("dest MAC is zero: %pM\n", mac_addr);
657 return true;
658 }
659
660 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
661 neigh_release(neigh);
662 rcu_read_unlock();
663 DEBUG_TRACE(ECM_IP_ADDR_OCTAL_FMT " maps to %pM\n", ECM_IP_ADDR_TO_OCTAL(addr), mac_addr);
664 return true;
665}
666#endif
667
668/*
669 * ecm_interface_mac_addr_get_ipv4_no_route()
670 * Finds the mac address of a node from its ip address reachable via
671 * the given device. It looks up the mac address in the neighbour entries.
672 * It doesn't do any route lookup to find the dst entry.
673 */
674static bool ecm_interface_mac_addr_get_ipv4_no_route(struct net_device *dev, ip_addr_t ip_addr, uint8_t *mac_addr)
675{
676 struct neighbour *neigh;
677 __be32 be_addr;
678 struct net_device *local_dev;
679
680 memset(mac_addr, 0, ETH_ALEN);
681
682 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, ip_addr);
683 local_dev = ip_dev_find(&init_net, be_addr);
684 if (local_dev) {
685 DEBUG_TRACE("%pI4n is a local address\n", &be_addr);
686 memcpy(mac_addr, dev->dev_addr, ETH_ALEN);
687 dev_put(local_dev);
688 return true;
689 }
690
691 rcu_read_lock();
692 neigh = neigh_lookup(&arp_tbl, &be_addr, dev);
693 if (!neigh) {
694 rcu_read_unlock();
695 DEBUG_WARN("no neigh\n");
696 return false;
697 }
698 if (!(neigh->nud_state & NUD_VALID)) {
699 neigh_release(neigh);
700 rcu_read_unlock();
701 DEBUG_WARN("neigh nud state is not valid\n");
702 return false;
703 }
704 if (!neigh->dev) {
705 neigh_release(neigh);
706 rcu_read_unlock();
707 DEBUG_WARN("neigh has no device\n");
708 return false;
709 }
710
711 if (neigh->dev->flags & IFF_NOARP) {
712 neigh_release(neigh);
713 rcu_read_unlock();
714 DEBUG_TRACE("dest MAC is zero: %pM\n", mac_addr);
715 return true;
716 }
717
718 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
719 neigh_release(neigh);
720 rcu_read_unlock();
721 DEBUG_TRACE("dest MAC: %pM\n", mac_addr);
722 return true;
723
724}
725
726/*
727 * ecm_interface_mac_addr_get_no_route()
728 * Return the mac address for the given IP address reacahble via the given device.
729 * Return false on failure, true on success.
730 */
731bool ecm_interface_mac_addr_get_no_route(struct net_device *dev, ip_addr_t addr, uint8_t *mac_addr)
732{
733 if (ECM_IP_ADDR_IS_V4(addr)) {
734 return ecm_interface_mac_addr_get_ipv4_no_route(dev, addr, mac_addr);
735 }
736
737#ifdef ECM_IPV6_ENABLE
738 return ecm_interface_mac_addr_get_ipv6_no_route(dev, addr, mac_addr);
739#else
740 return false;
741#endif
742}
743EXPORT_SYMBOL(ecm_interface_mac_addr_get_no_route);
744
Shyam Sunder6358b862015-05-04 15:06:24 +0530745#ifdef ECM_MULTICAST_ENABLE
746/*
747 * ecm_interface_multicast_check_for_br_dev()
748 * Find a bridge dev is present or not in an
749 * array of Ifindexs
750 */
751bool ecm_interface_multicast_check_for_br_dev(uint32_t dest_if[], uint8_t max_if)
752{
753 struct net_device *br_dev;
754 int i;
755
756 for (i = 0; i < max_if; i++) {
757 br_dev = dev_get_by_index(&init_net, dest_if[i]);
758 if (!br_dev) {
759 DEBUG_ASSERT(NULL, "expected only valid netdev here\n");
760 continue;
761 }
762
763 if (ecm_front_end_is_bridge_device(br_dev)) {
764 dev_put(br_dev);
765 return true;
766 }
767 dev_put(br_dev);
768 }
769 return false;
770}
771EXPORT_SYMBOL(ecm_interface_multicast_check_for_br_dev);
Shyam Sundera2e08ee2015-06-18 21:32:13 +0530772
773/*
774 * ecm_interface_multicast_check_for_src_if_index()
775 * Find if a source netdev ifindex is matching with list of
776 * multicast destination netdev ifindex. If find a match then
777 * returns a new list of destination netdev ifindex excluding
778 * the ifindex of source netdev.
779 */
780int32_t ecm_interface_multicast_check_for_src_ifindex(int32_t mc_if_index[], int32_t max_if_index, int32_t if_num)
781{
782 int32_t i;
783 int32_t valid_index;
784
785 for (i = 0, valid_index = 0; i < max_if_index; i++) {
786 if (mc_if_index[i] == 0) {
787 break;
788 }
789
790 if (mc_if_index[i] != if_num) {
791 mc_if_index[valid_index] = mc_if_index[i];
792 valid_index++;
793 continue;
794 }
795 }
796
797 return valid_index;
798}
799EXPORT_SYMBOL(ecm_interface_multicast_check_for_src_ifindex);
Shyam Sunder6358b862015-05-04 15:06:24 +0530800#endif
801
Ben Menchaca84f36632014-02-28 20:57:38 +0000802/*
803 * ecm_interface_addr_find_route_by_addr_ipv4()
804 * Return the route for the given IP address. Returns NULL on failure.
805 */
806static bool ecm_interface_find_route_by_addr_ipv4(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
807{
808 __be32 be_addr;
809
810 /*
811 * Get a route to the given IP address, this will allow us to also find the interface
812 * it is using to communicate with that IP address.
813 */
814 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, addr);
815 ecm_rt->rt.rtv4 = ip_route_output(&init_net, be_addr, 0, 0, 0);
816 if (IS_ERR(ecm_rt->rt.rtv4)) {
817 DEBUG_TRACE("No output route to: %pI4n\n", &be_addr);
818 return false;
819 }
820 DEBUG_TRACE("Output route to: %pI4n is: %p\n", &be_addr, ecm_rt->rt.rtv4);
821 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv4;
822 ecm_rt->v4_route = true;
823 return true;
824}
825
Gareth Williams8ac34292015-03-17 14:06:58 +0000826#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000827/*
828 * ecm_interface_addr_find_route_by_addr_ipv6()
829 * Return the route for the given IP address. Returns NULL on failure.
830 */
831static bool ecm_interface_find_route_by_addr_ipv6(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
832{
833 struct in6_addr naddr;
834
835 ECM_IP_ADDR_TO_NIN6_ADDR(naddr, addr);
836
837 /*
838 * Get a route to the given IP address, this will allow us to also find the interface
839 * it is using to communicate with that IP address.
840 */
841 ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, 0);
842 if (!ecm_rt->rt.rtv6) {
843 DEBUG_TRACE("No output route to: " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
844 return NULL;
845 }
846 DEBUG_TRACE("Output route to: " ECM_IP_ADDR_OCTAL_FMT " is: %p\n", ECM_IP_ADDR_TO_OCTAL(addr), ecm_rt->rt.rtv6);
847 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv6;
848 ecm_rt->v4_route = false;
849 return true;
850}
Murat Sezgin49465a42014-11-24 15:37:48 -0800851#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000852
853/*
854 * ecm_interface_addr_find_route_by_addr()
855 * Return the route (in the given parameter) for the given IP address. Returns false on failure.
856 *
857 * Route is the device on which the addr is reachable, which may be loopback for local addresses.
858 *
859 * Returns true if the route was able to be located. The route must be released using ecm_interface_route_release().
860 */
861bool ecm_interface_find_route_by_addr(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
862{
863 char __attribute__((unused)) addr_str[40];
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530864
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100865 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
Ben Menchaca84f36632014-02-28 20:57:38 +0000866 DEBUG_TRACE("Locate route to: %s\n", addr_str);
867
868 if (ECM_IP_ADDR_IS_V4(addr)) {
869 return ecm_interface_find_route_by_addr_ipv4(addr, ecm_rt);
870 }
871
Gareth Williams8ac34292015-03-17 14:06:58 +0000872#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000873 return ecm_interface_find_route_by_addr_ipv6(addr, ecm_rt);
Murat Sezgin49465a42014-11-24 15:37:48 -0800874#else
875 return false;
876#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000877}
878EXPORT_SYMBOL(ecm_interface_find_route_by_addr);
879
880/*
881 * ecm_interface_route_release()
882 * Release an ecm route
883 */
884void ecm_interface_route_release(struct ecm_interface_route *rt)
885{
886 dst_release(rt->dst);
887}
888EXPORT_SYMBOL(ecm_interface_route_release);
889
Murat Sezgin188b4a32015-06-03 10:58:59 -0700890#ifdef ECM_IPV6_ENABLE
891/*
892 * ecm_interface_send_neighbour_solicitation()
893 * Issue an IPv6 Neighbour soliciation request.
894 */
895void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t addr)
896{
897 struct in6_addr dst_addr, src_addr;
898 struct in6_addr mc_dst_addr;
899 struct rt6_info *rt6i;
900 struct neighbour *neigh;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700901 struct net *netf = dev_net(dev);
902 int ret;
903
Murat Sezgin188b4a32015-06-03 10:58:59 -0700904 /*
905 * Find source and destination addresses in Linux format. We need
906 * mcast destination address as well.
907 */
908 ECM_IP_ADDR_TO_NIN6_ADDR(dst_addr, addr);
909 addrconf_addr_solict_mult(&dst_addr, &mc_dst_addr);
Murat Sezgin96ed0342017-05-19 09:48:57 -0700910 ret = ipv6_dev_get_saddr(netf, dev, &mc_dst_addr, 0, &src_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700911
912 /*
Murat Sezgin188b4a32015-06-03 10:58:59 -0700913 * Find the route entry
914 */
915 rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0);
916 if (!rt6i) {
Murat Sezginf21210e2016-04-04 13:58:20 -0700917 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 -0700918 return;
919 }
920
921 /*
922 * Find the neighbor entry
923 */
924#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
925 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, &dst_addr);
926#else
927 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr);
928#endif
929 if (neigh == NULL) {
Murat Sezginf21210e2016-04-04 13:58:20 -0700930 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 -0700931 dst_release(&rt6i->dst);
932 return;
933 }
934
935 /*
936 * Issue a Neighbour soliciation request
937 */
938 DEBUG_TRACE("Issue Neighbour solicitation request\n");
Murat Sezgine1c51d82016-02-10 16:42:58 -0800939#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
Murat Sezgin188b4a32015-06-03 10:58:59 -0700940 ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr);
Murat Sezgine1c51d82016-02-10 16:42:58 -0800941#else
942 ndisc_send_ns(dev, &dst_addr, &mc_dst_addr, &src_addr);
943#endif
Murat Sezgin188b4a32015-06-03 10:58:59 -0700944 neigh_release(neigh);
945 dst_release(&rt6i->dst);
946}
947EXPORT_SYMBOL(ecm_interface_send_neighbour_solicitation);
948#endif
949
950/*
951 * ecm_interface_send_arp_request()
952 * Issue and ARP request.
953 */
954void ecm_interface_send_arp_request(struct net_device *dest_dev, ip_addr_t dest_addr, bool on_link, ip_addr_t gw_addr)
955{
956 /*
957 * Possible ARP does not know the address yet
958 */
Murat Sezgin4c093212016-03-24 14:59:02 -0700959 struct neighbour *neigh;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700960 __be32 ipv4_addr;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700961
962 /*
Murat Sezgin987493e2016-04-15 12:33:47 -0700963 * Convert the ECM IP address type to network order IPv4 address.
Murat Sezgin188b4a32015-06-03 10:58:59 -0700964 */
965 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700966
967 /*
968 * If we have a GW for this address, then we have to send ARP request to the GW
969 */
970 if (!on_link && !ECM_IP_ADDR_IS_NULL(gw_addr)) {
971 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, gw_addr);
972 }
973
Murat Sezgin4c093212016-03-24 14:59:02 -0700974 /*
975 * If we don't have this neighbor, create it before sending the arp request,
976 * so that when we receive the arp reply we update the neigh entry.
977 */
978 neigh = neigh_lookup(&arp_tbl, &ipv4_addr, dest_dev);
979 if (!neigh) {
Murat Sezgin987493e2016-04-15 12:33:47 -0700980 neigh = neigh_create(&arp_tbl, &ipv4_addr, dest_dev);
981 if (IS_ERR(neigh)) {
982 DEBUG_WARN("Unable to create ARP request neigh for %pI4\n", &ipv4_addr);
983 return;
984 }
Murat Sezgin4c093212016-03-24 14:59:02 -0700985 }
Murat Sezgin188b4a32015-06-03 10:58:59 -0700986
Murat Sezgin987493e2016-04-15 12:33:47 -0700987 DEBUG_TRACE("Send ARP for %pI4\n", &ipv4_addr);
988 neigh_event_send(neigh, NULL);
989 neigh_release(neigh);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700990}
991EXPORT_SYMBOL(ecm_interface_send_arp_request);
992
Xiaoping Fanc7735462015-08-09 18:57:26 -0700993/*
994 * ecm_interface_ipv4_neigh_get()
995 * Returns neighbour reference for a given IP address which must be released when you are done with it.
996 *
997 * Returns NULL on fail.
998 */
999struct neighbour *ecm_interface_ipv4_neigh_get(ip_addr_t addr)
1000{
1001 struct neighbour *neigh;
1002 struct rtable *rt;
1003 struct dst_entry *dst;
1004 __be32 ipv4_addr;
1005
1006 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
1007 rt = ip_route_output(&init_net, ipv4_addr, 0, 0, 0);
1008 if (IS_ERR(rt)) {
1009 return NULL;
1010 }
1011 dst = (struct dst_entry *)rt;
1012 neigh = dst_neigh_lookup(dst, &ipv4_addr);
1013 ip_rt_put(rt);
1014 return neigh;
1015}
1016
1017#ifdef ECM_IPV6_ENABLE
1018/*
1019 * ecm_interface_ipv6_neigh_get()
1020 * Returns neighbour reference for a given IP address which must be released when you are done with it.
1021 *
1022 * Returns NULL on fail.
1023 */
1024struct neighbour *ecm_interface_ipv6_neigh_get(ip_addr_t addr)
1025{
1026 struct neighbour *neigh;
1027 struct rt6_info *rt;
1028 struct dst_entry *dst;
1029 struct in6_addr ipv6_addr;
1030
1031 ECM_IP_ADDR_TO_NIN6_ADDR(ipv6_addr, addr);
1032 rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0);
1033 if (!rt) {
1034 return NULL;
1035 }
1036 dst = (struct dst_entry *)rt;
1037 neigh = dst_neigh_lookup(dst, &ipv6_addr);
1038 dst_release(dst);
1039 return neigh;
1040}
1041#endif
1042
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301043/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301044 * ecm_interface_is_pptp()
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301045 * skip pptp tunnel encapsulated traffic
1046 *
Shyam Sunder23f2e542015-09-28 14:56:49 +05301047 * ECM does not handle PPTP,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301048 * this function detects packets of that type so they can be skipped over to improve their throughput.
1049 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301050bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out)
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301051{
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301052 struct net_device *in;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301053
ratheesh kannothf4801a02016-12-09 22:46:39 +05301054 /*
1055 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1056 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301057 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301058 if (out->priv_flags & IFF_PPP_PPTP) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301059 return true;
1060 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301061 }
1062
1063 in = dev_get_by_index(&init_net, skb->skb_iif);
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301064 if (!in) {
1065 return true;
1066 }
1067
1068 if (in->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301069 if (in->priv_flags & IFF_PPP_PPTP) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301070 dev_put(in);
1071 return true;
1072 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05301073 }
1074
1075 dev_put(in);
1076 return false;
1077}
1078
Shyam Sunder2ca02492016-08-05 20:55:12 +05301079#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder23f2e542015-09-28 14:56:49 +05301080/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301081 * ecm_interface_is_l2tp_packet_by_version()
Shyam Sunder23f2e542015-09-28 14:56:49 +05301082 * Check version of l2tp tunnel encapsulated traffic
1083 *
1084 * ECM does not handle l2tp,
1085 * this function detects packets of that type so they can be skipped over to improve their throughput.
1086 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301087bool 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 +05301088{
ratheesh kannothf4801a02016-12-09 22:46:39 +05301089 uint32_t flag = 0;
Shyam Sunder23f2e542015-09-28 14:56:49 +05301090 struct net_device *in;
1091
ratheesh kannothf4801a02016-12-09 22:46:39 +05301092 switch (ver) {
1093 case 2:
1094 flag = IFF_PPP_L2TPV2;
1095 break;
1096 case 3:
1097 flag = IFF_PPP_L2TPV3;
1098 break;
1099 default:
1100 break;
1101 }
1102
1103 /*
1104 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1105 */
Shyam Sunder23f2e542015-09-28 14:56:49 +05301106 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301107 if (out->priv_flags & flag) {
Shyam Sunder23f2e542015-09-28 14:56:49 +05301108 return true;
1109 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05301110 }
1111
1112 in = dev_get_by_index(&init_net, skb->skb_iif);
1113 if (!in) {
1114 return true;
1115 }
1116
1117 if (in->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301118 if (in->priv_flags & flag) {
Shyam Sunder23f2e542015-09-28 14:56:49 +05301119 dev_put(in);
1120 return true;
1121 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301122 }
1123
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301124 dev_put(in);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301125 return false;
1126}
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301127
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001128/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301129 * ecm_interface_is_l2tp_pptp()
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001130 * skip l2tp/pptp tunnel encapsulated traffic
1131 *
1132 * ECM does not handle L2TP or PPTP encapsulated packets,
1133 * this function detects packets of that type so they can be skipped over to improve their throughput.
1134 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301135bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *out)
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001136{
ratheesh kannothf4801a02016-12-09 22:46:39 +05301137 struct net_device *in;
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001138
1139 /*
1140 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1141 */
1142 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301143 if (out->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 |
1144 IFF_PPP_PPTP)) {
1145 return true;
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001146 }
1147 }
1148
ratheesh kannothf4801a02016-12-09 22:46:39 +05301149 in = dev_get_by_index(&init_net, skb->skb_iif);
1150 if (!in) {
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001151 return true;
1152 }
1153
ratheesh kannothf4801a02016-12-09 22:46:39 +05301154 if (in->type == ARPHRD_PPP) {
1155 if (in->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 |
1156 IFF_PPP_PPTP)) {
1157 dev_put(in);
1158 return true;
1159 }
1160 }
1161
1162 dev_put(in);
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001163 return false;
ratheesh kannothf4801a02016-12-09 22:46:39 +05301164
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001165}
1166#endif
1167
Gareth Williams141d2382014-11-25 11:35:19 -08001168#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001169/*
Ben Menchaca84f36632014-02-28 20:57:38 +00001170 * ecm_interface_vlan_interface_establish()
1171 * Returns a reference to a iface of the VLAN type, possibly creating one if necessary.
1172 * Returns NULL on failure or a reference to interface.
1173 */
1174static 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 -07001175 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001176{
1177 struct ecm_db_iface_instance *nii;
1178 struct ecm_db_iface_instance *ii;
1179
Murat Sezgin91c5d712015-06-12 15:16:22 -07001180 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",
1181 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 +00001182
1183 /*
1184 * Locate the iface
1185 */
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301186 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 +00001187 if (ii) {
1188 DEBUG_TRACE("%p: iface established\n", ii);
1189 return ii;
1190 }
1191
1192 /*
1193 * No iface - create one
1194 */
1195 nii = ecm_db_iface_alloc();
1196 if (!nii) {
1197 DEBUG_WARN("Failed to establish iface\n");
1198 return NULL;
1199 }
1200
1201 /*
1202 * Add iface into the database, atomically to avoid races creating the same thing
1203 */
1204 spin_lock_bh(&ecm_interface_lock);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301205 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 +00001206 if (ii) {
1207 spin_unlock_bh(&ecm_interface_lock);
1208 ecm_db_iface_deref(nii);
1209 return ii;
1210 }
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301211 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 -07001212 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001213 spin_unlock_bh(&ecm_interface_lock);
1214
1215 DEBUG_TRACE("%p: vlan iface established\n", nii);
1216 return nii;
1217}
Gareth Williams141d2382014-11-25 11:35:19 -08001218#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001219
1220/*
1221 * ecm_interface_bridge_interface_establish()
1222 * Returns a reference to a iface of the BRIDGE type, possibly creating one if necessary.
1223 * Returns NULL on failure or a reference to interface.
1224 */
1225static 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 -07001226 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001227{
1228 struct ecm_db_iface_instance *nii;
1229 struct ecm_db_iface_instance *ii;
1230
Murat Sezgin91c5d712015-06-12 15:16:22 -07001231 DEBUG_INFO("Establish BRIDGE iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1232 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001233
1234 /*
1235 * Locate the iface
1236 */
1237 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1238 if (ii) {
1239 DEBUG_TRACE("%p: iface established\n", ii);
1240 return ii;
1241 }
1242
1243 /*
1244 * No iface - create one
1245 */
1246 nii = ecm_db_iface_alloc();
1247 if (!nii) {
1248 DEBUG_WARN("Failed to establish iface\n");
1249 return NULL;
1250 }
1251
1252 /*
1253 * Add iface into the database, atomically to avoid races creating the same thing
1254 */
1255 spin_lock_bh(&ecm_interface_lock);
1256 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1257 if (ii) {
1258 spin_unlock_bh(&ecm_interface_lock);
1259 ecm_db_iface_deref(nii);
1260 return ii;
1261 }
1262 ecm_db_iface_add_bridge(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001263 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001264 spin_unlock_bh(&ecm_interface_lock);
1265
1266 DEBUG_TRACE("%p: bridge iface established\n", nii);
1267 return nii;
1268}
1269
Murat Sezgin910c9662015-03-11 16:15:06 -07001270#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001271/*
1272 * ecm_interface_lag_interface_establish()
1273 * Returns a reference to a iface of the LAG type, possibly creating one if necessary.
1274 * Returns NULL on failure or a reference to interface.
1275 */
1276static 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 -07001277 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001278{
1279 struct ecm_db_iface_instance *nii;
1280 struct ecm_db_iface_instance *ii;
1281
Murat Sezgin91c5d712015-06-12 15:16:22 -07001282 DEBUG_INFO("Establish LAG iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1283 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001284
1285 /*
1286 * Locate the iface
1287 */
1288 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1289 if (ii) {
1290 DEBUG_TRACE("%p: iface established\n", ii);
1291 return ii;
1292 }
1293
1294 /*
1295 * No iface - create one
1296 */
1297 nii = ecm_db_iface_alloc();
1298 if (!nii) {
1299 DEBUG_WARN("Failed to establish iface\n");
1300 return NULL;
1301 }
1302
1303 /*
1304 * Add iface into the database, atomically to avoid races creating the same thing
1305 */
1306 spin_lock_bh(&ecm_interface_lock);
1307 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1308 if (ii) {
1309 spin_unlock_bh(&ecm_interface_lock);
1310 ecm_db_iface_deref(nii);
1311 return ii;
1312 }
1313 ecm_db_iface_add_lag(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001314 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001315 spin_unlock_bh(&ecm_interface_lock);
1316
1317 DEBUG_TRACE("%p: lag iface established\n", nii);
1318 return nii;
1319}
Murat Sezgin910c9662015-03-11 16:15:06 -07001320#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001321
1322/*
1323 * ecm_interface_ethernet_interface_establish()
1324 * Returns a reference to a iface of the ETHERNET type, possibly creating one if necessary.
1325 * Returns NULL on failure or a reference to interface.
1326 */
1327static 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 -07001328 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001329{
1330 struct ecm_db_iface_instance *nii;
1331 struct ecm_db_iface_instance *ii;
1332
Murat Sezgin91c5d712015-06-12 15:16:22 -07001333 DEBUG_INFO("Establish ETHERNET iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1334 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001335
1336 /*
1337 * Locate the iface
1338 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301339 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
1340
Ben Menchaca84f36632014-02-28 20:57:38 +00001341 if (ii) {
1342 DEBUG_TRACE("%p: iface established\n", ii);
Murat Sezgin5f2947a2016-06-28 12:09:33 -07001343 /*
1344 * Update the accel engine interface identifier, just in case it was changed.
1345 */
1346 ecm_db_iface_ae_interface_identifier_set(ii, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001347 return ii;
1348 }
1349
1350 /*
1351 * No iface - create one
1352 */
1353 nii = ecm_db_iface_alloc();
1354 if (!nii) {
1355 DEBUG_WARN("Failed to establish iface\n");
1356 return NULL;
1357 }
1358
1359 /*
1360 * Add iface into the database, atomically to avoid races creating the same thing
1361 */
1362 spin_lock_bh(&ecm_interface_lock);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301363 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001364 if (ii) {
1365 spin_unlock_bh(&ecm_interface_lock);
1366 ecm_db_iface_deref(nii);
1367 return ii;
1368 }
1369 ecm_db_iface_add_ethernet(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001370 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001371 spin_unlock_bh(&ecm_interface_lock);
1372
1373 DEBUG_TRACE("%p: ethernet iface established\n", nii);
1374 return nii;
1375}
1376
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301377#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001378/*
1379 * ecm_interface_pppoe_interface_establish()
1380 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1381 * Returns NULL on failure or a reference to interface.
1382 */
1383static 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 -07001384 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001385{
1386 struct ecm_db_iface_instance *nii;
1387 struct ecm_db_iface_instance *ii;
1388
Murat Sezgin91c5d712015-06-12 15:16:22 -07001389 DEBUG_INFO("Establish PPPoE iface: %s with session id: %u, remote mac: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1390 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 +00001391
1392 /*
1393 * Locate the iface
1394 */
1395 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1396 if (ii) {
1397 DEBUG_TRACE("%p: iface established\n", ii);
1398 return ii;
1399 }
1400
1401 /*
1402 * No iface - create one
1403 */
1404 nii = ecm_db_iface_alloc();
1405 if (!nii) {
1406 DEBUG_WARN("Failed to establish iface\n");
1407 return NULL;
1408 }
1409
1410 /*
1411 * Add iface into the database, atomically to avoid races creating the same thing
1412 */
1413 spin_lock_bh(&ecm_interface_lock);
1414 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1415 if (ii) {
1416 spin_unlock_bh(&ecm_interface_lock);
1417 ecm_db_iface_deref(nii);
1418 return ii;
1419 }
1420 ecm_db_iface_add_pppoe(nii, type_info->pppoe_session_id, type_info->remote_mac, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001421 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001422 spin_unlock_bh(&ecm_interface_lock);
1423
1424 DEBUG_TRACE("%p: pppoe iface established\n", nii);
1425 return nii;
1426}
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001427#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001428
ratheesh kannothcfdcb332015-12-24 07:19:18 +05301429#ifdef ECM_INTERFACE_MAP_T_ENABLE
1430/*
1431 * ecm_interface_map_t_interface_establish()
1432 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1433 * Returns NULL on failure or a reference to interface.
1434 */
1435static struct ecm_db_iface_instance *ecm_interface_map_t_interface_establish(struct ecm_db_interface_info_map_t *type_info,
1436 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1437{
1438 struct ecm_db_iface_instance *nii;
1439 struct ecm_db_iface_instance *ii;
1440
1441 DEBUG_TRACE("Establish MAP-T iface: %s MTU: %d, if num: %d, accel engine if id: %d\n",
1442 dev_name, mtu, dev_interface_num, ae_interface_num);
1443
1444 /*
1445 * Locate the iface
1446 */
1447 ii = ecm_db_iface_find_and_ref_map_t(type_info->if_index);
1448 if (ii) {
1449 DEBUG_TRACE("%p: iface established\n", ii);
1450 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1451 return ii;
1452 }
1453
1454 /*
1455 * No iface - create one
1456 */
1457 nii = ecm_db_iface_alloc();
1458 if (!nii) {
1459 DEBUG_WARN("Failed to establish iface\n");
1460 return NULL;
1461 }
1462
1463 /*
1464 * Add iface into the database, atomically to avoid races creating the same thing
1465 */
1466 spin_lock_bh(&ecm_interface_lock);
1467 ii = ecm_db_iface_find_and_ref_map_t(type_info->if_index);
1468 if (ii) {
1469 spin_unlock_bh(&ecm_interface_lock);
1470 ecm_db_iface_deref(nii);
1471 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1472 return ii;
1473 }
1474 ecm_db_iface_add_map_t(nii, type_info, dev_name,
1475 mtu, dev_interface_num, ae_interface_num, NULL, nii);
1476 spin_unlock_bh(&ecm_interface_lock);
1477
1478 DEBUG_TRACE("%p: map_t iface established\n", nii);
1479 return nii;
1480}
1481#endif
1482
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301483#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1484/*
1485 * ecm_interface_pppol2tpv2_interface_establish()
1486 * Returns a reference to a iface of the PPPoL2TPV2 type, possibly creating one if necessary.
1487 * Returns NULL on failure or a reference to interface.
1488 */
1489static struct ecm_db_iface_instance *ecm_interface_pppol2tpv2_interface_establish(struct ecm_db_interface_info_pppol2tpv2 *type_info,
1490 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1491{
1492 struct ecm_db_iface_instance *nii;
1493 struct ecm_db_iface_instance *ii;
1494
1495 DEBUG_INFO("Establish PPPol2tp iface: %s with tunnel id=%u session id %u\n", dev_name, type_info->l2tp.tunnel.tunnel_id,
1496 type_info->l2tp.session.session_id);
1497 /*
1498 * Locate the iface
1499 */
1500 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1501 if (ii) {
1502 DEBUG_TRACE("%p: iface established\n", ii);
ratheesh kannothed721852015-09-28 12:39:52 +05301503 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301504 return ii;
1505 }
1506
1507 /*
1508 * No iface - create one
1509 */
1510 nii = ecm_db_iface_alloc();
1511 if (!nii) {
1512 DEBUG_WARN("Failed to establish iface\n");
1513 return NULL;
1514 }
1515
1516 /*
1517 * Add iface into the database, atomically to avoid races creating the same thing
1518 */
1519 spin_lock_bh(&ecm_interface_lock);
1520 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1521 if (ii) {
1522 spin_unlock_bh(&ecm_interface_lock);
1523 ecm_db_iface_deref(nii);
ratheesh kannothed721852015-09-28 12:39:52 +05301524 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301525 return ii;
1526 }
1527
1528 ecm_db_iface_add_pppol2tpv2(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1529 spin_unlock_bh(&ecm_interface_lock);
1530
1531 DEBUG_TRACE("%p: pppol2tpv2 iface established\n", nii);
1532 return nii;
1533}
1534
1535#endif
1536
Shyam Sunder23f2e542015-09-28 14:56:49 +05301537#ifdef ECM_INTERFACE_PPTP_ENABLE
1538/*
1539 * ecm_interface_pptp_interface_establish()
1540 * Returns a reference to a iface of the PPTP type, possibly creating one if necessary.
1541 * Returns NULL on failure or a reference to interface.
1542 */
1543static struct ecm_db_iface_instance *ecm_interface_pptp_interface_establish(struct ecm_db_interface_info_pptp *type_info,
1544 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1545{
1546 struct ecm_db_iface_instance *nii;
1547 struct ecm_db_iface_instance *ii;
1548
1549 DEBUG_INFO("Establish PPTP iface: %s with local call id %u peer call id %u\n", dev_name, type_info->src_call_id,
1550 type_info->dst_call_id);
1551 /*
1552 * Locate the iface
1553 */
1554 ii = ecm_db_iface_find_and_ref_pptp(type_info->src_call_id, type_info->dst_call_id);
1555 if (ii) {
1556 DEBUG_TRACE("%p: iface established\n", ii);
1557 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1558 return ii;
1559 }
1560
1561 /*
1562 * No iface - create one
1563 */
1564 nii = ecm_db_iface_alloc();
1565 if (!nii) {
1566 DEBUG_WARN("Failed to establish iface\n");
1567 return NULL;
1568 }
1569
1570 /*
1571 * Add iface into the database, atomically to avoid races creating the same thing
1572 */
1573 spin_lock_bh(&ecm_interface_lock);
1574 ii = ecm_db_iface_find_and_ref_pptp(type_info->src_call_id, type_info->dst_call_id);
1575 if (ii) {
1576 spin_unlock_bh(&ecm_interface_lock);
1577 ecm_db_iface_deref(nii);
1578 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1579 return ii;
1580 }
1581
1582 ecm_db_iface_add_pptp(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1583 spin_unlock_bh(&ecm_interface_lock);
1584
1585 DEBUG_TRACE("%p: pptp iface established\n", nii);
1586 return nii;
1587}
1588#endif
1589
Ben Menchaca84f36632014-02-28 20:57:38 +00001590/*
1591 * ecm_interface_unknown_interface_establish()
1592 * Returns a reference to a iface of the UNKNOWN type, possibly creating one if necessary.
1593 * Returns NULL on failure or a reference to interface.
1594 */
1595static 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 -07001596 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001597{
1598 struct ecm_db_iface_instance *nii;
1599 struct ecm_db_iface_instance *ii;
1600
Murat Sezgin91c5d712015-06-12 15:16:22 -07001601 DEBUG_INFO("Establish UNKNOWN iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1602 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001603
1604 /*
1605 * Locate the iface
1606 */
1607 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1608 if (ii) {
1609 DEBUG_TRACE("%p: iface established\n", ii);
1610 return ii;
1611 }
1612
1613 /*
1614 * No iface - create one
1615 */
1616 nii = ecm_db_iface_alloc();
1617 if (!nii) {
1618 DEBUG_WARN("Failed to establish iface\n");
1619 return NULL;
1620 }
1621
1622 /*
1623 * Add iface into the database, atomically to avoid races creating the same thing
1624 */
1625 spin_lock_bh(&ecm_interface_lock);
1626 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1627 if (ii) {
1628 spin_unlock_bh(&ecm_interface_lock);
1629 ecm_db_iface_deref(nii);
1630 return ii;
1631 }
1632 ecm_db_iface_add_unknown(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001633 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001634 spin_unlock_bh(&ecm_interface_lock);
1635
1636 DEBUG_TRACE("%p: unknown iface established\n", nii);
1637 return nii;
1638}
1639
1640/*
1641 * ecm_interface_loopback_interface_establish()
1642 * Returns a reference to a iface of the LOOPBACK type, possibly creating one if necessary.
1643 * Returns NULL on failure or a reference to interface.
1644 */
1645static 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 -07001646 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001647{
1648 struct ecm_db_iface_instance *nii;
1649 struct ecm_db_iface_instance *ii;
1650
Murat Sezgin91c5d712015-06-12 15:16:22 -07001651 DEBUG_INFO("Establish LOOPBACK iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1652 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001653
1654 /*
1655 * Locate the iface
1656 */
1657 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1658 if (ii) {
1659 DEBUG_TRACE("%p: iface established\n", ii);
1660 return ii;
1661 }
1662
1663 /*
1664 * No iface - create one
1665 */
1666 nii = ecm_db_iface_alloc();
1667 if (!nii) {
1668 DEBUG_WARN("Failed to establish iface\n");
1669 return NULL;
1670 }
1671
1672 /*
1673 * Add iface into the database, atomically to avoid races creating the same thing
1674 */
1675 spin_lock_bh(&ecm_interface_lock);
1676 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1677 if (ii) {
1678 spin_unlock_bh(&ecm_interface_lock);
1679 ecm_db_iface_deref(nii);
1680 return ii;
1681 }
1682 ecm_db_iface_add_loopback(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001683 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001684 spin_unlock_bh(&ecm_interface_lock);
1685
1686 DEBUG_TRACE("%p: loopback iface established\n", nii);
1687 return nii;
1688}
1689
Murat Sezgin69a27532015-03-12 14:09:40 -07001690#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001691/*
1692 * ecm_interface_ipsec_tunnel_interface_establish()
1693 * Returns a reference to a iface of the IPSEC_TUNNEL type, possibly creating one if necessary.
1694 * Returns NULL on failure or a reference to interface.
1695 *
1696 * NOTE: GGG TODO THIS NEEDS TO TAKE A PROPER APPROACH TO IPSEC TUNNELS USING ENDPOINT ADDRESSING AS THE TYPE INFO KEYS
1697 */
1698static 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 -07001699 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001700{
1701 struct ecm_db_iface_instance *nii;
1702 struct ecm_db_iface_instance *ii;
1703
Murat Sezgin91c5d712015-06-12 15:16:22 -07001704 DEBUG_INFO("Establish IPSEC_TUNNEL iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1705 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001706
1707 /*
1708 * Locate the iface
1709 */
1710 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1711 if (ii) {
1712 DEBUG_TRACE("%p: iface established\n", ii);
1713 return ii;
1714 }
1715
1716 /*
1717 * No iface - create one
1718 */
1719 nii = ecm_db_iface_alloc();
1720 if (!nii) {
1721 DEBUG_WARN("Failed to establish iface\n");
1722 return NULL;
1723 }
1724
1725 /*
1726 * Add iface into the database, atomically to avoid races creating the same thing
1727 */
1728 spin_lock_bh(&ecm_interface_lock);
1729 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1730 if (ii) {
1731 spin_unlock_bh(&ecm_interface_lock);
1732 ecm_db_iface_deref(nii);
1733 return ii;
1734 }
1735 ecm_db_iface_add_ipsec_tunnel(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001736 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001737 spin_unlock_bh(&ecm_interface_lock);
1738
1739 DEBUG_TRACE("%p: ipsec_tunnel iface established\n", nii);
1740 return nii;
1741}
Murat Sezgin69a27532015-03-12 14:09:40 -07001742#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001743
Murat Sezginb3731e82014-11-26 12:20:59 -08001744#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07001745#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00001746/*
1747 * ecm_interface_sit_interface_establish()
1748 * Returns a reference to a iface of the SIT type, possibly creating one if necessary.
1749 * Returns NULL on failure or a reference to interface.
1750 */
1751static 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 -07001752 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001753{
1754 struct ecm_db_iface_instance *nii;
1755 struct ecm_db_iface_instance *ii;
1756
Murat Sezgin91c5d712015-06-12 15:16:22 -07001757 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",
1758 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 +00001759
1760 /*
1761 * Locate the iface
1762 */
1763 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr);
1764 if (ii) {
1765 DEBUG_TRACE("%p: iface established\n", ii);
1766 return ii;
1767 }
1768
1769 /*
1770 * No iface - create one
1771 */
1772 nii = ecm_db_iface_alloc();
1773 if (!nii) {
1774 DEBUG_WARN("Failed to establish iface\n");
1775 return NULL;
1776 }
1777
1778 /*
1779 * Add iface into the database, atomically to avoid races creating the same thing
1780 */
1781 spin_lock_bh(&ecm_interface_lock);
1782 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr);
1783 if (ii) {
1784 spin_unlock_bh(&ecm_interface_lock);
1785 ecm_db_iface_deref(nii);
1786 return ii;
1787 }
1788 ecm_db_iface_add_sit(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001789 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001790 spin_unlock_bh(&ecm_interface_lock);
1791
1792 DEBUG_TRACE("%p: sit iface established\n", nii);
1793 return nii;
1794}
Murat Sezgincc6eedf2014-05-09 23:59:19 -07001795#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08001796#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001797
Murat Sezginc1402562015-03-12 12:32:20 -07001798#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001799#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001800/*
1801 * ecm_interface_tunipip6_interface_establish()
1802 * Returns a reference to a iface of the TUNIPIP6 type, possibly creating one if necessary.
1803 * Returns NULL on failure or a reference to interface.
1804 */
1805static 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 -07001806 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001807{
1808 struct ecm_db_iface_instance *nii;
1809 struct ecm_db_iface_instance *ii;
1810
Murat Sezgin91c5d712015-06-12 15:16:22 -07001811 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",
1812 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 +00001813
1814 /*
1815 * Locate the iface
1816 */
1817 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1818 if (ii) {
1819 DEBUG_TRACE("%p: iface established\n", ii);
1820 return ii;
1821 }
1822
1823 /*
1824 * No iface - create one
1825 */
1826 nii = ecm_db_iface_alloc();
1827 if (!nii) {
1828 DEBUG_WARN("Failed to establish iface\n");
1829 return NULL;
1830 }
1831
1832 /*
1833 * Add iface into the database, atomically to avoid races creating the same thing
1834 */
1835 spin_lock_bh(&ecm_interface_lock);
1836 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1837 if (ii) {
1838 spin_unlock_bh(&ecm_interface_lock);
1839 ecm_db_iface_deref(nii);
1840 return ii;
1841 }
1842 ecm_db_iface_add_tunipip6(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001843 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001844 spin_unlock_bh(&ecm_interface_lock);
1845
1846 DEBUG_TRACE("%p: tunipip6 iface established\n", nii);
1847 return nii;
1848}
Murat Sezginc1402562015-03-12 12:32:20 -07001849#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001850#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001851
1852/*
1853 * ecm_interface_establish_and_ref()
1854 * Establish an interface instance for the given interface detail.
1855 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001856struct ecm_db_iface_instance *ecm_interface_establish_and_ref(struct ecm_front_end_connection_instance *feci,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301857 struct net_device *dev, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00001858{
1859 int32_t dev_interface_num;
1860 char *dev_name;
1861 int32_t dev_type;
1862 int32_t dev_mtu;
Murat Sezgin91c5d712015-06-12 15:16:22 -07001863 int32_t ae_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00001864 struct ecm_db_iface_instance *ii;
1865 union {
1866 struct ecm_db_interface_info_ethernet ethernet; /* type == ECM_DB_IFACE_TYPE_ETHERNET */
Gareth Williams141d2382014-11-25 11:35:19 -08001867#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001868 struct ecm_db_interface_info_vlan vlan; /* type == ECM_DB_IFACE_TYPE_VLAN */
Gareth Williams141d2382014-11-25 11:35:19 -08001869#endif
Murat Sezgin910c9662015-03-11 16:15:06 -07001870#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001871 struct ecm_db_interface_info_lag lag; /* type == ECM_DB_IFACE_TYPE_LAG */
Murat Sezgin910c9662015-03-11 16:15:06 -07001872#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001873 struct ecm_db_interface_info_bridge bridge; /* type == ECM_DB_IFACE_TYPE_BRIDGE */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301874#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001875 struct ecm_db_interface_info_pppoe pppoe; /* type == ECM_DB_IFACE_TYPE_PPPOE */
Murat Sezginaad635c2015-03-06 16:11:41 -08001876#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301877#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1878 struct ecm_db_interface_info_pppol2tpv2 pppol2tpv2; /* type == ECM_DB_IFACE_TYPE_PPPOL2TPV2 */
1879#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301880#ifdef ECM_INTERFACE_PPTP_ENABLE
1881 struct ecm_db_interface_info_pptp pptp; /* type == ECM_DB_IFACE_TYPE_PPTP */
1882#endif
ratheesh kannothcfdcb332015-12-24 07:19:18 +05301883#ifdef ECM_INTERFACE_MAP_T_ENABLE
1884 struct ecm_db_interface_info_map_t map_t; /* type == ECM_DB_IFACE_TYPE_MAP_T */
1885#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001886 struct ecm_db_interface_info_unknown unknown; /* type == ECM_DB_IFACE_TYPE_UNKNOWN */
1887 struct ecm_db_interface_info_loopback loopback; /* type == ECM_DB_IFACE_TYPE_LOOPBACK */
Murat Sezgin69a27532015-03-12 14:09:40 -07001888#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001889 struct ecm_db_interface_info_ipsec_tunnel ipsec_tunnel; /* type == ECM_DB_IFACE_TYPE_IPSEC_TUNNEL */
Murat Sezgin69a27532015-03-12 14:09:40 -07001890#endif
Murat Sezginbde55f92015-03-11 16:44:11 -07001891#ifdef ECM_INTERFACE_SIT_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001892 struct ecm_db_interface_info_sit sit; /* type == ECM_DB_IFACE_TYPE_SIT */
Murat Sezginbde55f92015-03-11 16:44:11 -07001893#endif
Murat Sezginc1402562015-03-12 12:32:20 -07001894#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001895#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001896 struct ecm_db_interface_info_tunipip6 tunipip6; /* type == ECM_DB_IFACE_TYPE_TUNIPIP6 */
Murat Sezginc1402562015-03-12 12:32:20 -07001897#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001898#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001899 } type_info;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001900
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08001901#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001902 int channel_count;
1903 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00001904 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301905#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001906 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001907#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301908#ifdef ECM_INTERFACE_PPTP_ENABLE
1909 int protocol = IPPROTO_IP;
1910 struct pptp_opt opt;
1911 struct iphdr *v4_hdr = NULL;
1912 if (skb) {
1913 v4_hdr = ip_hdr(skb);
1914 protocol = v4_hdr->protocol;
1915 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301916#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301917#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001918 /*
1919 * Get basic information about the given device
1920 */
1921 dev_interface_num = dev->ifindex;
1922 dev_name = dev->name;
1923 dev_type = dev->type;
1924 dev_mtu = dev->mtu;
1925
1926 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07001927 * Does the accel engine recognise this interface?
Ben Menchaca84f36632014-02-28 20:57:38 +00001928 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001929 ae_interface_num = feci->ae_interface_number_by_dev_get(dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00001930
Murat Sezgin91c5d712015-06-12 15:16:22 -07001931 DEBUG_TRACE("Establish interface instance for device: %p is type: %d, name: %s, ifindex: %d, ae_if: %d, mtu: %d\n",
1932 dev, dev_type, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00001933
1934 /*
1935 * Extract from the device more type-specific information
1936 */
1937 if (dev_type == ARPHRD_ETHER) {
Shyam Sunder39e25672015-09-03 14:28:09 +05301938
Ben Menchaca84f36632014-02-28 20:57:38 +00001939 /*
1940 * Ethernet - but what sub type?
1941 */
1942
Gareth Williams141d2382014-11-25 11:35:19 -08001943#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001944 /*
1945 * VLAN?
1946 */
1947 if (is_vlan_dev(dev)) {
1948 /*
1949 * VLAN master
1950 * GGG No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
1951 */
1952 memcpy(type_info.vlan.address, dev->dev_addr, 6);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301953 type_info.vlan.vlan_tag = vlan_dev_vlan_id(dev);
Amit Gupta8975f9d2017-07-12 20:34:36 +05301954#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
Murat Sezginb2676062015-06-12 17:05:31 -07001955 type_info.vlan.vlan_tpid = ETH_P_8021Q;
Amit Gupta8975f9d2017-07-12 20:34:36 +05301956#else
1957 type_info.vlan.vlan_tpid = ntohs(vlan_dev_vlan_proto(dev));
1958#endif
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301959 DEBUG_TRACE("Net device: %p is VLAN, mac: %pM, vlan_id: %x vlan_tpid: %x\n",
1960 dev, type_info.vlan.address, type_info.vlan.vlan_tag, type_info.vlan.vlan_tpid);
Ben Menchaca84f36632014-02-28 20:57:38 +00001961
1962 /*
1963 * Establish this type of interface
1964 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001965 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 +05301966 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00001967 }
Gareth Williams141d2382014-11-25 11:35:19 -08001968#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001969
1970 /*
1971 * BRIDGE?
1972 */
1973 if (ecm_front_end_is_bridge_device(dev)) {
1974 /*
1975 * Bridge
1976 */
1977 memcpy(type_info.bridge.address, dev->dev_addr, 6);
1978
1979 DEBUG_TRACE("Net device: %p is BRIDGE, mac: %pM\n",
1980 dev, type_info.bridge.address);
1981
1982 /*
1983 * Establish this type of interface
1984 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001985 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 +05301986 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00001987 }
1988
Murat Sezgin910c9662015-03-11 16:15:06 -07001989#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001990 /*
1991 * LAG?
1992 */
1993 if (ecm_front_end_is_lag_master(dev)) {
1994 /*
1995 * Link aggregation
1996 */
1997 memcpy(type_info.lag.address, dev->dev_addr, 6);
1998
1999 DEBUG_TRACE("Net device: %p is LAG, mac: %pM\n",
2000 dev, type_info.lag.address);
2001
2002 /*
2003 * Establish this type of interface
2004 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002005 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 +05302006 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00002007 }
Murat Sezgin910c9662015-03-11 16:15:06 -07002008#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002009
2010 /*
2011 * ETHERNET!
2012 * Just plain ethernet it seems
2013 */
2014 memcpy(type_info.ethernet.address, dev->dev_addr, 6);
2015 DEBUG_TRACE("Net device: %p is ETHERNET, mac: %pM\n",
2016 dev, type_info.ethernet.address);
2017
2018 /*
2019 * Establish this type of interface
2020 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002021 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 +05302022
2023identifier_update:
2024 if (ii) {
2025 /*
2026 * An interface identifier/ifindex can be change after network restart. Below
2027 * functtion will check interface_identifier present in 'ii' with new dev_interface_num.
2028 * If differ then update new ifindex and update the interface identifier hash table.
2029 */
2030 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2031 }
2032
Ben Menchaca84f36632014-02-28 20:57:38 +00002033 return ii;
2034 }
2035
2036 /*
2037 * LOOPBACK?
2038 */
2039 if (dev_type == ARPHRD_LOOPBACK) {
2040 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dev, dev_type);
2041 type_info.loopback.os_specific_ident = dev_interface_num;
Murat Sezgin91c5d712015-06-12 15:16:22 -07002042 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 +00002043 return ii;
2044 }
2045
Murat Sezgin69a27532015-03-12 14:09:40 -07002046#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002047 /*
2048 * IPSEC?
2049 */
2050 if (dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2051 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dev, dev_type);
2052 type_info.ipsec_tunnel.os_specific_ident = dev_interface_num;
Ankit Dhanuka6d5014a2014-06-22 17:21:44 +05302053
Ben Menchaca84f36632014-02-28 20:57:38 +00002054 // GGG TODO Flesh this out with tunnel endpoint addressing detail
Murat Sezgin91c5d712015-06-12 15:16:22 -07002055 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 +00002056 return ii;
2057 }
Murat Sezgin69a27532015-03-12 14:09:40 -07002058#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002059
ratheesh kannothcfdcb332015-12-24 07:19:18 +05302060#ifdef ECM_INTERFACE_MAP_T_ENABLE
2061 if (dev_type == ARPHRD_NONE) {
2062 if (is_map_t_dev(dev)) {
2063 type_info.map_t.if_index = dev_interface_num;
2064 ii = ecm_interface_map_t_interface_establish(&type_info.map_t, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2065 return ii;
2066 }
2067
2068 }
2069#endif
2070
Murat Sezginb3731e82014-11-26 12:20:59 -08002071#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07002072#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00002073 /*
2074 * SIT (6-in-4)?
2075 */
2076 if (dev_type == ARPHRD_SIT) {
2077 struct ip_tunnel *tunnel;
2078 struct ip_tunnel_6rd_parm *ip6rd;
2079 const struct iphdr *tiph;
2080
2081 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dev, dev_type);
2082
2083 tunnel = (struct ip_tunnel*)netdev_priv(dev);
2084 ip6rd = &tunnel->ip6rd;
2085
2086 /*
2087 * Get the Tunnel device IP header info
2088 */
2089 tiph = &tunnel->parms.iph ;
2090
2091 type_info.sit.prefixlen = ip6rd->prefixlen;
2092 type_info.sit.relay_prefix = ip6rd->relay_prefix;
2093 type_info.sit.relay_prefixlen = ip6rd->relay_prefixlen;
2094 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.saddr, tiph->saddr);
2095 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.daddr, tiph->daddr);
2096 type_info.sit.prefix[0] = ntohl(ip6rd->prefix.s6_addr32[0]);
2097 type_info.sit.prefix[1] = ntohl(ip6rd->prefix.s6_addr32[1]);
2098 type_info.sit.prefix[2] = ntohl(ip6rd->prefix.s6_addr32[2]);
2099 type_info.sit.prefix[3] = ntohl(ip6rd->prefix.s6_addr32[3]);
2100 type_info.sit.ttl = tiph->ttl;
2101 type_info.sit.tos = tiph->tos;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05302102
Murat Sezgin91c5d712015-06-12 15:16:22 -07002103 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 +00002104 return ii;
2105 }
Murat Sezgincc6eedf2014-05-09 23:59:19 -07002106#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08002107#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002108
Murat Sezginc1402562015-03-12 12:32:20 -07002109#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00002110#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002111 /*
2112 * IPIP6 Tunnel?
2113 */
2114 if (dev_type == ARPHRD_TUNNEL6) {
2115 struct ip6_tnl *tunnel;
2116 struct flowi6 *fl6;
2117
2118 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dev, dev_type);
2119
2120 /*
2121 * Get the tunnel device flow information (discover the output path of the tunnel)
2122 */
2123 tunnel = (struct ip6_tnl *)netdev_priv(dev);
2124 fl6 = &tunnel->fl.u.ip6;
2125
2126 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.saddr, fl6->saddr);
2127 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.daddr, fl6->daddr);
2128 type_info.tunipip6.hop_limit = tunnel->parms.hop_limit;
2129 type_info.tunipip6.flags = ntohl(tunnel->parms.flags);
2130 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 +05302131
Murat Sezgin91c5d712015-06-12 15:16:22 -07002132 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 +00002133 return ii;
2134 }
Murat Sezginc1402562015-03-12 12:32:20 -07002135#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00002136#endif
2137
Ben Menchaca84f36632014-02-28 20:57:38 +00002138 /*
2139 * If this is NOT PPP then it is unknown to the ecm
2140 */
2141 if (dev_type != ARPHRD_PPP) {
2142 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dev, dev_type);
2143 type_info.unknown.os_specific_ident = dev_interface_num;
2144
2145 /*
2146 * Establish this type of interface
2147 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002148 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 +00002149 return ii;
2150 }
2151
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08002152#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002153 /*
ratheesh kannothf4801a02016-12-09 22:46:39 +05302154 * PPP Support is NOT provided for.
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002155 * Interface is therefore unknown
2156 */
2157 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dev, dev_type);
2158 type_info.unknown.os_specific_ident = dev_interface_num;
2159
2160 /*
2161 * Establish this type of interface
2162 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002163 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 +01002164 return ii;
2165#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302166
2167#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2168 /*
2169 * ppp_xmit lock is held by linux kernel for l2tp packet in transmit
2170 * direction. we need to check for l2tp packet and avoid calls to
2171 * ppp_is_multilink() and ppp_hold_channels() which acquire same lock
2172 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05302173
2174 if ((dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(dev)) {
Murat Sezgindb0c5d82017-02-22 11:43:03 -08002175 if (skb && (skb->skb_iif == dev->ifindex)) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302176 struct pppol2tp_common_addr info;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302177
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302178 if (__ppp_is_multilink(dev) > 0) {
2179 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
2180 type_info.unknown.os_specific_ident = dev_interface_num;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302181
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302182 /*
2183 * Establish this type of interface
2184 */
2185 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2186 return ii;
2187 }
2188 channel_count = __ppp_hold_channels(dev, ppp_chan, 1);
2189 if (channel_count != 1) {
2190 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
2191 dev, channel_count);
2192 type_info.unknown.os_specific_ident = dev_interface_num;
2193
2194 /*
2195 * Establish this type of interface
2196 */
2197 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2198 return ii;
2199 }
2200
2201 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
2202 ppp_release_channels(ppp_chan, 1);
ratheesh kannothed721852015-09-28 12:39:52 +05302203 return NULL;
2204 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302205
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302206 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = info.local_tunnel_id;
2207 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = info.remote_tunnel_id;
2208 type_info.pppol2tpv2.l2tp.session.session_id = info.local_session_id;
2209 type_info.pppol2tpv2.l2tp.session.peer_session_id = info.remote_session_id;
2210 type_info.pppol2tpv2.udp.sport = ntohs(info.local_addr.sin_port);
2211 type_info.pppol2tpv2.udp.dport = ntohs(info.remote_addr.sin_port);
2212 type_info.pppol2tpv2.ip.saddr = ntohl(info.local_addr.sin_addr.s_addr);
2213 type_info.pppol2tpv2.ip.daddr = ntohl(info.remote_addr.sin_addr.s_addr);
ratheesh kannothed721852015-09-28 12:39:52 +05302214
2215 /*
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302216 * Release the channel. Note that next_dev is still (correctly) held.
ratheesh kannothed721852015-09-28 12:39:52 +05302217 */
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302218 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302219
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302220 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 +05302221
2222 /*
2223 * Establish this type of interface
2224 */
2225 ii = ecm_interface_pppol2tpv2_interface_establish(&type_info.pppol2tpv2, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2226 return ii;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302227 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302228 }
2229#endif
2230
Shyam Sunder23f2e542015-09-28 14:56:49 +05302231#ifdef ECM_INTERFACE_PPTP_ENABLE
2232 if ((protocol == IPPROTO_GRE) && skb && v4_hdr) {
2233 struct gre_hdr_pptp *gre_hdr;
2234 uint16_t proto;
2235 int ret;
2236
2237 skb_pull(skb, sizeof(struct iphdr));
2238 gre_hdr = (struct gre_hdr_pptp *)(skb->data);
2239 proto = ntohs(gre_hdr->protocol);
2240 if ((gre_hdr->version == GRE_VERSION_PPTP) && (proto == GRE_PROTOCOL_PPTP)) {
2241 ret = pptp_session_find(&opt, gre_hdr->call_id, v4_hdr->daddr);
2242 if (ret < 0) {
2243 skb_push(skb, sizeof(struct iphdr));
2244 DEBUG_WARN("PPTP session info not found\n");
2245 return NULL;
2246 }
2247
2248 /*
2249 * Get PPTP session info
2250 */
2251 type_info.pptp.src_call_id = ntohs(opt.src_addr.call_id);
2252 type_info.pptp.dst_call_id = ntohs(opt.dst_addr.call_id);
2253 type_info.pptp.src_ip = ntohl(opt.src_addr.sin_addr.s_addr);
2254 type_info.pptp.dst_ip = ntohl(opt.dst_addr.sin_addr.s_addr);
2255
2256 skb_push(skb, sizeof(struct iphdr));
2257
2258 /*
2259 * Establish this type of interface
2260 */
2261 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 +05302262 if (ii) {
2263 /*
2264 * The ifindex of a virtual netdevice like a PPTP session can change if it is destroyed
2265 * and comes up again. Detect if the ifindex has changed and update it if required
2266 */
2267 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2268 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05302269 return ii;
2270 }
2271
2272 skb_push(skb, sizeof(struct iphdr));
2273
2274 DEBUG_TRACE("Unknown GRE protocol \n");
2275 type_info.unknown.os_specific_ident = dev_interface_num;
2276
2277 /*
2278 * Establish this type of interface
2279 */
2280 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2281 return ii;
2282 }
2283#endif
2284
Ben Menchaca84f36632014-02-28 20:57:38 +00002285 /*
2286 * PPP - but what is the channel type?
2287 * First: If this is multi-link then we do not support it
2288 */
2289 if (ppp_is_multilink(dev) > 0) {
2290 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
2291 type_info.unknown.os_specific_ident = dev_interface_num;
2292
2293 /*
2294 * Establish this type of interface
2295 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002296 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 +00002297 return ii;
2298 }
2299
2300 DEBUG_TRACE("Net device: %p is PPP\n", dev);
2301
2302 /*
2303 * Get the PPP channel and then enquire what kind of channel it is
2304 * NOTE: Not multilink so only one channel to get.
2305 */
2306 channel_count = ppp_hold_channels(dev, ppp_chan, 1);
2307 if (channel_count != 1) {
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002308 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
2309 dev, channel_count);
Ben Menchaca84f36632014-02-28 20:57:38 +00002310 type_info.unknown.os_specific_ident = dev_interface_num;
2311
2312 /*
2313 * Establish this type of interface
2314 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002315 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 +00002316 return ii;
2317 }
2318
2319 /*
2320 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002321 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00002322 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002323 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302324
2325#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2326 if (channel_protocol == PX_PROTO_OL2TP) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302327 struct pppol2tp_common_addr info;
Ben Menchaca84f36632014-02-28 20:57:38 +00002328
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302329 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302330 ppp_release_channels(ppp_chan, 1);
2331 return NULL;
2332 }
2333
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302334 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = info.local_tunnel_id;
2335 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = info.remote_tunnel_id;
2336 type_info.pppol2tpv2.l2tp.session.session_id = info.local_session_id;
2337 type_info.pppol2tpv2.l2tp.session.peer_session_id = info.remote_session_id;
2338 type_info.pppol2tpv2.udp.sport = ntohs(info.local_addr.sin_port);
2339 type_info.pppol2tpv2.udp.dport = ntohs(info.remote_addr.sin_port);
2340 type_info.pppol2tpv2.ip.saddr = ntohl(info.local_addr.sin_addr.s_addr);
2341 type_info.pppol2tpv2.ip.daddr = ntohl(info.remote_addr.sin_addr.s_addr);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302342
2343 /*
2344 * Release the channel. Note that next_dev is still (correctly) held.
Ben Menchaca84f36632014-02-28 20:57:38 +00002345 */
2346 ppp_release_channels(ppp_chan, 1);
2347
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302348 DEBUG_TRACE("Net device: %p PPPo2L2TP session: %d,n", dev, type_info.pppol2tpv2.l2tp.session.peer_session_id);
2349
Ben Menchaca84f36632014-02-28 20:57:38 +00002350 /*
2351 * Establish this type of interface
2352 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302353 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 +00002354 return ii;
2355 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302356#endif
2357#ifdef ECM_INTERFACE_PPPOE_ENABLE
2358 if (channel_protocol == PX_PROTO_OE) {
2359
2360 /*
2361 * PPPoE channel
2362 */
2363 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dev);
2364
2365 /*
2366 * Get PPPoE session information and the underlying device it is using.
2367 */
2368 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2369 type_info.pppoe.pppoe_session_id = (uint16_t)ntohs((uint16_t)addressing.pa.sid);
2370 memcpy(type_info.pppoe.remote_mac, addressing.pa.remote, ETH_ALEN);
2371 dev_put(addressing.dev);
2372
2373 /*
2374 * Release the channel. Note that next_dev is still (correctly) held.
2375 */
2376 ppp_release_channels(ppp_chan, 1);
2377
2378 DEBUG_TRACE("Net device: %p PPPoE session: %x, remote mac: %pM\n",
2379 dev, type_info.pppoe.pppoe_session_id, type_info.pppoe.remote_mac);
2380
2381 /*
2382 * Establish this type of interface
2383 */
2384 ii = ecm_interface_pppoe_interface_establish(&type_info.pppoe, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2385 return ii;
2386 }
2387#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05302388
2389#ifdef ECM_INTERFACE_PPTP_ENABLE
2390 if (channel_protocol == PX_PROTO_PPTP) {
2391 pptp_channel_addressing_get(&opt, ppp_chan[0]);
2392
2393 /*
2394 * Get PPTP session info
2395 */
2396 type_info.pptp.src_call_id = ntohs(opt.src_addr.call_id);
2397 type_info.pptp.dst_call_id = ntohs(opt.dst_addr.call_id);
2398 type_info.pptp.src_ip = ntohl(opt.src_addr.sin_addr.s_addr);
2399 type_info.pptp.dst_ip = ntohl(opt.dst_addr.sin_addr.s_addr);
2400
2401 DEBUG_TRACE("Net device: %p PPTP source call id: %d,n", dev, type_info.pptp.src_call_id);
2402 ppp_release_channels(ppp_chan, 1);
2403
2404 /*
2405 * Establish this type of interface
2406 */
2407 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 +05302408 if (ii) {
2409 /*
2410 * The ifindex of a virtual netdevice like a PPTP session can change if it is destroyed
2411 * and comes up again. Detect if the ifindex has changed and update it if required
2412 */
2413 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2414 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05302415 return ii;
2416 }
2417#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302418 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n", dev, channel_protocol);
2419 type_info.unknown.os_specific_ident = dev_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00002420
2421 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302422 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00002423 */
2424 ppp_release_channels(ppp_chan, 1);
2425
Ben Menchaca84f36632014-02-28 20:57:38 +00002426 /*
2427 * Establish this type of interface
2428 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302429 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 +00002430 return ii;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002431#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002432}
2433EXPORT_SYMBOL(ecm_interface_establish_and_ref);
2434
Shyam Sunder6358b862015-05-04 15:06:24 +05302435#ifdef ECM_MULTICAST_ENABLE
2436/*
2437 * ecm_interface_multicast_heirarchy_construct_single()
2438 * Create and return an interface heirarchy for a single interface for a multicast connection
2439 *
2440 * src_addr IP source address
2441 * dest_addr IP Destination address/Group Address
2442 * interface Pointer to a single multicast interface heirarchy
2443 * given_dest_dev Netdev pointer for destination interface
2444 * br_slave_dev Netdev pointer to a bridge slave device. It could be NULL in case of pure
2445 * routed flow without any bridge interface in destination dev list.
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302446 * skb sk_buff
Shyam Sunder6358b862015-05-04 15:06:24 +05302447 */
Shyam Sunder81836832015-07-09 19:18:25 +05302448static uint32_t ecm_interface_multicast_heirarchy_construct_single(struct ecm_front_end_connection_instance *feci, ip_addr_t src_addr,
2449 ip_addr_t dest_addr, struct ecm_db_iface_instance *interface,
2450 struct net_device *given_dest_dev, struct net_device *br_slave_dev,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302451 uint8_t *src_node_addr, bool is_routed, __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302452{
2453 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2454 struct ecm_db_iface_instance **ifaces;
2455 struct ecm_db_iface_instance *ii_temp;
2456 struct net_device *dest_dev;
2457 int32_t current_interface_index;
2458 int32_t interfaces_cnt = 0;
2459 int32_t dest_dev_type;
2460
2461 dest_dev = given_dest_dev;
2462 dev_hold(dest_dev);
2463 dest_dev_type = dest_dev->type;
2464 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
2465
2466 while (current_interface_index > 0) {
2467 struct ecm_db_iface_instance *ii;
2468 struct net_device *next_dev;
2469
2470 /*
2471 * Get the ecm db interface instance for the device at hand
2472 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302473 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Shyam Sunder6358b862015-05-04 15:06:24 +05302474 interfaces_cnt++;
2475
2476 /*
2477 * If the interface could not be established then we abort
2478 */
2479 if (!ii) {
2480 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev->name);
2481 dev_put(dest_dev);
2482
2483 /*
2484 * Release the interfaces heirarchy we constructed to this point.
2485 */
2486 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2487 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2488 return ECM_DB_IFACE_HEIRARCHY_MAX;
2489 }
2490
2491 /*
2492 * Record the interface instance into the *ifaces
2493 */
2494 current_interface_index--;
2495 ii_temp = ecm_db_multicast_if_instance_get_at_index(interface, current_interface_index);
2496 ifaces = (struct ecm_db_iface_instance **)ii_temp;
2497 *ifaces = ii;
2498
2499 /*
2500 * Now we have to figure out what the next device will be (in the transmission path)
2501 */
2502 do {
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302503#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302504 int channel_count;
2505 struct ppp_channel *ppp_chan[1];
2506 int channel_protocol;
2507 struct pppoe_opt addressing;
2508#endif
2509 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev->name);
2510 next_dev = NULL;
2511
2512 if (dest_dev_type == ARPHRD_ETHER) {
2513 /*
2514 * Ethernet - but what sub type?
2515 */
2516
2517 /*
2518 * VLAN?
2519 */
2520 if (is_vlan_dev(dest_dev)) {
2521 /*
2522 * VLAN master
2523 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
2524 */
Shyam Sunder9db20852016-03-09 19:04:49 +05302525 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Shyam Sunder6358b862015-05-04 15:06:24 +05302526 dev_hold(next_dev);
2527 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
2528 dest_dev, next_dev, next_dev->name);
2529 break;
2530 }
2531
2532 /*
2533 * BRIDGE?
2534 */
2535 if (ecm_front_end_is_bridge_device(dest_dev)) {
2536 if (!ecm_front_end_is_bridge_port(br_slave_dev)) {
2537 DEBUG_ASSERT(NULL, "%p: expected only bridge slave here\n", interface);
2538
2539 /*
2540 * Release the interfaces heirarchy we constructed to this point.
2541 */
2542 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2543 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2544 dev_put(dest_dev);
2545 return ECM_DB_IFACE_HEIRARCHY_MAX;
2546 }
2547
2548 next_dev = br_slave_dev;
2549 if (!next_dev) {
2550 DEBUG_WARN("Unable to obtain output port \n");
2551
2552 /*
2553 * Release the interfaces heirarchy we constructed to this point.
2554 */
2555 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2556 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2557 dev_put(dest_dev);
2558 return ECM_DB_IFACE_HEIRARCHY_MAX;
2559 }
2560 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2561 dev_hold(next_dev);
2562 break;
2563 }
2564
Shyam Sunder81836832015-07-09 19:18:25 +05302565#ifdef ECM_INTERFACE_BOND_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302566 /*
2567 * LAG?
2568 */
2569 if (ecm_front_end_is_lag_master(dest_dev)) {
2570 /*
2571 * Link aggregation
2572 * Figure out which slave device of the link aggregation will be used to reach the destination.
2573 */
2574 uint32_t src_addr_32 = 0;
2575 uint32_t dest_addr_32 = 0;
Suman Ghoshf14d2172015-07-31 14:38:10 +05302576 struct in6_addr src_addr6;
2577 struct in6_addr dest_addr6;
Shyam Sunder6358b862015-05-04 15:06:24 +05302578 uint8_t src_mac_addr[ETH_ALEN];
2579 uint8_t dest_mac_addr[ETH_ALEN];
2580
2581 memset(src_mac_addr, 0, ETH_ALEN);
2582 memset(dest_mac_addr, 0, ETH_ALEN);
2583
Shyam Sunder81836832015-07-09 19:18:25 +05302584 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2585 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
2586 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
2587 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302588
Shyam Sunder81836832015-07-09 19:18:25 +05302589 if (!is_routed) {
2590 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
Shyam Sunder6358b862015-05-04 15:06:24 +05302591 } else {
Shyam Sunder81836832015-07-09 19:18:25 +05302592 struct net_device *dest_dev_master;
2593
2594 /*
2595 * Use appropriate source MAC address for routed packets
2596 */
2597 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
2598 if (dest_dev_master) {
2599 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
2600 dev_put(dest_dev_master);
2601 } else {
2602 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
2603 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302604 }
2605
2606 /*
2607 * Create Destination MAC address using IP multicast destination address
2608 */
2609 ecm_translate_multicast_mac(dest_addr, dest_mac_addr);
2610
Shyam Sunder81836832015-07-09 19:18:25 +05302611 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2612 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
2613 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302614 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302615 } else {
Suman Ghoshf14d2172015-07-31 14:38:10 +05302616 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
2617 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, dest_addr);
Shyam Sunder81836832015-07-09 19:18:25 +05302618 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
Suman Ghoshf14d2172015-07-31 14:38:10 +05302619 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05302620 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302621 }
2622
Shyam Sunder6358b862015-05-04 15:06:24 +05302623 if (!(next_dev && netif_carrier_ok(next_dev))) {
2624 DEBUG_WARN("Unable to obtain LAG output slave device\n");
2625 dev_put(dest_dev);
2626
2627 /*
2628 * Release the interfaces heirarchy we constructed to this point.
2629 */
2630 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2631 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2632 return ECM_DB_IFACE_HEIRARCHY_MAX;
2633 }
2634
2635 dev_hold(next_dev);
2636 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2637 break;
2638 }
2639#endif
2640
2641 /*
2642 * ETHERNET!
2643 * Just plain ethernet it seems.
2644 */
2645 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
2646 break;
2647 }
2648
2649 /*
2650 * LOOPBACK?
2651 */
2652 if (dest_dev_type == ARPHRD_LOOPBACK) {
2653 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
2654 break;
2655 }
2656
2657 /*
2658 * IPSEC?
2659 */
2660 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2661 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
2662 /*
2663 * TODO Figure out the next device the tunnel is using...
2664 */
2665 break;
2666 }
2667
2668 /*
2669 * SIT (6-in-4)?
2670 */
2671 if (dest_dev_type == ARPHRD_SIT) {
2672 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
2673 /*
2674 * TODO Figure out the next device the tunnel is using...
2675 */
2676 break;
2677 }
2678
2679 /*
2680 * IPIP6 Tunnel?
2681 */
2682 if (dest_dev_type == ARPHRD_TUNNEL6) {
2683 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
2684 /*
2685 * TODO Figure out the next device the tunnel is using...
2686 */
2687 break;
2688 }
2689
2690 /*
2691 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
2692 */
2693 if (dest_dev_type != ARPHRD_PPP) {
2694 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
2695 break;
2696 }
2697
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302698#ifndef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302699 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
2700#else
2701 /*
2702 * PPP - but what is the channel type?
2703 * First: If this is multi-link then we do not support it
2704 */
2705 if (ppp_is_multilink(dest_dev) > 0) {
2706 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
2707 break;
2708 }
2709
2710 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
2711
2712 /*
2713 * Get the PPP channel and then enquire what kind of channel it is
2714 * NOTE: Not multilink so only one channel to get.
2715 */
2716 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
2717 if (channel_count != 1) {
2718 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
2719 dest_dev, channel_count);
2720 break;
2721 }
2722
2723 /*
2724 * Get channel protocol type
2725 * NOTE: Not all PPP channels support channel specific methods.
2726 */
2727 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
2728 if (channel_protocol != PX_PROTO_OE) {
2729 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
2730 dest_dev, channel_protocol);
2731
2732 /*
2733 * Release the channel
2734 */
2735 ppp_release_channels(ppp_chan, 1);
2736
2737 break;
2738 }
2739
2740 /*
2741 * PPPoE channel
2742 */
2743 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
2744
2745 /*
2746 * Get PPPoE session information and the underlying device it is using.
2747 */
2748 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2749
2750 /*
2751 * Copy the dev hold into this, we will release the hold later
2752 */
2753 next_dev = addressing.dev;
2754
Shyam Sunder6358b862015-05-04 15:06:24 +05302755 /*
2756 * Release the channel. Note that next_dev is still (correctly) held.
2757 */
2758 ppp_release_channels(ppp_chan, 1);
2759#endif
2760 } while (false);
2761
2762 /*
2763 * No longer need dest_dev as it may become next_dev
2764 */
2765 dev_put(dest_dev);
2766
2767 /*
2768 * Check out the next_dev, if any
2769 */
2770 if (!next_dev) {
2771 int32_t i __attribute__((unused));
2772 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
2773#if DEBUG_LEVEL > 1
2774 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2775 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
2776 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n", \
2777 i, to_list_single[i], ecm_db_connection_iface_type_get(to_list_single[i]), \
2778 ecm_db_interface_type_to_string(ecm_db_connection_iface_type_get(to_list_single[i])));
2779 }
2780#endif
2781 return current_interface_index;
2782 }
2783
2784 /*
2785 * dest_dev becomes next_dev
2786 */
2787 dest_dev = next_dev;
2788 dest_dev_type = dest_dev->type;
2789 }
2790
2791 dev_put(dest_dev);
2792
2793 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2794 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2795 return ECM_DB_IFACE_HEIRARCHY_MAX;
2796}
2797
2798/*
2799 * ecm_interface_multicast_heirarchy_construct_routed()
2800 * Create destination interface heirarchy for a routed multicast connectiona
2801 *
2802 * interfaces Pointer to the 2-D array of multicast interface heirarchies
2803 * in_dev Pointer to the source netdev
2804 * packet_src_addr Source IP of the multicast flow
2805 * packet_dest_addr Group(dest) IP of the multicast flow
2806 * max_dst Maximum number of netdev joined the multicast group
2807 * dst_if_index_base An array of if index joined the multicast group
2808 * interface_first_base An array of the index of the first interface in the list
2809 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002810int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_connection_instance *feci,
2811 struct ecm_db_iface_instance *interfaces,
2812 struct net_device *in_dev,
2813 ip_addr_t packet_src_addr,
2814 ip_addr_t packet_dest_addr, uint8_t max_if,
2815 uint32_t *dst_if_index_base,
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302816 uint32_t *interface_first_base, bool mfc_update,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302817 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302818{
2819 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2820 struct ecm_db_iface_instance *ifaces;
2821 struct net_device *dest_dev = NULL;
2822 struct net_device *br_dev_src = NULL;
2823 uint32_t *dst_if_index;
2824 uint32_t *interface_first;
2825 uint32_t br_if;
2826 uint32_t valid_if;
Shyam Sunder41637872015-06-11 21:19:05 +05302827 int32_t if_num;
Shyam Sunder6358b862015-05-04 15:06:24 +05302828 int32_t dest_dev_type;
2829 int if_index;
2830 int ii_cnt;
2831 int total_ii_count = 0;
2832 bool src_dev_is_bridge = false;
2833
2834 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",
2835 ECM_IP_ADDR_TO_DOT(packet_dest_addr), ECM_IP_ADDR_TO_DOT(packet_src_addr), max_if);
2836
2837 /*
2838 * Check if the source net_dev is a bridge slave.
2839 */
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302840 if (in_dev && !mfc_update) {
Shyam Sunder6358b862015-05-04 15:06:24 +05302841 if (ecm_front_end_is_bridge_port(in_dev)) {
2842 src_dev_is_bridge = true;
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302843 br_dev_src = ecm_interface_get_and_hold_dev_master(in_dev);
2844 DEBUG_ASSERT(br_dev_src, "Expected a master\n");
Shyam Sunder6358b862015-05-04 15:06:24 +05302845
2846 /*
2847 * The source net_dev found as bridge slave. In case of routed interface
2848 * heirarchy MFC is not aware of any other bridge slave has joined the same
2849 * multicast group as a destination interface. Therfore we assume there
2850 * are bridge slaves present in multicast destination interface list
2851 * and increase the max_if by one.
2852 */
2853 max_if++;
2854 }
2855 }
2856
2857 ii_cnt = 0;
2858 br_if = if_num = 0;
2859
2860 /*
2861 * This loop is for creating the destination interface hierarchy list.
2862 * We take the destination interface array we got from MFC (in form of ifindex array)
2863 * as input for this.
2864 */
2865 for (if_index = 0, valid_if = 0; if_index < max_if; if_index++) {
2866 dst_if_index = ecm_db_multicast_if_first_get_at_index(dst_if_index_base, if_index);
2867
2868 if (*dst_if_index == ECM_INTERFACE_LOOPBACK_DEV_INDEX) {
2869 continue;
2870 }
2871
2872 dest_dev = dev_get_by_index(&init_net, *dst_if_index);
2873 if (!dest_dev) {
2874 if (!src_dev_is_bridge) {
2875 int i;
2876
2877 /*
2878 * If already constructed any interface heirarchies before hitting
2879 * this error condition then Deref all interface heirarchies.
2880 */
2881 if (valid_if > 0) {
2882 for (i = 0; i < valid_if; i++) {
2883 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2884 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2885 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2886 }
2887 }
2888
2889 /*
2890 * If valid netdev not found, Return 0
2891 */
2892 return 0;
2893 }
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302894
Shyam Sunder6358b862015-05-04 15:06:24 +05302895 dest_dev = br_dev_src;
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302896
Shyam Sunder6358b862015-05-04 15:06:24 +05302897 }
2898
2899 dest_dev_type = dest_dev->type;
2900
2901 if (ecm_front_end_is_bridge_device(dest_dev)) {
2902 struct net_device *mc_br_slave_dev = NULL;
2903 uint32_t mc_max_dst = ECM_DB_MULTICAST_IF_MAX;
2904 uint32_t mc_dst_if_index[ECM_DB_MULTICAST_IF_MAX];
2905
2906 if (ECM_IP_ADDR_IS_V4(packet_src_addr)) {
2907 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);
2908 } else {
2909 struct in6_addr origin6;
2910 struct in6_addr group6;
2911 ECM_IP_ADDR_TO_NIN6_ADDR(origin6, packet_src_addr);
2912 ECM_IP_ADDR_TO_NIN6_ADDR(group6, packet_dest_addr);
2913 if_num = mc_bridge_ipv6_get_if(dest_dev, &origin6, &group6, mc_max_dst, mc_dst_if_index);
2914 }
2915
Shyam Sunder81836832015-07-09 19:18:25 +05302916 if ((if_num < 0) || (if_num > ECM_DB_MULTICAST_IF_MAX)) {
2917 int i;
2918 DEBUG_WARN("MCS is not ready\n");
2919
2920 /*
2921 * If already constructed any interface heirarchies before hitting
2922 * this error condition then Deref all interface heirarchies.
2923 */
2924 if (valid_if > 0) {
2925 for (i = 0; i < valid_if; i++) {
2926 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2927 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2928 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2929 }
2930 }
2931
Shyam Sunder41637872015-06-11 21:19:05 +05302932 dev_put(dest_dev);
2933 return 0;
2934 }
2935
Shyam Sundera450b582016-07-22 14:44:14 +05302936 if (in_dev && !mfc_update) {
Shyam Sunder06588292016-04-18 19:57:39 +05302937 if_num = ecm_interface_multicast_check_for_src_ifindex(mc_dst_if_index, if_num, in_dev->ifindex);
2938 }
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302939
Shyam Sunder6358b862015-05-04 15:06:24 +05302940 for (br_if = 0; br_if < if_num; br_if++) {
2941 mc_br_slave_dev = dev_get_by_index(&init_net, mc_dst_if_index[br_if]);
2942 if (!mc_br_slave_dev) {
2943 continue;
2944 }
2945
2946 if ((valid_if + br_if) > ECM_DB_MULTICAST_IF_MAX) {
2947 int i;
2948
2949 /*
2950 * If already constructed any interface heirarchies before hitting
2951 * this error condition then Deref all interface heirarchies.
2952 */
2953 for (i = 0; i < (valid_if + br_if); i++) {
2954 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2955 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2956 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2957 }
2958
2959 dev_put(dest_dev);
2960 dev_put(mc_br_slave_dev);
2961 return 0;
2962 }
2963
2964 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if + br_if);
2965 /*
2966 * Construct a single interface heirarchy of a multicast dev.
2967 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302968 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 +05302969 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
2970
2971 /*
2972 * If already constructed any interface heirarchies before hitting
2973 * this error condition then Deref all interface heirarchies.
2974 */
2975 if ((valid_if + br_if) > 0) {
2976 int i;
2977 for (i = 0; i < (valid_if + br_if); i++) {
2978 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2979 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2980 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2981 }
2982 }
2983
2984 dev_put(dest_dev);
2985 dev_put(mc_br_slave_dev);
2986 return 0;
2987 }
2988
2989 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, (valid_if + br_if));
2990 *interface_first = ii_cnt;
2991 total_ii_count += ii_cnt;
2992 dev_put(mc_br_slave_dev);
2993 }
2994
2995 valid_if += br_if;
2996
2997 } else {
2998
2999 DEBUG_ASSERT(valid_if < ECM_DB_MULTICAST_IF_MAX, "Bad array index size %d\n", valid_if);
3000 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
3001 /*
3002 * Construct a single interface heirarchy of a multicast dev.
3003 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303004 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 +05303005 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3006
3007 /*
3008 * If already constructed any interface heirarchies before hitting
3009 * this error condition then Deref all interface heirarchies.
3010 */
3011 if (valid_if > 0) {
3012 int i;
3013 for (i = 0; i < valid_if; i++) {
3014 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3015 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3016 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3017 }
3018 }
3019
3020 dev_put(dest_dev);
3021 return 0;
3022 }
3023
3024 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
3025 *interface_first = ii_cnt;
3026 total_ii_count += ii_cnt;
3027 valid_if++;
3028 }
3029
3030 dev_put(dest_dev);
3031 }
3032 return total_ii_count;
3033}
3034EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed);
3035
3036/*
3037 * ecm_interface_multicast_heirarchy_construct_bridged()
3038 * This function called when the Hyfi bridge snooper has IGMP/IMLD updates, this function
3039 * creates destination interface heirarchy for a bridged multicast connection.
3040 *
3041 * interfaces Pointer to the 2-D array of multicast interface heirarchies
3042 * dest_dev Pointer to the destination dev, here dest_dev is always a bridge type
3043 * packet_src_addr Source IP of the multicast flow
3044 * packet_dest_addr Group(dest) IP of the multicast flow
3045 * mc_max_dst Maximum number of bridge slaves joined the multicast group
3046 * mc_dst_if_index_base An array of if index joined the multicast group
3047 * interface_first_base An array of the index of the first interface in the list
3048 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003049int32_t ecm_interface_multicast_heirarchy_construct_bridged(struct ecm_front_end_connection_instance *feci,
Shyam Sunder81836832015-07-09 19:18:25 +05303050 struct ecm_db_iface_instance *interfaces, struct net_device *dest_dev,
3051 ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, uint8_t mc_max_dst,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05303052 int *mc_dst_if_index_base, uint32_t *interface_first_base, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303053 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05303054{
3055 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
3056 struct ecm_db_iface_instance *ifaces;
3057 struct net_device *mc_br_slave_dev = NULL;
3058 uint32_t *interface_first;
3059 int *mc_dst_if_index;
3060 int valid_if;
3061 int ii_cnt = 0;
3062 int br_if;
3063 int total_ii_cnt = 0;
3064
3065 /*
3066 * Go through the newly joined interface index one by one and
3067 * create an interface heirarchy for each valid interface.
3068 */
3069 for (br_if = 0, valid_if = 0; br_if < mc_max_dst; br_if++) {
3070 mc_dst_if_index = (int *)ecm_db_multicast_if_num_get_at_index(mc_dst_if_index_base, br_if);
3071 mc_br_slave_dev = dev_get_by_index(&init_net, *mc_dst_if_index);
3072 if (!mc_br_slave_dev) {
3073
3074 /*
3075 * If already constructed any interface heirarchies before hitting
3076 * this error condition then Deref all interface heirarchies.
3077 */
3078 if (valid_if > 0) {
3079 int i;
3080 for (i = 0; i < valid_if; i++) {
3081 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3082 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3083 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3084 }
3085 }
3086
3087 /*
3088 * If valid netdev not found, Return 0
3089 */
3090 return 0;
3091 }
3092
3093 if (valid_if > ECM_DB_MULTICAST_IF_MAX) {
3094 int i;
3095
3096 /*
3097 * If already constructed any interface heirarchies before hitting
3098 * this error condition then Deref all interface heirarchies.
3099 */
3100 for (i = 0; i < valid_if; i++) {
3101 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3102 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3103 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3104 }
3105
3106 dev_put(mc_br_slave_dev);
3107 return 0;
3108 }
3109
3110 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
3111
3112 /*
3113 * Construct a single interface heirarchy of a multicast dev.
3114 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303115 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 +05303116 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3117
3118 /*
3119 * If already constructed any interface heirarchies before hitting
3120 * this error condition then Deref all interface heirarchies.
3121 */
3122 if (valid_if > 0) {
3123 int i;
3124 for (i = 0; i < valid_if; i++) {
3125 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3126 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3127 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3128 }
3129 }
3130
3131 dev_put(mc_br_slave_dev);
3132 return 0;
3133 }
3134
3135 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
3136 *interface_first = ii_cnt;
3137 total_ii_cnt += ii_cnt;
3138 valid_if++;
3139 dev_put(mc_br_slave_dev);
3140 }
3141
Shyam Sunder280b34a2016-06-22 19:30:22 +05303142 return valid_if;
Shyam Sunder6358b862015-05-04 15:06:24 +05303143}
3144EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_bridged);
Shyam Sunder6358b862015-05-04 15:06:24 +05303145
Ben Menchaca84f36632014-02-28 20:57:38 +00003146/*
Murat Sezgin5dae8832015-12-03 14:23:19 -08003147 * ecm_interface_multicast_get_next_node_mac_address()
3148 * Get the MAC address of the next node for multicast flows
3149 *
3150 * TODO: This function will be removed when the multicast flow code
3151 * is fixed to use the new interface hierarchy construction model.
3152 *
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003153 */
Murat Sezgin5dae8832015-12-03 14:23:19 -08003154static bool ecm_interface_multicast_get_next_node_mac_address(
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003155 ip_addr_t dest_addr, struct net_device *dest_dev, int ip_version,
3156 uint8_t *mac_addr)
3157{
3158 bool on_link;
3159 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3160
3161 if (!ecm_interface_mac_addr_get(dest_addr, mac_addr, &on_link, gw_addr)) {
3162 if (ip_version == 4) {
3163 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n",
3164 ECM_IP_ADDR_TO_DOT(dest_addr));
3165 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
3166 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003167#ifdef ECM_IPV6_ENABLE
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003168 if (ip_version == 6) {
3169 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n",
3170 ECM_IP_ADDR_TO_OCTAL(dest_addr));
3171 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
3172 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003173#endif
3174 return false;
3175 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003176
Murat Sezgin5dae8832015-12-03 14:23:19 -08003177 return true;
3178}
Murat Sezgin8f70b312016-02-02 23:33:10 -08003179#endif
Murat Sezgin5dae8832015-12-03 14:23:19 -08003180
3181/*
3182 * ecm_interface_get_next_node_mac_address()
3183 * Get the MAC address of the next node
3184 */
3185static bool ecm_interface_get_next_node_mac_address(
3186 ip_addr_t dest_addr, struct net_device *dest_dev, int ip_version,
3187 uint8_t *mac_addr)
3188{
3189 if (!ecm_interface_mac_addr_get_no_route(dest_dev, dest_addr, mac_addr)) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003190 /*
3191 * MAC address look up failed. The host IP address may not be in the
3192 * neighbour table. So, let's send an ARP or neighbour solicitation
3193 * request to this host IP address, so in the subsequent lookups it can be
3194 * found.
3195 */
Murat Sezgin5dae8832015-12-03 14:23:19 -08003196 if (ip_version == 4) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003197 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3198 bool on_link = true;
3199
3200 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT " send ARP request\n",
Murat Sezgin5dae8832015-12-03 14:23:19 -08003201 ECM_IP_ADDR_TO_DOT(dest_addr));
Murat Sezgin00627c12016-02-05 16:53:21 -08003202
3203 if (ecm_interface_find_gateway(dest_addr, gw_addr)) {
3204 on_link = false;
3205 }
Shyam Sunder9ac555d2016-09-16 17:58:15 +05303206
3207 if (ecm_interface_mac_addr_get_no_route(dest_dev, gw_addr, mac_addr)) {
3208 DEBUG_TRACE("Found the mac address for gateway\n");
3209 return true;
3210 }
3211
Murat Sezgin00627c12016-02-05 16:53:21 -08003212 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003213 }
3214#ifdef ECM_IPV6_ENABLE
3215 if (ip_version == 6) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003216 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 -08003217 ECM_IP_ADDR_TO_OCTAL(dest_addr));
Murat Sezgin00627c12016-02-05 16:53:21 -08003218 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003219 }
3220#endif
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003221 return false;
3222 }
3223
3224 return true;
3225}
3226
3227/*
3228 * ecm_interface_should_update_egress_device_bridged()
3229 * Determine if the egress port should be re-evaluated in the bridged case
3230 *
3231 * This will be done if:
3232 * - The egress port is the one provided from the front-end
3233 * - The egress port is not a bridge, but is a slave of the bridge
3234 * - Not routed
3235 *
3236 * If these conditions hold, this function will hold a reference to the bridge
3237 * port and return it to the caller. Otherwise no reference will be held and
3238 * it will return NULL.
3239 */
3240static struct net_device *ecm_interface_should_update_egress_device_bridged(
3241 struct net_device *given_dest_dev, struct net_device *dest_dev,
3242 bool is_routed)
3243{
3244 struct net_device *bridge;
3245
3246 /*
3247 * Determine if we should attempt to fetch the bridge device
3248 */
3249 if (!given_dest_dev || is_routed || (dest_dev != given_dest_dev) ||
3250 ecm_front_end_is_bridge_device(given_dest_dev))
3251 return NULL;
3252
3253 bridge = ecm_interface_get_and_hold_dev_master(given_dest_dev);
3254
3255 if (!bridge)
3256 return NULL;
3257
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003258 if (!ecm_front_end_is_bridge_device(bridge)) {
3259 /*
3260 * Master is not a bridge - free the reference and return
3261 */
3262 dev_put(bridge);
3263 return NULL;
3264 }
3265
3266 /*
3267 * Reference is held to bridge and must be freed by caller
3268 */
3269 return bridge;
3270}
3271
3272/*
Ben Menchaca84f36632014-02-28 20:57:38 +00003273 * ecm_interface_heirarchy_construct()
3274 * Construct an interface heirarchy.
3275 *
3276 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
3277 * This is the heirarchy of interfaces a packet would transit to emit from the device.
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003278 *
3279 * We will use the given src/dest devices when is_routed is false.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003280 * When is_routed is true we will use the construct and the other devices (which is the src device of the
3281 * construct device) whcih were obtained from the skb's route field and passed to this function..
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003282 *
Ben Menchaca84f36632014-02-28 20:57:38 +00003283 * For example, with this network arrangement:
3284 *
3285 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
3286 *
Gareth Williams43fc0852014-05-26 19:10:00 +01003287 * 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 +00003288 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
3289 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
3290 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
3291 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
3292 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
3293 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
3294 *
3295 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
3296 * they will be created and added automatically to the database.
Ben Menchaca84f36632014-02-28 20:57:38 +00003297 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003298int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
3299 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin5dae8832015-12-03 14:23:19 -08003300 struct net_device *const_if, struct net_device *other_if,
Murat Sezginf92db492016-07-15 11:33:15 -07003301 ip_addr_t lookup_src_addr,
3302 ip_addr_t lookup_dest_addr,
3303 ip_addr_t real_dest_addr,
Murat Sezgin5dae8832015-12-03 14:23:19 -08003304 int ip_version, int packet_protocol,
3305 struct net_device *given_dest_dev,
3306 bool is_routed, struct net_device *given_src_dev,
3307 uint8_t *dest_node_addr, uint8_t *src_node_addr,
3308 __be16 *layer4hdr, struct sk_buff *skb)
3309{
3310 int protocol;
3311 ip_addr_t src_addr;
3312 ip_addr_t dest_addr;
3313 struct net_device *dest_dev;
3314 char *dest_dev_name;
3315 int32_t dest_dev_type;
3316 struct net_device *src_dev;
3317 char *src_dev_name;
3318 int32_t src_dev_type;
3319 int32_t current_interface_index;
3320 bool from_local_addr;
3321 bool next_dest_addr_valid;
3322 bool next_dest_node_addr_valid = false;
3323 ip_addr_t next_dest_addr;
3324 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003325 struct net_device *bridge;
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303326 struct net_device *top_dev_vlan = NULL;
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003327 uint32_t serial = ecm_db_connection_serial_get(feci->ci);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003328
3329 /*
3330 * Get a big endian of the IPv4 address we have been given as our starting point.
3331 */
3332 protocol = packet_protocol;
Murat Sezginf92db492016-07-15 11:33:15 -07003333 ECM_IP_ADDR_COPY(src_addr, lookup_src_addr);
3334 ECM_IP_ADDR_COPY(dest_addr, lookup_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003335
3336 if (ip_version == 4) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003337 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",
3338 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol,
3339 serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003340#ifdef ECM_IPV6_ENABLE
3341 } else if (ip_version == 6) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003342 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",
3343 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol,
3344 serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003345#endif
3346 } else {
3347 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
3348 return ECM_DB_IFACE_HEIRARCHY_MAX;
3349 }
3350
3351 /*
3352 * Get device to reach the given destination address.
3353 * If the heirarchy is for a routed connection we must use the devices obtained from the skb's route information..
3354 * If the heirarchy is NOT for a routed connection we try the given_dest_dev.
3355 */
3356 from_local_addr = false;
3357 if (!is_routed) {
3358 dest_dev = given_dest_dev;
3359 dev_hold(dest_dev);
3360 } else {
3361 dest_dev = ecm_interface_dev_find_by_local_addr(dest_addr);
3362 if (dest_dev) {
3363 from_local_addr = true;
3364 } else {
3365 dest_dev = const_if;
3366 dev_hold(dest_dev);
3367 }
3368 }
3369
3370 /*
3371 * If the address is a local address and protocol is an IP tunnel
3372 * then this connection is a tunnel endpoint made to this device.
3373 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
3374 *
3375 * TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
3376 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
3377 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
3378 */
3379 if (dest_dev && from_local_addr) {
3380 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
3381 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
3382 dev_put(dest_dev);
3383 dest_dev = given_dest_dev;
3384 if (dest_dev) {
3385 dev_hold(dest_dev);
3386 if (ip_version == 4) {
3387 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);
3388 } else {
3389 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);
3390 }
3391 }
3392 }
3393 }
3394
3395#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05303396
Murat Sezgin5dae8832015-12-03 14:23:19 -08003397 /*
3398 * if the address is a local address and indev=l2tp.
3399 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05303400 if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003401 dev_put(dest_dev);
3402 dest_dev = given_dest_dev;
3403 if (dest_dev) {
3404 dev_hold(dest_dev);
3405 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);
3406 }
3407 }
3408#endif
3409
3410#ifdef ECM_INTERFACE_PPTP_ENABLE
3411 /*
3412 * if the address is a local address and indev=PPTP.
3413 */
3414 if (protocol == IPPROTO_GRE && given_dest_dev && given_dest_dev->type == ARPHRD_PPP) {
3415 dev_put(dest_dev);
3416 dest_dev = given_dest_dev;
3417 if (dest_dev) {
3418 dev_hold(dest_dev);
3419 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);
3420 }
3421 }
3422#endif
3423
3424 if (!dest_dev) {
3425 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
3426 return ECM_DB_IFACE_HEIRARCHY_MAX;
3427 }
3428 dest_dev_name = dest_dev->name;
3429 dest_dev_type = dest_dev->type;
3430
3431 /*
3432 * Get device to reach the given source address.
3433 * If the heirarchy is for a routed connection we must use the devices obtained from the skb's route information..
3434 * If the heirarchy is NOT for a routed connection we try the given_src_dev.
3435 */
3436 from_local_addr = false;
3437 if (!is_routed) {
3438 src_dev = given_src_dev;
3439 dev_hold(src_dev);
3440 } else {
3441 src_dev = ecm_interface_dev_find_by_local_addr(src_addr);
3442 if (src_dev) {
3443 from_local_addr = true;
3444 } else {
3445 src_dev = other_if;
3446 dev_hold(src_dev);
3447 }
3448 }
3449
3450 /*
3451 * If the address is a local address and protocol is an IP tunnel
3452 * then this connection is a tunnel endpoint made to this device.
3453 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
3454 *
3455 * TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
3456 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
3457 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
3458 */
3459 if (src_dev && from_local_addr) {
3460 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
3461 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
3462 dev_put(src_dev);
3463 src_dev = given_src_dev;
3464 if (src_dev) {
3465 dev_hold(src_dev);
3466 if (ip_version == 4) {
3467 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);
3468 } else {
3469 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);
3470 }
3471 }
3472 }
3473 }
3474
3475 if (!src_dev) {
3476 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
3477 dev_put(dest_dev);
3478 return ECM_DB_IFACE_HEIRARCHY_MAX;
3479 }
3480 src_dev_name = src_dev->name;
3481 src_dev_type = src_dev->type;
3482
3483 /*
3484 * Check if source and dest dev are same.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003485 */
3486 if (src_dev == dest_dev) {
ratheesh kannotha6d25952016-04-11 12:23:26 +05303487 bool skip = false;
3488
Murat Sezgin5dae8832015-12-03 14:23:19 -08003489 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
ratheesh kannotha6d25952016-04-11 12:23:26 +05303490
3491 switch (ip_version) {
3492 case 4:
3493 if ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)) {
3494 skip = true;
3495 break;
3496 }
3497
3498 if ((protocol == IPPROTO_UDP) && (udp_hdr(skb)->dest == htons(4500))) {
3499 skip = true;
3500 break;
3501 }
3502
3503 break;
3504
3505 case 6:
ratheesh kannotha6d25952016-04-11 12:23:26 +05303506 if ((protocol == IPPROTO_IPIP) || (protocol == IPPROTO_ESP)) {
3507 skip = true;
3508 break;
3509 }
3510
3511 break;
3512
3513 default:
3514 DEBUG_WARN("IP version = %d, Protocol = %d: Corrupted packet entered ecm\n", ip_version, protocol);
3515 skip = true;
3516 break;
3517 }
3518
3519 if (skip) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003520 /*
3521 * This happens from the input hook
3522 * We do not want to create a connection entry for this
3523 * TODO YES WE DO.
3524 * TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
3525 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
3526 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
3527 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
3528 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
3529 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
3530 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
3531 */
3532 dev_put(src_dev);
3533 dev_put(dest_dev);
3534 return ECM_DB_IFACE_HEIRARCHY_MAX;
3535 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003536 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003537
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003538 bridge = ecm_interface_should_update_egress_device_bridged(
3539 given_dest_dev, dest_dev, is_routed);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003540
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003541 if (bridge) {
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003542 struct net_device *new_dest_dev;
Murat Sezginb9bd5e02016-08-05 14:55:07 -07003543 new_dest_dev = br_port_dev_get(bridge, dest_node_addr, skb, serial);
3544 if (new_dest_dev) {
3545 dev_put(dest_dev);
3546 if (new_dest_dev != given_dest_dev) {
3547 DEBUG_INFO("Adjusted port for %pM is %s (given was %s)\n",
3548 dest_node_addr, new_dest_dev->name,
3549 given_dest_dev->name);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003550
Murat Sezginb9bd5e02016-08-05 14:55:07 -07003551 dest_dev = new_dest_dev;
3552 dest_dev_name = dest_dev->name;
3553 dest_dev_type = dest_dev->type;
Murat Sezgin5dae8832015-12-03 14:23:19 -08003554 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003555 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003556 dev_put(bridge);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003557 }
3558
3559 next_dest_addr_valid = true;
3560 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
3561
3562 /*
3563 * Iterate until we are done or get to the max number of interfaces we can record.
3564 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
3565 * because we add from the end first_interface grows downwards.
3566 */
3567 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
3568 while (current_interface_index > 0) {
3569 struct ecm_db_iface_instance *ii;
3570 struct net_device *next_dev;
3571 /*
3572 * Get the ecm db interface instance for the device at hand
3573 */
3574 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
3575
3576 /*
3577 * If the interface could not be established then we abort
3578 */
3579 if (!ii) {
3580 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
3581 dev_put(src_dev);
3582 dev_put(dest_dev);
3583
3584 /*
3585 * Release the interfaces heirarchy we constructed to this point.
3586 */
3587 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3588 return ECM_DB_IFACE_HEIRARCHY_MAX;
3589 }
3590
3591 /*
3592 * Record the interface instance into the interfaces[]
3593 */
3594 current_interface_index--;
3595 interfaces[current_interface_index] = ii;
3596
3597 /*
3598 * Now we have to figure out what the next device will be (in the transmission path) the skb
3599 * will use to emit to the destination address.
3600 */
3601 do {
3602#ifdef ECM_INTERFACE_PPP_ENABLE
3603 int channel_count;
3604 struct ppp_channel *ppp_chan[1];
3605 int channel_protocol;
3606#ifdef ECM_INTERFACE_PPPOE_ENABLE
3607 struct pppoe_opt addressing;
3608#endif
3609#endif
3610
3611 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
3612 next_dev = NULL;
3613
3614 if (dest_dev_type == ARPHRD_ETHER) {
3615 /*
3616 * Ethernet - but what sub type?
3617 */
3618
3619#ifdef ECM_INTERFACE_VLAN_ENABLE
3620 /*
3621 * VLAN?
3622 */
3623 if (is_vlan_dev(dest_dev)) {
3624 /*
3625 * VLAN master
3626 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
3627 */
Shyam Sunder9db20852016-03-09 19:04:49 +05303628 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003629 dev_hold(next_dev);
3630 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
3631 dest_dev, next_dev, next_dev->name);
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303632 if (current_interface_index == (ECM_DB_IFACE_HEIRARCHY_MAX - 1)) {
3633 top_dev_vlan = dest_dev;
3634 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003635 break;
3636 }
3637#endif
3638
3639 /*
3640 * BRIDGE?
3641 */
3642 if (ecm_front_end_is_bridge_device(dest_dev)) {
3643 /*
3644 * Bridge
3645 * Figure out which port device the skb will go to using the dest_addr.
3646 */
3647 uint8_t mac_addr[ETH_ALEN];
3648
3649 if (next_dest_node_addr_valid) {
3650 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
3651 } else if (!next_dest_addr_valid) {
3652 dev_put(src_dev);
3653 dev_put(dest_dev);
3654
3655 /*
3656 * Release the interfaces heirarchy we constructed to this point.
3657 */
3658 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3659 return ECM_DB_IFACE_HEIRARCHY_MAX;
3660 } else {
3661 if (!ecm_interface_get_next_node_mac_address(dest_addr, dest_dev, ip_version, mac_addr)) {
3662 dev_put(src_dev);
3663 dev_put(dest_dev);
3664
3665 /*
3666 * Release the interfaces heirarchy we constructed to this point.
3667 */
3668 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3669 return ECM_DB_IFACE_HEIRARCHY_MAX;
3670 }
3671 }
3672
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003673 next_dev = br_port_dev_get(dest_dev,
3674 mac_addr, skb, serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003675
3676 if (!next_dev) {
3677 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
3678 dev_put(src_dev);
3679 dev_put(dest_dev);
3680
3681 /*
3682 * Release the interfaces heirarchy we constructed to this point.
3683 */
3684 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3685 return ECM_DB_IFACE_HEIRARCHY_MAX;
3686 }
3687 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3688 break;
3689 }
3690
3691#ifdef ECM_INTERFACE_BOND_ENABLE
3692 /*
3693 * LAG?
3694 */
3695 if (ecm_front_end_is_lag_master(dest_dev)) {
3696 /*
3697 * Link aggregation
3698 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
3699 */
3700 uint32_t src_addr_32 = 0;
3701 uint32_t dest_addr_32 = 0;
3702 struct in6_addr src_addr6;
3703 struct in6_addr dest_addr6;
3704 uint8_t src_mac_addr[ETH_ALEN];
3705 uint8_t dest_mac_addr[ETH_ALEN];
3706
3707 memset(src_mac_addr, 0, ETH_ALEN);
3708 memset(dest_mac_addr, 0, ETH_ALEN);
3709
3710 if (ip_version == 4) {
3711 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
Murat Sezginf92db492016-07-15 11:33:15 -07003712 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, real_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003713 }
3714
3715 if (!is_routed) {
3716 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
3717 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
3718 } else {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003719 struct net_device *master_dev;
Murat Sezgin5dae8832015-12-03 14:23:19 -08003720
3721 /*
Murat Sezgin7be87d22016-01-29 17:41:37 -08003722 * Use appropriate source MAC address for routed packets and
3723 * find proper interface to find the destination mac address and
3724 * from which to issue ARP or neighbour solicitation packet.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003725 */
Murat Sezgin7be87d22016-01-29 17:41:37 -08003726 master_dev = ecm_interface_get_and_hold_dev_master(dest_dev);
3727 if (master_dev) {
3728 memcpy(src_mac_addr, master_dev->dev_addr, ETH_ALEN);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003729 } else {
3730 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003731 master_dev = dest_dev;
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303732 if (top_dev_vlan) {
3733 master_dev = top_dev_vlan;
3734 }
Murat Sezgin7be87d22016-01-29 17:41:37 -08003735 dev_hold(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003736 }
3737
3738 /*
3739 * Determine destination MAC address for this routed packet
3740 */
3741 if (next_dest_node_addr_valid) {
3742 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
3743 } else if (!next_dest_addr_valid) {
3744 dev_put(src_dev);
3745 dev_put(dest_dev);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003746 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003747 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3748 return ECM_DB_IFACE_HEIRARCHY_MAX;
3749 } else {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003750 if (!ecm_interface_mac_addr_get_no_route(master_dev, dest_addr, dest_mac_addr)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003751 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3752 /*
3753 * Try one more time with gateway ip address if it exists.
3754 */
3755 if (!ecm_interface_find_gateway(dest_addr, gw_addr)) {
3756 goto lag_fail;
3757 }
3758
3759 if (ip_version == 4) {
3760 DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(gw_addr));
3761 }
3762#ifdef ECM_IPV6_ENABLE
3763
3764 if (ip_version == 6) {
3765 DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr));
3766 }
3767#endif
Murat Sezgin7be87d22016-01-29 17:41:37 -08003768 if (ecm_interface_mac_addr_get_no_route(master_dev, gw_addr, dest_mac_addr)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003769 DEBUG_TRACE("Found the mac address for gateway\n");
Murat Sezgin7be87d22016-01-29 17:41:37 -08003770 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003771 goto lag_success;
3772 }
3773
3774 if (ip_version == 4) {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003775 ecm_interface_send_arp_request(master_dev, dest_addr, false, gw_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003776
3777 DEBUG_WARN("Unable to obtain any MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
3778 }
3779#ifdef ECM_IPV6_ENABLE
3780 if (ip_version == 6) {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003781 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003782
3783 DEBUG_WARN("Unable to obtain any MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
3784 }
3785#endif
3786lag_fail:
3787 dev_put(src_dev);
3788 dev_put(dest_dev);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003789 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003790
3791 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3792 return ECM_DB_IFACE_HEIRARCHY_MAX;
3793 }
Murat Sezgin7be87d22016-01-29 17:41:37 -08003794 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003795 }
3796 }
3797lag_success:
3798 if (ip_version == 4) {
3799 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3800 &src_addr_32, &dest_addr_32,
3801 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
3802 } else if (ip_version == 6) {
3803 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
Murat Sezginf92db492016-07-15 11:33:15 -07003804 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, real_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003805 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3806 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05303807 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003808 }
3809
3810 if (next_dev && netif_carrier_ok(next_dev)) {
3811 dev_hold(next_dev);
3812 } else {
3813 DEBUG_WARN("Unable to obtain LAG output slave device\n");
3814 dev_put(src_dev);
3815 dev_put(dest_dev);
3816
3817 /*
3818 * Release the interfaces heirarchy we constructed to this point.
3819 */
3820 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3821 return ECM_DB_IFACE_HEIRARCHY_MAX;
3822 }
3823
3824 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3825 break;
3826 }
3827#endif
3828
3829 /*
3830 * ETHERNET!
3831 * Just plain ethernet it seems.
3832 */
3833 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
3834 break;
3835 }
3836
3837 /*
3838 * LOOPBACK?
3839 */
3840 if (dest_dev_type == ARPHRD_LOOPBACK) {
3841 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
3842 break;
3843 }
3844
3845 /*
3846 * IPSEC?
3847 */
3848 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
3849 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
3850 /* TODO Figure out the next device the tunnel is using... */
3851 break;
3852 }
3853
3854 /*
3855 * SIT (6-in-4)?
3856 */
3857 if (dest_dev_type == ARPHRD_SIT) {
3858 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
3859 /* TODO Figure out the next device the tunnel is using... */
3860 break;
3861 }
3862
3863 /*
3864 * IPIP6 Tunnel?
3865 */
3866 if (dest_dev_type == ARPHRD_TUNNEL6) {
3867 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
3868 /* TODO Figure out the next device the tunnel is using... */
3869 break;
3870 }
3871
ratheesh kannothcfdcb332015-12-24 07:19:18 +05303872#ifdef ECM_INTERFACE_MAP_T_ENABLE
3873 /*
3874 * MAP-T xlate ?
3875 */
3876 if (dest_dev_type == ARPHRD_NONE) {
3877 if (is_map_t_dev(dest_dev)) {
3878 DEBUG_TRACE("Net device: %p is MAP-T type: %d\n", dest_dev, dest_dev_type);
3879 break;
3880 }
3881 }
3882#endif
3883
Murat Sezgin5dae8832015-12-03 14:23:19 -08003884 /*
3885 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
3886 */
3887 if (dest_dev_type != ARPHRD_PPP) {
3888 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
3889 break;
3890 }
3891
3892#ifndef ECM_INTERFACE_PPP_ENABLE
3893 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
3894#else
3895 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
3896
3897#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05303898 if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003899 if (skb->skb_iif == dest_dev->ifindex) {
3900 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
3901 break;
3902 }
3903 }
3904#endif
3905
3906#ifdef ECM_INTERFACE_PPTP_ENABLE
3907 if (protocol == IPPROTO_GRE && dest_dev && dest_dev->type == ARPHRD_PPP) {
3908 DEBUG_TRACE("Net device: %p PPP channel is PPTP\n", dest_dev);
3909 break;
3910 }
3911#endif
3912 /*
3913 * PPP - but what is the channel type?
3914 * First: If this is multi-link then we do not support it
3915 */
3916 if (ppp_is_multilink(dest_dev) > 0) {
3917 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
3918 break;
3919 }
3920
3921 /*
3922 * Get the PPP channel and then enquire what kind of channel it is
3923 * NOTE: Not multilink so only one channel to get.
3924 */
3925 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
3926 if (channel_count != 1) {
3927 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
3928 dest_dev, channel_count);
3929 break;
3930 }
3931
3932 /*
3933 * Get channel protocol type
3934 * NOTE: Not all PPP channels support channel specific methods.
3935 */
3936 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
3937
3938#ifdef ECM_INTERFACE_L2TPV2_ENABLE
3939 if (channel_protocol == PX_PROTO_OL2TP) {
3940
3941 /*
3942 * PPPoL2TPV2 channel
3943 */
3944 ppp_release_channels(ppp_chan, 1);
3945 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
3946
3947 /*
3948 * Release the channel. Note that next_dev not held.
3949 */
3950 break;
3951 }
3952#endif
3953#ifdef ECM_INTERFACE_PPPOE_ENABLE
3954 if (channel_protocol == PX_PROTO_OE) {
3955 /*
3956 * PPPoE channel
3957 */
3958 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
3959
3960 /*
3961 * Get PPPoE session information and the underlying device it is using.
3962 */
3963 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
3964
3965 /*
3966 * Copy the dev hold into this, we will release the hold later
3967 */
3968 next_dev = addressing.dev;
3969 next_dest_addr_valid = false;
3970 next_dest_node_addr_valid = true;
3971 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
3972
3973 /*
3974 * Release the channel. Note that next_dev is still (correctly) held.
3975 */
3976 ppp_release_channels(ppp_chan, 1);
3977 break;
3978 }
3979#endif
3980
3981 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
3982 dest_dev, channel_protocol);
3983
3984 /*
3985 * Release the channel
3986 */
3987 ppp_release_channels(ppp_chan, 1);
3988
3989#endif
3990 } while (false);
3991
3992 /*
3993 * No longer need dest_dev as it may become next_dev
3994 */
3995 dev_put(dest_dev);
3996
3997 /*
3998 * Check out the next_dev, if any
3999 */
4000 if (!next_dev) {
4001 int32_t i __attribute__((unused));
4002 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
4003#if DEBUG_LEVEL > 1
4004 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
4005 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
4006 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])));
4007
4008 }
4009#endif
4010
4011 /*
4012 * Release src_dev now
4013 */
4014 dev_put(src_dev);
4015 return current_interface_index;
4016 }
4017
4018 /*
4019 * dest_dev becomes next_dev
4020 */
4021 dest_dev = next_dev;
4022 dest_dev_name = dest_dev->name;
4023 dest_dev_type = dest_dev->type;
4024 }
4025
4026 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
4027 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
4028 dev_put(src_dev);
4029 dev_put(dest_dev);
4030
4031 /*
4032 * Release the interfaces heirarchy we constructed to this point.
4033 */
4034 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4035 return ECM_DB_IFACE_HEIRARCHY_MAX;
4036}
4037EXPORT_SYMBOL(ecm_interface_heirarchy_construct);
4038
4039#ifdef ECM_MULTICAST_ENABLE
4040/*
4041 * ecm_interface_multicast_from_heirarchy_construct()
4042 * Construct an interface heirarchy.
4043 *
4044 * TODO: This function will be removed later and ecm_interface_heirarchy_construct() function
4045 * will be used when the multicast code is fixed to use the new interface hierarchy
4046 * construction model which uses the skb's route information instead of doing
4047 * the route lookup based on the IP addresses.
4048 *
4049 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
4050 * This is the heirarchy of interfaces a packet would transit to emit from the device.
4051 *
4052 * We will use the given src/dest devices when is_routed is false.
4053 * When is_routed is true we will try routing tables first, failing back to any given.
4054 *
4055 * For example, with this network arrangement:
4056 *
4057 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
4058 *
4059 * Given the packet_dest_addr IP address 10.22.33.11 this will create an interface heirarchy (in interracfes[]) of:
4060 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
4061 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
4062 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
4063 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
4064 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
4065 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
4066 *
4067 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
4068 * they will be created and added automatically to the database.
4069 */
4070int32_t ecm_interface_multicast_from_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
4071 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin188b4a32015-06-03 10:58:59 -07004072 ip_addr_t packet_src_addr,
4073 ip_addr_t packet_dest_addr,
4074 int ip_version, int packet_protocol,
4075 struct net_device *given_dest_dev,
4076 bool is_routed, struct net_device *given_src_dev,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05304077 uint8_t *dest_node_addr, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304078 __be16 *layer4hdr, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00004079{
Ben Menchaca84f36632014-02-28 20:57:38 +00004080 int protocol;
4081 ip_addr_t src_addr;
4082 ip_addr_t dest_addr;
Ben Menchaca84f36632014-02-28 20:57:38 +00004083 struct net_device *dest_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00004084 char *dest_dev_name;
Ben Menchaca84f36632014-02-28 20:57:38 +00004085 int32_t dest_dev_type;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004086 struct net_device *src_dev;
4087 char *src_dev_name;
4088 int32_t src_dev_type;
Ben Menchaca84f36632014-02-28 20:57:38 +00004089 int32_t current_interface_index;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004090 bool from_local_addr;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004091 bool next_dest_addr_valid;
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004092 bool next_dest_node_addr_valid = false;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004093 ip_addr_t next_dest_addr;
4094 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004095 struct net_device *bridge;
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004096 uint32_t serial = ecm_db_connection_serial_get(feci->ci);
Ben Menchaca84f36632014-02-28 20:57:38 +00004097
4098 /*
4099 * Get a big endian of the IPv4 address we have been given as our starting point.
4100 */
4101 protocol = packet_protocol;
4102 ECM_IP_ADDR_COPY(src_addr, packet_src_addr);
4103 ECM_IP_ADDR_COPY(dest_addr, packet_dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004104
4105 if (ip_version == 4) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004106 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",
4107 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol,
4108 serial);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004109#ifdef ECM_IPV6_ENABLE
4110 } else if (ip_version == 6) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004111 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",
4112 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol,
4113 serial);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004114#endif
4115 } else {
4116 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
4117 return ECM_DB_IFACE_HEIRARCHY_MAX;
4118 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004119
4120 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004121 * Get device to reach the given destination address.
4122 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_dest_dev.
4123 * 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 +00004124 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004125 from_local_addr = false;
4126 if (is_routed) {
4127 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
4128 if (!dest_dev && given_dest_dev) {
4129 /*
4130 * Fall back to any given
4131 */
4132 dest_dev = given_dest_dev;
4133 dev_hold(dest_dev);
Gareth Williams43fc0852014-05-26 19:10:00 +01004134 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004135 } else if (given_dest_dev) {
4136 dest_dev = given_dest_dev;
4137 dev_hold(dest_dev);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304138 } else {
4139 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004140 * Fall back to routed look up
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304141 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004142 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
Gareth Williams43fc0852014-05-26 19:10:00 +01004143 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304144
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004145 /*
4146 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
4147 * then this connection is a tunnel endpoint made to this device.
4148 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
4149 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
4150 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
4151 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
4152 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07004153 if (dest_dev && from_local_addr) {
4154 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
4155 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
4156 dev_put(dest_dev);
4157 dest_dev = given_dest_dev;
4158 if (dest_dev) {
4159 dev_hold(dest_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05304160 if (ip_version == 4) {
4161 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);
4162 } else {
4163 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);
4164 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004165 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304166 }
Gareth Williams43fc0852014-05-26 19:10:00 +01004167 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304168
4169#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4170 /*
4171 * if the address is a local address and indev=l2tp.
4172 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05304173 if ((given_src_dev->type == ARPHRD_PPP) && (given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304174 dev_put(dest_dev);
4175 dest_dev = given_dest_dev;
4176 if (dest_dev) {
4177 dev_hold(dest_dev);
4178 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);
4179 }
4180 }
4181#endif
4182
Shyam Sunder23f2e542015-09-28 14:56:49 +05304183#ifdef ECM_INTERFACE_PPTP_ENABLE
4184 /*
4185 * if the address is a local address and indev=PPTP.
4186 */
4187 if (protocol == IPPROTO_GRE && given_dest_dev && given_dest_dev->type == ARPHRD_PPP) {
4188 dev_put(dest_dev);
4189 dest_dev = given_dest_dev;
4190 if (dest_dev) {
4191 dev_hold(dest_dev);
4192 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);
4193 }
4194 }
4195#endif
4196
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004197 if (!dest_dev) {
4198 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
4199 return ECM_DB_IFACE_HEIRARCHY_MAX;
4200 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004201 dest_dev_name = dest_dev->name;
4202 dest_dev_type = dest_dev->type;
4203
4204 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004205 * Get device to reach the given source address.
4206 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_src_dev.
4207 * If the heirarchy is NOT for a routed connection we try the given_src_dev first, followed by routed lookup.
4208 */
4209 from_local_addr = false;
4210 if (is_routed) {
4211 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
4212 if (!src_dev && given_src_dev) {
4213 /*
4214 * Fall back to any given
4215 */
4216 src_dev = given_src_dev;
4217 dev_hold(src_dev);
4218 }
4219 } else if (given_src_dev) {
4220 src_dev = given_src_dev;
4221 dev_hold(src_dev);
4222 } else {
4223 /*
4224 * Fall back to routed look up
4225 */
4226 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
4227 }
4228
4229 /*
4230 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
4231 * then this connection is a tunnel endpoint made to this device.
4232 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
4233 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
4234 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
4235 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
4236 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07004237 if (src_dev && from_local_addr) {
4238 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
4239 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
4240 dev_put(src_dev);
4241 src_dev = given_src_dev;
4242 if (src_dev) {
4243 dev_hold(src_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05304244 if (ip_version == 4) {
4245 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);
4246 } else {
4247 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);
4248 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004249 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004250 }
4251 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004252
ratheesh kannothed721852015-09-28 12:39:52 +05304253#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4254 /*
4255 * if the address is a local address and indev=l2tp.
4256 */
4257 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
4258 if (dest_dev != given_src_dev) {
4259 dev_put(src_dev);
4260 src_dev = given_src_dev;
4261 if (src_dev) {
4262 dev_hold(src_dev);
4263 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);
4264 }
4265 }
4266 }
4267#endif
4268
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004269 if (!src_dev) {
4270 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
4271 dev_put(dest_dev);
4272 return ECM_DB_IFACE_HEIRARCHY_MAX;
4273 }
4274 src_dev_name = src_dev->name;
4275 src_dev_type = src_dev->type;
4276
4277 /*
4278 * Check if source and dest dev are same.
4279 * For the forwarded flows which involve tunnels this will happen when called from input hook.
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304280 */
4281 if (src_dev == dest_dev) {
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004282 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004283 if (((ip_version == 4) && ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)))
4284 || ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304285 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004286 * This happens from the input hook
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304287 * We do not want to create a connection entry for this
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004288 * GGG TODO YES WE DO.
4289 * GGG TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
4290 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
4291 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
4292 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
4293 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
4294 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
4295 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304296 */
4297 dev_put(src_dev);
4298 dev_put(dest_dev);
4299 return ECM_DB_IFACE_HEIRARCHY_MAX;
4300 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004301 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004302
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004303 bridge = ecm_interface_should_update_egress_device_bridged(
4304 given_dest_dev, dest_dev, is_routed);
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004305
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004306 if (bridge) {
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004307 struct net_device *new_dest_dev;
Murat Sezginb9bd5e02016-08-05 14:55:07 -07004308 new_dest_dev = br_port_dev_get(bridge, dest_node_addr, skb, serial);
4309 if (new_dest_dev) {
4310 dev_put(dest_dev);
4311 if (new_dest_dev != given_dest_dev) {
4312 DEBUG_INFO("Adjusted port for %pM is %s (given was %s)\n",
4313 dest_node_addr, new_dest_dev->name,
4314 given_dest_dev->name);
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004315
Murat Sezginb9bd5e02016-08-05 14:55:07 -07004316 dest_dev = new_dest_dev;
4317 dest_dev_name = dest_dev->name;
4318 dest_dev_type = dest_dev->type;
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004319 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004320 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004321 dev_put(bridge);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304322 }
4323
Murat Sezgin7ef29962015-08-14 10:53:24 -07004324 next_dest_addr_valid = true;
Murat Sezgin5dae8832015-12-03 14:23:19 -08004325 next_dest_node_addr_valid = false;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004326 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
4327
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304328 /*
Ben Menchaca84f36632014-02-28 20:57:38 +00004329 * Iterate until we are done or get to the max number of interfaces we can record.
4330 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
4331 * because we add from the end first_interface grows downwards.
4332 */
4333 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
4334 while (current_interface_index > 0) {
4335 struct ecm_db_iface_instance *ii;
4336 struct net_device *next_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00004337 /*
4338 * Get the ecm db interface instance for the device at hand
4339 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304340 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Ben Menchaca84f36632014-02-28 20:57:38 +00004341
4342 /*
4343 * If the interface could not be established then we abort
4344 */
4345 if (!ii) {
4346 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
4347 dev_put(src_dev);
4348 dev_put(dest_dev);
4349
4350 /*
4351 * Release the interfaces heirarchy we constructed to this point.
4352 */
4353 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4354 return ECM_DB_IFACE_HEIRARCHY_MAX;
4355 }
4356
4357 /*
4358 * Record the interface instance into the interfaces[]
4359 */
4360 current_interface_index--;
4361 interfaces[current_interface_index] = ii;
4362
4363 /*
4364 * Now we have to figure out what the next device will be (in the transmission path) the skb
4365 * will use to emit to the destination address.
4366 */
4367 do {
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08004368#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004369 int channel_count;
4370 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00004371 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304372#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004373 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004374#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304375#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004376
4377 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
4378 next_dev = NULL;
4379
4380 if (dest_dev_type == ARPHRD_ETHER) {
4381 /*
4382 * Ethernet - but what sub type?
4383 */
4384
Gareth Williams141d2382014-11-25 11:35:19 -08004385#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004386 /*
4387 * VLAN?
4388 */
4389 if (is_vlan_dev(dest_dev)) {
4390 /*
4391 * VLAN master
4392 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
4393 */
Shyam Sunder9db20852016-03-09 19:04:49 +05304394 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004395 dev_hold(next_dev);
4396 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
4397 dest_dev, next_dev, next_dev->name);
4398 break;
4399 }
Gareth Williams141d2382014-11-25 11:35:19 -08004400#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004401
4402 /*
4403 * BRIDGE?
4404 */
4405 if (ecm_front_end_is_bridge_device(dest_dev)) {
4406 /*
4407 * Bridge
4408 * Figure out which port device the skb will go to using the dest_addr.
4409 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004410 uint8_t mac_addr[ETH_ALEN];
Murat Sezgin7ef29962015-08-14 10:53:24 -07004411
4412 if (next_dest_node_addr_valid) {
4413 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
4414 } else if (!next_dest_addr_valid) {
Ben Menchaca84f36632014-02-28 20:57:38 +00004415 dev_put(src_dev);
4416 dev_put(dest_dev);
4417
4418 /*
4419 * Release the interfaces heirarchy we constructed to this point.
4420 */
4421 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4422 return ECM_DB_IFACE_HEIRARCHY_MAX;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004423 } else {
Murat Sezgin5dae8832015-12-03 14:23:19 -08004424 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 -07004425 dev_put(src_dev);
4426 dev_put(dest_dev);
4427
4428 /*
4429 * Release the interfaces heirarchy we constructed to this point.
4430 */
4431 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4432 return ECM_DB_IFACE_HEIRARCHY_MAX;
4433 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004434 }
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004435 next_dev = br_port_dev_get(dest_dev,
4436 mac_addr, skb, serial);
Ben Menchaca84f36632014-02-28 20:57:38 +00004437 if (!next_dev) {
4438 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
4439 dev_put(src_dev);
4440 dev_put(dest_dev);
4441
4442 /*
4443 * Release the interfaces heirarchy we constructed to this point.
4444 */
4445 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4446 return ECM_DB_IFACE_HEIRARCHY_MAX;
4447 }
4448 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
4449 break;
4450 }
Gareth Williams8ac34292015-03-17 14:06:58 +00004451
Murat Sezginb3731e82014-11-26 12:20:59 -08004452#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004453 /*
4454 * LAG?
4455 */
4456 if (ecm_front_end_is_lag_master(dest_dev)) {
4457 /*
4458 * Link aggregation
Murat Sezginb3731e82014-11-26 12:20:59 -08004459 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
Ben Menchaca84f36632014-02-28 20:57:38 +00004460 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304461 bool dest_on_link = false;
4462 ip_addr_t dest_gw_addr = ECM_IP_ADDR_NULL;
4463 uint32_t src_addr_32 = 0;
4464 uint32_t dest_addr_32 = 0;
Suman Ghoshf14d2172015-07-31 14:38:10 +05304465 struct in6_addr src_addr6;
4466 struct in6_addr dest_addr6;
Ben Menchaca84f36632014-02-28 20:57:38 +00004467 uint8_t src_mac_addr[ETH_ALEN];
4468 uint8_t dest_mac_addr[ETH_ALEN];
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304469 struct net_device *master_dev = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00004470
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304471 memset(src_mac_addr, 0, ETH_ALEN);
4472 memset(dest_mac_addr, 0, ETH_ALEN);
Ben Menchaca84f36632014-02-28 20:57:38 +00004473
Gareth Williams341df382015-07-20 16:44:17 +01004474 if (ip_version == 4) {
4475 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
4476 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
4477 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304478
4479 if (!is_routed) {
4480 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
4481 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
4482 } else {
Murat Sezginb3731e82014-11-26 12:20:59 -08004483 struct net_device *dest_dev_master;
4484
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304485 /*
4486 * Use appropriate source MAC address for routed packets
4487 */
Murat Sezginb3731e82014-11-26 12:20:59 -08004488 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
4489 if (dest_dev_master) {
4490 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304491 } else {
4492 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
4493 }
4494
4495 /*
4496 * Determine destination MAC address for this routed packet
4497 */
Tushar Mathur78b5f432015-09-18 20:13:31 +05304498 if (next_dest_node_addr_valid) {
4499 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
4500 } else if (!next_dest_addr_valid) {
4501 dev_put(src_dev);
4502 dev_put(dest_dev);
Murat Sezginb3731e82014-11-26 12:20:59 -08004503 if (dest_dev_master) {
4504 dev_put(dest_dev_master);
4505 }
4506
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304507 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4508 return ECM_DB_IFACE_HEIRARCHY_MAX;
Tushar Mathur78b5f432015-09-18 20:13:31 +05304509 } else {
4510 if (!ecm_interface_mac_addr_get(dest_addr, dest_mac_addr,
4511 &dest_on_link, dest_gw_addr)) {
4512
4513 /*
4514 * Find proper interfce from which to issue ARP
4515 * or neighbour solicitation packet.
4516 */
4517 if (dest_dev_master) {
4518 master_dev = dest_dev_master;
4519 } else {
4520 master_dev = dest_dev;
4521 }
4522
4523 dev_hold(master_dev);
4524
4525 if (dest_dev_master) {
4526 dev_put(dest_dev_master);
4527 }
4528
4529 if (ip_version == 4) {
4530 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
4531 ecm_interface_send_arp_request(dest_dev, dest_addr, dest_on_link, dest_gw_addr);
4532 }
4533#ifdef ECM_IPV6_ENABLE
4534 if (ip_version == 6) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08004535 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 +05304536 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
4537 }
4538#endif
4539 dev_put(src_dev);
4540 dev_put(dest_dev);
4541 dev_put(master_dev);
4542 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4543 return ECM_DB_IFACE_HEIRARCHY_MAX;
4544 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304545 }
Murat Sezginb3731e82014-11-26 12:20:59 -08004546
4547 if (dest_dev_master) {
4548 dev_put(dest_dev_master);
4549 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304550 }
4551
Murat Sezgin188b4a32015-06-03 10:58:59 -07004552 if (ip_version == 4) {
4553 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
4554 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05304555 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004556 } else if (ip_version == 6) {
Suman Ghoshf14d2172015-07-31 14:38:10 +05304557 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
4558 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004559 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
Suman Ghoshf14d2172015-07-31 14:38:10 +05304560 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05304561 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004562 }
4563
Tushar Mathur933907c2014-06-24 17:06:14 +05304564 if (next_dev && netif_carrier_ok(next_dev)) {
Ben Menchaca84f36632014-02-28 20:57:38 +00004565 dev_hold(next_dev);
4566 } else {
4567 DEBUG_WARN("Unable to obtain LAG output slave device\n");
4568 dev_put(src_dev);
4569 dev_put(dest_dev);
4570
4571 /*
4572 * Release the interfaces heirarchy we constructed to this point.
4573 */
4574 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4575 return ECM_DB_IFACE_HEIRARCHY_MAX;
4576 }
4577
4578 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 +00004579 break;
4580 }
Murat Sezginb3731e82014-11-26 12:20:59 -08004581#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004582
4583 /*
4584 * ETHERNET!
4585 * Just plain ethernet it seems.
4586 */
4587 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
4588 break;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05304589 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004590
4591 /*
4592 * LOOPBACK?
4593 */
4594 if (dest_dev_type == ARPHRD_LOOPBACK) {
4595 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
4596 break;
4597 }
4598
4599 /*
4600 * IPSEC?
4601 */
4602 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
4603 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004604 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004605 break;
4606 }
4607
4608 /*
4609 * SIT (6-in-4)?
4610 */
4611 if (dest_dev_type == ARPHRD_SIT) {
4612 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 -08004613 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004614 break;
4615 }
4616
4617 /*
4618 * IPIP6 Tunnel?
4619 */
4620 if (dest_dev_type == ARPHRD_TUNNEL6) {
4621 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004622 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004623 break;
4624 }
4625
4626 /*
4627 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
4628 */
4629 if (dest_dev_type != ARPHRD_PPP) {
4630 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
4631 break;
4632 }
4633
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08004634#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004635 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
4636#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304637 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
4638
4639#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05304640 if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) {
ratheesh kannothed721852015-09-28 12:39:52 +05304641 if (skb->skb_iif == dest_dev->ifindex) {
4642 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
4643 break;
4644 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304645 }
4646#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05304647
4648#ifdef ECM_INTERFACE_PPTP_ENABLE
4649 if (protocol == IPPROTO_GRE && dest_dev && dest_dev->type == ARPHRD_PPP) {
4650 DEBUG_TRACE("Net device: %p PPP channel is PPTP\n", dest_dev);
4651 break;
4652 }
4653#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004654 /*
4655 * PPP - but what is the channel type?
4656 * First: If this is multi-link then we do not support it
4657 */
4658 if (ppp_is_multilink(dest_dev) > 0) {
4659 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
4660 break;
4661 }
4662
Ben Menchaca84f36632014-02-28 20:57:38 +00004663 /*
4664 * Get the PPP channel and then enquire what kind of channel it is
4665 * NOTE: Not multilink so only one channel to get.
4666 */
4667 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
4668 if (channel_count != 1) {
4669 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
4670 dest_dev, channel_count);
4671 break;
4672 }
4673
4674 /*
4675 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01004676 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00004677 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01004678 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304679
4680#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4681 if (channel_protocol == PX_PROTO_OL2TP) {
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05304682
Ben Menchaca84f36632014-02-28 20:57:38 +00004683 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304684 * PPPoL2TPV2 channel
Ben Menchaca84f36632014-02-28 20:57:38 +00004685 */
4686 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304687 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004688
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304689 /*
4690 * Release the channel. Note that next_dev not held.
4691 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004692 break;
4693 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304694#endif
4695#ifdef ECM_INTERFACE_PPPOE_ENABLE
4696 if (channel_protocol == PX_PROTO_OE) {
4697 /*
4698 * PPPoE channel
4699 */
4700 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
4701
4702 /*
4703 * Get PPPoE session information and the underlying device it is using.
4704 */
4705 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
4706
4707 /*
4708 * Copy the dev hold into this, we will release the hold later
4709 */
4710 next_dev = addressing.dev;
4711 next_dest_addr_valid = false;
4712 next_dest_node_addr_valid = true;
4713 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
4714
4715 /*
4716 * Release the channel. Note that next_dev is still (correctly) held.
4717 */
4718 ppp_release_channels(ppp_chan, 1);
4719 break;
4720 }
4721#endif
4722
4723 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
4724 dest_dev, channel_protocol);
Ben Menchaca84f36632014-02-28 20:57:38 +00004725
4726 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304727 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00004728 */
4729 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304730
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004731#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004732 } while (false);
4733
4734 /*
Gareth Williamsa11d4352014-05-14 18:25:49 +01004735 * No longer need dest_dev as it may become next_dev
Ben Menchaca84f36632014-02-28 20:57:38 +00004736 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004737 dev_put(dest_dev);
4738
4739 /*
4740 * Check out the next_dev, if any
4741 */
4742 if (!next_dev) {
4743 int32_t i __attribute__((unused));
4744 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
4745#if DEBUG_LEVEL > 1
4746 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
4747 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
4748 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 +05304749
Ben Menchaca84f36632014-02-28 20:57:38 +00004750 }
4751#endif
Gareth Williamsa11d4352014-05-14 18:25:49 +01004752
4753 /*
4754 * Release src_dev now
4755 */
4756 dev_put(src_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004757 return current_interface_index;
4758 }
4759
Gareth Williamsa11d4352014-05-14 18:25:49 +01004760 /*
4761 * dest_dev becomes next_dev
4762 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004763 dest_dev = next_dev;
4764 dest_dev_name = dest_dev->name;
4765 dest_dev_type = dest_dev->type;
4766 }
4767
4768 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
4769 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
4770 dev_put(src_dev);
4771 dev_put(dest_dev);
4772
4773 /*
4774 * Release the interfaces heirarchy we constructed to this point.
4775 */
4776 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4777 return ECM_DB_IFACE_HEIRARCHY_MAX;
4778}
Murat Sezgin5dae8832015-12-03 14:23:19 -08004779EXPORT_SYMBOL(ecm_interface_multicast_from_heirarchy_construct);
4780#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004781
4782/*
Gareth Williamsadf425f2014-05-26 19:29:02 +01004783 * ecm_interface_list_stats_update()
4784 * Given an interface list, walk the interfaces and update the stats for certain types.
4785 */
4786static 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 +05304787 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 +01004788{
4789 int list_index;
4790
4791 for (list_index = iface_list_first; (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) {
4792 struct ecm_db_iface_instance *ii;
4793 ecm_db_iface_type_t ii_type;
4794 char *ii_name;
4795 struct net_device *dev;
4796
4797 ii = iface_list[list_index];
4798 ii_type = ecm_db_connection_iface_type_get(ii);
4799 ii_name = ecm_db_interface_type_to_string(ii_type);
4800 DEBUG_TRACE("list_index: %d, ii: %p, type: %d (%s)\n", list_index, ii, ii_type, ii_name);
4801
4802 /*
4803 * Locate real device in system
4804 */
4805 dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii));
4806 if (!dev) {
4807 DEBUG_WARN("Could not locate interface\n");
4808 continue;
4809 }
4810 DEBUG_TRACE("found dev: %p (%s)\n", dev, dev->name);
4811
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304812 if (likely(!is_mcast_flow)) {
4813 /*
4814 * Refresh the bridge forward table entry if the port is a bridge port
4815 * Note: A bridge port can be of different interface type, e.g VLAN, ethernet.
4816 * This check, therefore, should be performed for all interface types.
4817 */
4818 if (is_valid_ether_addr(mac_addr) && ecm_front_end_is_bridge_port(dev) && rx_packets) {
4819 DEBUG_TRACE("Update bridge fdb entry for mac: %pM\n", mac_addr);
4820 br_refresh_fdb_entry(dev, mac_addr);
4821 }
Selin Dag1af781a2014-06-10 10:37:54 -07004822 }
4823
Gareth Williamsadf425f2014-05-26 19:29:02 +01004824 switch (ii_type) {
4825 struct rtnl_link_stats64 stats;
4826
Gareth Williams141d2382014-11-25 11:35:19 -08004827#ifdef ECM_INTERFACE_VLAN_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +01004828 case ECM_DB_IFACE_TYPE_VLAN:
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304829 DEBUG_INFO("VLAN\n");
Gareth Williamsadf425f2014-05-26 19:29:02 +01004830 stats.rx_packets = rx_packets;
4831 stats.rx_bytes = rx_bytes;
4832 stats.tx_packets = tx_packets;
4833 stats.tx_bytes = tx_bytes;
4834 __vlan_dev_update_accel_stats(dev, &stats);
4835 break;
Gareth Williams141d2382014-11-25 11:35:19 -08004836#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01004837 case ECM_DB_IFACE_TYPE_BRIDGE:
4838 DEBUG_INFO("BRIDGE\n");
4839 stats.rx_packets = rx_packets;
4840 stats.rx_bytes = rx_bytes;
4841 stats.tx_packets = tx_packets;
4842 stats.tx_bytes = tx_bytes;
4843 br_dev_update_stats(dev, &stats);
Gareth Williamsadf425f2014-05-26 19:29:02 +01004844 break;
Murat Sezgina683edd2015-01-20 10:48:30 -08004845
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304846#ifdef ECM_INTERFACE_PPPOE_ENABLE
Murat Sezgina683edd2015-01-20 10:48:30 -08004847 case ECM_DB_IFACE_TYPE_PPPOE:
4848 DEBUG_INFO("PPPOE\n");
ratheesh kannothb1b753a2015-09-28 11:17:35 +05304849 ppp_update_stats(dev, rx_packets, rx_bytes, tx_packets, tx_bytes, 0, 0, 0, 0);
Murat Sezgina683edd2015-01-20 10:48:30 -08004850 break;
4851#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01004852 default:
4853 /*
4854 * TODO: Extend it accordingly
4855 */
4856 break;
4857 }
4858
4859 dev_put(dev);
4860 }
4861}
4862
4863/*
4864 * ecm_interface_stats_update()
4865 * Using the interface lists for the given connection, update the interface statistics for each.
4866 *
4867 * 'from' here is wrt the connection 'from' side. Likewise with 'to'.
4868 * TX is wrt what the interface has transmitted. RX is what the interface has received.
4869 */
4870void ecm_interface_stats_update(struct ecm_db_connection_instance *ci,
4871 uint32_t from_tx_packets, uint32_t from_tx_bytes, uint32_t from_rx_packets, uint32_t from_rx_bytes,
4872 uint32_t to_tx_packets, uint32_t to_tx_bytes, uint32_t to_rx_packets, uint32_t to_rx_bytes)
4873{
4874 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
4875 struct ecm_db_iface_instance *to_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
4876 int from_ifaces_first;
4877 int to_ifaces_first;
4878 uint8_t mac_addr[ETH_ALEN];
4879
4880 /*
4881 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
4882 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
4883 * from_rx_packets / bytes: the amount received by the 'from' interface
4884 */
4885 DEBUG_INFO("%p: Update from interface stats\n", ci);
4886 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
4887 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304888 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 +01004889 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
4890
4891 /*
4892 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
4893 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
4894 * to_rx_packets / bytes: the amount received by the 'to' interface
4895 */
4896 DEBUG_INFO("%p: Update to interface stats\n", ci);
4897 to_ifaces_first = ecm_db_connection_to_interfaces_get_and_ref(ci, to_ifaces);
4898 ecm_db_connection_to_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304899 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 +01004900 ecm_db_connection_interfaces_deref(to_ifaces, to_ifaces_first);
4901}
4902EXPORT_SYMBOL(ecm_interface_stats_update);
4903
Shyam Sunder6358b862015-05-04 15:06:24 +05304904#ifdef ECM_MULTICAST_ENABLE
4905/*
Shyam Sunder6358b862015-05-04 15:06:24 +05304906 * ecm_interface_multicast_stats_update()
4907 * Using the interface lists for the given connection, update the interface statistics for each.
4908 *
4909 * 'from interface' here is the connection 'from' side. Likewise with 'to interface'.
4910 * TX is wrt what the interface has transmitted. RX is what the interface has received.
4911 */
4912void ecm_interface_multicast_stats_update(struct ecm_db_connection_instance *ci, uint32_t from_tx_packets, uint32_t from_tx_bytes,
4913 uint32_t from_rx_packets, uint32_t from_rx_bytes, uint32_t to_tx_packets, uint32_t to_tx_bytes,
4914 uint32_t to_rx_packets, uint32_t to_rx_bytes)
4915{
4916 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304917 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunder6358b862015-05-04 15:06:24 +05304918 struct ecm_db_iface_instance *to_ifaces;
4919 struct ecm_db_iface_instance *ii_temp;
4920 int from_ifaces_first;
4921 int *to_ifaces_first;
4922 int if_index;
4923 int ret;
4924 uint8_t mac_addr[ETH_ALEN];
4925
4926 /*
4927 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
4928 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
4929 * from_rx_packets / bytes: the amount received by the 'from' interface
4930 */
4931 DEBUG_INFO("%p: Update from interface stats\n", ci);
4932 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
4933 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304934 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 +05304935 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
4936
4937 /*
4938 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
4939 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
4940 * to_rx_packets / bytes: the amount received by the 'to' interface
4941 */
4942 DEBUG_INFO("%p: Update to interface stats\n", ci);
4943
4944 /*
4945 * This function allocates the memory for temporary destination interface heirarchies.
4946 * This memory needs to be free at the end.
4947 */
4948 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &to_ifaces, &to_ifaces_first);
4949 if (ret == 0) {
4950 DEBUG_WARN("%p: Get and ref to all multicast detination interface heirarchies failed\n", ci);
4951 return;
4952 }
4953
4954 for (if_index = 0; if_index < ECM_DB_MULTICAST_IF_MAX; if_index++) {
4955 if (to_ifaces_first[if_index] < ECM_DB_IFACE_HEIRARCHY_MAX) {
4956 ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, if_index);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304957 ecm_db_multicast_copy_if_heirarchy(to_list_single, ii_temp);
4958 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 +05304959 }
4960 }
4961
4962 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
4963}
4964EXPORT_SYMBOL(ecm_interface_multicast_stats_update);
4965#endif
4966
Gareth Williamsadf425f2014-05-26 19:29:02 +01004967/*
Ben Menchaca84f36632014-02-28 20:57:38 +00004968 * ecm_interface_regenerate_connections()
4969 * Cause regeneration of all connections that are using the specified interface.
4970 */
4971static void ecm_interface_regenerate_connections(struct ecm_db_iface_instance *ii)
4972{
Gareth Williamsb5903892015-03-20 15:13:07 +00004973#ifdef ECM_DB_XREF_ENABLE
Gareth Williamsa4390962015-08-26 12:51:31 +01004974 struct ecm_db_connection_instance *ci_from;
4975 struct ecm_db_connection_instance *ci_to;
4976 struct ecm_db_connection_instance *ci_from_nat;
4977 struct ecm_db_connection_instance *ci_to_nat;
4978 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
Gareth Williamsb5903892015-03-20 15:13:07 +00004979#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004980
4981 DEBUG_TRACE("Regenerate connections using interface: %p\n", ii);
4982
Gareth Williamsb5903892015-03-20 15:13:07 +00004983#ifndef ECM_DB_XREF_ENABLE
4984 /*
4985 * An interface has changed, re-generate the connections to ensure all state is updated.
4986 */
Tushar Mathurd38cacd2015-07-28 12:19:10 +05304987 ecm_db_regeneration_needed();
Gareth Williamsb5903892015-03-20 15:13:07 +00004988#else
Ben Menchaca84f36632014-02-28 20:57:38 +00004989 /*
Gareth Williamsa4390962015-08-26 12:51:31 +01004990 * If the interface has NO connections then we re-generate all.
4991 */
4992 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
4993 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
4994 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
4995 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
4996 if (!ci_from && !ci_to && !ci_from_nat && !ci_to_nat) {
4997 ecm_db_regeneration_needed();
4998 DEBUG_TRACE("%p: Regenerate (ALL) COMPLETE\n", ii);
4999 return;
5000 }
5001
5002 /*
5003 * Re-generate all connections associated with this interface
Ben Menchaca84f36632014-02-28 20:57:38 +00005004 */
5005 DEBUG_TRACE("%p: Regenerate 'from' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005006 while (ci_from) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005007 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005008 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
Ben Menchaca84f36632014-02-28 20:57:38 +00005009
Gareth Williamsa4390962015-08-26 12:51:31 +01005010 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005011 ecm_db_connection_regenerate(ci_from);
Gareth Williamsa4390962015-08-26 12:51:31 +01005012 ecm_db_connection_deref(ci_from);
5013 ci_from = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005014 }
5015
5016 DEBUG_TRACE("%p: Regenerate 'to' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005017 while (ci_to) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005018 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005019 cin = ecm_db_connection_iface_to_get_and_ref_next(ci_to);
Ben Menchaca84f36632014-02-28 20:57:38 +00005020
Gareth Williamsa4390962015-08-26 12:51:31 +01005021 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005022 ecm_db_connection_regenerate(ci_to);
Gareth Williamsa4390962015-08-26 12:51:31 +01005023 ecm_db_connection_deref(ci_to);
5024 ci_to = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005025 }
5026
Gareth Williamsa4390962015-08-26 12:51:31 +01005027 /*
5028 * GGG TODO These deprecated lists _nat_ lists will eventually be removed
5029 */
Ben Menchaca84f36632014-02-28 20:57:38 +00005030 DEBUG_TRACE("%p: Regenerate 'from_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005031 while (ci_from_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005032 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005033 cin = ecm_db_connection_iface_nat_from_get_and_ref_next(ci_from_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00005034
Gareth Williamsa4390962015-08-26 12:51:31 +01005035 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005036 ecm_db_connection_regenerate(ci_from_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01005037 ecm_db_connection_deref(ci_from_nat);
5038 ci_from_nat = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005039 }
5040
5041 DEBUG_TRACE("%p: Regenerate 'to_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005042 while (ci_to_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005043 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005044 cin = ecm_db_connection_iface_nat_to_get_and_ref_next(ci_to_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00005045
Gareth Williamsa4390962015-08-26 12:51:31 +01005046 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005047 ecm_db_connection_regenerate(ci_to_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01005048 ecm_db_connection_deref(ci_to_nat);
5049 ci_to_nat = cin;
5050 }
5051
5052#ifdef ECM_MULTICAST_ENABLE
5053 /*
5054 * Multicasts would not have recorded in the lists above.
5055 * Our only way to re-gen those is to iterate all multicasts.
5056 * GGG TODO This will be optimised in a future release.
5057 */
5058 ci_mcast = ecm_db_connections_get_and_ref_first();
5059 while (ci_mcast) {
5060 struct ecm_db_connection_instance *cin;
5061
5062 /*
5063 * Multicast and NOT flagged for re-gen?
5064 */
5065 if (ecm_db_multicast_connection_to_interfaces_set_check(ci_mcast)
5066 && ecm_db_connection_regeneration_required_peek(ci_mcast)) {
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005067 ecm_db_connection_regenerate(ci_mcast);
Gareth Williamsa4390962015-08-26 12:51:31 +01005068 }
5069
5070 cin = ecm_db_connection_get_and_ref_next(ci_mcast);
5071 ecm_db_connection_deref(ci_mcast);
5072 ci_mcast = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005073 }
Gareth Williamsb5903892015-03-20 15:13:07 +00005074#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005075
Gareth Williamsa4390962015-08-26 12:51:31 +01005076#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005077 DEBUG_TRACE("%p: Regenerate COMPLETE\n", ii);
5078}
5079
5080/*
5081 * ecm_interface_dev_regenerate_connections()
5082 * Cause regeneration of all connections that are using the specified interface.
5083 */
Tushar Mathurcccbf282015-01-13 01:22:44 +05305084void ecm_interface_dev_regenerate_connections(struct net_device *dev)
Ben Menchaca84f36632014-02-28 20:57:38 +00005085{
5086 struct ecm_db_iface_instance *ii;
5087
5088 DEBUG_INFO("Regenerate connections for: %p (%s)\n", dev, dev->name);
5089
5090 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07005091 * If the interface is known to us then we will get it returned by this
5092 * function and process it accordingly.
Ben Menchaca84f36632014-02-28 20:57:38 +00005093 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07005094 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00005095 if (!ii) {
5096 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5097 return;
5098 }
5099 ecm_interface_regenerate_connections(ii);
5100 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
5101 ecm_db_iface_deref(ii);
5102}
5103
5104/*
Suman Ghosh7a261712016-01-12 21:42:55 +05305105 * ecm_interface_defunct_connections()
5106 * Cause defunct of all connections that are using the specified interface.
5107 */
5108static void ecm_interface_defunct_connections(struct ecm_db_iface_instance *ii)
5109{
5110#ifndef ECM_DB_XREF_ENABLE
5111 ecm_db_connection_defunct_all();
5112#else
5113 struct ecm_db_connection_instance *ci_from;
5114 struct ecm_db_connection_instance *ci_to;
5115 struct ecm_db_connection_instance *ci_from_nat;
5116 struct ecm_db_connection_instance *ci_to_nat;
5117 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
5118
5119 DEBUG_TRACE("defunct connections using interface: %p\n", ii);
5120
5121 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
5122 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
5123 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
5124 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
5125
5126 /*
5127 * Defunct all connections associated with this interface
5128 */
5129 DEBUG_TRACE("%p: Defunct 'from' connections\n", ii);
5130 while (ci_from) {
5131 struct ecm_db_connection_instance *cin;
5132 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
5133
5134 DEBUG_TRACE("%p: Defunct: %p", ii, ci_from);
5135 ecm_db_connection_make_defunct(ci_from);
5136 ecm_db_connection_deref(ci_from);
5137 ci_from = cin;
5138 }
5139
5140 DEBUG_TRACE("%p: Defunct 'to' connections\n", ii);
5141 while (ci_to) {
5142 struct ecm_db_connection_instance *cin;
5143 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to);
5144
5145 DEBUG_TRACE("%p: Defunct: %p", ii, ci_to);
5146 ecm_db_connection_make_defunct(ci_to);
5147 ecm_db_connection_deref(ci_to);
5148 ci_to = cin;
5149 }
5150
5151 DEBUG_TRACE("%p: Defunct 'from_nat' connections\n", ii);
5152 while (ci_from_nat) {
5153 struct ecm_db_connection_instance *cin;
5154 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from_nat);
5155
5156 DEBUG_TRACE("%p: Defunct: %p", ii, ci_from_nat);
5157 ecm_db_connection_make_defunct(ci_from_nat);
5158 ecm_db_connection_deref(ci_from_nat);
5159 ci_from_nat = cin;
5160 }
5161
5162 DEBUG_TRACE("%p: Defunct 'to_nat' connections\n", ii);
5163 while (ci_to_nat) {
5164 struct ecm_db_connection_instance *cin;
5165 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to_nat);
5166
5167 DEBUG_TRACE("%p: Defunct: %p", ii, ci_to_nat);
5168 ecm_db_connection_make_defunct(ci_to_nat);
5169 ecm_db_connection_deref(ci_to_nat);
5170 ci_to_nat = cin;
5171 }
5172#endif
5173 DEBUG_TRACE("%p: Defunct COMPLETE\n", ii);
5174}
5175
5176/*
5177 * ecm_interface_dev_defunct_connections()
5178 * Cause defunct of all connections that are using the specified interface.
5179 */
5180void ecm_interface_dev_defunct_connections(struct net_device *dev)
5181{
5182 struct ecm_db_iface_instance *ii;
5183
5184 DEBUG_INFO("defunct connections for: %p (%s)\n", dev, dev->name);
5185
5186 /*
5187 * If the interface is known to us then we will get it returned by this
5188 * function and process it accordingly.
5189 */
5190 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
5191 if (!ii) {
5192 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5193 return;
5194 }
5195 ecm_interface_defunct_connections(ii);
5196 DEBUG_TRACE("%p: defunct for %p: COMPLETE\n", dev, ii);
5197 ecm_db_iface_deref(ii);
5198}
5199
5200/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005201 * ecm_interface_mtu_change()
5202 * MTU of interface has changed
5203 */
5204static void ecm_interface_mtu_change(struct net_device *dev)
5205{
5206 int mtu;
5207 struct ecm_db_iface_instance *ii;
5208
5209 mtu = dev->mtu;
5210 DEBUG_INFO("%p (%s): MTU Change to: %d\n", dev, dev->name, mtu);
5211
5212 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07005213 * Find the interface for the given device.
Ben Menchaca84f36632014-02-28 20:57:38 +00005214 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07005215 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00005216 if (!ii) {
5217 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5218 return;
5219 }
5220
5221 /*
5222 * Change the mtu
5223 */
5224 ecm_db_iface_mtu_reset(ii, mtu);
5225 DEBUG_TRACE("%p (%s): MTU Changed to: %d\n", dev, dev->name, mtu);
Tushar Mathurad534d62015-06-10 18:37:52 +05305226 if (netif_is_bond_slave(dev)) {
5227 struct net_device *master = NULL;
5228 master = ecm_interface_get_and_hold_dev_master(dev);
5229 DEBUG_ASSERT(master, "Expected a master\n");
5230 ecm_interface_dev_regenerate_connections(master);
5231 dev_put(master);
5232 } else {
5233 ecm_interface_regenerate_connections(ii);
5234 }
5235
Ben Menchaca84f36632014-02-28 20:57:38 +00005236 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
5237 ecm_db_iface_deref(ii);
5238}
5239
5240/*
5241 * ecm_interface_netdev_notifier_callback()
5242 * Netdevice notifier callback to inform us of change of state of a netdevice
5243 */
5244static int ecm_interface_netdev_notifier_callback(struct notifier_block *this, unsigned long event, void *ptr)
5245{
Stephen Wang69379c32015-02-04 18:37:13 -08005246#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0))
Ben Menchaca84f36632014-02-28 20:57:38 +00005247 struct net_device *dev __attribute__ ((unused)) = (struct net_device *)ptr;
Stephen Wang69379c32015-02-04 18:37:13 -08005248#else
5249 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
5250#endif
Tushar Mathurad534d62015-06-10 18:37:52 +05305251 struct net_device *master = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00005252
5253 DEBUG_INFO("Net device notifier for: %p, name: %s, event: %lx\n", dev, dev->name, event);
5254
5255 switch (event) {
5256 case NETDEV_DOWN:
5257 DEBUG_INFO("Net device: %p, DOWN\n", dev);
Tushar Mathurad534d62015-06-10 18:37:52 +05305258 if (netif_is_bond_slave(dev)) {
5259 master = ecm_interface_get_and_hold_dev_master(dev);
5260 DEBUG_ASSERT(master, "Expected a master\n");
5261 ecm_interface_dev_regenerate_connections(master);
5262 dev_put(master);
5263 } else {
5264 ecm_interface_dev_regenerate_connections(dev);
5265 }
Ben Menchaca84f36632014-02-28 20:57:38 +00005266 break;
5267
5268 case NETDEV_CHANGE:
5269 DEBUG_INFO("Net device: %p, CHANGE\n", dev);
5270 if (!netif_carrier_ok(dev)) {
5271 DEBUG_INFO("Net device: %p, CARRIER BAD\n", dev);
Tushar Mathur933907c2014-06-24 17:06:14 +05305272 if (netif_is_bond_slave(dev)) {
Murat Sezginb3731e82014-11-26 12:20:59 -08005273 master = ecm_interface_get_and_hold_dev_master(dev);
5274 DEBUG_ASSERT(master, "Expected a master\n");
5275 ecm_interface_dev_regenerate_connections(master);
5276 dev_put(master);
Tushar Mathur933907c2014-06-24 17:06:14 +05305277 } else {
5278 ecm_interface_dev_regenerate_connections(dev);
5279 }
Ben Menchaca84f36632014-02-28 20:57:38 +00005280 }
5281 break;
5282
5283 case NETDEV_CHANGEMTU:
5284 DEBUG_INFO("Net device: %p, MTU CHANGE\n", dev);
5285 ecm_interface_mtu_change(dev);
5286 break;
5287
5288 default:
5289 DEBUG_TRACE("Net device: %p, UNHANDLED: %lx\n", dev, event);
5290 break;
5291 }
5292
5293 return NOTIFY_DONE;
5294}
5295
5296/*
Murat Sezgin9304d472017-04-14 10:16:52 -07005297 * ecm_interface_node_connections_defunct()
5298 * Defunct the connections on this node.
Murat Sezgina205b042016-07-19 14:18:14 -07005299 */
Murat Sezgin9304d472017-04-14 10:16:52 -07005300void ecm_interface_node_connections_defunct(uint8_t *mac)
Murat Sezgina205b042016-07-19 14:18:14 -07005301{
Murat Sezgina5f3de12016-08-02 17:29:30 -07005302 struct ecm_db_node_instance *ni = NULL;
Murat Sezgina205b042016-07-19 14:18:14 -07005303
5304 if (unlikely(!mac)) {
5305 DEBUG_WARN("mac address is null\n");
5306 return;
5307 }
5308
Murat Sezgina5f3de12016-08-02 17:29:30 -07005309 ni = ecm_db_node_chain_get_and_ref_first(mac);
5310 while (ni) {
5311 struct ecm_db_node_instance *nin;
Murat Sezgina205b042016-07-19 14:18:14 -07005312
Murat Sezgina5f3de12016-08-02 17:29:30 -07005313 if (ecm_db_node_is_mac_addr_equal(ni, mac)) {
Murat Sezgin9304d472017-04-14 10:16:52 -07005314 ecm_db_traverse_node_from_connection_list_and_defunct(ni);
5315 ecm_db_traverse_node_to_connection_list_and_defunct(ni);
5316 ecm_db_traverse_node_from_nat_connection_list_and_defunct(ni);
5317 ecm_db_traverse_node_to_nat_connection_list_and_defunct(ni);
Murat Sezgina5f3de12016-08-02 17:29:30 -07005318 }
5319
5320 /*
5321 * Get next node in the chain
5322 */
5323 nin = ecm_db_node_chain_get_and_ref_next(ni);
5324 ecm_db_node_deref(ni);
5325 ni = nin;
Murat Sezgina205b042016-07-19 14:18:14 -07005326 }
Murat Sezgina205b042016-07-19 14:18:14 -07005327}
Murat Sezgin9304d472017-04-14 10:16:52 -07005328EXPORT_SYMBOL(ecm_interface_node_connections_defunct);
Murat Sezgina205b042016-07-19 14:18:14 -07005329
5330/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005331 * struct notifier_block ecm_interface_netdev_notifier
5332 * Registration for net device changes of state.
5333 */
5334static struct notifier_block ecm_interface_netdev_notifier __read_mostly = {
5335 .notifier_call = ecm_interface_netdev_notifier_callback,
5336};
Murat Sezgina205b042016-07-19 14:18:14 -07005337
Murat Sezgin8c345822015-05-27 15:35:38 -07005338#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
Ben Menchaca84f36632014-02-28 20:57:38 +00005339/*
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305340 * ecm_interfae_node_br_fdb_notify_event()
5341 * This is a call back for "bridge fdb update event/ageing timer expire
5342 * event".
5343 */
5344static int ecm_interface_node_br_fdb_notify_event(struct notifier_block *nb,
5345 unsigned long val,
5346 void *data)
5347{
5348 uint8_t *mac = (uint8_t *)data;
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305349
Murat Sezgin04470032017-07-07 14:53:32 -07005350 if (ECM_FRONT_END_TYPE_NSS == ecm_front_end_type_get()) {
5351 DEBUG_INFO("FDB updated for node %pM\n", mac);
5352 ecm_interface_node_connections_defunct(mac);
5353 }
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305354
5355 return NOTIFY_DONE;
5356}
5357
5358static struct notifier_block ecm_interface_node_br_fdb_update_nb = {
5359 .notifier_call = ecm_interface_node_br_fdb_notify_event,
5360};
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07005361
5362static int ecm_interface_node_br_fdb_delete_event(struct notifier_block *nb,
5363 unsigned long event,
5364 void *ctx)
5365{
5366 struct br_fdb_event *fe = (struct br_fdb_event *)ctx;
5367
5368 if ((event != BR_FDB_EVENT_DEL) || fe->is_local) {
5369 DEBUG_WARN("local fdb or not deleting event, ignore\n");
5370 return NOTIFY_DONE;
5371 }
5372
5373 return ecm_interface_node_br_fdb_notify_event(nb, event, fe->addr);
5374}
5375
5376static struct notifier_block ecm_interface_node_br_fdb_delete_nb = {
5377 .notifier_call = ecm_interface_node_br_fdb_delete_event,
5378};
Murat Sezgin8c345822015-05-27 15:35:38 -07005379#endif
Shyam Sunder6358b862015-05-04 15:06:24 +05305380
5381#ifdef ECM_MULTICAST_ENABLE
5382/*
5383 * ecm_interface_multicast_find_outdated_iface_instances()
5384 *
5385 * Called in the case of Routing/Bridging Multicast update events.
5386 *
5387 * This function takes a list of ifindex for the connection which was received
5388 * from MFC or bridge snooper, compares it against the existing list of interfaces
5389 * in the DB connection, and extracts the list of those interfaces that have left
5390 * the multicast group.
5391 *
5392 * ci A DB connection instance.
5393 * mc_updates Part of return Information. The function will mark the index of those
5394 * interfaces in the DB connection 'to_mcast_interfaces' array that have
5395 * left the group, in the mc_updates->if_leave_idx array. The caller uses this
5396 * information to delete those outdated interface heirarchies from the
5397 * connection.
5398 * is_bridged True if the function called due to bridge multicast snooper update event.
5399 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
5400 * by the update from MFC or Bridge snooper.
5401 * max_to_dev Size of the array 'dst_dev'
5402 *
5403 * Return true if outdated interfaces found
5404 */
5405static bool ecm_interface_multicast_find_outdated_iface_instances(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
5406 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5407{
5408 struct ecm_db_iface_instance *mc_ifaces;
5409 struct ecm_db_iface_instance *ii_temp;
5410 struct ecm_db_iface_instance *ii_single;
5411 struct ecm_db_iface_instance **ifaces;
5412 struct ecm_db_iface_instance *to_iface;
5413 int32_t *to_iface_first;
5414 int32_t *mc_ifaces_first;
5415 uint32_t *dst_if_index;
5416 ecm_db_iface_type_t ii_type;
5417 int32_t heirarchy_index;
5418 int32_t if_index;
5419 int32_t if_cnt = 0;
5420 int found = 0;
5421 int ii;
5422 int ret;
5423 int32_t ifaces_identifier;
5424
5425 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
5426 if (ret == 0) {
5427 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
5428 return false;
5429 }
5430
5431 /*
5432 * Loop through the current interface list in the DB
5433 * connection 'to_mcast_interfaces' array
5434 */
5435 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX; heirarchy_index++) {
5436 found = 0;
5437 to_iface_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5438
5439 /*
5440 * Invalid interface entry, skip
5441 */
5442 if (*to_iface_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5443 continue;
5444 }
5445
5446 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
5447 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ECM_DB_IFACE_HEIRARCHY_MAX - 1);
5448 ifaces = (struct ecm_db_iface_instance **)ii_single;
5449 to_iface = *ifaces;
5450 ii_type = ecm_db_connection_iface_type_get(to_iface);
5451
5452 /*
5453 * If the update was received from bridge snooper, do not consider entries in the
5454 * interface list that are not part of a bridge.
5455 */
5456 if (is_br_snooper && (ii_type != ECM_DB_IFACE_TYPE_BRIDGE)) {
5457 continue;
5458 }
5459
5460 /*
5461 * If the update was received from MFC, do not consider entries in the
5462 * interface list that are part of a bridge. The bridge entries will be
5463 * taken care by the Bridge Snooper Callback
5464 */
5465 if (ii_type == ECM_DB_IFACE_TYPE_BRIDGE) {
5466 if (!is_br_snooper && !(flags & ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG)) {
5467 continue;
5468 }
5469 }
5470
5471 /*
5472 * Try to find a match in the newly received interface list, for any of
5473 * the interface instance in the heirarchy. If found, it means that this
5474 * interface has not left the group. If not found, it means that this
5475 * interface has left the group.
5476 */
5477 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_iface_first; ii--) {
5478 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
5479 ifaces = (struct ecm_db_iface_instance **)ii_single;
5480 to_iface = *ifaces;
5481
5482 ii_type = ecm_db_connection_iface_type_get(to_iface);
5483 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_iface);
5484 for (if_index = 0; if_index < max_to_dev; if_index++) {
5485 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
5486 if (*dst_if_index == ifaces_identifier) {
5487 found = 1;
5488 break;
5489 }
5490 }
5491 if (found) {
5492 break;
5493 }
5494 }
5495
5496 /*
5497 * We did not find a match for the interface in the present list. So mark
5498 * if as one that has left the group.
5499 */
5500 if (!found) {
5501 if_cnt++;
5502 mc_updates->if_leave_idx[heirarchy_index] = 1;
5503 }
5504 }
5505
5506 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
5507 mc_updates->if_leave_cnt = if_cnt;
5508 return (if_cnt > 0);
5509}
5510
5511/*
5512 * ecm_interface_multicast_find_new_iface_instances()
5513 *
5514 * Called in the case of Routing/Bridging Multicast update events.
5515 *
5516 * This function takes a list of ifindex for the connection which was received
5517 * from MFC or bridge snooper, compares it against the existing list of interfaces
5518 * in the DB connection, and extracts the list of the new joinees for the multicast
5519 * group.
5520 *
5521 * ci A DB connection instance.
5522 * mc_updates Part of return Information. The function will mark the index of those
5523 * interfaces in the 'dst_dev' array that have joined the group, in the
5524 * mc_updates->if_join_idx array. The caller uses this information to add the new
5525 * interface heirarchies into the connection.
5526 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
5527 * by the update from MFC or Bridge snooper.
5528 * max_to_dev Size of the array 'dst_dev'
5529 *
5530 * Return true if new joinees found
5531 */
5532static bool ecm_interface_multicast_find_new_iface_instances(struct ecm_db_connection_instance *ci,
5533 struct ecm_multicast_if_update *mc_updates, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5534{
5535 struct ecm_db_iface_instance *mc_ifaces;
5536 struct ecm_db_iface_instance *ii_temp;
5537 struct ecm_db_iface_instance *ii_single;
5538 struct ecm_db_iface_instance **ifaces;
5539 int32_t *mc_ifaces_first;
5540 int32_t *to_list_first;
5541 int32_t heirarchy_index;
5542 int32_t if_index;
5543 int32_t if_cnt = 0;
5544 int found = 0;
5545 int ii;
5546 int ret;
5547 uint32_t *dst_if_index;
5548 int32_t ifaces_identifier;
5549 struct ecm_db_iface_instance *to_list;
5550
5551 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
5552 if (ret == 0) {
5553 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
5554 return false;
5555 }
5556
5557 /*
5558 * Loop through the new interface list 'dst_dev'
5559 */
5560 for (if_index = 0; if_index < max_to_dev; if_index++) {
5561 found = 0;
5562 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
5563 if (*dst_if_index == 0) {
5564 continue;
5565 }
5566
5567 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
5568 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5569
5570 /*
5571 * Invalid interface entry, skip
5572 */
5573 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5574 continue;
5575 }
5576
5577 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
5578
5579 /*
5580 * Try to find a match for this ifindex (dst_dev[if_index]), in any of the
5581 * interface instance in the heirarchy. If not found, it means that this
5582 * ifindex has joined the group. If found, it means that this ifindex was
5583 * already part of the list of destination interfaces.
5584 */
5585 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_list_first; ii--) {
5586 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
5587 ifaces = (struct ecm_db_iface_instance **)ii_single;
5588 to_list = *ifaces;
5589 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_list);
5590 if (*dst_if_index == ifaces_identifier) {
5591 found = 1;
5592 break;
5593 }
5594 }
5595
5596 if (found) {
5597 break;
5598 }
5599 }
5600
5601 /*
5602 * We did not find a match for the interface in the present list. So mark
5603 * it as one that has joined the group.
5604 */
5605 if (!found) {
5606
5607 /*
5608 * Store the if index of the new joinee
5609 */
5610 mc_updates->join_dev[if_cnt] = *dst_if_index;
5611
5612 /*
5613 * Identify a new vacant slot in the 'to_mcast_interfaces' to place
5614 * the new interface
5615 */
5616 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
5617 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5618 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5619 mc_updates->if_join_idx[heirarchy_index] = 1;
5620 break;
5621 }
5622 }
5623
5624 if_cnt++;
5625 }
5626 }
5627
5628 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
5629 mc_updates->if_join_cnt = if_cnt;
5630
5631 return (if_cnt > 0);
5632}
5633
5634/*
5635 * ecm_interface_multicast_find_updates_to_iface_list()
5636 * Process IGMP/MLD updates either from MFC or bridge snooper. Identity the interfaces
5637 * that have left the group and new interfaces that have joined the group.
5638 *
5639 * The function returns true if there was any update necessary to the current destination
5640 * interface list
5641 */
5642bool ecm_interface_multicast_find_updates_to_iface_list(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
5643 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5644{
5645 bool join;
5646 bool leave;
5647 /*
5648 * Find destination interfaces that have left the group
5649 */
5650 leave = ecm_interface_multicast_find_outdated_iface_instances(ci, mc_updates, flags, is_br_snooper, mc_dst_if_index, max_to_dev);
5651 /*
5652 * Find new destination interfaces that have joined the group
5653 */
5654 join = ecm_interface_multicast_find_new_iface_instances(ci, mc_updates, mc_dst_if_index, max_to_dev);
5655
5656 return (leave || join);
5657}
5658EXPORT_SYMBOL(ecm_interface_multicast_find_updates_to_iface_list);
5659#endif
5660
Murat Sezgin42a44c22016-05-05 14:06:39 -07005661#ifdef ECM_DB_XREF_ENABLE
5662/*
5663 * ecm_interface_neigh_mac_update_notify_event()
5664 * Neighbour mac address change handler.
5665 */
5666static int ecm_interface_neigh_mac_update_notify_event(struct notifier_block *nb,
5667 unsigned long val,
5668 void *data)
5669{
Murat Sezgin42a44c22016-05-05 14:06:39 -07005670 struct neigh_mac_update *nmu = (struct neigh_mac_update *)data;
5671
5672 /*
5673 * If the old and new mac addresses are equal, do nothing.
5674 * This case shouldn't happen.
5675 */
5676 if (!ecm_mac_addr_equal(nmu->old_mac, nmu->update_mac)) {
5677 DEBUG_TRACE("old and new mac addresses are equal: %pM\n", nmu->old_mac);
5678 return NOTIFY_DONE;
5679 }
5680
5681 /*
5682 * If the old mac is zero, do nothing. When a host joins the arp table first
5683 * time, its old mac comes as zero. We shouldn't handle this case, because
5684 * there is not any connection in ECM db with zero mac.
5685 */
5686 if (is_zero_ether_addr(nmu->old_mac)) {
5687 DEBUG_WARN("old mac is zero\n");
5688 return NOTIFY_DONE;
5689 }
5690
5691 DEBUG_TRACE("old mac: %pM new mac: %pM\n", nmu->old_mac, nmu->update_mac);
5692
Murat Sezgina205b042016-07-19 14:18:14 -07005693 DEBUG_INFO("neigh mac update notify for node %pM\n", nmu->old_mac);
Murat Sezgin9304d472017-04-14 10:16:52 -07005694 ecm_interface_node_connections_defunct((uint8_t *)nmu->old_mac);
Murat Sezgin42a44c22016-05-05 14:06:39 -07005695
5696 return NOTIFY_DONE;
5697}
5698
5699/*
5700 * struct notifier_block ecm_interface_neigh_mac_update_nb
5701 * Registration for neighbour mac address update.
5702 */
5703static struct notifier_block ecm_interface_neigh_mac_update_nb = {
5704 .notifier_call = ecm_interface_neigh_mac_update_notify_event,
5705};
5706#endif
5707
Murat Sezgin1f381852014-11-20 09:51:07 -08005708/*
Murat Sezgina205b042016-07-19 14:18:14 -07005709 * ecm_interface_wifi_event_iwevent
5710 * wireless event handler
5711 */
5712static int ecm_interface_wifi_event_iwevent(int ifindex, unsigned char *buf, size_t len)
5713{
5714 struct iw_event iwe_buf, *iwe = &iwe_buf;
5715 char *pos, *end;
5716
5717 pos = buf;
5718 end = buf + len;
5719 while (pos + IW_EV_LCP_LEN <= end) {
5720
5721 /*
5722 * Copy the base data structure to get iwe->len
5723 */
5724 memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
5725
5726 /*
5727 * Check that len is valid and that we have that much in the buffer.
5728 *
5729 */
5730 if (iwe->len < IW_EV_LCP_LEN) {
5731 return -1;
5732 }
5733
5734 if ((iwe->len > sizeof (struct iw_event)) || (iwe->len + pos) > end) {
5735 return -1;
5736 }
5737
5738 /*
5739 * Do the copy again with the full length.
5740 */
5741 memcpy(&iwe_buf, pos, iwe->len);
5742
5743 if (iwe->cmd == IWEVREGISTERED) {
5744 DEBUG_INFO("STA %pM joining\n", (uint8_t *)iwe->u.addr.sa_data);
5745 } else if (iwe->cmd == IWEVEXPIRED) {
5746 DEBUG_INFO("STA %pM leaving\n", (uint8_t *)iwe->u.addr.sa_data);
Murat Sezgin9304d472017-04-14 10:16:52 -07005747 ecm_interface_node_connections_defunct((uint8_t *)iwe->u.addr.sa_data);
Murat Sezgina205b042016-07-19 14:18:14 -07005748 } else {
5749 DEBUG_INFO("iwe->cmd is %d for STA %pM\n", iwe->cmd, (unsigned char *) iwe->u.addr.sa_data);
5750 }
5751
5752 pos += iwe->len;
5753 }
5754
5755 return 0;
5756}
5757
5758/*
5759 * ecm_interface_wifi_event_newlink
5760 * Link event handler
5761 */
5762static int ecm_interface_wifi_event_newlink(struct ifinfomsg *ifi, unsigned char *buf, size_t len)
5763{
5764 struct rtattr *attr;
5765 int attrlen, rta_len;
5766
5767 DEBUG_TRACE("Event from interface %d\n", ifi->ifi_index);
5768
5769 attrlen = len;
5770 attr = (struct rtattr *) buf;
5771 rta_len = RTA_ALIGN(sizeof(struct rtattr));
5772
5773 while (RTA_OK(attr, attrlen)) {
5774 if (attr->rta_type == IFLA_WIRELESS) {
5775 ecm_interface_wifi_event_iwevent(ifi->ifi_index, ((char *) attr) + rta_len, attr->rta_len - rta_len);
5776 }
5777 attr = RTA_NEXT(attr, attrlen);
5778 }
5779
5780 return 0;
5781}
5782
5783/*
5784 * ecm_interface_wifi_event_handler
5785 * Netlink event handler
5786 */
5787static int ecm_interface_wifi_event_handler(unsigned char *buf, int len)
5788{
5789 struct nlmsghdr *nlh;
5790 struct ifinfomsg *ifi;
5791 int left;
5792
5793 nlh = (struct nlmsghdr *) buf;
5794 left = len;
5795
5796 while (NLMSG_OK(nlh, left)) {
5797 switch (nlh->nlmsg_type) {
5798 case RTM_NEWLINK:
5799 case RTM_DELLINK:
5800 if (NLMSG_PAYLOAD(nlh, 0) < sizeof(struct ifinfomsg)) {
5801 DEBUG_INFO("invalid netlink message\n");
5802 break;
5803 }
5804
5805 ifi = NLMSG_DATA(nlh);
5806 DEBUG_INFO("ifi->ifi_family: %d\n", ifi->ifi_family);
5807 if (ifi->ifi_family != AF_BRIDGE) {
5808 ecm_interface_wifi_event_newlink(ifi, (u8 *)ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
5809 NLMSG_PAYLOAD(nlh, sizeof(struct ifinfomsg)));
5810 }
5811 break;
5812 }
5813
5814 nlh = NLMSG_NEXT(nlh, left);
5815 }
5816
5817 return 0;
5818}
5819
5820/*
5821 * ecm_interface_wifi_event_rx
5822 * Receive netlink message from socket
5823 */
5824static int ecm_interface_wifi_event_rx(struct socket *sock, struct sockaddr_nl *addr, unsigned char *buf, int len)
5825{
5826 struct msghdr msg;
5827 struct iovec iov;
5828 mm_segment_t oldfs;
5829 int size;
5830
5831 iov.iov_base = buf;
5832 iov.iov_len = len;
5833
5834 msg.msg_flags = 0;
5835 msg.msg_name = addr;
5836 msg.msg_namelen = sizeof(struct sockaddr_nl);
5837 msg.msg_control = NULL;
5838 msg.msg_controllen = 0;
5839#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
5840 msg.msg_iov = &iov;
5841 msg.msg_iovlen = 1;
5842#else
5843 iov_iter_init(&msg.msg_iter, READ, &iov, 1, 1);
5844#endif
5845 oldfs = get_fs();
5846 set_fs(KERNEL_DS);
5847 size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
5848 set_fs(oldfs);
5849
5850 return size;
5851}
5852
5853/*
5854 * ecm_interface_wifi_event_thread
5855 */
5856static void ecm_interface_wifi_event_thread(void)
5857{
5858 int err;
5859 int size;
5860 struct sockaddr_nl saddr;
5861 unsigned char buf[512];
5862 int len = sizeof(buf);
5863
5864 allow_signal(SIGKILL|SIGSTOP);
5865 err = sock_create(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, &__ewn.sock);
5866 if (err < 0) {
5867 DEBUG_ERROR("failed to create sock\n");
5868 goto exit1;
5869 }
5870
Murat Sezginac267642016-11-02 15:55:11 -07005871 memset(&saddr, 0, sizeof(saddr));
Murat Sezgina205b042016-07-19 14:18:14 -07005872 saddr.nl_family = AF_NETLINK;
5873 saddr.nl_groups = RTNLGRP_LINK;
5874 saddr.nl_pid = current->pid;
5875
5876 err = __ewn.sock->ops->bind(__ewn.sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr));
5877 if (err < 0) {
5878 DEBUG_ERROR("failed to bind sock\n");
5879 goto exit2;
5880 }
5881
5882 DEBUG_INFO("ecm_interface_wifi_event thread started\n");
5883 while (!kthread_should_stop()) {
5884 size = ecm_interface_wifi_event_rx(__ewn.sock, &saddr, buf, len);
5885 DEBUG_TRACE("got a netlink msg with len %d\n", size);
5886
5887 if (signal_pending(current))
5888 break;
5889
5890 if (size < 0) {
5891 DEBUG_WARN("netlink rx error\n");
5892 } else {
5893 ecm_interface_wifi_event_handler(buf, size);
5894 }
5895 }
5896
5897 DEBUG_INFO("ecm_interface_wifi_event thread stopped\n");
5898exit2:
5899 sock_release(__ewn.sock);
5900exit1:
5901 __ewn.sock = NULL;
5902
5903 return;
5904}
5905
5906/*
5907 * ecm_interface_wifi_event_start()
5908 */
5909int ecm_interface_wifi_event_start(void)
5910{
5911 if (__ewn.thread) {
5912 return 0;
5913 }
5914
5915 __ewn.thread = kthread_run((void *)ecm_interface_wifi_event_thread, NULL, "ECM_wifi_event");
5916 if (IS_ERR(__ewn.thread)) {
5917 DEBUG_ERROR("Unable to start kernel thread\n");
5918 return -ENOMEM;
5919 }
5920
5921 return 0;
5922}
5923
5924/*
5925 * ecm_interface_wifi_event_stop()
5926 */
5927int ecm_interface_wifi_event_stop(void)
5928{
5929 int err;
5930
5931 if (__ewn.thread == NULL) {
5932 return 0;
5933 }
5934
5935 DEBUG_INFO("kill ecm_interface_wifi_event thread\n");
5936 force_sig(SIGKILL, __ewn.thread);
5937 err = kthread_stop(__ewn.thread);
5938 __ewn.thread = NULL;
5939
5940 return err;
5941}
5942
5943/*
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005944 * ecm_interface_init()
Ben Menchaca84f36632014-02-28 20:57:38 +00005945 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005946int ecm_interface_init(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00005947{
5948 int result;
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005949 DEBUG_INFO("ECM Interface init\n");
Ben Menchaca84f36632014-02-28 20:57:38 +00005950
Ben Menchaca84f36632014-02-28 20:57:38 +00005951 result = register_netdevice_notifier(&ecm_interface_netdev_notifier);
5952 if (result != 0) {
5953 DEBUG_ERROR("Failed to register netdevice notifier %d\n", result);
Murat Sezgin908ecb32015-05-10 20:54:36 -07005954 return result;
Ben Menchaca84f36632014-02-28 20:57:38 +00005955 }
Murat Sezgin8c345822015-05-27 15:35:38 -07005956#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305957 /*
5958 * register for bridge fdb database modificationevents
5959 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05305960 br_fdb_update_register_notify(&ecm_interface_node_br_fdb_update_nb);
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07005961 br_fdb_register_notify(&ecm_interface_node_br_fdb_delete_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07005962#endif
Murat Sezgin42a44c22016-05-05 14:06:39 -07005963#ifdef ECM_DB_XREF_ENABLE
5964 neigh_mac_update_register_notify(&ecm_interface_neigh_mac_update_nb);
5965#endif
Murat Sezgina205b042016-07-19 14:18:14 -07005966 ecm_interface_wifi_event_start();
5967
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005968 return 0;
Ben Menchaca84f36632014-02-28 20:57:38 +00005969}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005970EXPORT_SYMBOL(ecm_interface_init);
Ben Menchaca84f36632014-02-28 20:57:38 +00005971
5972/*
5973 * ecm_interface_exit()
5974 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005975void ecm_interface_exit(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00005976{
5977 DEBUG_INFO("ECM Interface exit\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005978
5979 spin_lock_bh(&ecm_interface_lock);
5980 ecm_interface_terminate_pending = true;
5981 spin_unlock_bh(&ecm_interface_lock);
5982
5983 unregister_netdevice_notifier(&ecm_interface_netdev_notifier);
Murat Sezgin42a44c22016-05-05 14:06:39 -07005984#ifdef ECM_DB_XREF_ENABLE
5985 neigh_mac_update_unregister_notify(&ecm_interface_neigh_mac_update_nb);
5986#endif
5987
Murat Sezgin8c345822015-05-27 15:35:38 -07005988#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305989 /*
5990 * unregister for bridge fdb update events
5991 */
5992 br_fdb_update_unregister_notify(&ecm_interface_node_br_fdb_update_nb);
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07005993 br_fdb_unregister_notify(&ecm_interface_node_br_fdb_delete_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07005994#endif
Murat Sezgina205b042016-07-19 14:18:14 -07005995 ecm_interface_wifi_event_stop();
Ben Menchaca84f36632014-02-28 20:57:38 +00005996}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05005997EXPORT_SYMBOL(ecm_interface_exit);