blob: 1ef54665921be86a938b3ed5dfd3b5a1be9b386d [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 Sezgineebedb92017-11-17 17:14:32 -0800146 * Source interface check flag.
147 * If it is enabled, the acceleration engine will check the flow's interface to see
148 * whether it matches with the rule's source interface or not.
149 */
150int ecm_interface_src_check;
151
152static struct ctl_table_header *ecm_interface_ctl_table_header; /* Sysctl table header */
153
154/*
Murat Sezginb3731e82014-11-26 12:20:59 -0800155 * ecm_interface_get_and_hold_dev_master()
156 * Returns the master device of a net device if any.
157 */
158struct net_device *ecm_interface_get_and_hold_dev_master(struct net_device *dev)
159{
160 struct net_device *master;
161#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,6,0))
162 rcu_read_lock();
163 master = netdev_master_upper_dev_get_rcu(dev);
164 if (!master) {
165 rcu_read_unlock();
166 return NULL;
167 }
168 dev_hold(master);
169 rcu_read_unlock();
170#else
171 master = dev->master;
172 if (!master) {
173 return NULL;
174 }
175 dev_hold(master);
176#endif
177 return master;
178}
179EXPORT_SYMBOL(ecm_interface_get_and_hold_dev_master);
180
181/*
Shyam Sunder9db20852016-03-09 19:04:49 +0530182 * ecm_interface_vlan_real_dev()
183 * Return immediate VLAN net device or Physical device pointer
184 */
185static inline struct net_device *ecm_interface_vlan_real_dev(struct net_device *vlan_dev)
186{
187#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 6, 0))
188 return vlan_dev_next_dev(vlan_dev);
189#else
190 return vlan_dev_real_dev(vlan_dev);
191#endif
192}
193
194/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100195 * ecm_interface_dev_find_by_local_addr_ipv4()
Shyam Sunder9db20852016-03-09 19:04:49 +0530196 * Return a hold to the device for the given local IP address. Returns NULL on failure.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100197 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100198static struct net_device *ecm_interface_dev_find_by_local_addr_ipv4(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100199{
200 __be32 be_addr;
201 struct net_device *dev;
202
203 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, addr);
204 dev = ip_dev_find(&init_net, be_addr);
205 return dev;
206}
207
Gareth Williams8ac34292015-03-17 14:06:58 +0000208#ifdef ECM_IPV6_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +0100209/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100210 * ecm_interface_dev_find_by_local_addr_ipv6()
211 * Return a hold to the device for the given local IP address. Returns NULL on failure.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100212 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100213static struct net_device *ecm_interface_dev_find_by_local_addr_ipv6(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100214{
215 struct in6_addr addr6;
216 struct net_device *dev;
217
218 ECM_IP_ADDR_TO_NIN6_ADDR(addr6, addr);
219 dev = (struct net_device *)ipv6_dev_find(&init_net, &addr6, 1);
220 return dev;
221}
Murat Sezgin49465a42014-11-24 15:37:48 -0800222#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +0100223
224/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100225 * ecm_interface_dev_find_by_local_addr()
226 * Return the device on which the local address resides.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100227 *
228 * Returns a hold to the device or NULL on failure.
229 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100230struct net_device *ecm_interface_dev_find_by_local_addr(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100231{
232 char __attribute__((unused)) addr_str[40];
233
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100234 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
Gareth Williamsadf425f2014-05-26 19:29:02 +0100235 DEBUG_TRACE("Locate dev for: %s\n", addr_str);
236
237 if (ECM_IP_ADDR_IS_V4(addr)) {
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100238 return ecm_interface_dev_find_by_local_addr_ipv4(addr);
Gareth Williamsadf425f2014-05-26 19:29:02 +0100239 }
240
Gareth Williams8ac34292015-03-17 14:06:58 +0000241#ifdef ECM_IPV6_ENABLE
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100242 return ecm_interface_dev_find_by_local_addr_ipv6(addr);
Murat Sezgin49465a42014-11-24 15:37:48 -0800243#else
244 return NULL;
245#endif
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100246}
247EXPORT_SYMBOL(ecm_interface_dev_find_by_local_addr);
248
249/*
250 * ecm_interface_dev_find_by_addr()
251 * Return the net device on which the given IP address resides. Returns NULL on faiure.
252 *
253 * NOTE: The device may be the device upon which has a default gateway to reach the address.
254 * from_local_addr is true when the device was found by a local address search.
255 */
256struct net_device *ecm_interface_dev_find_by_addr(ip_addr_t addr, bool *from_local_addr)
257{
258 char __attribute__((unused)) addr_str[40];
259 struct ecm_interface_route ecm_rt;
260 struct net_device *dev;
261 struct dst_entry *dst;
262
263 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
264
265 /*
266 * Is the address a local IP?
267 */
268 DEBUG_TRACE("find net device for address: %s\n", addr_str);
269 dev = ecm_interface_dev_find_by_local_addr(addr);
270 if (dev) {
271 *from_local_addr = true;
272 DEBUG_TRACE("addr: %s is local: %p (%s)\n", addr_str, dev, dev->name);
273 return dev;
274 }
275
276 DEBUG_TRACE("addr: %s is not local\n", addr_str);
277
278 /*
279 * Try a route to the address instead
280 * NOTE: This will locate a route entry in the route destination *cache*.
281 */
282 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
283 DEBUG_WARN("addr: %s - no dev locatable\n", addr_str);
284 return NULL;
285 }
286
287 *from_local_addr = false;
288 dst = ecm_rt.dst;
289 dev = dst->dev;
290 dev_hold(dev);
291 ecm_interface_route_release(&ecm_rt);
292 DEBUG_TRACE("dest_addr: %s uses dev: %p(%s)\n", addr_str, dev, dev->name);
293 return dev;
Gareth Williamsadf425f2014-05-26 19:29:02 +0100294}
295EXPORT_SYMBOL(ecm_interface_dev_find_by_addr);
296
Gareth Williams8ac34292015-03-17 14:06:58 +0000297#ifdef ECM_IPV6_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +0100298/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000299 * ecm_interface_mac_addr_get_ipv6()
300 * Return mac for an IPv6 address
301 *
302 * GGG TODO Need to make sure this also works for local IP addresses too.
303 */
304static bool ecm_interface_mac_addr_get_ipv6(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
305{
306 struct in6_addr daddr;
307 struct ecm_interface_route ecm_rt;
308 struct neighbour *neigh;
309 struct rt6_info *rt;
310 struct dst_entry *dst;
311
312 /*
313 * Get the MAC address that corresponds to IP address given.
314 * We look up the rt6_info entries and, from its neighbour structure, obtain the hardware address.
315 * This means we will also work if the neighbours are routers too.
316 */
317 ECM_IP_ADDR_TO_NIN6_ADDR(daddr, addr);
318 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
Kiran Kumar C. S. K7d178222014-06-27 18:47:29 +0530319 *on_link = false;
Ben Menchaca84f36632014-02-28 20:57:38 +0000320 return false;
321 }
322 DEBUG_ASSERT(!ecm_rt.v4_route, "Did not locate a v6 route!\n");
323
324 /*
325 * Is this destination on link or off-link via a gateway?
326 */
327 rt = ecm_rt.rt.rtv6;
328 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)) {
329 *on_link = false;
330 ECM_NIN6_ADDR_TO_IP_ADDR(gw_addr, rt->rt6i_gateway)
331 } else {
332 *on_link = true;
333 }
334
335 rcu_read_lock();
336 dst = ecm_rt.dst;
Murat Sezgine9b84582015-01-27 17:34:14 -0800337#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000338 neigh = dst_get_neighbour_noref(dst);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700339 if (neigh) {
340 neigh_hold(neigh);
Murat Sezgine9b84582015-01-27 17:34:14 -0800341 }
342#else
343 neigh = dst_neigh_lookup(dst, &daddr);
344#endif
345 if (!neigh) {
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700346 neigh = neigh_lookup(&nd_tbl, &daddr, dst->dev);
347 }
Murat Sezgine9b84582015-01-27 17:34:14 -0800348
Ben Menchaca84f36632014-02-28 20:57:38 +0000349 if (!neigh) {
350 rcu_read_unlock();
351 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700352 DEBUG_WARN("No neigh reference\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000353 return false;
354 }
355 if (!(neigh->nud_state & NUD_VALID)) {
356 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700357 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000358 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700359 DEBUG_WARN("NUD invalid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000360 return false;
361 }
362 if (!neigh->dev) {
363 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700364 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000365 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700366 DEBUG_WARN("Neigh dev invalid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000367 return false;
368 }
369
370 /*
371 * If neigh->dev is a loopback then addr is a local address in which case we take the MAC from given device
372 */
373 if (neigh->dev->flags & IFF_LOOPBACK) {
374 // GGG TODO Create an equivalent logic to that for ipv4, maybe need to create an ip6_dev_find()?
375 DEBUG_TRACE("local address " ECM_IP_ADDR_OCTAL_FMT " (found loopback)\n", ECM_IP_ADDR_TO_OCTAL(addr));
376 memset(mac_addr, 0, 6);
377 } else {
378 memcpy(mac_addr, neigh->ha, 6);
379 }
380 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700381 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000382 ecm_interface_route_release(&ecm_rt);
383
384 DEBUG_TRACE(ECM_IP_ADDR_OCTAL_FMT " maps to %pM\n", ECM_IP_ADDR_TO_OCTAL(addr), mac_addr);
385 return true;
386}
Murat Sezgin5dae8832015-12-03 14:23:19 -0800387
388/*
389 * ecm_interface_find_gateway_ipv6()
390 * Finds the ipv6 gateway ip address of a given ipv6 address.
391 */
392static bool ecm_interface_find_gateway_ipv6(ip_addr_t addr, ip_addr_t gw_addr)
393{
394 struct ecm_interface_route ecm_rt;
395 struct rt6_info *rt;
396
397 /*
398 * Find the ipv6 route of the given ip address to look up
399 * whether we have a gateway to reach to that ip address or not.
400 */
401 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
402 return false;
403 }
404 DEBUG_ASSERT(!ecm_rt.v4_route, "Did not locate a v6 route!\n");
405 DEBUG_TRACE("Found route\n");
406
407 /*
408 * Is this destination reachable via a gateway?
409 */
410 rt = ecm_rt.rt.rtv6;
411 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 -0700412 ecm_interface_route_release(&ecm_rt);
Murat Sezgin5dae8832015-12-03 14:23:19 -0800413 return false;
414 }
415
416 ECM_NIN6_ADDR_TO_IP_ADDR(gw_addr, rt->rt6i_gateway)
Murat Sezgin313f2222016-08-11 12:22:10 -0700417 ecm_interface_route_release(&ecm_rt);
Murat Sezgin5dae8832015-12-03 14:23:19 -0800418 return true;
419}
Murat Sezgin49465a42014-11-24 15:37:48 -0800420#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000421
422/*
Murat Sezgin5dae8832015-12-03 14:23:19 -0800423 * ecm_interface_find_gateway_ipv4()
424 * Finds the ipv4 gateway address of a given ipv4 address.
425 */
426static bool ecm_interface_find_gateway_ipv4(ip_addr_t addr, ip_addr_t gw_addr)
427{
428 struct ecm_interface_route ecm_rt;
429 struct rtable *rt;
430
431 /*
432 * Find the ipv4 route of the given ip address to look up
433 * whether we have a gateway to reach to that ip address or not.
434 */
435 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
436 return false;
437 }
438 DEBUG_ASSERT(ecm_rt.v4_route, "Did not locate a v4 route!\n");
439 DEBUG_TRACE("Found route\n");
440
441 /*
442 * Is this destination reachable via a gateway?
443 */
444 rt = ecm_rt.rt.rtv4;
445#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
446 if (!(rt->rt_dst != rt->rt_gateway) && !(rt->rt_flags & RTF_GATEWAY)) {
447#else
448 if (!rt->rt_uses_gateway && !(rt->rt_flags & RTF_GATEWAY)) {
449#endif
Murat Sezgin313f2222016-08-11 12:22:10 -0700450 ecm_interface_route_release(&ecm_rt);
Murat Sezgin5dae8832015-12-03 14:23:19 -0800451 return false;
452 }
453
454 ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway)
Murat Sezgin313f2222016-08-11 12:22:10 -0700455 ecm_interface_route_release(&ecm_rt);
Murat Sezgin5dae8832015-12-03 14:23:19 -0800456 return true;
457}
458
459/*
460 * ecm_interface_find_gateway()
461 * Finds the gateway ip address of a given ECM ip address type.
462 */
463bool ecm_interface_find_gateway(ip_addr_t addr, ip_addr_t gw_addr)
464{
465 if (ECM_IP_ADDR_IS_V4(addr)) {
466 return ecm_interface_find_gateway_ipv4(addr, gw_addr);
467 }
468
469#ifdef ECM_IPV6_ENABLE
470 return ecm_interface_find_gateway_ipv6(addr, gw_addr);
471#else
472 return false;
473#endif
474}
475EXPORT_SYMBOL(ecm_interface_find_gateway);
476
477/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000478 * ecm_interface_mac_addr_get_ipv4()
479 * Return mac for an IPv4 address
480 */
481static bool ecm_interface_mac_addr_get_ipv4(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
482{
483 struct neighbour *neigh;
484 struct ecm_interface_route ecm_rt;
485 struct rtable *rt;
486 struct dst_entry *dst;
487 __be32 ipv4_addr;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530488
Ben Menchaca84f36632014-02-28 20:57:38 +0000489 /*
490 * Get the MAC address that corresponds to IP address given.
491 * We look up the rtable entries and, from its neighbour structure, obtain the hardware address.
492 * This means we will also work if the neighbours are routers too.
493 * We also locate the MAC if the address is a local host address.
494 */
495 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
496 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
Kiran Kumar C. S. K7d178222014-06-27 18:47:29 +0530497 *on_link = false;
Ben Menchaca84f36632014-02-28 20:57:38 +0000498 return false;
499 }
500 DEBUG_ASSERT(ecm_rt.v4_route, "Did not locate a v4 route!\n");
Murat Sezginb3731e82014-11-26 12:20:59 -0800501 DEBUG_TRACE("Found route\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000502
503 /*
504 * Is this destination on link or off-link via a gateway?
505 */
506 rt = ecm_rt.rt.rtv4;
Murat Sezginb3731e82014-11-26 12:20:59 -0800507#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000508 if ((rt->rt_dst != rt->rt_gateway) || (rt->rt_flags & RTF_GATEWAY)) {
Murat Sezginb3731e82014-11-26 12:20:59 -0800509#else
510 if (rt->rt_uses_gateway || (rt->rt_flags & RTF_GATEWAY)) {
511#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000512 *on_link = false;
513 ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway)
514 } else {
515 *on_link = true;
516 }
517
518 /*
519 * Get the neighbour entry for the address
520 */
521 rcu_read_lock();
522 dst = ecm_rt.dst;
Murat Sezginb3731e82014-11-26 12:20:59 -0800523#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000524 neigh = dst_get_neighbour_noref(dst);
525 if (neigh) {
526 neigh_hold(neigh);
Murat Sezginb3731e82014-11-26 12:20:59 -0800527 }
528#else
529 neigh = dst_neigh_lookup(dst, &ipv4_addr);
530#endif
531 if (!neigh) {
Ben Menchaca84f36632014-02-28 20:57:38 +0000532 neigh = neigh_lookup(&arp_tbl, &ipv4_addr, dst->dev);
533 }
534 if (!neigh) {
535 rcu_read_unlock();
536 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800537 DEBUG_WARN("no neigh\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000538 return false;
539 }
540 if (!(neigh->nud_state & NUD_VALID)) {
541 rcu_read_unlock();
542 neigh_release(neigh);
543 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800544 DEBUG_WARN("neigh nud state is not valid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000545 return false;
546 }
547 if (!neigh->dev) {
548 rcu_read_unlock();
549 neigh_release(neigh);
550 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800551 DEBUG_WARN("neigh has no device\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000552 return false;
553 }
554
555 /*
556 * If the device is loopback this will be because the address is a local address
557 * In this case locate the device that has this local address and get its mac.
558 */
559 if (neigh->dev->type == ARPHRD_LOOPBACK) {
560 struct net_device *dev;
561
562 DEBUG_TRACE("%pI4 finds loopback device, dev: %p (%s)\n", &ipv4_addr, neigh->dev, neigh->dev->name);
563 rcu_read_unlock();
564 neigh_release(neigh);
565 ecm_interface_route_release(&ecm_rt);
566
567 /*
568 * Lookup the device that has this IP address assigned
569 */
570 dev = ip_dev_find(&init_net, ipv4_addr);
571 if (!dev) {
572 DEBUG_WARN("Unable to locate dev for: %pI4\n", &ipv4_addr);
573 return false;
574 }
575 memcpy(mac_addr, dev->dev_addr, (size_t)dev->addr_len);
576 DEBUG_TRACE("is local addr: %pI4, mac: %pM, dev ifindex: %d, dev: %p (%s), dev_type: %d\n",
577 &ipv4_addr, mac_addr, dev->ifindex, dev, dev->name, dev->type);
578 dev_put(dev);
579 return true;
580 }
581
582 if (!(neigh->dev->flags & IFF_NOARP)) {
583 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
584 } else {
585 DEBUG_TRACE("non-arp device: %p (%s, type: %d) to reach %pI4\n", neigh->dev, neigh->dev->name, neigh->dev->type, &ipv4_addr);
586 memset(mac_addr, 0, 6);
587 }
588 DEBUG_TRACE("addr: %pI4, mac: %pM, iif: %d, neigh dev ifindex: %d, dev: %p (%s), dev_type: %d\n",
589 &ipv4_addr, mac_addr, rt->rt_iif, neigh->dev->ifindex, neigh->dev, neigh->dev->name, neigh->dev->type);
590
591 rcu_read_unlock();
592 neigh_release(neigh);
593 ecm_interface_route_release(&ecm_rt);
594 return true;
595}
596
597/*
598 * ecm_interface_mac_addr_get()
599 * Return the mac address for the given IP address. Returns false on failure.
Ben Menchaca84f36632014-02-28 20:57:38 +0000600 */
601bool ecm_interface_mac_addr_get(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
602{
603 if (ECM_IP_ADDR_IS_V4(addr)) {
604 return ecm_interface_mac_addr_get_ipv4(addr, mac_addr, on_link, gw_addr);
605 }
606
Gareth Williams8ac34292015-03-17 14:06:58 +0000607#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000608 return ecm_interface_mac_addr_get_ipv6(addr, mac_addr, on_link, gw_addr);
Murat Sezgin49465a42014-11-24 15:37:48 -0800609#else
610 return false;
611#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000612}
613EXPORT_SYMBOL(ecm_interface_mac_addr_get);
614
Murat Sezgin5dae8832015-12-03 14:23:19 -0800615#ifdef ECM_IPV6_ENABLE
616/*
617 * ecm_interface_mac_addr_get_ipv6_no_route()
618 * Finds the mac address of a node from its ip address reachable via
619 * the given device. It looks up the mac address in the neighbour entries.
620 * It doesn't do any route lookup to find the dst entry.
621 */
622static bool ecm_interface_mac_addr_get_ipv6_no_route(struct net_device *dev, ip_addr_t addr, uint8_t *mac_addr)
623{
624 struct in6_addr daddr;
625 struct neighbour *neigh;
626 struct net_device *local_dev;
627
628 memset(mac_addr, 0, ETH_ALEN);
629
630 /*
631 * Get the MAC address that corresponds to IP address given.
632 */
633 ECM_IP_ADDR_TO_NIN6_ADDR(daddr, addr);
634 local_dev = ipv6_dev_find(&init_net, &daddr, 1);
635 if (local_dev) {
636 DEBUG_TRACE("%pi6 is a local address\n", &daddr);
637 memcpy(mac_addr, dev->dev_addr, ETH_ALEN);
638 dev_put(local_dev);
639 return true;
640 }
641
642 rcu_read_lock();
643 neigh = neigh_lookup(&nd_tbl, &daddr, dev);
644 if (!neigh) {
645 rcu_read_unlock();
646 DEBUG_WARN("No neigh reference\n");
647 return false;
648 }
649 if (!(neigh->nud_state & NUD_VALID)) {
650 neigh_release(neigh);
651 rcu_read_unlock();
652 DEBUG_WARN("NUD invalid\n");
653 return false;
654 }
655 if (!neigh->dev) {
656 neigh_release(neigh);
657 rcu_read_unlock();
658 DEBUG_WARN("Neigh dev invalid\n");
659 return false;
660 }
661
662 if (neigh->dev->flags & IFF_NOARP) {
663 neigh_release(neigh);
664 rcu_read_unlock();
665 DEBUG_TRACE("dest MAC is zero: %pM\n", mac_addr);
666 return true;
667 }
668
669 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
670 neigh_release(neigh);
671 rcu_read_unlock();
672 DEBUG_TRACE(ECM_IP_ADDR_OCTAL_FMT " maps to %pM\n", ECM_IP_ADDR_TO_OCTAL(addr), mac_addr);
673 return true;
674}
675#endif
676
677/*
678 * ecm_interface_mac_addr_get_ipv4_no_route()
679 * Finds the mac address of a node from its ip address reachable via
680 * the given device. It looks up the mac address in the neighbour entries.
681 * It doesn't do any route lookup to find the dst entry.
682 */
683static bool ecm_interface_mac_addr_get_ipv4_no_route(struct net_device *dev, ip_addr_t ip_addr, uint8_t *mac_addr)
684{
685 struct neighbour *neigh;
686 __be32 be_addr;
687 struct net_device *local_dev;
688
689 memset(mac_addr, 0, ETH_ALEN);
690
691 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, ip_addr);
692 local_dev = ip_dev_find(&init_net, be_addr);
693 if (local_dev) {
694 DEBUG_TRACE("%pI4n is a local address\n", &be_addr);
695 memcpy(mac_addr, dev->dev_addr, ETH_ALEN);
696 dev_put(local_dev);
697 return true;
698 }
699
700 rcu_read_lock();
701 neigh = neigh_lookup(&arp_tbl, &be_addr, dev);
702 if (!neigh) {
703 rcu_read_unlock();
704 DEBUG_WARN("no neigh\n");
705 return false;
706 }
707 if (!(neigh->nud_state & NUD_VALID)) {
708 neigh_release(neigh);
709 rcu_read_unlock();
710 DEBUG_WARN("neigh nud state is not valid\n");
711 return false;
712 }
713 if (!neigh->dev) {
714 neigh_release(neigh);
715 rcu_read_unlock();
716 DEBUG_WARN("neigh has no device\n");
717 return false;
718 }
719
720 if (neigh->dev->flags & IFF_NOARP) {
721 neigh_release(neigh);
722 rcu_read_unlock();
723 DEBUG_TRACE("dest MAC is zero: %pM\n", mac_addr);
724 return true;
725 }
726
727 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
728 neigh_release(neigh);
729 rcu_read_unlock();
730 DEBUG_TRACE("dest MAC: %pM\n", mac_addr);
731 return true;
732
733}
734
735/*
736 * ecm_interface_mac_addr_get_no_route()
737 * Return the mac address for the given IP address reacahble via the given device.
738 * Return false on failure, true on success.
739 */
740bool ecm_interface_mac_addr_get_no_route(struct net_device *dev, ip_addr_t addr, uint8_t *mac_addr)
741{
742 if (ECM_IP_ADDR_IS_V4(addr)) {
743 return ecm_interface_mac_addr_get_ipv4_no_route(dev, addr, mac_addr);
744 }
745
746#ifdef ECM_IPV6_ENABLE
747 return ecm_interface_mac_addr_get_ipv6_no_route(dev, addr, mac_addr);
748#else
749 return false;
750#endif
751}
752EXPORT_SYMBOL(ecm_interface_mac_addr_get_no_route);
753
Shyam Sunder6358b862015-05-04 15:06:24 +0530754#ifdef ECM_MULTICAST_ENABLE
755/*
756 * ecm_interface_multicast_check_for_br_dev()
757 * Find a bridge dev is present or not in an
758 * array of Ifindexs
759 */
760bool ecm_interface_multicast_check_for_br_dev(uint32_t dest_if[], uint8_t max_if)
761{
762 struct net_device *br_dev;
763 int i;
764
765 for (i = 0; i < max_if; i++) {
766 br_dev = dev_get_by_index(&init_net, dest_if[i]);
767 if (!br_dev) {
768 DEBUG_ASSERT(NULL, "expected only valid netdev here\n");
769 continue;
770 }
771
772 if (ecm_front_end_is_bridge_device(br_dev)) {
773 dev_put(br_dev);
774 return true;
775 }
776 dev_put(br_dev);
777 }
778 return false;
779}
780EXPORT_SYMBOL(ecm_interface_multicast_check_for_br_dev);
Shyam Sundera2e08ee2015-06-18 21:32:13 +0530781
782/*
783 * ecm_interface_multicast_check_for_src_if_index()
784 * Find if a source netdev ifindex is matching with list of
785 * multicast destination netdev ifindex. If find a match then
786 * returns a new list of destination netdev ifindex excluding
787 * the ifindex of source netdev.
788 */
789int32_t ecm_interface_multicast_check_for_src_ifindex(int32_t mc_if_index[], int32_t max_if_index, int32_t if_num)
790{
791 int32_t i;
792 int32_t valid_index;
793
794 for (i = 0, valid_index = 0; i < max_if_index; i++) {
795 if (mc_if_index[i] == 0) {
796 break;
797 }
798
799 if (mc_if_index[i] != if_num) {
800 mc_if_index[valid_index] = mc_if_index[i];
801 valid_index++;
802 continue;
803 }
804 }
805
806 return valid_index;
807}
808EXPORT_SYMBOL(ecm_interface_multicast_check_for_src_ifindex);
Shyam Sunder6358b862015-05-04 15:06:24 +0530809#endif
810
Ben Menchaca84f36632014-02-28 20:57:38 +0000811/*
812 * ecm_interface_addr_find_route_by_addr_ipv4()
813 * Return the route for the given IP address. Returns NULL on failure.
814 */
815static bool ecm_interface_find_route_by_addr_ipv4(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
816{
817 __be32 be_addr;
818
819 /*
820 * Get a route to the given IP address, this will allow us to also find the interface
821 * it is using to communicate with that IP address.
822 */
823 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, addr);
824 ecm_rt->rt.rtv4 = ip_route_output(&init_net, be_addr, 0, 0, 0);
825 if (IS_ERR(ecm_rt->rt.rtv4)) {
826 DEBUG_TRACE("No output route to: %pI4n\n", &be_addr);
827 return false;
828 }
829 DEBUG_TRACE("Output route to: %pI4n is: %p\n", &be_addr, ecm_rt->rt.rtv4);
830 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv4;
831 ecm_rt->v4_route = true;
832 return true;
833}
834
Gareth Williams8ac34292015-03-17 14:06:58 +0000835#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000836/*
837 * ecm_interface_addr_find_route_by_addr_ipv6()
838 * Return the route for the given IP address. Returns NULL on failure.
839 */
840static bool ecm_interface_find_route_by_addr_ipv6(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
841{
842 struct in6_addr naddr;
843
844 ECM_IP_ADDR_TO_NIN6_ADDR(naddr, addr);
845
846 /*
847 * Get a route to the given IP address, this will allow us to also find the interface
848 * it is using to communicate with that IP address.
849 */
850 ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, 0);
851 if (!ecm_rt->rt.rtv6) {
852 DEBUG_TRACE("No output route to: " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
853 return NULL;
854 }
855 DEBUG_TRACE("Output route to: " ECM_IP_ADDR_OCTAL_FMT " is: %p\n", ECM_IP_ADDR_TO_OCTAL(addr), ecm_rt->rt.rtv6);
856 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv6;
857 ecm_rt->v4_route = false;
858 return true;
859}
Murat Sezgin49465a42014-11-24 15:37:48 -0800860#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000861
862/*
863 * ecm_interface_addr_find_route_by_addr()
864 * Return the route (in the given parameter) for the given IP address. Returns false on failure.
865 *
866 * Route is the device on which the addr is reachable, which may be loopback for local addresses.
867 *
868 * Returns true if the route was able to be located. The route must be released using ecm_interface_route_release().
869 */
870bool ecm_interface_find_route_by_addr(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
871{
872 char __attribute__((unused)) addr_str[40];
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530873
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100874 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
Ben Menchaca84f36632014-02-28 20:57:38 +0000875 DEBUG_TRACE("Locate route to: %s\n", addr_str);
876
877 if (ECM_IP_ADDR_IS_V4(addr)) {
878 return ecm_interface_find_route_by_addr_ipv4(addr, ecm_rt);
879 }
880
Gareth Williams8ac34292015-03-17 14:06:58 +0000881#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000882 return ecm_interface_find_route_by_addr_ipv6(addr, ecm_rt);
Murat Sezgin49465a42014-11-24 15:37:48 -0800883#else
884 return false;
885#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000886}
887EXPORT_SYMBOL(ecm_interface_find_route_by_addr);
888
889/*
890 * ecm_interface_route_release()
891 * Release an ecm route
892 */
893void ecm_interface_route_release(struct ecm_interface_route *rt)
894{
895 dst_release(rt->dst);
896}
897EXPORT_SYMBOL(ecm_interface_route_release);
898
Murat Sezgin188b4a32015-06-03 10:58:59 -0700899#ifdef ECM_IPV6_ENABLE
900/*
901 * ecm_interface_send_neighbour_solicitation()
902 * Issue an IPv6 Neighbour soliciation request.
903 */
904void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t addr)
905{
906 struct in6_addr dst_addr, src_addr;
907 struct in6_addr mc_dst_addr;
908 struct rt6_info *rt6i;
909 struct neighbour *neigh;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700910 struct net *netf = dev_net(dev);
911 int ret;
912
Murat Sezgin188b4a32015-06-03 10:58:59 -0700913 /*
914 * Find source and destination addresses in Linux format. We need
915 * mcast destination address as well.
916 */
917 ECM_IP_ADDR_TO_NIN6_ADDR(dst_addr, addr);
918 addrconf_addr_solict_mult(&dst_addr, &mc_dst_addr);
Murat Sezgin96ed0342017-05-19 09:48:57 -0700919 ret = ipv6_dev_get_saddr(netf, dev, &mc_dst_addr, 0, &src_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700920
921 /*
Murat Sezgin188b4a32015-06-03 10:58:59 -0700922 * Find the route entry
923 */
924 rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0);
925 if (!rt6i) {
Murat Sezginf21210e2016-04-04 13:58:20 -0700926 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 -0700927 return;
928 }
929
930 /*
931 * Find the neighbor entry
932 */
933#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
934 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, &dst_addr);
935#else
936 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr);
937#endif
938 if (neigh == NULL) {
Murat Sezginf21210e2016-04-04 13:58:20 -0700939 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 -0700940 dst_release(&rt6i->dst);
941 return;
942 }
943
944 /*
945 * Issue a Neighbour soliciation request
946 */
947 DEBUG_TRACE("Issue Neighbour solicitation request\n");
Murat Sezgine1c51d82016-02-10 16:42:58 -0800948#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
Murat Sezgin188b4a32015-06-03 10:58:59 -0700949 ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr);
Murat Sezgine1c51d82016-02-10 16:42:58 -0800950#else
951 ndisc_send_ns(dev, &dst_addr, &mc_dst_addr, &src_addr);
952#endif
Murat Sezgin188b4a32015-06-03 10:58:59 -0700953 neigh_release(neigh);
954 dst_release(&rt6i->dst);
955}
956EXPORT_SYMBOL(ecm_interface_send_neighbour_solicitation);
957#endif
958
959/*
960 * ecm_interface_send_arp_request()
961 * Issue and ARP request.
962 */
963void ecm_interface_send_arp_request(struct net_device *dest_dev, ip_addr_t dest_addr, bool on_link, ip_addr_t gw_addr)
964{
965 /*
966 * Possible ARP does not know the address yet
967 */
Murat Sezgin4c093212016-03-24 14:59:02 -0700968 struct neighbour *neigh;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700969 __be32 ipv4_addr;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700970
971 /*
Murat Sezgin987493e2016-04-15 12:33:47 -0700972 * Convert the ECM IP address type to network order IPv4 address.
Murat Sezgin188b4a32015-06-03 10:58:59 -0700973 */
974 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700975
976 /*
977 * If we have a GW for this address, then we have to send ARP request to the GW
978 */
979 if (!on_link && !ECM_IP_ADDR_IS_NULL(gw_addr)) {
980 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, gw_addr);
981 }
982
Murat Sezgin4c093212016-03-24 14:59:02 -0700983 /*
984 * If we don't have this neighbor, create it before sending the arp request,
985 * so that when we receive the arp reply we update the neigh entry.
986 */
987 neigh = neigh_lookup(&arp_tbl, &ipv4_addr, dest_dev);
988 if (!neigh) {
Murat Sezgin987493e2016-04-15 12:33:47 -0700989 neigh = neigh_create(&arp_tbl, &ipv4_addr, dest_dev);
990 if (IS_ERR(neigh)) {
991 DEBUG_WARN("Unable to create ARP request neigh for %pI4\n", &ipv4_addr);
992 return;
993 }
Murat Sezgin4c093212016-03-24 14:59:02 -0700994 }
Murat Sezgin188b4a32015-06-03 10:58:59 -0700995
Murat Sezgin987493e2016-04-15 12:33:47 -0700996 DEBUG_TRACE("Send ARP for %pI4\n", &ipv4_addr);
997 neigh_event_send(neigh, NULL);
998 neigh_release(neigh);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700999}
1000EXPORT_SYMBOL(ecm_interface_send_arp_request);
1001
Xiaoping Fanc7735462015-08-09 18:57:26 -07001002/*
1003 * ecm_interface_ipv4_neigh_get()
1004 * Returns neighbour reference for a given IP address which must be released when you are done with it.
1005 *
1006 * Returns NULL on fail.
1007 */
1008struct neighbour *ecm_interface_ipv4_neigh_get(ip_addr_t addr)
1009{
1010 struct neighbour *neigh;
1011 struct rtable *rt;
1012 struct dst_entry *dst;
1013 __be32 ipv4_addr;
1014
1015 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
1016 rt = ip_route_output(&init_net, ipv4_addr, 0, 0, 0);
1017 if (IS_ERR(rt)) {
1018 return NULL;
1019 }
1020 dst = (struct dst_entry *)rt;
1021 neigh = dst_neigh_lookup(dst, &ipv4_addr);
1022 ip_rt_put(rt);
1023 return neigh;
1024}
1025
1026#ifdef ECM_IPV6_ENABLE
1027/*
1028 * ecm_interface_ipv6_neigh_get()
1029 * Returns neighbour reference for a given IP address which must be released when you are done with it.
1030 *
1031 * Returns NULL on fail.
1032 */
1033struct neighbour *ecm_interface_ipv6_neigh_get(ip_addr_t addr)
1034{
1035 struct neighbour *neigh;
1036 struct rt6_info *rt;
1037 struct dst_entry *dst;
1038 struct in6_addr ipv6_addr;
1039
1040 ECM_IP_ADDR_TO_NIN6_ADDR(ipv6_addr, addr);
1041 rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0);
1042 if (!rt) {
1043 return NULL;
1044 }
1045 dst = (struct dst_entry *)rt;
1046 neigh = dst_neigh_lookup(dst, &ipv6_addr);
1047 dst_release(dst);
1048 return neigh;
1049}
1050#endif
1051
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301052/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301053 * ecm_interface_is_pptp()
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301054 * skip pptp tunnel encapsulated traffic
1055 *
Shyam Sunder23f2e542015-09-28 14:56:49 +05301056 * ECM does not handle PPTP,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301057 * this function detects packets of that type so they can be skipped over to improve their throughput.
1058 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301059bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out)
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301060{
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301061 struct net_device *in;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301062
ratheesh kannothf4801a02016-12-09 22:46:39 +05301063 /*
1064 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1065 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301066 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301067 if (out->priv_flags & IFF_PPP_PPTP) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301068 return true;
1069 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301070 }
1071
1072 in = dev_get_by_index(&init_net, skb->skb_iif);
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301073 if (!in) {
1074 return true;
1075 }
1076
1077 if (in->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301078 if (in->priv_flags & IFF_PPP_PPTP) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301079 dev_put(in);
1080 return true;
1081 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05301082 }
1083
1084 dev_put(in);
1085 return false;
1086}
1087
Shyam Sunder2ca02492016-08-05 20:55:12 +05301088#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder23f2e542015-09-28 14:56:49 +05301089/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301090 * ecm_interface_is_l2tp_packet_by_version()
Shyam Sunder23f2e542015-09-28 14:56:49 +05301091 * Check version of l2tp tunnel encapsulated traffic
1092 *
1093 * ECM does not handle l2tp,
1094 * this function detects packets of that type so they can be skipped over to improve their throughput.
1095 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301096bool 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 +05301097{
ratheesh kannothf4801a02016-12-09 22:46:39 +05301098 uint32_t flag = 0;
Shyam Sunder23f2e542015-09-28 14:56:49 +05301099 struct net_device *in;
1100
ratheesh kannothf4801a02016-12-09 22:46:39 +05301101 switch (ver) {
1102 case 2:
1103 flag = IFF_PPP_L2TPV2;
1104 break;
1105 case 3:
1106 flag = IFF_PPP_L2TPV3;
1107 break;
1108 default:
1109 break;
1110 }
1111
1112 /*
1113 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1114 */
Shyam Sunder23f2e542015-09-28 14:56:49 +05301115 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301116 if (out->priv_flags & flag) {
Shyam Sunder23f2e542015-09-28 14:56:49 +05301117 return true;
1118 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05301119 }
1120
1121 in = dev_get_by_index(&init_net, skb->skb_iif);
1122 if (!in) {
1123 return true;
1124 }
1125
1126 if (in->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301127 if (in->priv_flags & flag) {
Shyam Sunder23f2e542015-09-28 14:56:49 +05301128 dev_put(in);
1129 return true;
1130 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301131 }
1132
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301133 dev_put(in);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301134 return false;
1135}
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301136
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001137/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301138 * ecm_interface_is_l2tp_pptp()
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001139 * skip l2tp/pptp tunnel encapsulated traffic
1140 *
1141 * ECM does not handle L2TP or PPTP encapsulated packets,
1142 * this function detects packets of that type so they can be skipped over to improve their throughput.
1143 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301144bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *out)
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001145{
ratheesh kannothf4801a02016-12-09 22:46:39 +05301146 struct net_device *in;
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001147
1148 /*
1149 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1150 */
1151 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301152 if (out->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 |
1153 IFF_PPP_PPTP)) {
1154 return true;
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001155 }
1156 }
1157
ratheesh kannothf4801a02016-12-09 22:46:39 +05301158 in = dev_get_by_index(&init_net, skb->skb_iif);
1159 if (!in) {
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001160 return true;
1161 }
1162
ratheesh kannothf4801a02016-12-09 22:46:39 +05301163 if (in->type == ARPHRD_PPP) {
1164 if (in->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 |
1165 IFF_PPP_PPTP)) {
1166 dev_put(in);
1167 return true;
1168 }
1169 }
1170
1171 dev_put(in);
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001172 return false;
ratheesh kannothf4801a02016-12-09 22:46:39 +05301173
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001174}
1175#endif
1176
Gareth Williams141d2382014-11-25 11:35:19 -08001177#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001178/*
Ben Menchaca84f36632014-02-28 20:57:38 +00001179 * ecm_interface_vlan_interface_establish()
1180 * Returns a reference to a iface of the VLAN type, possibly creating one if necessary.
1181 * Returns NULL on failure or a reference to interface.
1182 */
1183static 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 -07001184 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001185{
1186 struct ecm_db_iface_instance *nii;
1187 struct ecm_db_iface_instance *ii;
1188
Murat Sezgin91c5d712015-06-12 15:16:22 -07001189 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",
1190 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 +00001191
1192 /*
1193 * Locate the iface
1194 */
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301195 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 +00001196 if (ii) {
1197 DEBUG_TRACE("%p: iface established\n", ii);
1198 return ii;
1199 }
1200
1201 /*
1202 * No iface - create one
1203 */
1204 nii = ecm_db_iface_alloc();
1205 if (!nii) {
1206 DEBUG_WARN("Failed to establish iface\n");
1207 return NULL;
1208 }
1209
1210 /*
1211 * Add iface into the database, atomically to avoid races creating the same thing
1212 */
1213 spin_lock_bh(&ecm_interface_lock);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301214 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 +00001215 if (ii) {
1216 spin_unlock_bh(&ecm_interface_lock);
1217 ecm_db_iface_deref(nii);
1218 return ii;
1219 }
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301220 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 -07001221 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001222 spin_unlock_bh(&ecm_interface_lock);
1223
1224 DEBUG_TRACE("%p: vlan iface established\n", nii);
1225 return nii;
1226}
Gareth Williams141d2382014-11-25 11:35:19 -08001227#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001228
1229/*
1230 * ecm_interface_bridge_interface_establish()
1231 * Returns a reference to a iface of the BRIDGE type, possibly creating one if necessary.
1232 * Returns NULL on failure or a reference to interface.
1233 */
1234static 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 -07001235 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001236{
1237 struct ecm_db_iface_instance *nii;
1238 struct ecm_db_iface_instance *ii;
1239
Murat Sezgin91c5d712015-06-12 15:16:22 -07001240 DEBUG_INFO("Establish BRIDGE iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1241 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001242
1243 /*
1244 * Locate the iface
1245 */
1246 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1247 if (ii) {
1248 DEBUG_TRACE("%p: iface established\n", ii);
1249 return ii;
1250 }
1251
1252 /*
1253 * No iface - create one
1254 */
1255 nii = ecm_db_iface_alloc();
1256 if (!nii) {
1257 DEBUG_WARN("Failed to establish iface\n");
1258 return NULL;
1259 }
1260
1261 /*
1262 * Add iface into the database, atomically to avoid races creating the same thing
1263 */
1264 spin_lock_bh(&ecm_interface_lock);
1265 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1266 if (ii) {
1267 spin_unlock_bh(&ecm_interface_lock);
1268 ecm_db_iface_deref(nii);
1269 return ii;
1270 }
1271 ecm_db_iface_add_bridge(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001272 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001273 spin_unlock_bh(&ecm_interface_lock);
1274
1275 DEBUG_TRACE("%p: bridge iface established\n", nii);
1276 return nii;
1277}
1278
Murat Sezgin910c9662015-03-11 16:15:06 -07001279#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001280/*
1281 * ecm_interface_lag_interface_establish()
1282 * Returns a reference to a iface of the LAG type, possibly creating one if necessary.
1283 * Returns NULL on failure or a reference to interface.
1284 */
1285static 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 -07001286 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001287{
1288 struct ecm_db_iface_instance *nii;
1289 struct ecm_db_iface_instance *ii;
1290
Murat Sezgin91c5d712015-06-12 15:16:22 -07001291 DEBUG_INFO("Establish LAG iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1292 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001293
1294 /*
1295 * Locate the iface
1296 */
1297 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1298 if (ii) {
1299 DEBUG_TRACE("%p: iface established\n", ii);
1300 return ii;
1301 }
1302
1303 /*
1304 * No iface - create one
1305 */
1306 nii = ecm_db_iface_alloc();
1307 if (!nii) {
1308 DEBUG_WARN("Failed to establish iface\n");
1309 return NULL;
1310 }
1311
1312 /*
1313 * Add iface into the database, atomically to avoid races creating the same thing
1314 */
1315 spin_lock_bh(&ecm_interface_lock);
1316 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1317 if (ii) {
1318 spin_unlock_bh(&ecm_interface_lock);
1319 ecm_db_iface_deref(nii);
1320 return ii;
1321 }
1322 ecm_db_iface_add_lag(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001323 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001324 spin_unlock_bh(&ecm_interface_lock);
1325
1326 DEBUG_TRACE("%p: lag iface established\n", nii);
1327 return nii;
1328}
Murat Sezgin910c9662015-03-11 16:15:06 -07001329#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001330
1331/*
1332 * ecm_interface_ethernet_interface_establish()
1333 * Returns a reference to a iface of the ETHERNET type, possibly creating one if necessary.
1334 * Returns NULL on failure or a reference to interface.
1335 */
1336static 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 -07001337 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001338{
1339 struct ecm_db_iface_instance *nii;
1340 struct ecm_db_iface_instance *ii;
1341
Murat Sezgin91c5d712015-06-12 15:16:22 -07001342 DEBUG_INFO("Establish ETHERNET iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1343 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001344
1345 /*
1346 * Locate the iface
1347 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301348 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
1349
Ben Menchaca84f36632014-02-28 20:57:38 +00001350 if (ii) {
1351 DEBUG_TRACE("%p: iface established\n", ii);
Murat Sezgin5f2947a2016-06-28 12:09:33 -07001352 /*
1353 * Update the accel engine interface identifier, just in case it was changed.
1354 */
1355 ecm_db_iface_ae_interface_identifier_set(ii, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001356 return ii;
1357 }
1358
1359 /*
1360 * No iface - create one
1361 */
1362 nii = ecm_db_iface_alloc();
1363 if (!nii) {
1364 DEBUG_WARN("Failed to establish iface\n");
1365 return NULL;
1366 }
1367
1368 /*
1369 * Add iface into the database, atomically to avoid races creating the same thing
1370 */
1371 spin_lock_bh(&ecm_interface_lock);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301372 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001373 if (ii) {
1374 spin_unlock_bh(&ecm_interface_lock);
1375 ecm_db_iface_deref(nii);
1376 return ii;
1377 }
1378 ecm_db_iface_add_ethernet(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001379 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001380 spin_unlock_bh(&ecm_interface_lock);
1381
1382 DEBUG_TRACE("%p: ethernet iface established\n", nii);
1383 return nii;
1384}
1385
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301386#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001387/*
1388 * ecm_interface_pppoe_interface_establish()
1389 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1390 * Returns NULL on failure or a reference to interface.
1391 */
1392static 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 -07001393 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001394{
1395 struct ecm_db_iface_instance *nii;
1396 struct ecm_db_iface_instance *ii;
1397
Murat Sezgin91c5d712015-06-12 15:16:22 -07001398 DEBUG_INFO("Establish PPPoE iface: %s with session id: %u, remote mac: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1399 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 +00001400
1401 /*
1402 * Locate the iface
1403 */
1404 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1405 if (ii) {
1406 DEBUG_TRACE("%p: iface established\n", ii);
1407 return ii;
1408 }
1409
1410 /*
1411 * No iface - create one
1412 */
1413 nii = ecm_db_iface_alloc();
1414 if (!nii) {
1415 DEBUG_WARN("Failed to establish iface\n");
1416 return NULL;
1417 }
1418
1419 /*
1420 * Add iface into the database, atomically to avoid races creating the same thing
1421 */
1422 spin_lock_bh(&ecm_interface_lock);
1423 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1424 if (ii) {
1425 spin_unlock_bh(&ecm_interface_lock);
1426 ecm_db_iface_deref(nii);
1427 return ii;
1428 }
1429 ecm_db_iface_add_pppoe(nii, type_info->pppoe_session_id, type_info->remote_mac, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001430 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001431 spin_unlock_bh(&ecm_interface_lock);
1432
1433 DEBUG_TRACE("%p: pppoe iface established\n", nii);
1434 return nii;
1435}
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001436#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001437
ratheesh kannothcfdcb332015-12-24 07:19:18 +05301438#ifdef ECM_INTERFACE_MAP_T_ENABLE
1439/*
1440 * ecm_interface_map_t_interface_establish()
1441 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1442 * Returns NULL on failure or a reference to interface.
1443 */
1444static struct ecm_db_iface_instance *ecm_interface_map_t_interface_establish(struct ecm_db_interface_info_map_t *type_info,
1445 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1446{
1447 struct ecm_db_iface_instance *nii;
1448 struct ecm_db_iface_instance *ii;
1449
1450 DEBUG_TRACE("Establish MAP-T iface: %s MTU: %d, if num: %d, accel engine if id: %d\n",
1451 dev_name, mtu, dev_interface_num, ae_interface_num);
1452
1453 /*
1454 * Locate the iface
1455 */
1456 ii = ecm_db_iface_find_and_ref_map_t(type_info->if_index);
1457 if (ii) {
1458 DEBUG_TRACE("%p: iface established\n", ii);
1459 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1460 return ii;
1461 }
1462
1463 /*
1464 * No iface - create one
1465 */
1466 nii = ecm_db_iface_alloc();
1467 if (!nii) {
1468 DEBUG_WARN("Failed to establish iface\n");
1469 return NULL;
1470 }
1471
1472 /*
1473 * Add iface into the database, atomically to avoid races creating the same thing
1474 */
1475 spin_lock_bh(&ecm_interface_lock);
1476 ii = ecm_db_iface_find_and_ref_map_t(type_info->if_index);
1477 if (ii) {
1478 spin_unlock_bh(&ecm_interface_lock);
1479 ecm_db_iface_deref(nii);
1480 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1481 return ii;
1482 }
1483 ecm_db_iface_add_map_t(nii, type_info, dev_name,
1484 mtu, dev_interface_num, ae_interface_num, NULL, nii);
1485 spin_unlock_bh(&ecm_interface_lock);
1486
1487 DEBUG_TRACE("%p: map_t iface established\n", nii);
1488 return nii;
1489}
1490#endif
1491
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301492#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1493/*
1494 * ecm_interface_pppol2tpv2_interface_establish()
1495 * Returns a reference to a iface of the PPPoL2TPV2 type, possibly creating one if necessary.
1496 * Returns NULL on failure or a reference to interface.
1497 */
1498static struct ecm_db_iface_instance *ecm_interface_pppol2tpv2_interface_establish(struct ecm_db_interface_info_pppol2tpv2 *type_info,
1499 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1500{
1501 struct ecm_db_iface_instance *nii;
1502 struct ecm_db_iface_instance *ii;
1503
1504 DEBUG_INFO("Establish PPPol2tp iface: %s with tunnel id=%u session id %u\n", dev_name, type_info->l2tp.tunnel.tunnel_id,
1505 type_info->l2tp.session.session_id);
1506 /*
1507 * Locate the iface
1508 */
1509 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1510 if (ii) {
1511 DEBUG_TRACE("%p: iface established\n", ii);
ratheesh kannothed721852015-09-28 12:39:52 +05301512 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301513 return ii;
1514 }
1515
1516 /*
1517 * No iface - create one
1518 */
1519 nii = ecm_db_iface_alloc();
1520 if (!nii) {
1521 DEBUG_WARN("Failed to establish iface\n");
1522 return NULL;
1523 }
1524
1525 /*
1526 * Add iface into the database, atomically to avoid races creating the same thing
1527 */
1528 spin_lock_bh(&ecm_interface_lock);
1529 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1530 if (ii) {
1531 spin_unlock_bh(&ecm_interface_lock);
1532 ecm_db_iface_deref(nii);
ratheesh kannothed721852015-09-28 12:39:52 +05301533 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301534 return ii;
1535 }
1536
1537 ecm_db_iface_add_pppol2tpv2(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1538 spin_unlock_bh(&ecm_interface_lock);
1539
1540 DEBUG_TRACE("%p: pppol2tpv2 iface established\n", nii);
1541 return nii;
1542}
1543
1544#endif
1545
Shyam Sunder23f2e542015-09-28 14:56:49 +05301546#ifdef ECM_INTERFACE_PPTP_ENABLE
1547/*
1548 * ecm_interface_pptp_interface_establish()
1549 * Returns a reference to a iface of the PPTP type, possibly creating one if necessary.
1550 * Returns NULL on failure or a reference to interface.
1551 */
1552static struct ecm_db_iface_instance *ecm_interface_pptp_interface_establish(struct ecm_db_interface_info_pptp *type_info,
1553 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1554{
1555 struct ecm_db_iface_instance *nii;
1556 struct ecm_db_iface_instance *ii;
1557
1558 DEBUG_INFO("Establish PPTP iface: %s with local call id %u peer call id %u\n", dev_name, type_info->src_call_id,
1559 type_info->dst_call_id);
1560 /*
1561 * Locate the iface
1562 */
1563 ii = ecm_db_iface_find_and_ref_pptp(type_info->src_call_id, type_info->dst_call_id);
1564 if (ii) {
1565 DEBUG_TRACE("%p: iface established\n", ii);
1566 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1567 return ii;
1568 }
1569
1570 /*
1571 * No iface - create one
1572 */
1573 nii = ecm_db_iface_alloc();
1574 if (!nii) {
1575 DEBUG_WARN("Failed to establish iface\n");
1576 return NULL;
1577 }
1578
1579 /*
1580 * Add iface into the database, atomically to avoid races creating the same thing
1581 */
1582 spin_lock_bh(&ecm_interface_lock);
1583 ii = ecm_db_iface_find_and_ref_pptp(type_info->src_call_id, type_info->dst_call_id);
1584 if (ii) {
1585 spin_unlock_bh(&ecm_interface_lock);
1586 ecm_db_iface_deref(nii);
1587 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1588 return ii;
1589 }
1590
1591 ecm_db_iface_add_pptp(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1592 spin_unlock_bh(&ecm_interface_lock);
1593
1594 DEBUG_TRACE("%p: pptp iface established\n", nii);
1595 return nii;
1596}
1597#endif
1598
Ben Menchaca84f36632014-02-28 20:57:38 +00001599/*
1600 * ecm_interface_unknown_interface_establish()
1601 * Returns a reference to a iface of the UNKNOWN type, possibly creating one if necessary.
1602 * Returns NULL on failure or a reference to interface.
1603 */
1604static 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 -07001605 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001606{
1607 struct ecm_db_iface_instance *nii;
1608 struct ecm_db_iface_instance *ii;
1609
Murat Sezgin91c5d712015-06-12 15:16:22 -07001610 DEBUG_INFO("Establish UNKNOWN iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1611 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001612
1613 /*
1614 * Locate the iface
1615 */
1616 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1617 if (ii) {
1618 DEBUG_TRACE("%p: iface established\n", ii);
1619 return ii;
1620 }
1621
1622 /*
1623 * No iface - create one
1624 */
1625 nii = ecm_db_iface_alloc();
1626 if (!nii) {
1627 DEBUG_WARN("Failed to establish iface\n");
1628 return NULL;
1629 }
1630
1631 /*
1632 * Add iface into the database, atomically to avoid races creating the same thing
1633 */
1634 spin_lock_bh(&ecm_interface_lock);
1635 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1636 if (ii) {
1637 spin_unlock_bh(&ecm_interface_lock);
1638 ecm_db_iface_deref(nii);
1639 return ii;
1640 }
1641 ecm_db_iface_add_unknown(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001642 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001643 spin_unlock_bh(&ecm_interface_lock);
1644
1645 DEBUG_TRACE("%p: unknown iface established\n", nii);
1646 return nii;
1647}
1648
1649/*
1650 * ecm_interface_loopback_interface_establish()
1651 * Returns a reference to a iface of the LOOPBACK type, possibly creating one if necessary.
1652 * Returns NULL on failure or a reference to interface.
1653 */
1654static 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 -07001655 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001656{
1657 struct ecm_db_iface_instance *nii;
1658 struct ecm_db_iface_instance *ii;
1659
Murat Sezgin91c5d712015-06-12 15:16:22 -07001660 DEBUG_INFO("Establish LOOPBACK iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1661 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001662
1663 /*
1664 * Locate the iface
1665 */
1666 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1667 if (ii) {
1668 DEBUG_TRACE("%p: iface established\n", ii);
1669 return ii;
1670 }
1671
1672 /*
1673 * No iface - create one
1674 */
1675 nii = ecm_db_iface_alloc();
1676 if (!nii) {
1677 DEBUG_WARN("Failed to establish iface\n");
1678 return NULL;
1679 }
1680
1681 /*
1682 * Add iface into the database, atomically to avoid races creating the same thing
1683 */
1684 spin_lock_bh(&ecm_interface_lock);
1685 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1686 if (ii) {
1687 spin_unlock_bh(&ecm_interface_lock);
1688 ecm_db_iface_deref(nii);
1689 return ii;
1690 }
1691 ecm_db_iface_add_loopback(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001692 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001693 spin_unlock_bh(&ecm_interface_lock);
1694
1695 DEBUG_TRACE("%p: loopback iface established\n", nii);
1696 return nii;
1697}
1698
Murat Sezgin69a27532015-03-12 14:09:40 -07001699#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001700/*
1701 * ecm_interface_ipsec_tunnel_interface_establish()
1702 * Returns a reference to a iface of the IPSEC_TUNNEL type, possibly creating one if necessary.
1703 * Returns NULL on failure or a reference to interface.
1704 *
1705 * NOTE: GGG TODO THIS NEEDS TO TAKE A PROPER APPROACH TO IPSEC TUNNELS USING ENDPOINT ADDRESSING AS THE TYPE INFO KEYS
1706 */
1707static 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 -07001708 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001709{
1710 struct ecm_db_iface_instance *nii;
1711 struct ecm_db_iface_instance *ii;
1712
Murat Sezgin91c5d712015-06-12 15:16:22 -07001713 DEBUG_INFO("Establish IPSEC_TUNNEL iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1714 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001715
1716 /*
1717 * Locate the iface
1718 */
1719 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1720 if (ii) {
1721 DEBUG_TRACE("%p: iface established\n", ii);
1722 return ii;
1723 }
1724
1725 /*
1726 * No iface - create one
1727 */
1728 nii = ecm_db_iface_alloc();
1729 if (!nii) {
1730 DEBUG_WARN("Failed to establish iface\n");
1731 return NULL;
1732 }
1733
1734 /*
1735 * Add iface into the database, atomically to avoid races creating the same thing
1736 */
1737 spin_lock_bh(&ecm_interface_lock);
1738 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1739 if (ii) {
1740 spin_unlock_bh(&ecm_interface_lock);
1741 ecm_db_iface_deref(nii);
1742 return ii;
1743 }
1744 ecm_db_iface_add_ipsec_tunnel(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001745 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001746 spin_unlock_bh(&ecm_interface_lock);
1747
1748 DEBUG_TRACE("%p: ipsec_tunnel iface established\n", nii);
1749 return nii;
1750}
Murat Sezgin69a27532015-03-12 14:09:40 -07001751#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001752
Murat Sezginb3731e82014-11-26 12:20:59 -08001753#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07001754#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00001755/*
1756 * ecm_interface_sit_interface_establish()
1757 * Returns a reference to a iface of the SIT type, possibly creating one if necessary.
1758 * Returns NULL on failure or a reference to interface.
1759 */
1760static 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 -07001761 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001762{
1763 struct ecm_db_iface_instance *nii;
1764 struct ecm_db_iface_instance *ii;
1765
Murat Sezgin91c5d712015-06-12 15:16:22 -07001766 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",
1767 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 +00001768
1769 /*
1770 * Locate the iface
1771 */
1772 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr);
1773 if (ii) {
1774 DEBUG_TRACE("%p: iface established\n", ii);
1775 return ii;
1776 }
1777
1778 /*
1779 * No iface - create one
1780 */
1781 nii = ecm_db_iface_alloc();
1782 if (!nii) {
1783 DEBUG_WARN("Failed to establish iface\n");
1784 return NULL;
1785 }
1786
1787 /*
1788 * Add iface into the database, atomically to avoid races creating the same thing
1789 */
1790 spin_lock_bh(&ecm_interface_lock);
1791 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr);
1792 if (ii) {
1793 spin_unlock_bh(&ecm_interface_lock);
1794 ecm_db_iface_deref(nii);
1795 return ii;
1796 }
1797 ecm_db_iface_add_sit(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001798 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001799 spin_unlock_bh(&ecm_interface_lock);
1800
1801 DEBUG_TRACE("%p: sit iface established\n", nii);
1802 return nii;
1803}
Murat Sezgincc6eedf2014-05-09 23:59:19 -07001804#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08001805#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001806
Murat Sezginc1402562015-03-12 12:32:20 -07001807#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001808#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001809/*
1810 * ecm_interface_tunipip6_interface_establish()
1811 * Returns a reference to a iface of the TUNIPIP6 type, possibly creating one if necessary.
1812 * Returns NULL on failure or a reference to interface.
1813 */
1814static 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 -07001815 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001816{
1817 struct ecm_db_iface_instance *nii;
1818 struct ecm_db_iface_instance *ii;
1819
Murat Sezgin91c5d712015-06-12 15:16:22 -07001820 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",
1821 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 +00001822
1823 /*
1824 * Locate the iface
1825 */
1826 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1827 if (ii) {
1828 DEBUG_TRACE("%p: iface established\n", ii);
1829 return ii;
1830 }
1831
1832 /*
1833 * No iface - create one
1834 */
1835 nii = ecm_db_iface_alloc();
1836 if (!nii) {
1837 DEBUG_WARN("Failed to establish iface\n");
1838 return NULL;
1839 }
1840
1841 /*
1842 * Add iface into the database, atomically to avoid races creating the same thing
1843 */
1844 spin_lock_bh(&ecm_interface_lock);
1845 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1846 if (ii) {
1847 spin_unlock_bh(&ecm_interface_lock);
1848 ecm_db_iface_deref(nii);
1849 return ii;
1850 }
1851 ecm_db_iface_add_tunipip6(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001852 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001853 spin_unlock_bh(&ecm_interface_lock);
1854
1855 DEBUG_TRACE("%p: tunipip6 iface established\n", nii);
1856 return nii;
1857}
Murat Sezginc1402562015-03-12 12:32:20 -07001858#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001859#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001860
1861/*
1862 * ecm_interface_establish_and_ref()
1863 * Establish an interface instance for the given interface detail.
1864 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001865struct ecm_db_iface_instance *ecm_interface_establish_and_ref(struct ecm_front_end_connection_instance *feci,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301866 struct net_device *dev, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00001867{
1868 int32_t dev_interface_num;
1869 char *dev_name;
1870 int32_t dev_type;
1871 int32_t dev_mtu;
Murat Sezgin91c5d712015-06-12 15:16:22 -07001872 int32_t ae_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00001873 struct ecm_db_iface_instance *ii;
1874 union {
1875 struct ecm_db_interface_info_ethernet ethernet; /* type == ECM_DB_IFACE_TYPE_ETHERNET */
Gareth Williams141d2382014-11-25 11:35:19 -08001876#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001877 struct ecm_db_interface_info_vlan vlan; /* type == ECM_DB_IFACE_TYPE_VLAN */
Gareth Williams141d2382014-11-25 11:35:19 -08001878#endif
Murat Sezgin910c9662015-03-11 16:15:06 -07001879#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001880 struct ecm_db_interface_info_lag lag; /* type == ECM_DB_IFACE_TYPE_LAG */
Murat Sezgin910c9662015-03-11 16:15:06 -07001881#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001882 struct ecm_db_interface_info_bridge bridge; /* type == ECM_DB_IFACE_TYPE_BRIDGE */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301883#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001884 struct ecm_db_interface_info_pppoe pppoe; /* type == ECM_DB_IFACE_TYPE_PPPOE */
Murat Sezginaad635c2015-03-06 16:11:41 -08001885#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301886#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1887 struct ecm_db_interface_info_pppol2tpv2 pppol2tpv2; /* type == ECM_DB_IFACE_TYPE_PPPOL2TPV2 */
1888#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301889#ifdef ECM_INTERFACE_PPTP_ENABLE
1890 struct ecm_db_interface_info_pptp pptp; /* type == ECM_DB_IFACE_TYPE_PPTP */
1891#endif
ratheesh kannothcfdcb332015-12-24 07:19:18 +05301892#ifdef ECM_INTERFACE_MAP_T_ENABLE
1893 struct ecm_db_interface_info_map_t map_t; /* type == ECM_DB_IFACE_TYPE_MAP_T */
1894#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001895 struct ecm_db_interface_info_unknown unknown; /* type == ECM_DB_IFACE_TYPE_UNKNOWN */
1896 struct ecm_db_interface_info_loopback loopback; /* type == ECM_DB_IFACE_TYPE_LOOPBACK */
Murat Sezgin69a27532015-03-12 14:09:40 -07001897#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001898 struct ecm_db_interface_info_ipsec_tunnel ipsec_tunnel; /* type == ECM_DB_IFACE_TYPE_IPSEC_TUNNEL */
Murat Sezgin69a27532015-03-12 14:09:40 -07001899#endif
Murat Sezginbde55f92015-03-11 16:44:11 -07001900#ifdef ECM_INTERFACE_SIT_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001901 struct ecm_db_interface_info_sit sit; /* type == ECM_DB_IFACE_TYPE_SIT */
Murat Sezginbde55f92015-03-11 16:44:11 -07001902#endif
Murat Sezginc1402562015-03-12 12:32:20 -07001903#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001904#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001905 struct ecm_db_interface_info_tunipip6 tunipip6; /* type == ECM_DB_IFACE_TYPE_TUNIPIP6 */
Murat Sezginc1402562015-03-12 12:32:20 -07001906#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001907#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001908 } type_info;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001909
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08001910#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001911 int channel_count;
1912 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00001913 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301914#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001915 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001916#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301917#ifdef ECM_INTERFACE_PPTP_ENABLE
1918 int protocol = IPPROTO_IP;
1919 struct pptp_opt opt;
1920 struct iphdr *v4_hdr = NULL;
1921 if (skb) {
1922 v4_hdr = ip_hdr(skb);
1923 protocol = v4_hdr->protocol;
1924 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301925#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301926#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001927 /*
1928 * Get basic information about the given device
1929 */
1930 dev_interface_num = dev->ifindex;
1931 dev_name = dev->name;
1932 dev_type = dev->type;
1933 dev_mtu = dev->mtu;
1934
1935 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07001936 * Does the accel engine recognise this interface?
Ben Menchaca84f36632014-02-28 20:57:38 +00001937 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001938 ae_interface_num = feci->ae_interface_number_by_dev_get(dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00001939
Murat Sezgin91c5d712015-06-12 15:16:22 -07001940 DEBUG_TRACE("Establish interface instance for device: %p is type: %d, name: %s, ifindex: %d, ae_if: %d, mtu: %d\n",
1941 dev, dev_type, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00001942
1943 /*
1944 * Extract from the device more type-specific information
1945 */
1946 if (dev_type == ARPHRD_ETHER) {
Shyam Sunder39e25672015-09-03 14:28:09 +05301947
Ben Menchaca84f36632014-02-28 20:57:38 +00001948 /*
1949 * Ethernet - but what sub type?
1950 */
1951
Gareth Williams141d2382014-11-25 11:35:19 -08001952#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001953 /*
1954 * VLAN?
1955 */
1956 if (is_vlan_dev(dev)) {
1957 /*
1958 * VLAN master
1959 * GGG No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
1960 */
1961 memcpy(type_info.vlan.address, dev->dev_addr, 6);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301962 type_info.vlan.vlan_tag = vlan_dev_vlan_id(dev);
Amit Gupta8975f9d2017-07-12 20:34:36 +05301963#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
Murat Sezginb2676062015-06-12 17:05:31 -07001964 type_info.vlan.vlan_tpid = ETH_P_8021Q;
Amit Gupta8975f9d2017-07-12 20:34:36 +05301965#else
1966 type_info.vlan.vlan_tpid = ntohs(vlan_dev_vlan_proto(dev));
1967#endif
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301968 DEBUG_TRACE("Net device: %p is VLAN, mac: %pM, vlan_id: %x vlan_tpid: %x\n",
1969 dev, type_info.vlan.address, type_info.vlan.vlan_tag, type_info.vlan.vlan_tpid);
Ben Menchaca84f36632014-02-28 20:57:38 +00001970
1971 /*
1972 * Establish this type of interface
1973 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001974 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 +05301975 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00001976 }
Gareth Williams141d2382014-11-25 11:35:19 -08001977#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001978
1979 /*
1980 * BRIDGE?
1981 */
1982 if (ecm_front_end_is_bridge_device(dev)) {
1983 /*
1984 * Bridge
1985 */
1986 memcpy(type_info.bridge.address, dev->dev_addr, 6);
1987
1988 DEBUG_TRACE("Net device: %p is BRIDGE, mac: %pM\n",
1989 dev, type_info.bridge.address);
1990
1991 /*
1992 * Establish this type of interface
1993 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001994 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 +05301995 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00001996 }
1997
Murat Sezgin910c9662015-03-11 16:15:06 -07001998#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001999 /*
2000 * LAG?
2001 */
2002 if (ecm_front_end_is_lag_master(dev)) {
2003 /*
2004 * Link aggregation
2005 */
2006 memcpy(type_info.lag.address, dev->dev_addr, 6);
2007
2008 DEBUG_TRACE("Net device: %p is LAG, mac: %pM\n",
2009 dev, type_info.lag.address);
2010
2011 /*
2012 * Establish this type of interface
2013 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002014 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 +05302015 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00002016 }
Murat Sezgin910c9662015-03-11 16:15:06 -07002017#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002018
Murat Sezgin31effef2017-11-13 15:09:34 -08002019#ifdef ECM_INTERFACE_GRE_ENABLE
2020 /*
2021 * GRE TAP?
2022 */
2023 if (dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)) {
2024 /*
2025 * GRE TAP interface is handled as ethernet interface, however it is possible
2026 * that the acceleration engine may not be ready yet to handle the connection.
2027 * In this case the acceleration engine interface is not found for this type and
2028 * we should wait until it is ready.
2029 */
2030 if (ae_interface_num < 0) {
2031 DEBUG_TRACE("GRE interface is not ready yet\n");
2032 return NULL;
2033 }
2034 }
2035#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002036 /*
2037 * ETHERNET!
2038 * Just plain ethernet it seems
2039 */
2040 memcpy(type_info.ethernet.address, dev->dev_addr, 6);
2041 DEBUG_TRACE("Net device: %p is ETHERNET, mac: %pM\n",
2042 dev, type_info.ethernet.address);
2043
2044 /*
2045 * Establish this type of interface
2046 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002047 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 +05302048
2049identifier_update:
2050 if (ii) {
2051 /*
2052 * An interface identifier/ifindex can be change after network restart. Below
2053 * functtion will check interface_identifier present in 'ii' with new dev_interface_num.
2054 * If differ then update new ifindex and update the interface identifier hash table.
2055 */
2056 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2057 }
2058
Ben Menchaca84f36632014-02-28 20:57:38 +00002059 return ii;
2060 }
2061
2062 /*
2063 * LOOPBACK?
2064 */
2065 if (dev_type == ARPHRD_LOOPBACK) {
2066 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dev, dev_type);
2067 type_info.loopback.os_specific_ident = dev_interface_num;
Murat Sezgin91c5d712015-06-12 15:16:22 -07002068 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 +00002069 return ii;
2070 }
2071
Murat Sezgin69a27532015-03-12 14:09:40 -07002072#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002073 /*
2074 * IPSEC?
2075 */
2076 if (dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2077 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dev, dev_type);
2078 type_info.ipsec_tunnel.os_specific_ident = dev_interface_num;
Ankit Dhanuka6d5014a2014-06-22 17:21:44 +05302079
Ben Menchaca84f36632014-02-28 20:57:38 +00002080 // GGG TODO Flesh this out with tunnel endpoint addressing detail
Murat Sezgin91c5d712015-06-12 15:16:22 -07002081 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 +00002082 return ii;
2083 }
Murat Sezgin69a27532015-03-12 14:09:40 -07002084#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002085
ratheesh kannothcfdcb332015-12-24 07:19:18 +05302086#ifdef ECM_INTERFACE_MAP_T_ENABLE
2087 if (dev_type == ARPHRD_NONE) {
2088 if (is_map_t_dev(dev)) {
2089 type_info.map_t.if_index = dev_interface_num;
2090 ii = ecm_interface_map_t_interface_establish(&type_info.map_t, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2091 return ii;
2092 }
2093
2094 }
2095#endif
2096
Murat Sezginb3731e82014-11-26 12:20:59 -08002097#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07002098#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00002099 /*
2100 * SIT (6-in-4)?
2101 */
2102 if (dev_type == ARPHRD_SIT) {
2103 struct ip_tunnel *tunnel;
2104 struct ip_tunnel_6rd_parm *ip6rd;
2105 const struct iphdr *tiph;
2106
2107 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dev, dev_type);
2108
2109 tunnel = (struct ip_tunnel*)netdev_priv(dev);
2110 ip6rd = &tunnel->ip6rd;
2111
2112 /*
2113 * Get the Tunnel device IP header info
2114 */
2115 tiph = &tunnel->parms.iph ;
2116
2117 type_info.sit.prefixlen = ip6rd->prefixlen;
2118 type_info.sit.relay_prefix = ip6rd->relay_prefix;
2119 type_info.sit.relay_prefixlen = ip6rd->relay_prefixlen;
2120 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.saddr, tiph->saddr);
2121 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.daddr, tiph->daddr);
2122 type_info.sit.prefix[0] = ntohl(ip6rd->prefix.s6_addr32[0]);
2123 type_info.sit.prefix[1] = ntohl(ip6rd->prefix.s6_addr32[1]);
2124 type_info.sit.prefix[2] = ntohl(ip6rd->prefix.s6_addr32[2]);
2125 type_info.sit.prefix[3] = ntohl(ip6rd->prefix.s6_addr32[3]);
2126 type_info.sit.ttl = tiph->ttl;
2127 type_info.sit.tos = tiph->tos;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05302128
Murat Sezgin91c5d712015-06-12 15:16:22 -07002129 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 +00002130 return ii;
2131 }
Murat Sezgincc6eedf2014-05-09 23:59:19 -07002132#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08002133#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002134
Murat Sezginc1402562015-03-12 12:32:20 -07002135#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00002136#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002137 /*
2138 * IPIP6 Tunnel?
2139 */
2140 if (dev_type == ARPHRD_TUNNEL6) {
2141 struct ip6_tnl *tunnel;
2142 struct flowi6 *fl6;
2143
2144 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dev, dev_type);
2145
2146 /*
2147 * Get the tunnel device flow information (discover the output path of the tunnel)
2148 */
2149 tunnel = (struct ip6_tnl *)netdev_priv(dev);
2150 fl6 = &tunnel->fl.u.ip6;
2151
2152 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.saddr, fl6->saddr);
2153 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.daddr, fl6->daddr);
2154 type_info.tunipip6.hop_limit = tunnel->parms.hop_limit;
2155 type_info.tunipip6.flags = ntohl(tunnel->parms.flags);
2156 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 +05302157
Murat Sezgin91c5d712015-06-12 15:16:22 -07002158 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 +00002159 return ii;
2160 }
Murat Sezginc1402562015-03-12 12:32:20 -07002161#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00002162#endif
2163
Ben Menchaca84f36632014-02-28 20:57:38 +00002164 /*
2165 * If this is NOT PPP then it is unknown to the ecm
2166 */
2167 if (dev_type != ARPHRD_PPP) {
2168 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dev, dev_type);
2169 type_info.unknown.os_specific_ident = dev_interface_num;
2170
2171 /*
2172 * Establish this type of interface
2173 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002174 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 +00002175 return ii;
2176 }
2177
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08002178#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002179 /*
ratheesh kannothf4801a02016-12-09 22:46:39 +05302180 * PPP Support is NOT provided for.
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002181 * Interface is therefore unknown
2182 */
2183 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dev, dev_type);
2184 type_info.unknown.os_specific_ident = dev_interface_num;
2185
2186 /*
2187 * Establish this type of interface
2188 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002189 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 +01002190 return ii;
2191#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302192
2193#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2194 /*
2195 * ppp_xmit lock is held by linux kernel for l2tp packet in transmit
2196 * direction. we need to check for l2tp packet and avoid calls to
2197 * ppp_is_multilink() and ppp_hold_channels() which acquire same lock
2198 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05302199
2200 if ((dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(dev)) {
Murat Sezgindb0c5d82017-02-22 11:43:03 -08002201 if (skb && (skb->skb_iif == dev->ifindex)) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302202 struct pppol2tp_common_addr info;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302203
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302204 if (__ppp_is_multilink(dev) > 0) {
2205 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
2206 type_info.unknown.os_specific_ident = dev_interface_num;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302207
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302208 /*
2209 * Establish this type of interface
2210 */
2211 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2212 return ii;
2213 }
2214 channel_count = __ppp_hold_channels(dev, ppp_chan, 1);
2215 if (channel_count != 1) {
2216 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
2217 dev, channel_count);
2218 type_info.unknown.os_specific_ident = dev_interface_num;
2219
2220 /*
2221 * Establish this type of interface
2222 */
2223 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2224 return ii;
2225 }
2226
2227 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
2228 ppp_release_channels(ppp_chan, 1);
ratheesh kannothed721852015-09-28 12:39:52 +05302229 return NULL;
2230 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302231
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302232 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = info.local_tunnel_id;
2233 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = info.remote_tunnel_id;
2234 type_info.pppol2tpv2.l2tp.session.session_id = info.local_session_id;
2235 type_info.pppol2tpv2.l2tp.session.peer_session_id = info.remote_session_id;
2236 type_info.pppol2tpv2.udp.sport = ntohs(info.local_addr.sin_port);
2237 type_info.pppol2tpv2.udp.dport = ntohs(info.remote_addr.sin_port);
2238 type_info.pppol2tpv2.ip.saddr = ntohl(info.local_addr.sin_addr.s_addr);
2239 type_info.pppol2tpv2.ip.daddr = ntohl(info.remote_addr.sin_addr.s_addr);
ratheesh kannothed721852015-09-28 12:39:52 +05302240
2241 /*
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302242 * Release the channel. Note that next_dev is still (correctly) held.
ratheesh kannothed721852015-09-28 12:39:52 +05302243 */
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302244 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302245
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302246 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 +05302247
2248 /*
2249 * Establish this type of interface
2250 */
2251 ii = ecm_interface_pppol2tpv2_interface_establish(&type_info.pppol2tpv2, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2252 return ii;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302253 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302254 }
2255#endif
2256
Shyam Sunder23f2e542015-09-28 14:56:49 +05302257#ifdef ECM_INTERFACE_PPTP_ENABLE
2258 if ((protocol == IPPROTO_GRE) && skb && v4_hdr) {
2259 struct gre_hdr_pptp *gre_hdr;
2260 uint16_t proto;
2261 int ret;
2262
2263 skb_pull(skb, sizeof(struct iphdr));
2264 gre_hdr = (struct gre_hdr_pptp *)(skb->data);
2265 proto = ntohs(gre_hdr->protocol);
2266 if ((gre_hdr->version == GRE_VERSION_PPTP) && (proto == GRE_PROTOCOL_PPTP)) {
2267 ret = pptp_session_find(&opt, gre_hdr->call_id, v4_hdr->daddr);
2268 if (ret < 0) {
2269 skb_push(skb, sizeof(struct iphdr));
2270 DEBUG_WARN("PPTP session info not found\n");
2271 return NULL;
2272 }
2273
2274 /*
2275 * Get PPTP session info
2276 */
2277 type_info.pptp.src_call_id = ntohs(opt.src_addr.call_id);
2278 type_info.pptp.dst_call_id = ntohs(opt.dst_addr.call_id);
2279 type_info.pptp.src_ip = ntohl(opt.src_addr.sin_addr.s_addr);
2280 type_info.pptp.dst_ip = ntohl(opt.dst_addr.sin_addr.s_addr);
2281
2282 skb_push(skb, sizeof(struct iphdr));
2283
2284 /*
2285 * Establish this type of interface
2286 */
2287 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 +05302288 if (ii) {
2289 /*
2290 * The ifindex of a virtual netdevice like a PPTP session can change if it is destroyed
2291 * and comes up again. Detect if the ifindex has changed and update it if required
2292 */
2293 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2294 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05302295 return ii;
2296 }
2297
2298 skb_push(skb, sizeof(struct iphdr));
2299
2300 DEBUG_TRACE("Unknown GRE protocol \n");
2301 type_info.unknown.os_specific_ident = dev_interface_num;
2302
2303 /*
2304 * Establish this type of interface
2305 */
2306 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2307 return ii;
2308 }
2309#endif
2310
Ben Menchaca84f36632014-02-28 20:57:38 +00002311 /*
2312 * PPP - but what is the channel type?
2313 * First: If this is multi-link then we do not support it
2314 */
2315 if (ppp_is_multilink(dev) > 0) {
2316 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
2317 type_info.unknown.os_specific_ident = dev_interface_num;
2318
2319 /*
2320 * Establish this type of interface
2321 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002322 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 +00002323 return ii;
2324 }
2325
2326 DEBUG_TRACE("Net device: %p is PPP\n", dev);
2327
2328 /*
2329 * Get the PPP channel and then enquire what kind of channel it is
2330 * NOTE: Not multilink so only one channel to get.
2331 */
2332 channel_count = ppp_hold_channels(dev, ppp_chan, 1);
2333 if (channel_count != 1) {
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002334 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
2335 dev, channel_count);
Ben Menchaca84f36632014-02-28 20:57:38 +00002336 type_info.unknown.os_specific_ident = dev_interface_num;
2337
2338 /*
2339 * Establish this type of interface
2340 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002341 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00002342 return ii;
2343 }
2344
2345 /*
2346 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002347 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00002348 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002349 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302350
2351#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2352 if (channel_protocol == PX_PROTO_OL2TP) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302353 struct pppol2tp_common_addr info;
Ben Menchaca84f36632014-02-28 20:57:38 +00002354
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302355 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302356 ppp_release_channels(ppp_chan, 1);
2357 return NULL;
2358 }
2359
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302360 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = info.local_tunnel_id;
2361 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = info.remote_tunnel_id;
2362 type_info.pppol2tpv2.l2tp.session.session_id = info.local_session_id;
2363 type_info.pppol2tpv2.l2tp.session.peer_session_id = info.remote_session_id;
2364 type_info.pppol2tpv2.udp.sport = ntohs(info.local_addr.sin_port);
2365 type_info.pppol2tpv2.udp.dport = ntohs(info.remote_addr.sin_port);
2366 type_info.pppol2tpv2.ip.saddr = ntohl(info.local_addr.sin_addr.s_addr);
2367 type_info.pppol2tpv2.ip.daddr = ntohl(info.remote_addr.sin_addr.s_addr);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302368
2369 /*
2370 * Release the channel. Note that next_dev is still (correctly) held.
Ben Menchaca84f36632014-02-28 20:57:38 +00002371 */
2372 ppp_release_channels(ppp_chan, 1);
2373
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302374 DEBUG_TRACE("Net device: %p PPPo2L2TP session: %d,n", dev, type_info.pppol2tpv2.l2tp.session.peer_session_id);
2375
Ben Menchaca84f36632014-02-28 20:57:38 +00002376 /*
2377 * Establish this type of interface
2378 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302379 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 +00002380 return ii;
2381 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302382#endif
2383#ifdef ECM_INTERFACE_PPPOE_ENABLE
2384 if (channel_protocol == PX_PROTO_OE) {
2385
2386 /*
2387 * PPPoE channel
2388 */
2389 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dev);
2390
2391 /*
2392 * Get PPPoE session information and the underlying device it is using.
2393 */
2394 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2395 type_info.pppoe.pppoe_session_id = (uint16_t)ntohs((uint16_t)addressing.pa.sid);
2396 memcpy(type_info.pppoe.remote_mac, addressing.pa.remote, ETH_ALEN);
2397 dev_put(addressing.dev);
2398
2399 /*
2400 * Release the channel. Note that next_dev is still (correctly) held.
2401 */
2402 ppp_release_channels(ppp_chan, 1);
2403
2404 DEBUG_TRACE("Net device: %p PPPoE session: %x, remote mac: %pM\n",
2405 dev, type_info.pppoe.pppoe_session_id, type_info.pppoe.remote_mac);
2406
2407 /*
2408 * Establish this type of interface
2409 */
2410 ii = ecm_interface_pppoe_interface_establish(&type_info.pppoe, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2411 return ii;
2412 }
2413#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05302414
2415#ifdef ECM_INTERFACE_PPTP_ENABLE
2416 if (channel_protocol == PX_PROTO_PPTP) {
2417 pptp_channel_addressing_get(&opt, ppp_chan[0]);
2418
2419 /*
2420 * Get PPTP session info
2421 */
2422 type_info.pptp.src_call_id = ntohs(opt.src_addr.call_id);
2423 type_info.pptp.dst_call_id = ntohs(opt.dst_addr.call_id);
2424 type_info.pptp.src_ip = ntohl(opt.src_addr.sin_addr.s_addr);
2425 type_info.pptp.dst_ip = ntohl(opt.dst_addr.sin_addr.s_addr);
2426
2427 DEBUG_TRACE("Net device: %p PPTP source call id: %d,n", dev, type_info.pptp.src_call_id);
2428 ppp_release_channels(ppp_chan, 1);
2429
2430 /*
2431 * Establish this type of interface
2432 */
2433 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 +05302434 if (ii) {
2435 /*
2436 * The ifindex of a virtual netdevice like a PPTP session can change if it is destroyed
2437 * and comes up again. Detect if the ifindex has changed and update it if required
2438 */
2439 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2440 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05302441 return ii;
2442 }
2443#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302444 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n", dev, channel_protocol);
2445 type_info.unknown.os_specific_ident = dev_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00002446
2447 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302448 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00002449 */
2450 ppp_release_channels(ppp_chan, 1);
2451
Ben Menchaca84f36632014-02-28 20:57:38 +00002452 /*
2453 * Establish this type of interface
2454 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302455 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 +00002456 return ii;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002457#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002458}
2459EXPORT_SYMBOL(ecm_interface_establish_and_ref);
2460
Shyam Sunder6358b862015-05-04 15:06:24 +05302461#ifdef ECM_MULTICAST_ENABLE
2462/*
2463 * ecm_interface_multicast_heirarchy_construct_single()
2464 * Create and return an interface heirarchy for a single interface for a multicast connection
2465 *
2466 * src_addr IP source address
2467 * dest_addr IP Destination address/Group Address
2468 * interface Pointer to a single multicast interface heirarchy
2469 * given_dest_dev Netdev pointer for destination interface
2470 * br_slave_dev Netdev pointer to a bridge slave device. It could be NULL in case of pure
2471 * routed flow without any bridge interface in destination dev list.
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302472 * skb sk_buff
Shyam Sunder6358b862015-05-04 15:06:24 +05302473 */
Shyam Sunder81836832015-07-09 19:18:25 +05302474static uint32_t ecm_interface_multicast_heirarchy_construct_single(struct ecm_front_end_connection_instance *feci, ip_addr_t src_addr,
2475 ip_addr_t dest_addr, struct ecm_db_iface_instance *interface,
2476 struct net_device *given_dest_dev, struct net_device *br_slave_dev,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302477 uint8_t *src_node_addr, bool is_routed, __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302478{
2479 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2480 struct ecm_db_iface_instance **ifaces;
2481 struct ecm_db_iface_instance *ii_temp;
2482 struct net_device *dest_dev;
2483 int32_t current_interface_index;
2484 int32_t interfaces_cnt = 0;
2485 int32_t dest_dev_type;
2486
2487 dest_dev = given_dest_dev;
2488 dev_hold(dest_dev);
2489 dest_dev_type = dest_dev->type;
2490 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
2491
2492 while (current_interface_index > 0) {
2493 struct ecm_db_iface_instance *ii;
2494 struct net_device *next_dev;
2495
2496 /*
2497 * Get the ecm db interface instance for the device at hand
2498 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302499 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Shyam Sunder6358b862015-05-04 15:06:24 +05302500 interfaces_cnt++;
2501
2502 /*
2503 * If the interface could not be established then we abort
2504 */
2505 if (!ii) {
2506 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev->name);
2507 dev_put(dest_dev);
2508
2509 /*
2510 * Release the interfaces heirarchy we constructed to this point.
2511 */
2512 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2513 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2514 return ECM_DB_IFACE_HEIRARCHY_MAX;
2515 }
2516
2517 /*
2518 * Record the interface instance into the *ifaces
2519 */
2520 current_interface_index--;
2521 ii_temp = ecm_db_multicast_if_instance_get_at_index(interface, current_interface_index);
2522 ifaces = (struct ecm_db_iface_instance **)ii_temp;
2523 *ifaces = ii;
2524
2525 /*
2526 * Now we have to figure out what the next device will be (in the transmission path)
2527 */
2528 do {
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302529#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302530 int channel_count;
2531 struct ppp_channel *ppp_chan[1];
2532 int channel_protocol;
2533 struct pppoe_opt addressing;
2534#endif
2535 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev->name);
2536 next_dev = NULL;
2537
2538 if (dest_dev_type == ARPHRD_ETHER) {
2539 /*
2540 * Ethernet - but what sub type?
2541 */
2542
2543 /*
2544 * VLAN?
2545 */
2546 if (is_vlan_dev(dest_dev)) {
2547 /*
2548 * VLAN master
2549 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
2550 */
Shyam Sunder9db20852016-03-09 19:04:49 +05302551 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Shyam Sunder6358b862015-05-04 15:06:24 +05302552 dev_hold(next_dev);
2553 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
2554 dest_dev, next_dev, next_dev->name);
2555 break;
2556 }
2557
2558 /*
2559 * BRIDGE?
2560 */
2561 if (ecm_front_end_is_bridge_device(dest_dev)) {
2562 if (!ecm_front_end_is_bridge_port(br_slave_dev)) {
2563 DEBUG_ASSERT(NULL, "%p: expected only bridge slave here\n", interface);
2564
2565 /*
2566 * Release the interfaces heirarchy we constructed to this point.
2567 */
2568 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2569 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2570 dev_put(dest_dev);
2571 return ECM_DB_IFACE_HEIRARCHY_MAX;
2572 }
2573
2574 next_dev = br_slave_dev;
2575 if (!next_dev) {
2576 DEBUG_WARN("Unable to obtain output port \n");
2577
2578 /*
2579 * Release the interfaces heirarchy we constructed to this point.
2580 */
2581 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2582 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2583 dev_put(dest_dev);
2584 return ECM_DB_IFACE_HEIRARCHY_MAX;
2585 }
2586 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2587 dev_hold(next_dev);
2588 break;
2589 }
2590
Shyam Sunder81836832015-07-09 19:18:25 +05302591#ifdef ECM_INTERFACE_BOND_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302592 /*
2593 * LAG?
2594 */
2595 if (ecm_front_end_is_lag_master(dest_dev)) {
2596 /*
2597 * Link aggregation
2598 * Figure out which slave device of the link aggregation will be used to reach the destination.
2599 */
2600 uint32_t src_addr_32 = 0;
2601 uint32_t dest_addr_32 = 0;
Suman Ghoshf14d2172015-07-31 14:38:10 +05302602 struct in6_addr src_addr6;
2603 struct in6_addr dest_addr6;
Shyam Sunder6358b862015-05-04 15:06:24 +05302604 uint8_t src_mac_addr[ETH_ALEN];
2605 uint8_t dest_mac_addr[ETH_ALEN];
2606
2607 memset(src_mac_addr, 0, ETH_ALEN);
2608 memset(dest_mac_addr, 0, ETH_ALEN);
2609
Shyam Sunder81836832015-07-09 19:18:25 +05302610 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2611 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
2612 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
2613 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302614
Shyam Sunder81836832015-07-09 19:18:25 +05302615 if (!is_routed) {
2616 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
Shyam Sunder6358b862015-05-04 15:06:24 +05302617 } else {
Shyam Sunder81836832015-07-09 19:18:25 +05302618 struct net_device *dest_dev_master;
2619
2620 /*
2621 * Use appropriate source MAC address for routed packets
2622 */
2623 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
2624 if (dest_dev_master) {
2625 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
2626 dev_put(dest_dev_master);
2627 } else {
2628 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
2629 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302630 }
2631
2632 /*
2633 * Create Destination MAC address using IP multicast destination address
2634 */
2635 ecm_translate_multicast_mac(dest_addr, dest_mac_addr);
2636
Shyam Sunder81836832015-07-09 19:18:25 +05302637 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2638 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
2639 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302640 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302641 } else {
Suman Ghoshf14d2172015-07-31 14:38:10 +05302642 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
2643 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, dest_addr);
Shyam Sunder81836832015-07-09 19:18:25 +05302644 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
Suman Ghoshf14d2172015-07-31 14:38:10 +05302645 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05302646 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302647 }
2648
Shyam Sunder6358b862015-05-04 15:06:24 +05302649 if (!(next_dev && netif_carrier_ok(next_dev))) {
2650 DEBUG_WARN("Unable to obtain LAG output slave device\n");
2651 dev_put(dest_dev);
2652
2653 /*
2654 * Release the interfaces heirarchy we constructed to this point.
2655 */
2656 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2657 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2658 return ECM_DB_IFACE_HEIRARCHY_MAX;
2659 }
2660
2661 dev_hold(next_dev);
2662 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2663 break;
2664 }
2665#endif
2666
2667 /*
2668 * ETHERNET!
2669 * Just plain ethernet it seems.
2670 */
2671 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
2672 break;
2673 }
2674
2675 /*
2676 * LOOPBACK?
2677 */
2678 if (dest_dev_type == ARPHRD_LOOPBACK) {
2679 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
2680 break;
2681 }
2682
2683 /*
2684 * IPSEC?
2685 */
2686 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2687 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
2688 /*
2689 * TODO Figure out the next device the tunnel is using...
2690 */
2691 break;
2692 }
2693
2694 /*
2695 * SIT (6-in-4)?
2696 */
2697 if (dest_dev_type == ARPHRD_SIT) {
2698 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
2699 /*
2700 * TODO Figure out the next device the tunnel is using...
2701 */
2702 break;
2703 }
2704
2705 /*
2706 * IPIP6 Tunnel?
2707 */
2708 if (dest_dev_type == ARPHRD_TUNNEL6) {
2709 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
2710 /*
2711 * TODO Figure out the next device the tunnel is using...
2712 */
2713 break;
2714 }
2715
2716 /*
2717 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
2718 */
2719 if (dest_dev_type != ARPHRD_PPP) {
2720 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
2721 break;
2722 }
2723
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302724#ifndef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302725 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
2726#else
2727 /*
2728 * PPP - but what is the channel type?
2729 * First: If this is multi-link then we do not support it
2730 */
2731 if (ppp_is_multilink(dest_dev) > 0) {
2732 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
2733 break;
2734 }
2735
2736 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
2737
2738 /*
2739 * Get the PPP channel and then enquire what kind of channel it is
2740 * NOTE: Not multilink so only one channel to get.
2741 */
2742 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
2743 if (channel_count != 1) {
2744 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
2745 dest_dev, channel_count);
2746 break;
2747 }
2748
2749 /*
2750 * Get channel protocol type
2751 * NOTE: Not all PPP channels support channel specific methods.
2752 */
2753 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
2754 if (channel_protocol != PX_PROTO_OE) {
2755 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
2756 dest_dev, channel_protocol);
2757
2758 /*
2759 * Release the channel
2760 */
2761 ppp_release_channels(ppp_chan, 1);
2762
2763 break;
2764 }
2765
2766 /*
2767 * PPPoE channel
2768 */
2769 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
2770
2771 /*
2772 * Get PPPoE session information and the underlying device it is using.
2773 */
2774 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2775
2776 /*
2777 * Copy the dev hold into this, we will release the hold later
2778 */
2779 next_dev = addressing.dev;
2780
Shyam Sunder6358b862015-05-04 15:06:24 +05302781 /*
2782 * Release the channel. Note that next_dev is still (correctly) held.
2783 */
2784 ppp_release_channels(ppp_chan, 1);
2785#endif
2786 } while (false);
2787
2788 /*
2789 * No longer need dest_dev as it may become next_dev
2790 */
2791 dev_put(dest_dev);
2792
2793 /*
2794 * Check out the next_dev, if any
2795 */
2796 if (!next_dev) {
2797 int32_t i __attribute__((unused));
2798 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
2799#if DEBUG_LEVEL > 1
2800 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2801 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
2802 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n", \
2803 i, to_list_single[i], ecm_db_connection_iface_type_get(to_list_single[i]), \
2804 ecm_db_interface_type_to_string(ecm_db_connection_iface_type_get(to_list_single[i])));
2805 }
2806#endif
2807 return current_interface_index;
2808 }
2809
2810 /*
2811 * dest_dev becomes next_dev
2812 */
2813 dest_dev = next_dev;
2814 dest_dev_type = dest_dev->type;
2815 }
2816
2817 dev_put(dest_dev);
2818
2819 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2820 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2821 return ECM_DB_IFACE_HEIRARCHY_MAX;
2822}
2823
2824/*
2825 * ecm_interface_multicast_heirarchy_construct_routed()
2826 * Create destination interface heirarchy for a routed multicast connectiona
2827 *
2828 * interfaces Pointer to the 2-D array of multicast interface heirarchies
2829 * in_dev Pointer to the source netdev
2830 * packet_src_addr Source IP of the multicast flow
2831 * packet_dest_addr Group(dest) IP of the multicast flow
2832 * max_dst Maximum number of netdev joined the multicast group
2833 * dst_if_index_base An array of if index joined the multicast group
2834 * interface_first_base An array of the index of the first interface in the list
2835 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002836int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_connection_instance *feci,
2837 struct ecm_db_iface_instance *interfaces,
2838 struct net_device *in_dev,
2839 ip_addr_t packet_src_addr,
2840 ip_addr_t packet_dest_addr, uint8_t max_if,
2841 uint32_t *dst_if_index_base,
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302842 uint32_t *interface_first_base, bool mfc_update,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302843 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302844{
2845 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2846 struct ecm_db_iface_instance *ifaces;
2847 struct net_device *dest_dev = NULL;
2848 struct net_device *br_dev_src = NULL;
2849 uint32_t *dst_if_index;
2850 uint32_t *interface_first;
2851 uint32_t br_if;
2852 uint32_t valid_if;
Shyam Sunder41637872015-06-11 21:19:05 +05302853 int32_t if_num;
Shyam Sunder6358b862015-05-04 15:06:24 +05302854 int32_t dest_dev_type;
2855 int if_index;
2856 int ii_cnt;
2857 int total_ii_count = 0;
2858 bool src_dev_is_bridge = false;
2859
2860 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",
2861 ECM_IP_ADDR_TO_DOT(packet_dest_addr), ECM_IP_ADDR_TO_DOT(packet_src_addr), max_if);
2862
2863 /*
2864 * Check if the source net_dev is a bridge slave.
2865 */
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302866 if (in_dev && !mfc_update) {
Shyam Sunder6358b862015-05-04 15:06:24 +05302867 if (ecm_front_end_is_bridge_port(in_dev)) {
2868 src_dev_is_bridge = true;
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302869 br_dev_src = ecm_interface_get_and_hold_dev_master(in_dev);
2870 DEBUG_ASSERT(br_dev_src, "Expected a master\n");
Shyam Sunder6358b862015-05-04 15:06:24 +05302871
2872 /*
2873 * The source net_dev found as bridge slave. In case of routed interface
2874 * heirarchy MFC is not aware of any other bridge slave has joined the same
2875 * multicast group as a destination interface. Therfore we assume there
2876 * are bridge slaves present in multicast destination interface list
2877 * and increase the max_if by one.
2878 */
2879 max_if++;
2880 }
2881 }
2882
2883 ii_cnt = 0;
2884 br_if = if_num = 0;
2885
2886 /*
2887 * This loop is for creating the destination interface hierarchy list.
2888 * We take the destination interface array we got from MFC (in form of ifindex array)
2889 * as input for this.
2890 */
2891 for (if_index = 0, valid_if = 0; if_index < max_if; if_index++) {
2892 dst_if_index = ecm_db_multicast_if_first_get_at_index(dst_if_index_base, if_index);
2893
2894 if (*dst_if_index == ECM_INTERFACE_LOOPBACK_DEV_INDEX) {
2895 continue;
2896 }
2897
2898 dest_dev = dev_get_by_index(&init_net, *dst_if_index);
2899 if (!dest_dev) {
2900 if (!src_dev_is_bridge) {
2901 int i;
2902
2903 /*
2904 * If already constructed any interface heirarchies before hitting
2905 * this error condition then Deref all interface heirarchies.
2906 */
2907 if (valid_if > 0) {
2908 for (i = 0; i < valid_if; i++) {
2909 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2910 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2911 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2912 }
2913 }
2914
2915 /*
2916 * If valid netdev not found, Return 0
2917 */
2918 return 0;
2919 }
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302920
Shyam Sunder6358b862015-05-04 15:06:24 +05302921 dest_dev = br_dev_src;
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302922
Shyam Sunder6358b862015-05-04 15:06:24 +05302923 }
2924
2925 dest_dev_type = dest_dev->type;
2926
2927 if (ecm_front_end_is_bridge_device(dest_dev)) {
2928 struct net_device *mc_br_slave_dev = NULL;
2929 uint32_t mc_max_dst = ECM_DB_MULTICAST_IF_MAX;
2930 uint32_t mc_dst_if_index[ECM_DB_MULTICAST_IF_MAX];
2931
2932 if (ECM_IP_ADDR_IS_V4(packet_src_addr)) {
2933 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);
2934 } else {
2935 struct in6_addr origin6;
2936 struct in6_addr group6;
2937 ECM_IP_ADDR_TO_NIN6_ADDR(origin6, packet_src_addr);
2938 ECM_IP_ADDR_TO_NIN6_ADDR(group6, packet_dest_addr);
2939 if_num = mc_bridge_ipv6_get_if(dest_dev, &origin6, &group6, mc_max_dst, mc_dst_if_index);
2940 }
2941
Shyam Sunder81836832015-07-09 19:18:25 +05302942 if ((if_num < 0) || (if_num > ECM_DB_MULTICAST_IF_MAX)) {
2943 int i;
2944 DEBUG_WARN("MCS is not ready\n");
2945
2946 /*
2947 * If already constructed any interface heirarchies before hitting
2948 * this error condition then Deref all interface heirarchies.
2949 */
2950 if (valid_if > 0) {
2951 for (i = 0; i < valid_if; i++) {
2952 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2953 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2954 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2955 }
2956 }
2957
Shyam Sunder41637872015-06-11 21:19:05 +05302958 dev_put(dest_dev);
2959 return 0;
2960 }
2961
Shyam Sundera450b582016-07-22 14:44:14 +05302962 if (in_dev && !mfc_update) {
Shyam Sunder06588292016-04-18 19:57:39 +05302963 if_num = ecm_interface_multicast_check_for_src_ifindex(mc_dst_if_index, if_num, in_dev->ifindex);
2964 }
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302965
Shyam Sunder6358b862015-05-04 15:06:24 +05302966 for (br_if = 0; br_if < if_num; br_if++) {
2967 mc_br_slave_dev = dev_get_by_index(&init_net, mc_dst_if_index[br_if]);
2968 if (!mc_br_slave_dev) {
2969 continue;
2970 }
2971
2972 if ((valid_if + br_if) > ECM_DB_MULTICAST_IF_MAX) {
2973 int i;
2974
2975 /*
2976 * If already constructed any interface heirarchies before hitting
2977 * this error condition then Deref all interface heirarchies.
2978 */
2979 for (i = 0; i < (valid_if + br_if); i++) {
2980 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2981 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2982 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2983 }
2984
2985 dev_put(dest_dev);
2986 dev_put(mc_br_slave_dev);
2987 return 0;
2988 }
2989
2990 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if + br_if);
2991 /*
2992 * Construct a single interface heirarchy of a multicast dev.
2993 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302994 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 +05302995 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
2996
2997 /*
2998 * If already constructed any interface heirarchies before hitting
2999 * this error condition then Deref all interface heirarchies.
3000 */
3001 if ((valid_if + br_if) > 0) {
3002 int i;
3003 for (i = 0; i < (valid_if + br_if); i++) {
3004 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3005 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3006 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3007 }
3008 }
3009
3010 dev_put(dest_dev);
3011 dev_put(mc_br_slave_dev);
3012 return 0;
3013 }
3014
3015 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, (valid_if + br_if));
3016 *interface_first = ii_cnt;
3017 total_ii_count += ii_cnt;
3018 dev_put(mc_br_slave_dev);
3019 }
3020
3021 valid_if += br_if;
3022
3023 } else {
3024
3025 DEBUG_ASSERT(valid_if < ECM_DB_MULTICAST_IF_MAX, "Bad array index size %d\n", valid_if);
3026 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
3027 /*
3028 * Construct a single interface heirarchy of a multicast dev.
3029 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303030 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 +05303031 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3032
3033 /*
3034 * If already constructed any interface heirarchies before hitting
3035 * this error condition then Deref all interface heirarchies.
3036 */
3037 if (valid_if > 0) {
3038 int i;
3039 for (i = 0; i < valid_if; i++) {
3040 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3041 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3042 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3043 }
3044 }
3045
3046 dev_put(dest_dev);
3047 return 0;
3048 }
3049
3050 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
3051 *interface_first = ii_cnt;
3052 total_ii_count += ii_cnt;
3053 valid_if++;
3054 }
3055
3056 dev_put(dest_dev);
3057 }
3058 return total_ii_count;
3059}
3060EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed);
3061
3062/*
3063 * ecm_interface_multicast_heirarchy_construct_bridged()
3064 * This function called when the Hyfi bridge snooper has IGMP/IMLD updates, this function
3065 * creates destination interface heirarchy for a bridged multicast connection.
3066 *
3067 * interfaces Pointer to the 2-D array of multicast interface heirarchies
3068 * dest_dev Pointer to the destination dev, here dest_dev is always a bridge type
3069 * packet_src_addr Source IP of the multicast flow
3070 * packet_dest_addr Group(dest) IP of the multicast flow
3071 * mc_max_dst Maximum number of bridge slaves joined the multicast group
3072 * mc_dst_if_index_base An array of if index joined the multicast group
3073 * interface_first_base An array of the index of the first interface in the list
3074 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003075int32_t ecm_interface_multicast_heirarchy_construct_bridged(struct ecm_front_end_connection_instance *feci,
Shyam Sunder81836832015-07-09 19:18:25 +05303076 struct ecm_db_iface_instance *interfaces, struct net_device *dest_dev,
3077 ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, uint8_t mc_max_dst,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05303078 int *mc_dst_if_index_base, uint32_t *interface_first_base, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303079 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05303080{
3081 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
3082 struct ecm_db_iface_instance *ifaces;
3083 struct net_device *mc_br_slave_dev = NULL;
3084 uint32_t *interface_first;
3085 int *mc_dst_if_index;
3086 int valid_if;
3087 int ii_cnt = 0;
3088 int br_if;
3089 int total_ii_cnt = 0;
3090
3091 /*
3092 * Go through the newly joined interface index one by one and
3093 * create an interface heirarchy for each valid interface.
3094 */
3095 for (br_if = 0, valid_if = 0; br_if < mc_max_dst; br_if++) {
3096 mc_dst_if_index = (int *)ecm_db_multicast_if_num_get_at_index(mc_dst_if_index_base, br_if);
3097 mc_br_slave_dev = dev_get_by_index(&init_net, *mc_dst_if_index);
3098 if (!mc_br_slave_dev) {
3099
3100 /*
3101 * If already constructed any interface heirarchies before hitting
3102 * this error condition then Deref all interface heirarchies.
3103 */
3104 if (valid_if > 0) {
3105 int i;
3106 for (i = 0; i < valid_if; i++) {
3107 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3108 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3109 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3110 }
3111 }
3112
3113 /*
3114 * If valid netdev not found, Return 0
3115 */
3116 return 0;
3117 }
3118
3119 if (valid_if > ECM_DB_MULTICAST_IF_MAX) {
3120 int i;
3121
3122 /*
3123 * If already constructed any interface heirarchies before hitting
3124 * this error condition then Deref all interface heirarchies.
3125 */
3126 for (i = 0; i < valid_if; i++) {
3127 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3128 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3129 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3130 }
3131
3132 dev_put(mc_br_slave_dev);
3133 return 0;
3134 }
3135
3136 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
3137
3138 /*
3139 * Construct a single interface heirarchy of a multicast dev.
3140 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303141 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 +05303142 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3143
3144 /*
3145 * If already constructed any interface heirarchies before hitting
3146 * this error condition then Deref all interface heirarchies.
3147 */
3148 if (valid_if > 0) {
3149 int i;
3150 for (i = 0; i < valid_if; i++) {
3151 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3152 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3153 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3154 }
3155 }
3156
3157 dev_put(mc_br_slave_dev);
3158 return 0;
3159 }
3160
3161 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
3162 *interface_first = ii_cnt;
3163 total_ii_cnt += ii_cnt;
3164 valid_if++;
3165 dev_put(mc_br_slave_dev);
3166 }
3167
Shyam Sunder280b34a2016-06-22 19:30:22 +05303168 return valid_if;
Shyam Sunder6358b862015-05-04 15:06:24 +05303169}
3170EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_bridged);
Shyam Sunder6358b862015-05-04 15:06:24 +05303171
Ben Menchaca84f36632014-02-28 20:57:38 +00003172/*
Murat Sezgin5dae8832015-12-03 14:23:19 -08003173 * ecm_interface_multicast_get_next_node_mac_address()
3174 * Get the MAC address of the next node for multicast flows
3175 *
3176 * TODO: This function will be removed when the multicast flow code
3177 * is fixed to use the new interface hierarchy construction model.
3178 *
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003179 */
Murat Sezgin5dae8832015-12-03 14:23:19 -08003180static bool ecm_interface_multicast_get_next_node_mac_address(
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003181 ip_addr_t dest_addr, struct net_device *dest_dev, int ip_version,
3182 uint8_t *mac_addr)
3183{
3184 bool on_link;
3185 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3186
3187 if (!ecm_interface_mac_addr_get(dest_addr, mac_addr, &on_link, gw_addr)) {
3188 if (ip_version == 4) {
3189 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n",
3190 ECM_IP_ADDR_TO_DOT(dest_addr));
3191 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
3192 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003193#ifdef ECM_IPV6_ENABLE
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003194 if (ip_version == 6) {
3195 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n",
3196 ECM_IP_ADDR_TO_OCTAL(dest_addr));
3197 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
3198 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003199#endif
3200 return false;
3201 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003202
Murat Sezgin5dae8832015-12-03 14:23:19 -08003203 return true;
3204}
Murat Sezgin8f70b312016-02-02 23:33:10 -08003205#endif
Murat Sezgin5dae8832015-12-03 14:23:19 -08003206
3207/*
3208 * ecm_interface_get_next_node_mac_address()
3209 * Get the MAC address of the next node
3210 */
3211static bool ecm_interface_get_next_node_mac_address(
3212 ip_addr_t dest_addr, struct net_device *dest_dev, int ip_version,
3213 uint8_t *mac_addr)
3214{
3215 if (!ecm_interface_mac_addr_get_no_route(dest_dev, dest_addr, mac_addr)) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003216 /*
3217 * MAC address look up failed. The host IP address may not be in the
3218 * neighbour table. So, let's send an ARP or neighbour solicitation
3219 * request to this host IP address, so in the subsequent lookups it can be
3220 * found.
3221 */
Murat Sezgin5dae8832015-12-03 14:23:19 -08003222 if (ip_version == 4) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003223 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3224 bool on_link = true;
3225
3226 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT " send ARP request\n",
Murat Sezgin5dae8832015-12-03 14:23:19 -08003227 ECM_IP_ADDR_TO_DOT(dest_addr));
Murat Sezgin00627c12016-02-05 16:53:21 -08003228
3229 if (ecm_interface_find_gateway(dest_addr, gw_addr)) {
3230 on_link = false;
3231 }
Shyam Sunder9ac555d2016-09-16 17:58:15 +05303232
3233 if (ecm_interface_mac_addr_get_no_route(dest_dev, gw_addr, mac_addr)) {
3234 DEBUG_TRACE("Found the mac address for gateway\n");
3235 return true;
3236 }
3237
Murat Sezgin00627c12016-02-05 16:53:21 -08003238 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003239 }
3240#ifdef ECM_IPV6_ENABLE
3241 if (ip_version == 6) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003242 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 -08003243 ECM_IP_ADDR_TO_OCTAL(dest_addr));
Murat Sezgin00627c12016-02-05 16:53:21 -08003244 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003245 }
3246#endif
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003247 return false;
3248 }
3249
3250 return true;
3251}
3252
3253/*
3254 * ecm_interface_should_update_egress_device_bridged()
3255 * Determine if the egress port should be re-evaluated in the bridged case
3256 *
3257 * This will be done if:
3258 * - The egress port is the one provided from the front-end
3259 * - The egress port is not a bridge, but is a slave of the bridge
3260 * - Not routed
3261 *
3262 * If these conditions hold, this function will hold a reference to the bridge
3263 * port and return it to the caller. Otherwise no reference will be held and
3264 * it will return NULL.
3265 */
3266static struct net_device *ecm_interface_should_update_egress_device_bridged(
3267 struct net_device *given_dest_dev, struct net_device *dest_dev,
3268 bool is_routed)
3269{
3270 struct net_device *bridge;
3271
3272 /*
3273 * Determine if we should attempt to fetch the bridge device
3274 */
3275 if (!given_dest_dev || is_routed || (dest_dev != given_dest_dev) ||
3276 ecm_front_end_is_bridge_device(given_dest_dev))
3277 return NULL;
3278
3279 bridge = ecm_interface_get_and_hold_dev_master(given_dest_dev);
3280
3281 if (!bridge)
3282 return NULL;
3283
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003284 if (!ecm_front_end_is_bridge_device(bridge)) {
3285 /*
3286 * Master is not a bridge - free the reference and return
3287 */
3288 dev_put(bridge);
3289 return NULL;
3290 }
3291
3292 /*
3293 * Reference is held to bridge and must be freed by caller
3294 */
3295 return bridge;
3296}
3297
3298/*
Ben Menchaca84f36632014-02-28 20:57:38 +00003299 * ecm_interface_heirarchy_construct()
3300 * Construct an interface heirarchy.
3301 *
3302 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
3303 * This is the heirarchy of interfaces a packet would transit to emit from the device.
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003304 *
3305 * We will use the given src/dest devices when is_routed is false.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003306 * When is_routed is true we will use the construct and the other devices (which is the src device of the
3307 * construct device) whcih were obtained from the skb's route field and passed to this function..
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003308 *
Ben Menchaca84f36632014-02-28 20:57:38 +00003309 * For example, with this network arrangement:
3310 *
3311 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
3312 *
Gareth Williams43fc0852014-05-26 19:10:00 +01003313 * 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 +00003314 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
3315 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
3316 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
3317 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
3318 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
3319 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
3320 *
3321 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
3322 * they will be created and added automatically to the database.
Ben Menchaca84f36632014-02-28 20:57:38 +00003323 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003324int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
3325 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin5dae8832015-12-03 14:23:19 -08003326 struct net_device *const_if, struct net_device *other_if,
Murat Sezginf92db492016-07-15 11:33:15 -07003327 ip_addr_t lookup_src_addr,
3328 ip_addr_t lookup_dest_addr,
3329 ip_addr_t real_dest_addr,
Murat Sezgin5dae8832015-12-03 14:23:19 -08003330 int ip_version, int packet_protocol,
3331 struct net_device *given_dest_dev,
3332 bool is_routed, struct net_device *given_src_dev,
3333 uint8_t *dest_node_addr, uint8_t *src_node_addr,
3334 __be16 *layer4hdr, struct sk_buff *skb)
3335{
3336 int protocol;
3337 ip_addr_t src_addr;
3338 ip_addr_t dest_addr;
3339 struct net_device *dest_dev;
3340 char *dest_dev_name;
3341 int32_t dest_dev_type;
3342 struct net_device *src_dev;
3343 char *src_dev_name;
3344 int32_t src_dev_type;
3345 int32_t current_interface_index;
3346 bool from_local_addr;
3347 bool next_dest_addr_valid;
3348 bool next_dest_node_addr_valid = false;
3349 ip_addr_t next_dest_addr;
3350 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003351 struct net_device *bridge;
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303352 struct net_device *top_dev_vlan = NULL;
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003353 uint32_t serial = ecm_db_connection_serial_get(feci->ci);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003354
3355 /*
3356 * Get a big endian of the IPv4 address we have been given as our starting point.
3357 */
3358 protocol = packet_protocol;
Murat Sezginf92db492016-07-15 11:33:15 -07003359 ECM_IP_ADDR_COPY(src_addr, lookup_src_addr);
3360 ECM_IP_ADDR_COPY(dest_addr, lookup_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003361
3362 if (ip_version == 4) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003363 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",
3364 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol,
3365 serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003366#ifdef ECM_IPV6_ENABLE
3367 } else if (ip_version == 6) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003368 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",
3369 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol,
3370 serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003371#endif
3372 } else {
3373 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
3374 return ECM_DB_IFACE_HEIRARCHY_MAX;
3375 }
3376
3377 /*
3378 * Get device to reach the given destination address.
3379 * If the heirarchy is for a routed connection we must use the devices obtained from the skb's route information..
3380 * If the heirarchy is NOT for a routed connection we try the given_dest_dev.
3381 */
3382 from_local_addr = false;
3383 if (!is_routed) {
3384 dest_dev = given_dest_dev;
3385 dev_hold(dest_dev);
3386 } else {
3387 dest_dev = ecm_interface_dev_find_by_local_addr(dest_addr);
3388 if (dest_dev) {
3389 from_local_addr = true;
3390 } else {
3391 dest_dev = const_if;
3392 dev_hold(dest_dev);
3393 }
3394 }
3395
3396 /*
3397 * If the address is a local address and protocol is an IP tunnel
3398 * then this connection is a tunnel endpoint made to this device.
3399 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
3400 *
3401 * TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
3402 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
3403 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
3404 */
3405 if (dest_dev && from_local_addr) {
3406 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
Murat Sezgin31effef2017-11-13 15:09:34 -08003407 ((ip_version == 6) && (protocol == IPPROTO_IPIP))
3408#ifdef ECM_INTERFACE_GRE_ENABLE
3409 || ((protocol == IPPROTO_GRE) && (given_dest_dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)))) {
3410#else
3411 {
3412#endif
Murat Sezgin5dae8832015-12-03 14:23:19 -08003413 dev_put(dest_dev);
3414 dest_dev = given_dest_dev;
3415 if (dest_dev) {
3416 dev_hold(dest_dev);
3417 if (ip_version == 4) {
3418 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);
3419 } else {
3420 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);
3421 }
3422 }
3423 }
3424 }
3425
3426#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05303427
Murat Sezgin5dae8832015-12-03 14:23:19 -08003428 /*
3429 * if the address is a local address and indev=l2tp.
3430 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05303431 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 -08003432 dev_put(dest_dev);
3433 dest_dev = given_dest_dev;
3434 if (dest_dev) {
3435 dev_hold(dest_dev);
3436 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);
3437 }
3438 }
3439#endif
3440
3441#ifdef ECM_INTERFACE_PPTP_ENABLE
3442 /*
3443 * if the address is a local address and indev=PPTP.
3444 */
3445 if (protocol == IPPROTO_GRE && given_dest_dev && given_dest_dev->type == ARPHRD_PPP) {
3446 dev_put(dest_dev);
3447 dest_dev = given_dest_dev;
3448 if (dest_dev) {
3449 dev_hold(dest_dev);
3450 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);
3451 }
3452 }
3453#endif
3454
3455 if (!dest_dev) {
3456 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
3457 return ECM_DB_IFACE_HEIRARCHY_MAX;
3458 }
3459 dest_dev_name = dest_dev->name;
3460 dest_dev_type = dest_dev->type;
3461
3462 /*
3463 * Get device to reach the given source address.
3464 * If the heirarchy is for a routed connection we must use the devices obtained from the skb's route information..
3465 * If the heirarchy is NOT for a routed connection we try the given_src_dev.
3466 */
3467 from_local_addr = false;
3468 if (!is_routed) {
3469 src_dev = given_src_dev;
3470 dev_hold(src_dev);
3471 } else {
3472 src_dev = ecm_interface_dev_find_by_local_addr(src_addr);
3473 if (src_dev) {
3474 from_local_addr = true;
3475 } else {
3476 src_dev = other_if;
3477 dev_hold(src_dev);
3478 }
3479 }
3480
3481 /*
3482 * If the address is a local address and protocol is an IP tunnel
3483 * then this connection is a tunnel endpoint made to this device.
3484 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
3485 *
3486 * TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
3487 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
3488 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
3489 */
3490 if (src_dev && from_local_addr) {
3491 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
Murat Sezgin31effef2017-11-13 15:09:34 -08003492 ((ip_version == 6) && (protocol == IPPROTO_IPIP))
3493#ifdef ECM_INTERFACE_GRE_ENABLE
3494 || ((protocol == IPPROTO_GRE) && (given_src_dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)))) {
3495#else
3496 {
3497#endif
Murat Sezgin5dae8832015-12-03 14:23:19 -08003498 dev_put(src_dev);
3499 src_dev = given_src_dev;
3500 if (src_dev) {
3501 dev_hold(src_dev);
3502 if (ip_version == 4) {
3503 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);
3504 } else {
3505 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);
3506 }
3507 }
3508 }
3509 }
3510
3511 if (!src_dev) {
3512 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
3513 dev_put(dest_dev);
3514 return ECM_DB_IFACE_HEIRARCHY_MAX;
3515 }
3516 src_dev_name = src_dev->name;
3517 src_dev_type = src_dev->type;
3518
3519 /*
3520 * Check if source and dest dev are same.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003521 */
3522 if (src_dev == dest_dev) {
ratheesh kannotha6d25952016-04-11 12:23:26 +05303523 bool skip = false;
3524
Murat Sezgin5dae8832015-12-03 14:23:19 -08003525 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
ratheesh kannotha6d25952016-04-11 12:23:26 +05303526
3527 switch (ip_version) {
3528 case 4:
3529 if ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)) {
3530 skip = true;
3531 break;
3532 }
3533
3534 if ((protocol == IPPROTO_UDP) && (udp_hdr(skb)->dest == htons(4500))) {
3535 skip = true;
3536 break;
3537 }
3538
3539 break;
3540
3541 case 6:
ratheesh kannotha6d25952016-04-11 12:23:26 +05303542 if ((protocol == IPPROTO_IPIP) || (protocol == IPPROTO_ESP)) {
3543 skip = true;
3544 break;
3545 }
3546
3547 break;
3548
3549 default:
3550 DEBUG_WARN("IP version = %d, Protocol = %d: Corrupted packet entered ecm\n", ip_version, protocol);
3551 skip = true;
3552 break;
3553 }
3554
3555 if (skip) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003556 /*
3557 * This happens from the input hook
3558 * We do not want to create a connection entry for this
3559 * TODO YES WE DO.
3560 * TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
3561 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
3562 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
3563 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
3564 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
3565 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
3566 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
3567 */
3568 dev_put(src_dev);
3569 dev_put(dest_dev);
3570 return ECM_DB_IFACE_HEIRARCHY_MAX;
3571 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003572 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003573
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003574 bridge = ecm_interface_should_update_egress_device_bridged(
3575 given_dest_dev, dest_dev, is_routed);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003576
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003577 if (bridge) {
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003578 struct net_device *new_dest_dev;
Murat Sezginb9bd5e02016-08-05 14:55:07 -07003579 new_dest_dev = br_port_dev_get(bridge, dest_node_addr, skb, serial);
3580 if (new_dest_dev) {
3581 dev_put(dest_dev);
3582 if (new_dest_dev != given_dest_dev) {
3583 DEBUG_INFO("Adjusted port for %pM is %s (given was %s)\n",
3584 dest_node_addr, new_dest_dev->name,
3585 given_dest_dev->name);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003586
Murat Sezginb9bd5e02016-08-05 14:55:07 -07003587 dest_dev = new_dest_dev;
3588 dest_dev_name = dest_dev->name;
3589 dest_dev_type = dest_dev->type;
Murat Sezgin5dae8832015-12-03 14:23:19 -08003590 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003591 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003592 dev_put(bridge);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003593 }
3594
3595 next_dest_addr_valid = true;
3596 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
3597
3598 /*
3599 * Iterate until we are done or get to the max number of interfaces we can record.
3600 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
3601 * because we add from the end first_interface grows downwards.
3602 */
3603 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
3604 while (current_interface_index > 0) {
3605 struct ecm_db_iface_instance *ii;
3606 struct net_device *next_dev;
3607 /*
3608 * Get the ecm db interface instance for the device at hand
3609 */
3610 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
3611
3612 /*
3613 * If the interface could not be established then we abort
3614 */
3615 if (!ii) {
3616 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
3617 dev_put(src_dev);
3618 dev_put(dest_dev);
3619
3620 /*
3621 * Release the interfaces heirarchy we constructed to this point.
3622 */
3623 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3624 return ECM_DB_IFACE_HEIRARCHY_MAX;
3625 }
3626
3627 /*
3628 * Record the interface instance into the interfaces[]
3629 */
3630 current_interface_index--;
3631 interfaces[current_interface_index] = ii;
3632
3633 /*
3634 * Now we have to figure out what the next device will be (in the transmission path) the skb
3635 * will use to emit to the destination address.
3636 */
3637 do {
3638#ifdef ECM_INTERFACE_PPP_ENABLE
3639 int channel_count;
3640 struct ppp_channel *ppp_chan[1];
3641 int channel_protocol;
3642#ifdef ECM_INTERFACE_PPPOE_ENABLE
3643 struct pppoe_opt addressing;
3644#endif
3645#endif
3646
3647 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
3648 next_dev = NULL;
3649
3650 if (dest_dev_type == ARPHRD_ETHER) {
3651 /*
3652 * Ethernet - but what sub type?
3653 */
3654
3655#ifdef ECM_INTERFACE_VLAN_ENABLE
3656 /*
3657 * VLAN?
3658 */
3659 if (is_vlan_dev(dest_dev)) {
3660 /*
3661 * VLAN master
3662 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
3663 */
Shyam Sunder9db20852016-03-09 19:04:49 +05303664 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003665 dev_hold(next_dev);
3666 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
3667 dest_dev, next_dev, next_dev->name);
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303668 if (current_interface_index == (ECM_DB_IFACE_HEIRARCHY_MAX - 1)) {
3669 top_dev_vlan = dest_dev;
3670 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003671 break;
3672 }
3673#endif
3674
3675 /*
3676 * BRIDGE?
3677 */
3678 if (ecm_front_end_is_bridge_device(dest_dev)) {
3679 /*
3680 * Bridge
3681 * Figure out which port device the skb will go to using the dest_addr.
3682 */
3683 uint8_t mac_addr[ETH_ALEN];
3684
3685 if (next_dest_node_addr_valid) {
3686 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
3687 } else if (!next_dest_addr_valid) {
3688 dev_put(src_dev);
3689 dev_put(dest_dev);
3690
3691 /*
3692 * Release the interfaces heirarchy we constructed to this point.
3693 */
3694 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3695 return ECM_DB_IFACE_HEIRARCHY_MAX;
3696 } else {
3697 if (!ecm_interface_get_next_node_mac_address(dest_addr, dest_dev, ip_version, mac_addr)) {
3698 dev_put(src_dev);
3699 dev_put(dest_dev);
3700
3701 /*
3702 * Release the interfaces heirarchy we constructed to this point.
3703 */
3704 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3705 return ECM_DB_IFACE_HEIRARCHY_MAX;
3706 }
3707 }
3708
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003709 next_dev = br_port_dev_get(dest_dev,
3710 mac_addr, skb, serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003711
3712 if (!next_dev) {
3713 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
3714 dev_put(src_dev);
3715 dev_put(dest_dev);
3716
3717 /*
3718 * Release the interfaces heirarchy we constructed to this point.
3719 */
3720 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3721 return ECM_DB_IFACE_HEIRARCHY_MAX;
3722 }
3723 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3724 break;
3725 }
3726
3727#ifdef ECM_INTERFACE_BOND_ENABLE
3728 /*
3729 * LAG?
3730 */
3731 if (ecm_front_end_is_lag_master(dest_dev)) {
3732 /*
3733 * Link aggregation
3734 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
3735 */
3736 uint32_t src_addr_32 = 0;
3737 uint32_t dest_addr_32 = 0;
3738 struct in6_addr src_addr6;
3739 struct in6_addr dest_addr6;
3740 uint8_t src_mac_addr[ETH_ALEN];
3741 uint8_t dest_mac_addr[ETH_ALEN];
3742
3743 memset(src_mac_addr, 0, ETH_ALEN);
3744 memset(dest_mac_addr, 0, ETH_ALEN);
3745
3746 if (ip_version == 4) {
3747 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
Murat Sezginf92db492016-07-15 11:33:15 -07003748 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, real_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003749 }
3750
3751 if (!is_routed) {
3752 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
3753 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
3754 } else {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003755 struct net_device *master_dev;
Murat Sezgin5dae8832015-12-03 14:23:19 -08003756
3757 /*
Murat Sezgin7be87d22016-01-29 17:41:37 -08003758 * Use appropriate source MAC address for routed packets and
3759 * find proper interface to find the destination mac address and
3760 * from which to issue ARP or neighbour solicitation packet.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003761 */
Murat Sezgin7be87d22016-01-29 17:41:37 -08003762 master_dev = ecm_interface_get_and_hold_dev_master(dest_dev);
3763 if (master_dev) {
3764 memcpy(src_mac_addr, master_dev->dev_addr, ETH_ALEN);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003765 } else {
3766 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003767 master_dev = dest_dev;
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303768 if (top_dev_vlan) {
3769 master_dev = top_dev_vlan;
3770 }
Murat Sezgin7be87d22016-01-29 17:41:37 -08003771 dev_hold(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003772 }
3773
3774 /*
3775 * Determine destination MAC address for this routed packet
3776 */
3777 if (next_dest_node_addr_valid) {
3778 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
3779 } else if (!next_dest_addr_valid) {
3780 dev_put(src_dev);
3781 dev_put(dest_dev);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003782 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003783 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3784 return ECM_DB_IFACE_HEIRARCHY_MAX;
3785 } else {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003786 if (!ecm_interface_mac_addr_get_no_route(master_dev, dest_addr, dest_mac_addr)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003787 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3788 /*
3789 * Try one more time with gateway ip address if it exists.
3790 */
3791 if (!ecm_interface_find_gateway(dest_addr, gw_addr)) {
3792 goto lag_fail;
3793 }
3794
3795 if (ip_version == 4) {
3796 DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(gw_addr));
3797 }
3798#ifdef ECM_IPV6_ENABLE
3799
3800 if (ip_version == 6) {
3801 DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr));
3802 }
3803#endif
Murat Sezgin7be87d22016-01-29 17:41:37 -08003804 if (ecm_interface_mac_addr_get_no_route(master_dev, gw_addr, dest_mac_addr)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003805 DEBUG_TRACE("Found the mac address for gateway\n");
Murat Sezgin7be87d22016-01-29 17:41:37 -08003806 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003807 goto lag_success;
3808 }
3809
3810 if (ip_version == 4) {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003811 ecm_interface_send_arp_request(master_dev, dest_addr, false, gw_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003812
3813 DEBUG_WARN("Unable to obtain any MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
3814 }
3815#ifdef ECM_IPV6_ENABLE
3816 if (ip_version == 6) {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003817 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003818
3819 DEBUG_WARN("Unable to obtain any MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
3820 }
3821#endif
3822lag_fail:
3823 dev_put(src_dev);
3824 dev_put(dest_dev);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003825 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003826
3827 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3828 return ECM_DB_IFACE_HEIRARCHY_MAX;
3829 }
Murat Sezgin7be87d22016-01-29 17:41:37 -08003830 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003831 }
3832 }
3833lag_success:
3834 if (ip_version == 4) {
3835 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3836 &src_addr_32, &dest_addr_32,
3837 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
3838 } else if (ip_version == 6) {
3839 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
Murat Sezginf92db492016-07-15 11:33:15 -07003840 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, real_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003841 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3842 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05303843 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003844 }
3845
3846 if (next_dev && netif_carrier_ok(next_dev)) {
3847 dev_hold(next_dev);
3848 } else {
3849 DEBUG_WARN("Unable to obtain LAG output slave device\n");
3850 dev_put(src_dev);
3851 dev_put(dest_dev);
3852
3853 /*
3854 * Release the interfaces heirarchy we constructed to this point.
3855 */
3856 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3857 return ECM_DB_IFACE_HEIRARCHY_MAX;
3858 }
3859
3860 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3861 break;
3862 }
3863#endif
3864
3865 /*
3866 * ETHERNET!
3867 * Just plain ethernet it seems.
3868 */
3869 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
3870 break;
3871 }
3872
3873 /*
3874 * LOOPBACK?
3875 */
3876 if (dest_dev_type == ARPHRD_LOOPBACK) {
3877 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
3878 break;
3879 }
3880
3881 /*
3882 * IPSEC?
3883 */
3884 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
3885 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
3886 /* TODO Figure out the next device the tunnel is using... */
3887 break;
3888 }
3889
3890 /*
3891 * SIT (6-in-4)?
3892 */
3893 if (dest_dev_type == ARPHRD_SIT) {
3894 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
3895 /* TODO Figure out the next device the tunnel is using... */
3896 break;
3897 }
3898
3899 /*
3900 * IPIP6 Tunnel?
3901 */
3902 if (dest_dev_type == ARPHRD_TUNNEL6) {
3903 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
3904 /* TODO Figure out the next device the tunnel is using... */
3905 break;
3906 }
3907
ratheesh kannothcfdcb332015-12-24 07:19:18 +05303908#ifdef ECM_INTERFACE_MAP_T_ENABLE
3909 /*
3910 * MAP-T xlate ?
3911 */
3912 if (dest_dev_type == ARPHRD_NONE) {
3913 if (is_map_t_dev(dest_dev)) {
3914 DEBUG_TRACE("Net device: %p is MAP-T type: %d\n", dest_dev, dest_dev_type);
3915 break;
3916 }
3917 }
3918#endif
3919
Murat Sezgin5dae8832015-12-03 14:23:19 -08003920 /*
3921 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
3922 */
3923 if (dest_dev_type != ARPHRD_PPP) {
3924 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
3925 break;
3926 }
3927
3928#ifndef ECM_INTERFACE_PPP_ENABLE
3929 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
3930#else
3931 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
3932
3933#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05303934 if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003935 if (skb->skb_iif == dest_dev->ifindex) {
3936 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
3937 break;
3938 }
3939 }
3940#endif
3941
3942#ifdef ECM_INTERFACE_PPTP_ENABLE
3943 if (protocol == IPPROTO_GRE && dest_dev && dest_dev->type == ARPHRD_PPP) {
3944 DEBUG_TRACE("Net device: %p PPP channel is PPTP\n", dest_dev);
3945 break;
3946 }
3947#endif
3948 /*
3949 * PPP - but what is the channel type?
3950 * First: If this is multi-link then we do not support it
3951 */
3952 if (ppp_is_multilink(dest_dev) > 0) {
3953 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
3954 break;
3955 }
3956
3957 /*
3958 * Get the PPP channel and then enquire what kind of channel it is
3959 * NOTE: Not multilink so only one channel to get.
3960 */
3961 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
3962 if (channel_count != 1) {
3963 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
3964 dest_dev, channel_count);
3965 break;
3966 }
3967
3968 /*
3969 * Get channel protocol type
3970 * NOTE: Not all PPP channels support channel specific methods.
3971 */
3972 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
3973
3974#ifdef ECM_INTERFACE_L2TPV2_ENABLE
3975 if (channel_protocol == PX_PROTO_OL2TP) {
3976
3977 /*
3978 * PPPoL2TPV2 channel
3979 */
3980 ppp_release_channels(ppp_chan, 1);
3981 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
3982
3983 /*
3984 * Release the channel. Note that next_dev not held.
3985 */
3986 break;
3987 }
3988#endif
3989#ifdef ECM_INTERFACE_PPPOE_ENABLE
3990 if (channel_protocol == PX_PROTO_OE) {
3991 /*
3992 * PPPoE channel
3993 */
3994 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
3995
3996 /*
3997 * Get PPPoE session information and the underlying device it is using.
3998 */
3999 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
4000
4001 /*
4002 * Copy the dev hold into this, we will release the hold later
4003 */
4004 next_dev = addressing.dev;
4005 next_dest_addr_valid = false;
4006 next_dest_node_addr_valid = true;
4007 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
4008
4009 /*
4010 * Release the channel. Note that next_dev is still (correctly) held.
4011 */
4012 ppp_release_channels(ppp_chan, 1);
4013 break;
4014 }
4015#endif
4016
4017 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
4018 dest_dev, channel_protocol);
4019
4020 /*
4021 * Release the channel
4022 */
4023 ppp_release_channels(ppp_chan, 1);
4024
4025#endif
4026 } while (false);
4027
4028 /*
4029 * No longer need dest_dev as it may become next_dev
4030 */
4031 dev_put(dest_dev);
4032
4033 /*
4034 * Check out the next_dev, if any
4035 */
4036 if (!next_dev) {
4037 int32_t i __attribute__((unused));
4038 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
4039#if DEBUG_LEVEL > 1
4040 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
4041 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
4042 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])));
4043
4044 }
4045#endif
4046
4047 /*
4048 * Release src_dev now
4049 */
4050 dev_put(src_dev);
4051 return current_interface_index;
4052 }
4053
4054 /*
4055 * dest_dev becomes next_dev
4056 */
4057 dest_dev = next_dev;
4058 dest_dev_name = dest_dev->name;
4059 dest_dev_type = dest_dev->type;
4060 }
4061
4062 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
4063 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
4064 dev_put(src_dev);
4065 dev_put(dest_dev);
4066
4067 /*
4068 * Release the interfaces heirarchy we constructed to this point.
4069 */
4070 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4071 return ECM_DB_IFACE_HEIRARCHY_MAX;
4072}
4073EXPORT_SYMBOL(ecm_interface_heirarchy_construct);
4074
4075#ifdef ECM_MULTICAST_ENABLE
4076/*
4077 * ecm_interface_multicast_from_heirarchy_construct()
4078 * Construct an interface heirarchy.
4079 *
4080 * TODO: This function will be removed later and ecm_interface_heirarchy_construct() function
4081 * will be used when the multicast code is fixed to use the new interface hierarchy
4082 * construction model which uses the skb's route information instead of doing
4083 * the route lookup based on the IP addresses.
4084 *
4085 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
4086 * This is the heirarchy of interfaces a packet would transit to emit from the device.
4087 *
4088 * We will use the given src/dest devices when is_routed is false.
4089 * When is_routed is true we will try routing tables first, failing back to any given.
4090 *
4091 * For example, with this network arrangement:
4092 *
4093 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
4094 *
4095 * Given the packet_dest_addr IP address 10.22.33.11 this will create an interface heirarchy (in interracfes[]) of:
4096 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
4097 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
4098 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
4099 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
4100 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
4101 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
4102 *
4103 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
4104 * they will be created and added automatically to the database.
4105 */
4106int32_t ecm_interface_multicast_from_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
4107 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin188b4a32015-06-03 10:58:59 -07004108 ip_addr_t packet_src_addr,
4109 ip_addr_t packet_dest_addr,
4110 int ip_version, int packet_protocol,
4111 struct net_device *given_dest_dev,
4112 bool is_routed, struct net_device *given_src_dev,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05304113 uint8_t *dest_node_addr, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304114 __be16 *layer4hdr, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00004115{
Ben Menchaca84f36632014-02-28 20:57:38 +00004116 int protocol;
4117 ip_addr_t src_addr;
4118 ip_addr_t dest_addr;
Ben Menchaca84f36632014-02-28 20:57:38 +00004119 struct net_device *dest_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00004120 char *dest_dev_name;
Ben Menchaca84f36632014-02-28 20:57:38 +00004121 int32_t dest_dev_type;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004122 struct net_device *src_dev;
4123 char *src_dev_name;
4124 int32_t src_dev_type;
Ben Menchaca84f36632014-02-28 20:57:38 +00004125 int32_t current_interface_index;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004126 bool from_local_addr;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004127 bool next_dest_addr_valid;
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004128 bool next_dest_node_addr_valid = false;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004129 ip_addr_t next_dest_addr;
4130 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004131 struct net_device *bridge;
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004132 uint32_t serial = ecm_db_connection_serial_get(feci->ci);
Ben Menchaca84f36632014-02-28 20:57:38 +00004133
4134 /*
4135 * Get a big endian of the IPv4 address we have been given as our starting point.
4136 */
4137 protocol = packet_protocol;
4138 ECM_IP_ADDR_COPY(src_addr, packet_src_addr);
4139 ECM_IP_ADDR_COPY(dest_addr, packet_dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004140
4141 if (ip_version == 4) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004142 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",
4143 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol,
4144 serial);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004145#ifdef ECM_IPV6_ENABLE
4146 } else if (ip_version == 6) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004147 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",
4148 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol,
4149 serial);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004150#endif
4151 } else {
4152 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
4153 return ECM_DB_IFACE_HEIRARCHY_MAX;
4154 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004155
4156 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004157 * Get device to reach the given destination address.
4158 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_dest_dev.
4159 * 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 +00004160 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004161 from_local_addr = false;
4162 if (is_routed) {
4163 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
4164 if (!dest_dev && given_dest_dev) {
4165 /*
4166 * Fall back to any given
4167 */
4168 dest_dev = given_dest_dev;
4169 dev_hold(dest_dev);
Gareth Williams43fc0852014-05-26 19:10:00 +01004170 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004171 } else if (given_dest_dev) {
4172 dest_dev = given_dest_dev;
4173 dev_hold(dest_dev);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304174 } else {
4175 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004176 * Fall back to routed look up
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304177 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004178 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
Gareth Williams43fc0852014-05-26 19:10:00 +01004179 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304180
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004181 /*
4182 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
4183 * then this connection is a tunnel endpoint made to this device.
4184 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
4185 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
4186 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
4187 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
4188 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07004189 if (dest_dev && from_local_addr) {
4190 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
4191 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
4192 dev_put(dest_dev);
4193 dest_dev = given_dest_dev;
4194 if (dest_dev) {
4195 dev_hold(dest_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05304196 if (ip_version == 4) {
4197 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);
4198 } else {
4199 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);
4200 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004201 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304202 }
Gareth Williams43fc0852014-05-26 19:10:00 +01004203 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304204
4205#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4206 /*
4207 * if the address is a local address and indev=l2tp.
4208 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05304209 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 +05304210 dev_put(dest_dev);
4211 dest_dev = given_dest_dev;
4212 if (dest_dev) {
4213 dev_hold(dest_dev);
4214 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);
4215 }
4216 }
4217#endif
4218
Shyam Sunder23f2e542015-09-28 14:56:49 +05304219#ifdef ECM_INTERFACE_PPTP_ENABLE
4220 /*
4221 * if the address is a local address and indev=PPTP.
4222 */
4223 if (protocol == IPPROTO_GRE && given_dest_dev && given_dest_dev->type == ARPHRD_PPP) {
4224 dev_put(dest_dev);
4225 dest_dev = given_dest_dev;
4226 if (dest_dev) {
4227 dev_hold(dest_dev);
4228 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);
4229 }
4230 }
4231#endif
4232
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004233 if (!dest_dev) {
4234 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
4235 return ECM_DB_IFACE_HEIRARCHY_MAX;
4236 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004237 dest_dev_name = dest_dev->name;
4238 dest_dev_type = dest_dev->type;
4239
4240 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004241 * Get device to reach the given source address.
4242 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_src_dev.
4243 * If the heirarchy is NOT for a routed connection we try the given_src_dev first, followed by routed lookup.
4244 */
4245 from_local_addr = false;
4246 if (is_routed) {
4247 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
4248 if (!src_dev && given_src_dev) {
4249 /*
4250 * Fall back to any given
4251 */
4252 src_dev = given_src_dev;
4253 dev_hold(src_dev);
4254 }
4255 } else if (given_src_dev) {
4256 src_dev = given_src_dev;
4257 dev_hold(src_dev);
4258 } else {
4259 /*
4260 * Fall back to routed look up
4261 */
4262 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
4263 }
4264
4265 /*
4266 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
4267 * then this connection is a tunnel endpoint made to this device.
4268 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
4269 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
4270 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
4271 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
4272 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07004273 if (src_dev && from_local_addr) {
4274 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
4275 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
4276 dev_put(src_dev);
4277 src_dev = given_src_dev;
4278 if (src_dev) {
4279 dev_hold(src_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05304280 if (ip_version == 4) {
4281 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);
4282 } else {
4283 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);
4284 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004285 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004286 }
4287 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004288
ratheesh kannothed721852015-09-28 12:39:52 +05304289#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4290 /*
4291 * if the address is a local address and indev=l2tp.
4292 */
4293 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
4294 if (dest_dev != given_src_dev) {
4295 dev_put(src_dev);
4296 src_dev = given_src_dev;
4297 if (src_dev) {
4298 dev_hold(src_dev);
4299 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);
4300 }
4301 }
4302 }
4303#endif
4304
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004305 if (!src_dev) {
4306 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
4307 dev_put(dest_dev);
4308 return ECM_DB_IFACE_HEIRARCHY_MAX;
4309 }
4310 src_dev_name = src_dev->name;
4311 src_dev_type = src_dev->type;
4312
4313 /*
4314 * Check if source and dest dev are same.
4315 * For the forwarded flows which involve tunnels this will happen when called from input hook.
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304316 */
4317 if (src_dev == dest_dev) {
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004318 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004319 if (((ip_version == 4) && ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)))
4320 || ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304321 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004322 * This happens from the input hook
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304323 * We do not want to create a connection entry for this
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004324 * GGG TODO YES WE DO.
4325 * GGG TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
4326 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
4327 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
4328 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
4329 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
4330 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
4331 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304332 */
4333 dev_put(src_dev);
4334 dev_put(dest_dev);
4335 return ECM_DB_IFACE_HEIRARCHY_MAX;
4336 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004337 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004338
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004339 bridge = ecm_interface_should_update_egress_device_bridged(
4340 given_dest_dev, dest_dev, is_routed);
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004341
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004342 if (bridge) {
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004343 struct net_device *new_dest_dev;
Murat Sezginb9bd5e02016-08-05 14:55:07 -07004344 new_dest_dev = br_port_dev_get(bridge, dest_node_addr, skb, serial);
4345 if (new_dest_dev) {
4346 dev_put(dest_dev);
4347 if (new_dest_dev != given_dest_dev) {
4348 DEBUG_INFO("Adjusted port for %pM is %s (given was %s)\n",
4349 dest_node_addr, new_dest_dev->name,
4350 given_dest_dev->name);
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004351
Murat Sezginb9bd5e02016-08-05 14:55:07 -07004352 dest_dev = new_dest_dev;
4353 dest_dev_name = dest_dev->name;
4354 dest_dev_type = dest_dev->type;
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004355 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004356 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004357 dev_put(bridge);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304358 }
4359
Murat Sezgin7ef29962015-08-14 10:53:24 -07004360 next_dest_addr_valid = true;
Murat Sezgin5dae8832015-12-03 14:23:19 -08004361 next_dest_node_addr_valid = false;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004362 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
4363
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304364 /*
Ben Menchaca84f36632014-02-28 20:57:38 +00004365 * Iterate until we are done or get to the max number of interfaces we can record.
4366 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
4367 * because we add from the end first_interface grows downwards.
4368 */
4369 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
4370 while (current_interface_index > 0) {
4371 struct ecm_db_iface_instance *ii;
4372 struct net_device *next_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00004373 /*
4374 * Get the ecm db interface instance for the device at hand
4375 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304376 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Ben Menchaca84f36632014-02-28 20:57:38 +00004377
4378 /*
4379 * If the interface could not be established then we abort
4380 */
4381 if (!ii) {
4382 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
4383 dev_put(src_dev);
4384 dev_put(dest_dev);
4385
4386 /*
4387 * Release the interfaces heirarchy we constructed to this point.
4388 */
4389 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4390 return ECM_DB_IFACE_HEIRARCHY_MAX;
4391 }
4392
4393 /*
4394 * Record the interface instance into the interfaces[]
4395 */
4396 current_interface_index--;
4397 interfaces[current_interface_index] = ii;
4398
4399 /*
4400 * Now we have to figure out what the next device will be (in the transmission path) the skb
4401 * will use to emit to the destination address.
4402 */
4403 do {
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08004404#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004405 int channel_count;
4406 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00004407 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304408#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004409 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004410#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304411#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004412
4413 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
4414 next_dev = NULL;
4415
4416 if (dest_dev_type == ARPHRD_ETHER) {
4417 /*
4418 * Ethernet - but what sub type?
4419 */
4420
Gareth Williams141d2382014-11-25 11:35:19 -08004421#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004422 /*
4423 * VLAN?
4424 */
4425 if (is_vlan_dev(dest_dev)) {
4426 /*
4427 * VLAN master
4428 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
4429 */
Shyam Sunder9db20852016-03-09 19:04:49 +05304430 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004431 dev_hold(next_dev);
4432 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
4433 dest_dev, next_dev, next_dev->name);
4434 break;
4435 }
Gareth Williams141d2382014-11-25 11:35:19 -08004436#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004437
4438 /*
4439 * BRIDGE?
4440 */
4441 if (ecm_front_end_is_bridge_device(dest_dev)) {
4442 /*
4443 * Bridge
4444 * Figure out which port device the skb will go to using the dest_addr.
4445 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004446 uint8_t mac_addr[ETH_ALEN];
Murat Sezgin7ef29962015-08-14 10:53:24 -07004447
4448 if (next_dest_node_addr_valid) {
4449 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
4450 } else if (!next_dest_addr_valid) {
Ben Menchaca84f36632014-02-28 20:57:38 +00004451 dev_put(src_dev);
4452 dev_put(dest_dev);
4453
4454 /*
4455 * Release the interfaces heirarchy we constructed to this point.
4456 */
4457 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4458 return ECM_DB_IFACE_HEIRARCHY_MAX;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004459 } else {
Murat Sezgin5dae8832015-12-03 14:23:19 -08004460 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 -07004461 dev_put(src_dev);
4462 dev_put(dest_dev);
4463
4464 /*
4465 * Release the interfaces heirarchy we constructed to this point.
4466 */
4467 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4468 return ECM_DB_IFACE_HEIRARCHY_MAX;
4469 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004470 }
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004471 next_dev = br_port_dev_get(dest_dev,
4472 mac_addr, skb, serial);
Ben Menchaca84f36632014-02-28 20:57:38 +00004473 if (!next_dev) {
4474 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
4475 dev_put(src_dev);
4476 dev_put(dest_dev);
4477
4478 /*
4479 * Release the interfaces heirarchy we constructed to this point.
4480 */
4481 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4482 return ECM_DB_IFACE_HEIRARCHY_MAX;
4483 }
4484 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
4485 break;
4486 }
Gareth Williams8ac34292015-03-17 14:06:58 +00004487
Murat Sezginb3731e82014-11-26 12:20:59 -08004488#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004489 /*
4490 * LAG?
4491 */
4492 if (ecm_front_end_is_lag_master(dest_dev)) {
4493 /*
4494 * Link aggregation
Murat Sezginb3731e82014-11-26 12:20:59 -08004495 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
Ben Menchaca84f36632014-02-28 20:57:38 +00004496 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304497 bool dest_on_link = false;
4498 ip_addr_t dest_gw_addr = ECM_IP_ADDR_NULL;
4499 uint32_t src_addr_32 = 0;
4500 uint32_t dest_addr_32 = 0;
Suman Ghoshf14d2172015-07-31 14:38:10 +05304501 struct in6_addr src_addr6;
4502 struct in6_addr dest_addr6;
Ben Menchaca84f36632014-02-28 20:57:38 +00004503 uint8_t src_mac_addr[ETH_ALEN];
4504 uint8_t dest_mac_addr[ETH_ALEN];
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304505 struct net_device *master_dev = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00004506
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304507 memset(src_mac_addr, 0, ETH_ALEN);
4508 memset(dest_mac_addr, 0, ETH_ALEN);
Ben Menchaca84f36632014-02-28 20:57:38 +00004509
Gareth Williams341df382015-07-20 16:44:17 +01004510 if (ip_version == 4) {
4511 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
4512 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
4513 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304514
4515 if (!is_routed) {
4516 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
4517 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
4518 } else {
Murat Sezginb3731e82014-11-26 12:20:59 -08004519 struct net_device *dest_dev_master;
4520
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304521 /*
4522 * Use appropriate source MAC address for routed packets
4523 */
Murat Sezginb3731e82014-11-26 12:20:59 -08004524 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
4525 if (dest_dev_master) {
4526 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304527 } else {
4528 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
4529 }
4530
4531 /*
4532 * Determine destination MAC address for this routed packet
4533 */
Tushar Mathur78b5f432015-09-18 20:13:31 +05304534 if (next_dest_node_addr_valid) {
4535 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
4536 } else if (!next_dest_addr_valid) {
4537 dev_put(src_dev);
4538 dev_put(dest_dev);
Murat Sezginb3731e82014-11-26 12:20:59 -08004539 if (dest_dev_master) {
4540 dev_put(dest_dev_master);
4541 }
4542
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304543 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4544 return ECM_DB_IFACE_HEIRARCHY_MAX;
Tushar Mathur78b5f432015-09-18 20:13:31 +05304545 } else {
4546 if (!ecm_interface_mac_addr_get(dest_addr, dest_mac_addr,
4547 &dest_on_link, dest_gw_addr)) {
4548
4549 /*
4550 * Find proper interfce from which to issue ARP
4551 * or neighbour solicitation packet.
4552 */
4553 if (dest_dev_master) {
4554 master_dev = dest_dev_master;
4555 } else {
4556 master_dev = dest_dev;
4557 }
4558
4559 dev_hold(master_dev);
4560
4561 if (dest_dev_master) {
4562 dev_put(dest_dev_master);
4563 }
4564
4565 if (ip_version == 4) {
4566 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
4567 ecm_interface_send_arp_request(dest_dev, dest_addr, dest_on_link, dest_gw_addr);
4568 }
4569#ifdef ECM_IPV6_ENABLE
4570 if (ip_version == 6) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08004571 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 +05304572 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
4573 }
4574#endif
4575 dev_put(src_dev);
4576 dev_put(dest_dev);
4577 dev_put(master_dev);
4578 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4579 return ECM_DB_IFACE_HEIRARCHY_MAX;
4580 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304581 }
Murat Sezginb3731e82014-11-26 12:20:59 -08004582
4583 if (dest_dev_master) {
4584 dev_put(dest_dev_master);
4585 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304586 }
4587
Murat Sezgin188b4a32015-06-03 10:58:59 -07004588 if (ip_version == 4) {
4589 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
4590 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05304591 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004592 } else if (ip_version == 6) {
Suman Ghoshf14d2172015-07-31 14:38:10 +05304593 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
4594 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004595 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
Suman Ghoshf14d2172015-07-31 14:38:10 +05304596 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05304597 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004598 }
4599
Tushar Mathur933907c2014-06-24 17:06:14 +05304600 if (next_dev && netif_carrier_ok(next_dev)) {
Ben Menchaca84f36632014-02-28 20:57:38 +00004601 dev_hold(next_dev);
4602 } else {
4603 DEBUG_WARN("Unable to obtain LAG output slave device\n");
4604 dev_put(src_dev);
4605 dev_put(dest_dev);
4606
4607 /*
4608 * Release the interfaces heirarchy we constructed to this point.
4609 */
4610 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4611 return ECM_DB_IFACE_HEIRARCHY_MAX;
4612 }
4613
4614 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 +00004615 break;
4616 }
Murat Sezginb3731e82014-11-26 12:20:59 -08004617#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004618
4619 /*
4620 * ETHERNET!
4621 * Just plain ethernet it seems.
4622 */
4623 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
4624 break;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05304625 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004626
4627 /*
4628 * LOOPBACK?
4629 */
4630 if (dest_dev_type == ARPHRD_LOOPBACK) {
4631 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
4632 break;
4633 }
4634
4635 /*
4636 * IPSEC?
4637 */
4638 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
4639 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004640 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004641 break;
4642 }
4643
4644 /*
4645 * SIT (6-in-4)?
4646 */
4647 if (dest_dev_type == ARPHRD_SIT) {
4648 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 -08004649 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004650 break;
4651 }
4652
4653 /*
4654 * IPIP6 Tunnel?
4655 */
4656 if (dest_dev_type == ARPHRD_TUNNEL6) {
4657 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004658 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004659 break;
4660 }
4661
4662 /*
4663 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
4664 */
4665 if (dest_dev_type != ARPHRD_PPP) {
4666 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
4667 break;
4668 }
4669
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08004670#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004671 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
4672#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304673 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
4674
4675#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05304676 if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) {
ratheesh kannothed721852015-09-28 12:39:52 +05304677 if (skb->skb_iif == dest_dev->ifindex) {
4678 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
4679 break;
4680 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304681 }
4682#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05304683
4684#ifdef ECM_INTERFACE_PPTP_ENABLE
4685 if (protocol == IPPROTO_GRE && dest_dev && dest_dev->type == ARPHRD_PPP) {
4686 DEBUG_TRACE("Net device: %p PPP channel is PPTP\n", dest_dev);
4687 break;
4688 }
4689#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004690 /*
4691 * PPP - but what is the channel type?
4692 * First: If this is multi-link then we do not support it
4693 */
4694 if (ppp_is_multilink(dest_dev) > 0) {
4695 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
4696 break;
4697 }
4698
Ben Menchaca84f36632014-02-28 20:57:38 +00004699 /*
4700 * Get the PPP channel and then enquire what kind of channel it is
4701 * NOTE: Not multilink so only one channel to get.
4702 */
4703 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
4704 if (channel_count != 1) {
4705 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
4706 dest_dev, channel_count);
4707 break;
4708 }
4709
4710 /*
4711 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01004712 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00004713 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01004714 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304715
4716#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4717 if (channel_protocol == PX_PROTO_OL2TP) {
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05304718
Ben Menchaca84f36632014-02-28 20:57:38 +00004719 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304720 * PPPoL2TPV2 channel
Ben Menchaca84f36632014-02-28 20:57:38 +00004721 */
4722 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304723 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004724
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304725 /*
4726 * Release the channel. Note that next_dev not held.
4727 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004728 break;
4729 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304730#endif
4731#ifdef ECM_INTERFACE_PPPOE_ENABLE
4732 if (channel_protocol == PX_PROTO_OE) {
4733 /*
4734 * PPPoE channel
4735 */
4736 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
4737
4738 /*
4739 * Get PPPoE session information and the underlying device it is using.
4740 */
4741 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
4742
4743 /*
4744 * Copy the dev hold into this, we will release the hold later
4745 */
4746 next_dev = addressing.dev;
4747 next_dest_addr_valid = false;
4748 next_dest_node_addr_valid = true;
4749 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
4750
4751 /*
4752 * Release the channel. Note that next_dev is still (correctly) held.
4753 */
4754 ppp_release_channels(ppp_chan, 1);
4755 break;
4756 }
4757#endif
4758
4759 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
4760 dest_dev, channel_protocol);
Ben Menchaca84f36632014-02-28 20:57:38 +00004761
4762 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304763 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00004764 */
4765 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304766
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004767#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004768 } while (false);
4769
4770 /*
Gareth Williamsa11d4352014-05-14 18:25:49 +01004771 * No longer need dest_dev as it may become next_dev
Ben Menchaca84f36632014-02-28 20:57:38 +00004772 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004773 dev_put(dest_dev);
4774
4775 /*
4776 * Check out the next_dev, if any
4777 */
4778 if (!next_dev) {
4779 int32_t i __attribute__((unused));
4780 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
4781#if DEBUG_LEVEL > 1
4782 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
4783 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
4784 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 +05304785
Ben Menchaca84f36632014-02-28 20:57:38 +00004786 }
4787#endif
Gareth Williamsa11d4352014-05-14 18:25:49 +01004788
4789 /*
4790 * Release src_dev now
4791 */
4792 dev_put(src_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004793 return current_interface_index;
4794 }
4795
Gareth Williamsa11d4352014-05-14 18:25:49 +01004796 /*
4797 * dest_dev becomes next_dev
4798 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004799 dest_dev = next_dev;
4800 dest_dev_name = dest_dev->name;
4801 dest_dev_type = dest_dev->type;
4802 }
4803
4804 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
4805 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
4806 dev_put(src_dev);
4807 dev_put(dest_dev);
4808
4809 /*
4810 * Release the interfaces heirarchy we constructed to this point.
4811 */
4812 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4813 return ECM_DB_IFACE_HEIRARCHY_MAX;
4814}
Murat Sezgin5dae8832015-12-03 14:23:19 -08004815EXPORT_SYMBOL(ecm_interface_multicast_from_heirarchy_construct);
4816#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004817
4818/*
Gareth Williamsadf425f2014-05-26 19:29:02 +01004819 * ecm_interface_list_stats_update()
4820 * Given an interface list, walk the interfaces and update the stats for certain types.
4821 */
4822static 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 +05304823 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 +01004824{
4825 int list_index;
4826
4827 for (list_index = iface_list_first; (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) {
4828 struct ecm_db_iface_instance *ii;
4829 ecm_db_iface_type_t ii_type;
4830 char *ii_name;
4831 struct net_device *dev;
4832
4833 ii = iface_list[list_index];
4834 ii_type = ecm_db_connection_iface_type_get(ii);
4835 ii_name = ecm_db_interface_type_to_string(ii_type);
4836 DEBUG_TRACE("list_index: %d, ii: %p, type: %d (%s)\n", list_index, ii, ii_type, ii_name);
4837
4838 /*
4839 * Locate real device in system
4840 */
4841 dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii));
4842 if (!dev) {
4843 DEBUG_WARN("Could not locate interface\n");
4844 continue;
4845 }
4846 DEBUG_TRACE("found dev: %p (%s)\n", dev, dev->name);
4847
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304848 if (likely(!is_mcast_flow)) {
4849 /*
4850 * Refresh the bridge forward table entry if the port is a bridge port
4851 * Note: A bridge port can be of different interface type, e.g VLAN, ethernet.
4852 * This check, therefore, should be performed for all interface types.
4853 */
4854 if (is_valid_ether_addr(mac_addr) && ecm_front_end_is_bridge_port(dev) && rx_packets) {
4855 DEBUG_TRACE("Update bridge fdb entry for mac: %pM\n", mac_addr);
4856 br_refresh_fdb_entry(dev, mac_addr);
4857 }
Selin Dag1af781a2014-06-10 10:37:54 -07004858 }
4859
Gareth Williamsadf425f2014-05-26 19:29:02 +01004860 switch (ii_type) {
4861 struct rtnl_link_stats64 stats;
4862
Gareth Williams141d2382014-11-25 11:35:19 -08004863#ifdef ECM_INTERFACE_VLAN_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +01004864 case ECM_DB_IFACE_TYPE_VLAN:
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304865 DEBUG_INFO("VLAN\n");
Gareth Williamsadf425f2014-05-26 19:29:02 +01004866 stats.rx_packets = rx_packets;
4867 stats.rx_bytes = rx_bytes;
4868 stats.tx_packets = tx_packets;
4869 stats.tx_bytes = tx_bytes;
4870 __vlan_dev_update_accel_stats(dev, &stats);
4871 break;
Gareth Williams141d2382014-11-25 11:35:19 -08004872#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01004873 case ECM_DB_IFACE_TYPE_BRIDGE:
4874 DEBUG_INFO("BRIDGE\n");
4875 stats.rx_packets = rx_packets;
4876 stats.rx_bytes = rx_bytes;
4877 stats.tx_packets = tx_packets;
4878 stats.tx_bytes = tx_bytes;
4879 br_dev_update_stats(dev, &stats);
Gareth Williamsadf425f2014-05-26 19:29:02 +01004880 break;
Murat Sezgina683edd2015-01-20 10:48:30 -08004881
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304882#ifdef ECM_INTERFACE_PPPOE_ENABLE
Murat Sezgina683edd2015-01-20 10:48:30 -08004883 case ECM_DB_IFACE_TYPE_PPPOE:
4884 DEBUG_INFO("PPPOE\n");
ratheesh kannothb1b753a2015-09-28 11:17:35 +05304885 ppp_update_stats(dev, rx_packets, rx_bytes, tx_packets, tx_bytes, 0, 0, 0, 0);
Murat Sezgina683edd2015-01-20 10:48:30 -08004886 break;
4887#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01004888 default:
4889 /*
4890 * TODO: Extend it accordingly
4891 */
4892 break;
4893 }
4894
4895 dev_put(dev);
4896 }
4897}
4898
4899/*
4900 * ecm_interface_stats_update()
4901 * Using the interface lists for the given connection, update the interface statistics for each.
4902 *
4903 * 'from' here is wrt the connection 'from' side. Likewise with 'to'.
4904 * TX is wrt what the interface has transmitted. RX is what the interface has received.
4905 */
4906void ecm_interface_stats_update(struct ecm_db_connection_instance *ci,
4907 uint32_t from_tx_packets, uint32_t from_tx_bytes, uint32_t from_rx_packets, uint32_t from_rx_bytes,
4908 uint32_t to_tx_packets, uint32_t to_tx_bytes, uint32_t to_rx_packets, uint32_t to_rx_bytes)
4909{
4910 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
4911 struct ecm_db_iface_instance *to_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
4912 int from_ifaces_first;
4913 int to_ifaces_first;
4914 uint8_t mac_addr[ETH_ALEN];
4915
4916 /*
4917 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
4918 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
4919 * from_rx_packets / bytes: the amount received by the 'from' interface
4920 */
4921 DEBUG_INFO("%p: Update from interface stats\n", ci);
4922 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
4923 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304924 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 +01004925 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
4926
4927 /*
4928 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
4929 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
4930 * to_rx_packets / bytes: the amount received by the 'to' interface
4931 */
4932 DEBUG_INFO("%p: Update to interface stats\n", ci);
4933 to_ifaces_first = ecm_db_connection_to_interfaces_get_and_ref(ci, to_ifaces);
4934 ecm_db_connection_to_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304935 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 +01004936 ecm_db_connection_interfaces_deref(to_ifaces, to_ifaces_first);
4937}
4938EXPORT_SYMBOL(ecm_interface_stats_update);
4939
Shyam Sunder6358b862015-05-04 15:06:24 +05304940#ifdef ECM_MULTICAST_ENABLE
4941/*
Shyam Sunder6358b862015-05-04 15:06:24 +05304942 * ecm_interface_multicast_stats_update()
4943 * Using the interface lists for the given connection, update the interface statistics for each.
4944 *
4945 * 'from interface' here is the connection 'from' side. Likewise with 'to interface'.
4946 * TX is wrt what the interface has transmitted. RX is what the interface has received.
4947 */
4948void ecm_interface_multicast_stats_update(struct ecm_db_connection_instance *ci, uint32_t from_tx_packets, uint32_t from_tx_bytes,
4949 uint32_t from_rx_packets, uint32_t from_rx_bytes, uint32_t to_tx_packets, uint32_t to_tx_bytes,
4950 uint32_t to_rx_packets, uint32_t to_rx_bytes)
4951{
4952 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304953 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunder6358b862015-05-04 15:06:24 +05304954 struct ecm_db_iface_instance *to_ifaces;
4955 struct ecm_db_iface_instance *ii_temp;
4956 int from_ifaces_first;
4957 int *to_ifaces_first;
4958 int if_index;
4959 int ret;
4960 uint8_t mac_addr[ETH_ALEN];
4961
4962 /*
4963 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
4964 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
4965 * from_rx_packets / bytes: the amount received by the 'from' interface
4966 */
4967 DEBUG_INFO("%p: Update from interface stats\n", ci);
4968 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
4969 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304970 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 +05304971 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
4972
4973 /*
4974 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
4975 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
4976 * to_rx_packets / bytes: the amount received by the 'to' interface
4977 */
4978 DEBUG_INFO("%p: Update to interface stats\n", ci);
4979
4980 /*
4981 * This function allocates the memory for temporary destination interface heirarchies.
4982 * This memory needs to be free at the end.
4983 */
4984 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &to_ifaces, &to_ifaces_first);
4985 if (ret == 0) {
4986 DEBUG_WARN("%p: Get and ref to all multicast detination interface heirarchies failed\n", ci);
4987 return;
4988 }
4989
4990 for (if_index = 0; if_index < ECM_DB_MULTICAST_IF_MAX; if_index++) {
4991 if (to_ifaces_first[if_index] < ECM_DB_IFACE_HEIRARCHY_MAX) {
4992 ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, if_index);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304993 ecm_db_multicast_copy_if_heirarchy(to_list_single, ii_temp);
4994 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 +05304995 }
4996 }
4997
4998 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
4999}
5000EXPORT_SYMBOL(ecm_interface_multicast_stats_update);
5001#endif
5002
Gareth Williamsadf425f2014-05-26 19:29:02 +01005003/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005004 * ecm_interface_regenerate_connections()
5005 * Cause regeneration of all connections that are using the specified interface.
5006 */
5007static void ecm_interface_regenerate_connections(struct ecm_db_iface_instance *ii)
5008{
Gareth Williamsb5903892015-03-20 15:13:07 +00005009#ifdef ECM_DB_XREF_ENABLE
Gareth Williamsa4390962015-08-26 12:51:31 +01005010 struct ecm_db_connection_instance *ci_from;
5011 struct ecm_db_connection_instance *ci_to;
5012 struct ecm_db_connection_instance *ci_from_nat;
5013 struct ecm_db_connection_instance *ci_to_nat;
5014 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
Gareth Williamsb5903892015-03-20 15:13:07 +00005015#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005016
5017 DEBUG_TRACE("Regenerate connections using interface: %p\n", ii);
5018
Gareth Williamsb5903892015-03-20 15:13:07 +00005019#ifndef ECM_DB_XREF_ENABLE
5020 /*
5021 * An interface has changed, re-generate the connections to ensure all state is updated.
5022 */
Tushar Mathurd38cacd2015-07-28 12:19:10 +05305023 ecm_db_regeneration_needed();
Gareth Williamsb5903892015-03-20 15:13:07 +00005024#else
Ben Menchaca84f36632014-02-28 20:57:38 +00005025 /*
Gareth Williamsa4390962015-08-26 12:51:31 +01005026 * If the interface has NO connections then we re-generate all.
5027 */
5028 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
5029 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
5030 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
5031 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
5032 if (!ci_from && !ci_to && !ci_from_nat && !ci_to_nat) {
5033 ecm_db_regeneration_needed();
5034 DEBUG_TRACE("%p: Regenerate (ALL) COMPLETE\n", ii);
5035 return;
5036 }
5037
5038 /*
5039 * Re-generate all connections associated with this interface
Ben Menchaca84f36632014-02-28 20:57:38 +00005040 */
5041 DEBUG_TRACE("%p: Regenerate 'from' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005042 while (ci_from) {
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_from_get_and_ref_next(ci_from);
Ben Menchaca84f36632014-02-28 20:57:38 +00005045
Gareth Williamsa4390962015-08-26 12:51:31 +01005046 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005047 ecm_db_connection_regenerate(ci_from);
Gareth Williamsa4390962015-08-26 12:51:31 +01005048 ecm_db_connection_deref(ci_from);
5049 ci_from = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005050 }
5051
5052 DEBUG_TRACE("%p: Regenerate 'to' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005053 while (ci_to) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005054 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005055 cin = ecm_db_connection_iface_to_get_and_ref_next(ci_to);
Ben Menchaca84f36632014-02-28 20:57:38 +00005056
Gareth Williamsa4390962015-08-26 12:51:31 +01005057 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005058 ecm_db_connection_regenerate(ci_to);
Gareth Williamsa4390962015-08-26 12:51:31 +01005059 ecm_db_connection_deref(ci_to);
5060 ci_to = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005061 }
5062
Gareth Williamsa4390962015-08-26 12:51:31 +01005063 /*
5064 * GGG TODO These deprecated lists _nat_ lists will eventually be removed
5065 */
Ben Menchaca84f36632014-02-28 20:57:38 +00005066 DEBUG_TRACE("%p: Regenerate 'from_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005067 while (ci_from_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005068 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005069 cin = ecm_db_connection_iface_nat_from_get_and_ref_next(ci_from_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00005070
Gareth Williamsa4390962015-08-26 12:51:31 +01005071 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005072 ecm_db_connection_regenerate(ci_from_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01005073 ecm_db_connection_deref(ci_from_nat);
5074 ci_from_nat = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005075 }
5076
5077 DEBUG_TRACE("%p: Regenerate 'to_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005078 while (ci_to_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005079 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005080 cin = ecm_db_connection_iface_nat_to_get_and_ref_next(ci_to_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00005081
Gareth Williamsa4390962015-08-26 12:51:31 +01005082 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005083 ecm_db_connection_regenerate(ci_to_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01005084 ecm_db_connection_deref(ci_to_nat);
5085 ci_to_nat = cin;
5086 }
5087
5088#ifdef ECM_MULTICAST_ENABLE
5089 /*
5090 * Multicasts would not have recorded in the lists above.
5091 * Our only way to re-gen those is to iterate all multicasts.
5092 * GGG TODO This will be optimised in a future release.
5093 */
5094 ci_mcast = ecm_db_connections_get_and_ref_first();
5095 while (ci_mcast) {
5096 struct ecm_db_connection_instance *cin;
5097
5098 /*
5099 * Multicast and NOT flagged for re-gen?
5100 */
5101 if (ecm_db_multicast_connection_to_interfaces_set_check(ci_mcast)
5102 && ecm_db_connection_regeneration_required_peek(ci_mcast)) {
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005103 ecm_db_connection_regenerate(ci_mcast);
Gareth Williamsa4390962015-08-26 12:51:31 +01005104 }
5105
5106 cin = ecm_db_connection_get_and_ref_next(ci_mcast);
5107 ecm_db_connection_deref(ci_mcast);
5108 ci_mcast = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005109 }
Gareth Williamsb5903892015-03-20 15:13:07 +00005110#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005111
Gareth Williamsa4390962015-08-26 12:51:31 +01005112#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005113 DEBUG_TRACE("%p: Regenerate COMPLETE\n", ii);
5114}
5115
5116/*
5117 * ecm_interface_dev_regenerate_connections()
5118 * Cause regeneration of all connections that are using the specified interface.
5119 */
Tushar Mathurcccbf282015-01-13 01:22:44 +05305120void ecm_interface_dev_regenerate_connections(struct net_device *dev)
Ben Menchaca84f36632014-02-28 20:57:38 +00005121{
5122 struct ecm_db_iface_instance *ii;
5123
5124 DEBUG_INFO("Regenerate connections for: %p (%s)\n", dev, dev->name);
5125
5126 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07005127 * If the interface is known to us then we will get it returned by this
5128 * function and process it accordingly.
Ben Menchaca84f36632014-02-28 20:57:38 +00005129 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07005130 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00005131 if (!ii) {
5132 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5133 return;
5134 }
5135 ecm_interface_regenerate_connections(ii);
5136 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
5137 ecm_db_iface_deref(ii);
5138}
5139
5140/*
Suman Ghosh7a261712016-01-12 21:42:55 +05305141 * ecm_interface_defunct_connections()
5142 * Cause defunct of all connections that are using the specified interface.
5143 */
5144static void ecm_interface_defunct_connections(struct ecm_db_iface_instance *ii)
5145{
5146#ifndef ECM_DB_XREF_ENABLE
5147 ecm_db_connection_defunct_all();
5148#else
5149 struct ecm_db_connection_instance *ci_from;
5150 struct ecm_db_connection_instance *ci_to;
5151 struct ecm_db_connection_instance *ci_from_nat;
5152 struct ecm_db_connection_instance *ci_to_nat;
5153 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
5154
5155 DEBUG_TRACE("defunct connections using interface: %p\n", ii);
5156
5157 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
5158 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
5159 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
5160 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
5161
5162 /*
5163 * Defunct all connections associated with this interface
5164 */
5165 DEBUG_TRACE("%p: Defunct 'from' connections\n", ii);
5166 while (ci_from) {
5167 struct ecm_db_connection_instance *cin;
5168 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
5169
5170 DEBUG_TRACE("%p: Defunct: %p", ii, ci_from);
5171 ecm_db_connection_make_defunct(ci_from);
5172 ecm_db_connection_deref(ci_from);
5173 ci_from = cin;
5174 }
5175
5176 DEBUG_TRACE("%p: Defunct 'to' connections\n", ii);
5177 while (ci_to) {
5178 struct ecm_db_connection_instance *cin;
5179 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to);
5180
5181 DEBUG_TRACE("%p: Defunct: %p", ii, ci_to);
5182 ecm_db_connection_make_defunct(ci_to);
5183 ecm_db_connection_deref(ci_to);
5184 ci_to = cin;
5185 }
5186
5187 DEBUG_TRACE("%p: Defunct 'from_nat' connections\n", ii);
5188 while (ci_from_nat) {
5189 struct ecm_db_connection_instance *cin;
5190 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from_nat);
5191
5192 DEBUG_TRACE("%p: Defunct: %p", ii, ci_from_nat);
5193 ecm_db_connection_make_defunct(ci_from_nat);
5194 ecm_db_connection_deref(ci_from_nat);
5195 ci_from_nat = cin;
5196 }
5197
5198 DEBUG_TRACE("%p: Defunct 'to_nat' connections\n", ii);
5199 while (ci_to_nat) {
5200 struct ecm_db_connection_instance *cin;
5201 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to_nat);
5202
5203 DEBUG_TRACE("%p: Defunct: %p", ii, ci_to_nat);
5204 ecm_db_connection_make_defunct(ci_to_nat);
5205 ecm_db_connection_deref(ci_to_nat);
5206 ci_to_nat = cin;
5207 }
5208#endif
5209 DEBUG_TRACE("%p: Defunct COMPLETE\n", ii);
5210}
5211
5212/*
5213 * ecm_interface_dev_defunct_connections()
5214 * Cause defunct of all connections that are using the specified interface.
5215 */
5216void ecm_interface_dev_defunct_connections(struct net_device *dev)
5217{
5218 struct ecm_db_iface_instance *ii;
5219
5220 DEBUG_INFO("defunct connections for: %p (%s)\n", dev, dev->name);
5221
5222 /*
5223 * If the interface is known to us then we will get it returned by this
5224 * function and process it accordingly.
5225 */
5226 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
5227 if (!ii) {
5228 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5229 return;
5230 }
5231 ecm_interface_defunct_connections(ii);
5232 DEBUG_TRACE("%p: defunct for %p: COMPLETE\n", dev, ii);
5233 ecm_db_iface_deref(ii);
5234}
5235
5236/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005237 * ecm_interface_mtu_change()
5238 * MTU of interface has changed
5239 */
5240static void ecm_interface_mtu_change(struct net_device *dev)
5241{
5242 int mtu;
5243 struct ecm_db_iface_instance *ii;
5244
5245 mtu = dev->mtu;
5246 DEBUG_INFO("%p (%s): MTU Change to: %d\n", dev, dev->name, mtu);
5247
5248 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07005249 * Find the interface for the given device.
Ben Menchaca84f36632014-02-28 20:57:38 +00005250 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07005251 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00005252 if (!ii) {
5253 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5254 return;
5255 }
5256
5257 /*
5258 * Change the mtu
5259 */
5260 ecm_db_iface_mtu_reset(ii, mtu);
5261 DEBUG_TRACE("%p (%s): MTU Changed to: %d\n", dev, dev->name, mtu);
Tushar Mathurad534d62015-06-10 18:37:52 +05305262 if (netif_is_bond_slave(dev)) {
5263 struct net_device *master = NULL;
5264 master = ecm_interface_get_and_hold_dev_master(dev);
5265 DEBUG_ASSERT(master, "Expected a master\n");
5266 ecm_interface_dev_regenerate_connections(master);
5267 dev_put(master);
5268 } else {
5269 ecm_interface_regenerate_connections(ii);
5270 }
5271
Ben Menchaca84f36632014-02-28 20:57:38 +00005272 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
5273 ecm_db_iface_deref(ii);
5274}
5275
5276/*
5277 * ecm_interface_netdev_notifier_callback()
5278 * Netdevice notifier callback to inform us of change of state of a netdevice
5279 */
5280static int ecm_interface_netdev_notifier_callback(struct notifier_block *this, unsigned long event, void *ptr)
5281{
Stephen Wang69379c32015-02-04 18:37:13 -08005282#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0))
Ben Menchaca84f36632014-02-28 20:57:38 +00005283 struct net_device *dev __attribute__ ((unused)) = (struct net_device *)ptr;
Stephen Wang69379c32015-02-04 18:37:13 -08005284#else
5285 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
5286#endif
Tushar Mathurad534d62015-06-10 18:37:52 +05305287 struct net_device *master = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00005288
5289 DEBUG_INFO("Net device notifier for: %p, name: %s, event: %lx\n", dev, dev->name, event);
5290
5291 switch (event) {
5292 case NETDEV_DOWN:
5293 DEBUG_INFO("Net device: %p, DOWN\n", dev);
Tushar Mathurad534d62015-06-10 18:37:52 +05305294 if (netif_is_bond_slave(dev)) {
5295 master = ecm_interface_get_and_hold_dev_master(dev);
5296 DEBUG_ASSERT(master, "Expected a master\n");
Murat Sezgina52ce612017-11-14 17:08:08 -08005297 ecm_interface_dev_defunct_connections(master);
Tushar Mathurad534d62015-06-10 18:37:52 +05305298 dev_put(master);
5299 } else {
Murat Sezgina52ce612017-11-14 17:08:08 -08005300 ecm_interface_dev_defunct_connections(dev);
Tushar Mathurad534d62015-06-10 18:37:52 +05305301 }
Ben Menchaca84f36632014-02-28 20:57:38 +00005302 break;
5303
5304 case NETDEV_CHANGE:
5305 DEBUG_INFO("Net device: %p, CHANGE\n", dev);
5306 if (!netif_carrier_ok(dev)) {
5307 DEBUG_INFO("Net device: %p, CARRIER BAD\n", dev);
Tushar Mathur933907c2014-06-24 17:06:14 +05305308 if (netif_is_bond_slave(dev)) {
Murat Sezginb3731e82014-11-26 12:20:59 -08005309 master = ecm_interface_get_and_hold_dev_master(dev);
5310 DEBUG_ASSERT(master, "Expected a master\n");
5311 ecm_interface_dev_regenerate_connections(master);
5312 dev_put(master);
Tushar Mathur933907c2014-06-24 17:06:14 +05305313 } else {
5314 ecm_interface_dev_regenerate_connections(dev);
5315 }
Ben Menchaca84f36632014-02-28 20:57:38 +00005316 }
5317 break;
5318
5319 case NETDEV_CHANGEMTU:
5320 DEBUG_INFO("Net device: %p, MTU CHANGE\n", dev);
5321 ecm_interface_mtu_change(dev);
5322 break;
5323
5324 default:
5325 DEBUG_TRACE("Net device: %p, UNHANDLED: %lx\n", dev, event);
5326 break;
5327 }
5328
5329 return NOTIFY_DONE;
5330}
5331
5332/*
Murat Sezgin9304d472017-04-14 10:16:52 -07005333 * ecm_interface_node_connections_defunct()
5334 * Defunct the connections on this node.
Murat Sezgina205b042016-07-19 14:18:14 -07005335 */
Murat Sezgin9304d472017-04-14 10:16:52 -07005336void ecm_interface_node_connections_defunct(uint8_t *mac)
Murat Sezgina205b042016-07-19 14:18:14 -07005337{
Murat Sezgina5f3de12016-08-02 17:29:30 -07005338 struct ecm_db_node_instance *ni = NULL;
Murat Sezgina205b042016-07-19 14:18:14 -07005339
5340 if (unlikely(!mac)) {
5341 DEBUG_WARN("mac address is null\n");
5342 return;
5343 }
5344
Murat Sezgina5f3de12016-08-02 17:29:30 -07005345 ni = ecm_db_node_chain_get_and_ref_first(mac);
5346 while (ni) {
5347 struct ecm_db_node_instance *nin;
Murat Sezgina205b042016-07-19 14:18:14 -07005348
Murat Sezgina5f3de12016-08-02 17:29:30 -07005349 if (ecm_db_node_is_mac_addr_equal(ni, mac)) {
Murat Sezgin9304d472017-04-14 10:16:52 -07005350 ecm_db_traverse_node_from_connection_list_and_defunct(ni);
5351 ecm_db_traverse_node_to_connection_list_and_defunct(ni);
5352 ecm_db_traverse_node_from_nat_connection_list_and_defunct(ni);
5353 ecm_db_traverse_node_to_nat_connection_list_and_defunct(ni);
Murat Sezgina5f3de12016-08-02 17:29:30 -07005354 }
5355
5356 /*
5357 * Get next node in the chain
5358 */
5359 nin = ecm_db_node_chain_get_and_ref_next(ni);
5360 ecm_db_node_deref(ni);
5361 ni = nin;
Murat Sezgina205b042016-07-19 14:18:14 -07005362 }
Murat Sezgina205b042016-07-19 14:18:14 -07005363}
Murat Sezgin9304d472017-04-14 10:16:52 -07005364EXPORT_SYMBOL(ecm_interface_node_connections_defunct);
Murat Sezgina205b042016-07-19 14:18:14 -07005365
5366/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005367 * struct notifier_block ecm_interface_netdev_notifier
5368 * Registration for net device changes of state.
5369 */
5370static struct notifier_block ecm_interface_netdev_notifier __read_mostly = {
5371 .notifier_call = ecm_interface_netdev_notifier_callback,
5372};
Murat Sezgina205b042016-07-19 14:18:14 -07005373
Murat Sezgin8c345822015-05-27 15:35:38 -07005374#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
Ben Menchaca84f36632014-02-28 20:57:38 +00005375/*
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305376 * ecm_interfae_node_br_fdb_notify_event()
5377 * This is a call back for "bridge fdb update event/ageing timer expire
5378 * event".
5379 */
5380static int ecm_interface_node_br_fdb_notify_event(struct notifier_block *nb,
5381 unsigned long val,
5382 void *data)
5383{
5384 uint8_t *mac = (uint8_t *)data;
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305385
Murat Sezgin04470032017-07-07 14:53:32 -07005386 if (ECM_FRONT_END_TYPE_NSS == ecm_front_end_type_get()) {
5387 DEBUG_INFO("FDB updated for node %pM\n", mac);
5388 ecm_interface_node_connections_defunct(mac);
5389 }
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305390
5391 return NOTIFY_DONE;
5392}
5393
5394static struct notifier_block ecm_interface_node_br_fdb_update_nb = {
5395 .notifier_call = ecm_interface_node_br_fdb_notify_event,
5396};
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07005397
5398static int ecm_interface_node_br_fdb_delete_event(struct notifier_block *nb,
5399 unsigned long event,
5400 void *ctx)
5401{
5402 struct br_fdb_event *fe = (struct br_fdb_event *)ctx;
5403
5404 if ((event != BR_FDB_EVENT_DEL) || fe->is_local) {
5405 DEBUG_WARN("local fdb or not deleting event, ignore\n");
5406 return NOTIFY_DONE;
5407 }
5408
5409 return ecm_interface_node_br_fdb_notify_event(nb, event, fe->addr);
5410}
5411
5412static struct notifier_block ecm_interface_node_br_fdb_delete_nb = {
5413 .notifier_call = ecm_interface_node_br_fdb_delete_event,
5414};
Murat Sezgin8c345822015-05-27 15:35:38 -07005415#endif
Shyam Sunder6358b862015-05-04 15:06:24 +05305416
5417#ifdef ECM_MULTICAST_ENABLE
5418/*
5419 * ecm_interface_multicast_find_outdated_iface_instances()
5420 *
5421 * Called in the case of Routing/Bridging Multicast update events.
5422 *
5423 * This function takes a list of ifindex for the connection which was received
5424 * from MFC or bridge snooper, compares it against the existing list of interfaces
5425 * in the DB connection, and extracts the list of those interfaces that have left
5426 * the multicast group.
5427 *
5428 * ci A DB connection instance.
5429 * mc_updates Part of return Information. The function will mark the index of those
5430 * interfaces in the DB connection 'to_mcast_interfaces' array that have
5431 * left the group, in the mc_updates->if_leave_idx array. The caller uses this
5432 * information to delete those outdated interface heirarchies from the
5433 * connection.
5434 * is_bridged True if the function called due to bridge multicast snooper update event.
5435 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
5436 * by the update from MFC or Bridge snooper.
5437 * max_to_dev Size of the array 'dst_dev'
5438 *
5439 * Return true if outdated interfaces found
5440 */
5441static bool ecm_interface_multicast_find_outdated_iface_instances(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
5442 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5443{
5444 struct ecm_db_iface_instance *mc_ifaces;
5445 struct ecm_db_iface_instance *ii_temp;
5446 struct ecm_db_iface_instance *ii_single;
5447 struct ecm_db_iface_instance **ifaces;
5448 struct ecm_db_iface_instance *to_iface;
5449 int32_t *to_iface_first;
5450 int32_t *mc_ifaces_first;
5451 uint32_t *dst_if_index;
5452 ecm_db_iface_type_t ii_type;
5453 int32_t heirarchy_index;
5454 int32_t if_index;
5455 int32_t if_cnt = 0;
5456 int found = 0;
5457 int ii;
5458 int ret;
5459 int32_t ifaces_identifier;
5460
5461 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
5462 if (ret == 0) {
5463 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
5464 return false;
5465 }
5466
5467 /*
5468 * Loop through the current interface list in the DB
5469 * connection 'to_mcast_interfaces' array
5470 */
5471 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX; heirarchy_index++) {
5472 found = 0;
5473 to_iface_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5474
5475 /*
5476 * Invalid interface entry, skip
5477 */
5478 if (*to_iface_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5479 continue;
5480 }
5481
5482 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
5483 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ECM_DB_IFACE_HEIRARCHY_MAX - 1);
5484 ifaces = (struct ecm_db_iface_instance **)ii_single;
5485 to_iface = *ifaces;
5486 ii_type = ecm_db_connection_iface_type_get(to_iface);
5487
5488 /*
5489 * If the update was received from bridge snooper, do not consider entries in the
5490 * interface list that are not part of a bridge.
5491 */
5492 if (is_br_snooper && (ii_type != ECM_DB_IFACE_TYPE_BRIDGE)) {
5493 continue;
5494 }
5495
5496 /*
5497 * If the update was received from MFC, do not consider entries in the
5498 * interface list that are part of a bridge. The bridge entries will be
5499 * taken care by the Bridge Snooper Callback
5500 */
5501 if (ii_type == ECM_DB_IFACE_TYPE_BRIDGE) {
5502 if (!is_br_snooper && !(flags & ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG)) {
5503 continue;
5504 }
5505 }
5506
5507 /*
5508 * Try to find a match in the newly received interface list, for any of
5509 * the interface instance in the heirarchy. If found, it means that this
5510 * interface has not left the group. If not found, it means that this
5511 * interface has left the group.
5512 */
5513 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_iface_first; ii--) {
5514 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
5515 ifaces = (struct ecm_db_iface_instance **)ii_single;
5516 to_iface = *ifaces;
5517
5518 ii_type = ecm_db_connection_iface_type_get(to_iface);
5519 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_iface);
5520 for (if_index = 0; if_index < max_to_dev; if_index++) {
5521 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
5522 if (*dst_if_index == ifaces_identifier) {
5523 found = 1;
5524 break;
5525 }
5526 }
5527 if (found) {
5528 break;
5529 }
5530 }
5531
5532 /*
5533 * We did not find a match for the interface in the present list. So mark
5534 * if as one that has left the group.
5535 */
5536 if (!found) {
5537 if_cnt++;
5538 mc_updates->if_leave_idx[heirarchy_index] = 1;
5539 }
5540 }
5541
5542 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
5543 mc_updates->if_leave_cnt = if_cnt;
5544 return (if_cnt > 0);
5545}
5546
5547/*
5548 * ecm_interface_multicast_find_new_iface_instances()
5549 *
5550 * Called in the case of Routing/Bridging Multicast update events.
5551 *
5552 * This function takes a list of ifindex for the connection which was received
5553 * from MFC or bridge snooper, compares it against the existing list of interfaces
5554 * in the DB connection, and extracts the list of the new joinees for the multicast
5555 * group.
5556 *
5557 * ci A DB connection instance.
5558 * mc_updates Part of return Information. The function will mark the index of those
5559 * interfaces in the 'dst_dev' array that have joined the group, in the
5560 * mc_updates->if_join_idx array. The caller uses this information to add the new
5561 * interface heirarchies into the connection.
5562 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
5563 * by the update from MFC or Bridge snooper.
5564 * max_to_dev Size of the array 'dst_dev'
5565 *
5566 * Return true if new joinees found
5567 */
5568static bool ecm_interface_multicast_find_new_iface_instances(struct ecm_db_connection_instance *ci,
5569 struct ecm_multicast_if_update *mc_updates, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5570{
5571 struct ecm_db_iface_instance *mc_ifaces;
5572 struct ecm_db_iface_instance *ii_temp;
5573 struct ecm_db_iface_instance *ii_single;
5574 struct ecm_db_iface_instance **ifaces;
5575 int32_t *mc_ifaces_first;
5576 int32_t *to_list_first;
5577 int32_t heirarchy_index;
5578 int32_t if_index;
5579 int32_t if_cnt = 0;
5580 int found = 0;
5581 int ii;
5582 int ret;
5583 uint32_t *dst_if_index;
5584 int32_t ifaces_identifier;
5585 struct ecm_db_iface_instance *to_list;
5586
5587 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
5588 if (ret == 0) {
5589 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
5590 return false;
5591 }
5592
5593 /*
5594 * Loop through the new interface list 'dst_dev'
5595 */
5596 for (if_index = 0; if_index < max_to_dev; if_index++) {
5597 found = 0;
5598 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
5599 if (*dst_if_index == 0) {
5600 continue;
5601 }
5602
5603 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
5604 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5605
5606 /*
5607 * Invalid interface entry, skip
5608 */
5609 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5610 continue;
5611 }
5612
5613 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
5614
5615 /*
5616 * Try to find a match for this ifindex (dst_dev[if_index]), in any of the
5617 * interface instance in the heirarchy. If not found, it means that this
5618 * ifindex has joined the group. If found, it means that this ifindex was
5619 * already part of the list of destination interfaces.
5620 */
5621 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_list_first; ii--) {
5622 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
5623 ifaces = (struct ecm_db_iface_instance **)ii_single;
5624 to_list = *ifaces;
5625 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_list);
5626 if (*dst_if_index == ifaces_identifier) {
5627 found = 1;
5628 break;
5629 }
5630 }
5631
5632 if (found) {
5633 break;
5634 }
5635 }
5636
5637 /*
5638 * We did not find a match for the interface in the present list. So mark
5639 * it as one that has joined the group.
5640 */
5641 if (!found) {
5642
5643 /*
5644 * Store the if index of the new joinee
5645 */
5646 mc_updates->join_dev[if_cnt] = *dst_if_index;
5647
5648 /*
5649 * Identify a new vacant slot in the 'to_mcast_interfaces' to place
5650 * the new interface
5651 */
5652 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
5653 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5654 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5655 mc_updates->if_join_idx[heirarchy_index] = 1;
5656 break;
5657 }
5658 }
5659
5660 if_cnt++;
5661 }
5662 }
5663
5664 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
5665 mc_updates->if_join_cnt = if_cnt;
5666
5667 return (if_cnt > 0);
5668}
5669
5670/*
5671 * ecm_interface_multicast_find_updates_to_iface_list()
5672 * Process IGMP/MLD updates either from MFC or bridge snooper. Identity the interfaces
5673 * that have left the group and new interfaces that have joined the group.
5674 *
5675 * The function returns true if there was any update necessary to the current destination
5676 * interface list
5677 */
5678bool ecm_interface_multicast_find_updates_to_iface_list(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
5679 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5680{
5681 bool join;
5682 bool leave;
5683 /*
5684 * Find destination interfaces that have left the group
5685 */
5686 leave = ecm_interface_multicast_find_outdated_iface_instances(ci, mc_updates, flags, is_br_snooper, mc_dst_if_index, max_to_dev);
5687 /*
5688 * Find new destination interfaces that have joined the group
5689 */
5690 join = ecm_interface_multicast_find_new_iface_instances(ci, mc_updates, mc_dst_if_index, max_to_dev);
5691
5692 return (leave || join);
5693}
5694EXPORT_SYMBOL(ecm_interface_multicast_find_updates_to_iface_list);
5695#endif
5696
Murat Sezgin42a44c22016-05-05 14:06:39 -07005697#ifdef ECM_DB_XREF_ENABLE
5698/*
5699 * ecm_interface_neigh_mac_update_notify_event()
5700 * Neighbour mac address change handler.
5701 */
5702static int ecm_interface_neigh_mac_update_notify_event(struct notifier_block *nb,
5703 unsigned long val,
5704 void *data)
5705{
Murat Sezgin42a44c22016-05-05 14:06:39 -07005706 struct neigh_mac_update *nmu = (struct neigh_mac_update *)data;
5707
5708 /*
5709 * If the old and new mac addresses are equal, do nothing.
5710 * This case shouldn't happen.
5711 */
5712 if (!ecm_mac_addr_equal(nmu->old_mac, nmu->update_mac)) {
5713 DEBUG_TRACE("old and new mac addresses are equal: %pM\n", nmu->old_mac);
5714 return NOTIFY_DONE;
5715 }
5716
5717 /*
5718 * If the old mac is zero, do nothing. When a host joins the arp table first
5719 * time, its old mac comes as zero. We shouldn't handle this case, because
5720 * there is not any connection in ECM db with zero mac.
5721 */
5722 if (is_zero_ether_addr(nmu->old_mac)) {
5723 DEBUG_WARN("old mac is zero\n");
5724 return NOTIFY_DONE;
5725 }
5726
5727 DEBUG_TRACE("old mac: %pM new mac: %pM\n", nmu->old_mac, nmu->update_mac);
5728
Murat Sezgina205b042016-07-19 14:18:14 -07005729 DEBUG_INFO("neigh mac update notify for node %pM\n", nmu->old_mac);
Murat Sezgin9304d472017-04-14 10:16:52 -07005730 ecm_interface_node_connections_defunct((uint8_t *)nmu->old_mac);
Murat Sezgin42a44c22016-05-05 14:06:39 -07005731
5732 return NOTIFY_DONE;
5733}
5734
5735/*
5736 * struct notifier_block ecm_interface_neigh_mac_update_nb
5737 * Registration for neighbour mac address update.
5738 */
5739static struct notifier_block ecm_interface_neigh_mac_update_nb = {
5740 .notifier_call = ecm_interface_neigh_mac_update_notify_event,
5741};
5742#endif
5743
Murat Sezgin1f381852014-11-20 09:51:07 -08005744/*
Murat Sezgina205b042016-07-19 14:18:14 -07005745 * ecm_interface_wifi_event_iwevent
5746 * wireless event handler
5747 */
5748static int ecm_interface_wifi_event_iwevent(int ifindex, unsigned char *buf, size_t len)
5749{
5750 struct iw_event iwe_buf, *iwe = &iwe_buf;
5751 char *pos, *end;
5752
5753 pos = buf;
5754 end = buf + len;
5755 while (pos + IW_EV_LCP_LEN <= end) {
5756
5757 /*
5758 * Copy the base data structure to get iwe->len
5759 */
5760 memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
5761
5762 /*
5763 * Check that len is valid and that we have that much in the buffer.
5764 *
5765 */
5766 if (iwe->len < IW_EV_LCP_LEN) {
5767 return -1;
5768 }
5769
5770 if ((iwe->len > sizeof (struct iw_event)) || (iwe->len + pos) > end) {
5771 return -1;
5772 }
5773
5774 /*
5775 * Do the copy again with the full length.
5776 */
5777 memcpy(&iwe_buf, pos, iwe->len);
5778
5779 if (iwe->cmd == IWEVREGISTERED) {
5780 DEBUG_INFO("STA %pM joining\n", (uint8_t *)iwe->u.addr.sa_data);
5781 } else if (iwe->cmd == IWEVEXPIRED) {
5782 DEBUG_INFO("STA %pM leaving\n", (uint8_t *)iwe->u.addr.sa_data);
Murat Sezgin9304d472017-04-14 10:16:52 -07005783 ecm_interface_node_connections_defunct((uint8_t *)iwe->u.addr.sa_data);
Murat Sezgina205b042016-07-19 14:18:14 -07005784 } else {
5785 DEBUG_INFO("iwe->cmd is %d for STA %pM\n", iwe->cmd, (unsigned char *) iwe->u.addr.sa_data);
5786 }
5787
5788 pos += iwe->len;
5789 }
5790
5791 return 0;
5792}
5793
5794/*
5795 * ecm_interface_wifi_event_newlink
5796 * Link event handler
5797 */
5798static int ecm_interface_wifi_event_newlink(struct ifinfomsg *ifi, unsigned char *buf, size_t len)
5799{
5800 struct rtattr *attr;
5801 int attrlen, rta_len;
5802
5803 DEBUG_TRACE("Event from interface %d\n", ifi->ifi_index);
5804
5805 attrlen = len;
5806 attr = (struct rtattr *) buf;
5807 rta_len = RTA_ALIGN(sizeof(struct rtattr));
5808
5809 while (RTA_OK(attr, attrlen)) {
5810 if (attr->rta_type == IFLA_WIRELESS) {
5811 ecm_interface_wifi_event_iwevent(ifi->ifi_index, ((char *) attr) + rta_len, attr->rta_len - rta_len);
5812 }
5813 attr = RTA_NEXT(attr, attrlen);
5814 }
5815
5816 return 0;
5817}
5818
5819/*
5820 * ecm_interface_wifi_event_handler
5821 * Netlink event handler
5822 */
5823static int ecm_interface_wifi_event_handler(unsigned char *buf, int len)
5824{
5825 struct nlmsghdr *nlh;
5826 struct ifinfomsg *ifi;
5827 int left;
5828
5829 nlh = (struct nlmsghdr *) buf;
5830 left = len;
5831
5832 while (NLMSG_OK(nlh, left)) {
5833 switch (nlh->nlmsg_type) {
5834 case RTM_NEWLINK:
5835 case RTM_DELLINK:
5836 if (NLMSG_PAYLOAD(nlh, 0) < sizeof(struct ifinfomsg)) {
5837 DEBUG_INFO("invalid netlink message\n");
5838 break;
5839 }
5840
5841 ifi = NLMSG_DATA(nlh);
5842 DEBUG_INFO("ifi->ifi_family: %d\n", ifi->ifi_family);
5843 if (ifi->ifi_family != AF_BRIDGE) {
5844 ecm_interface_wifi_event_newlink(ifi, (u8 *)ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
5845 NLMSG_PAYLOAD(nlh, sizeof(struct ifinfomsg)));
5846 }
5847 break;
5848 }
5849
5850 nlh = NLMSG_NEXT(nlh, left);
5851 }
5852
5853 return 0;
5854}
5855
5856/*
5857 * ecm_interface_wifi_event_rx
5858 * Receive netlink message from socket
5859 */
5860static int ecm_interface_wifi_event_rx(struct socket *sock, struct sockaddr_nl *addr, unsigned char *buf, int len)
5861{
5862 struct msghdr msg;
5863 struct iovec iov;
5864 mm_segment_t oldfs;
5865 int size;
5866
5867 iov.iov_base = buf;
5868 iov.iov_len = len;
5869
5870 msg.msg_flags = 0;
5871 msg.msg_name = addr;
5872 msg.msg_namelen = sizeof(struct sockaddr_nl);
5873 msg.msg_control = NULL;
5874 msg.msg_controllen = 0;
5875#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
5876 msg.msg_iov = &iov;
5877 msg.msg_iovlen = 1;
5878#else
5879 iov_iter_init(&msg.msg_iter, READ, &iov, 1, 1);
5880#endif
5881 oldfs = get_fs();
5882 set_fs(KERNEL_DS);
5883 size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
5884 set_fs(oldfs);
5885
5886 return size;
5887}
5888
5889/*
5890 * ecm_interface_wifi_event_thread
5891 */
5892static void ecm_interface_wifi_event_thread(void)
5893{
5894 int err;
5895 int size;
5896 struct sockaddr_nl saddr;
5897 unsigned char buf[512];
5898 int len = sizeof(buf);
5899
5900 allow_signal(SIGKILL|SIGSTOP);
5901 err = sock_create(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, &__ewn.sock);
5902 if (err < 0) {
5903 DEBUG_ERROR("failed to create sock\n");
5904 goto exit1;
5905 }
5906
Murat Sezginac267642016-11-02 15:55:11 -07005907 memset(&saddr, 0, sizeof(saddr));
Murat Sezgina205b042016-07-19 14:18:14 -07005908 saddr.nl_family = AF_NETLINK;
5909 saddr.nl_groups = RTNLGRP_LINK;
5910 saddr.nl_pid = current->pid;
5911
5912 err = __ewn.sock->ops->bind(__ewn.sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr));
5913 if (err < 0) {
5914 DEBUG_ERROR("failed to bind sock\n");
5915 goto exit2;
5916 }
5917
5918 DEBUG_INFO("ecm_interface_wifi_event thread started\n");
5919 while (!kthread_should_stop()) {
5920 size = ecm_interface_wifi_event_rx(__ewn.sock, &saddr, buf, len);
5921 DEBUG_TRACE("got a netlink msg with len %d\n", size);
5922
5923 if (signal_pending(current))
5924 break;
5925
5926 if (size < 0) {
5927 DEBUG_WARN("netlink rx error\n");
5928 } else {
5929 ecm_interface_wifi_event_handler(buf, size);
5930 }
5931 }
5932
5933 DEBUG_INFO("ecm_interface_wifi_event thread stopped\n");
5934exit2:
5935 sock_release(__ewn.sock);
5936exit1:
5937 __ewn.sock = NULL;
5938
5939 return;
5940}
5941
5942/*
5943 * ecm_interface_wifi_event_start()
5944 */
5945int ecm_interface_wifi_event_start(void)
5946{
5947 if (__ewn.thread) {
5948 return 0;
5949 }
5950
5951 __ewn.thread = kthread_run((void *)ecm_interface_wifi_event_thread, NULL, "ECM_wifi_event");
5952 if (IS_ERR(__ewn.thread)) {
5953 DEBUG_ERROR("Unable to start kernel thread\n");
5954 return -ENOMEM;
5955 }
5956
5957 return 0;
5958}
5959
5960/*
5961 * ecm_interface_wifi_event_stop()
5962 */
5963int ecm_interface_wifi_event_stop(void)
5964{
5965 int err;
5966
5967 if (__ewn.thread == NULL) {
5968 return 0;
5969 }
5970
5971 DEBUG_INFO("kill ecm_interface_wifi_event thread\n");
5972 force_sig(SIGKILL, __ewn.thread);
5973 err = kthread_stop(__ewn.thread);
5974 __ewn.thread = NULL;
5975
5976 return err;
5977}
5978
5979/*
Murat Sezgineebedb92017-11-17 17:14:32 -08005980 * ecm_interface_src_check_handler()
5981 * Source interface check sysctl node handler.
5982 */
5983static int ecm_interface_src_check_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
5984{
5985 int ret;
5986 int current_value;
5987
5988 /*
5989 * Take the current value
5990 */
5991 current_value = ecm_interface_src_check;
5992
5993 /*
5994 * Write the variable with user input
5995 */
5996 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
5997 if (ret || (!write)) {
5998 return ret;
5999 }
6000
6001 if (ECM_FRONT_END_TYPE_NSS != ecm_front_end_type_get()) {
6002 DEBUG_WARN("Source interface check is for NSS only.\n");
6003 return -EINVAL;
6004 }
6005
6006 if ((ecm_interface_src_check != 1) && (ecm_interface_src_check != 0)) {
6007 DEBUG_WARN("Invalid input. Valid values 0/1\n");
6008 ecm_interface_src_check = current_value;
6009 return -EINVAL;
6010 }
6011
6012 return ret;
6013}
6014
6015static struct ctl_table ecm_interface_table[] = {
6016 {
6017 .procname = "src_interface_check",
6018 .data = &ecm_interface_src_check,
6019 .maxlen = sizeof(int),
6020 .mode = 0644,
6021 .proc_handler = &ecm_interface_src_check_handler,
6022 },
6023 { }
6024};
6025
6026static struct ctl_table ecm_interface_root_dir[] = {
6027 {
6028 .procname = "ecm",
6029 .mode = 0555,
6030 .child = ecm_interface_table,
6031 },
6032 { }
6033};
6034
6035static struct ctl_table ecm_interface_root[] = {
6036 {
6037 .procname = "net",
6038 .mode = 0555,
6039 .child = ecm_interface_root_dir,
6040 },
6041 { }
6042};
6043
6044/*
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006045 * ecm_interface_init()
Ben Menchaca84f36632014-02-28 20:57:38 +00006046 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006047int ecm_interface_init(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00006048{
6049 int result;
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006050 DEBUG_INFO("ECM Interface init\n");
Ben Menchaca84f36632014-02-28 20:57:38 +00006051
Murat Sezgineebedb92017-11-17 17:14:32 -08006052 /*
6053 * Register sysctl table.
6054 */
6055 ecm_interface_ctl_table_header = register_sysctl_table(ecm_interface_root);
6056
Ben Menchaca84f36632014-02-28 20:57:38 +00006057 result = register_netdevice_notifier(&ecm_interface_netdev_notifier);
6058 if (result != 0) {
6059 DEBUG_ERROR("Failed to register netdevice notifier %d\n", result);
Murat Sezgineebedb92017-11-17 17:14:32 -08006060 unregister_sysctl_table(ecm_interface_ctl_table_header);
Murat Sezgin908ecb32015-05-10 20:54:36 -07006061 return result;
Ben Menchaca84f36632014-02-28 20:57:38 +00006062 }
Murat Sezgin8c345822015-05-27 15:35:38 -07006063#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05306064 /*
6065 * register for bridge fdb database modificationevents
6066 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05306067 br_fdb_update_register_notify(&ecm_interface_node_br_fdb_update_nb);
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07006068 br_fdb_register_notify(&ecm_interface_node_br_fdb_delete_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07006069#endif
Murat Sezgin42a44c22016-05-05 14:06:39 -07006070#ifdef ECM_DB_XREF_ENABLE
6071 neigh_mac_update_register_notify(&ecm_interface_neigh_mac_update_nb);
6072#endif
Murat Sezgina205b042016-07-19 14:18:14 -07006073 ecm_interface_wifi_event_start();
6074
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006075 return 0;
Ben Menchaca84f36632014-02-28 20:57:38 +00006076}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006077EXPORT_SYMBOL(ecm_interface_init);
Ben Menchaca84f36632014-02-28 20:57:38 +00006078
6079/*
6080 * ecm_interface_exit()
6081 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006082void ecm_interface_exit(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00006083{
6084 DEBUG_INFO("ECM Interface exit\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006085
6086 spin_lock_bh(&ecm_interface_lock);
6087 ecm_interface_terminate_pending = true;
6088 spin_unlock_bh(&ecm_interface_lock);
6089
6090 unregister_netdevice_notifier(&ecm_interface_netdev_notifier);
Murat Sezgin42a44c22016-05-05 14:06:39 -07006091#ifdef ECM_DB_XREF_ENABLE
6092 neigh_mac_update_unregister_notify(&ecm_interface_neigh_mac_update_nb);
6093#endif
6094
Murat Sezgin8c345822015-05-27 15:35:38 -07006095#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05306096 /*
6097 * unregister for bridge fdb update events
6098 */
6099 br_fdb_update_unregister_notify(&ecm_interface_node_br_fdb_update_nb);
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07006100 br_fdb_unregister_notify(&ecm_interface_node_br_fdb_delete_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07006101#endif
Murat Sezgina205b042016-07-19 14:18:14 -07006102 ecm_interface_wifi_event_stop();
Murat Sezgineebedb92017-11-17 17:14:32 -08006103
6104 /*
6105 * Unregister sysctl table.
6106 */
6107 if (ecm_interface_ctl_table_header) {
6108 unregister_sysctl_table(ecm_interface_ctl_table_header);
6109 }
Ben Menchaca84f36632014-02-28 20:57:38 +00006110}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006111EXPORT_SYMBOL(ecm_interface_exit);