blob: e5018f8fbb7d86a5553cfef8ad3f362b70fd4eea [file] [log] [blame]
Ben Menchaca84f36632014-02-28 20:57:38 +00001/*
2 **************************************************************************
Murat Sezgined9c1c62017-07-14 16:57:23 -07003 * Copyright (c) 2014-2018 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) {
ratheesh kannothc5df16c2018-03-16 21:07:23 +0530768 /*
769 * Interface got deleted; but is yet to be updated in MFC table
770 */
771 DEBUG_WARN("Could not find a valid netdev here\n");
Shyam Sunder6358b862015-05-04 15:06:24 +0530772 continue;
773 }
774
775 if (ecm_front_end_is_bridge_device(br_dev)) {
776 dev_put(br_dev);
777 return true;
778 }
779 dev_put(br_dev);
780 }
781 return false;
782}
783EXPORT_SYMBOL(ecm_interface_multicast_check_for_br_dev);
Shyam Sundera2e08ee2015-06-18 21:32:13 +0530784
785/*
ratheesh kannothc5df16c2018-03-16 21:07:23 +0530786 * ecm_interface_multicast_is_iface_type()
787 * Checks if interface of type exist in mc_if_index
788 */
789bool ecm_interface_multicast_is_iface_type(int32_t mc_if_index[], int32_t max_if_index, unsigned short type)
790{
791 int32_t i;
792 struct net_device *dev;
793
794 for (i = 0; i < max_if_index; i++) {
795
796 if (!mc_if_index[i]) {
797 break;
798 }
799
800 dev = dev_get_by_index(&init_net, mc_if_index[i]);
801 if (!dev) {
802 DEBUG_WARN("Could not find a valid interface with index = %d\n", mc_if_index[i]);
803 continue;
804 }
805
806 if (dev->type == type) {
807 DEBUG_TRACE("Interface dev = %s of type %u\n", dev->name, type);
808 dev_put(dev);
809 return true;
810 }
811
812 dev_put(dev);
813 }
814
815 return false;
816}
817
818/*
Shyam Sundera2e08ee2015-06-18 21:32:13 +0530819 * ecm_interface_multicast_check_for_src_if_index()
820 * Find if a source netdev ifindex is matching with list of
821 * multicast destination netdev ifindex. If find a match then
822 * returns a new list of destination netdev ifindex excluding
823 * the ifindex of source netdev.
824 */
825int32_t ecm_interface_multicast_check_for_src_ifindex(int32_t mc_if_index[], int32_t max_if_index, int32_t if_num)
826{
827 int32_t i;
828 int32_t valid_index;
829
830 for (i = 0, valid_index = 0; i < max_if_index; i++) {
831 if (mc_if_index[i] == 0) {
832 break;
833 }
834
835 if (mc_if_index[i] != if_num) {
836 mc_if_index[valid_index] = mc_if_index[i];
837 valid_index++;
838 continue;
839 }
840 }
841
842 return valid_index;
843}
844EXPORT_SYMBOL(ecm_interface_multicast_check_for_src_ifindex);
Shyam Sunder6358b862015-05-04 15:06:24 +0530845#endif
846
Ben Menchaca84f36632014-02-28 20:57:38 +0000847/*
848 * ecm_interface_addr_find_route_by_addr_ipv4()
849 * Return the route for the given IP address. Returns NULL on failure.
850 */
851static bool ecm_interface_find_route_by_addr_ipv4(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
852{
853 __be32 be_addr;
854
855 /*
856 * Get a route to the given IP address, this will allow us to also find the interface
857 * it is using to communicate with that IP address.
858 */
859 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, addr);
860 ecm_rt->rt.rtv4 = ip_route_output(&init_net, be_addr, 0, 0, 0);
861 if (IS_ERR(ecm_rt->rt.rtv4)) {
862 DEBUG_TRACE("No output route to: %pI4n\n", &be_addr);
863 return false;
864 }
865 DEBUG_TRACE("Output route to: %pI4n is: %p\n", &be_addr, ecm_rt->rt.rtv4);
866 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv4;
867 ecm_rt->v4_route = true;
868 return true;
869}
870
Gareth Williams8ac34292015-03-17 14:06:58 +0000871#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000872/*
873 * ecm_interface_addr_find_route_by_addr_ipv6()
874 * Return the route for the given IP address. Returns NULL on failure.
875 */
876static bool ecm_interface_find_route_by_addr_ipv6(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
877{
878 struct in6_addr naddr;
879
880 ECM_IP_ADDR_TO_NIN6_ADDR(naddr, addr);
881
882 /*
883 * Get a route to the given IP address, this will allow us to also find the interface
884 * it is using to communicate with that IP address.
885 */
886 ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, 0);
887 if (!ecm_rt->rt.rtv6) {
888 DEBUG_TRACE("No output route to: " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
889 return NULL;
890 }
891 DEBUG_TRACE("Output route to: " ECM_IP_ADDR_OCTAL_FMT " is: %p\n", ECM_IP_ADDR_TO_OCTAL(addr), ecm_rt->rt.rtv6);
892 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv6;
893 ecm_rt->v4_route = false;
894 return true;
895}
Murat Sezgin49465a42014-11-24 15:37:48 -0800896#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000897
898/*
899 * ecm_interface_addr_find_route_by_addr()
900 * Return the route (in the given parameter) for the given IP address. Returns false on failure.
901 *
902 * Route is the device on which the addr is reachable, which may be loopback for local addresses.
903 *
904 * Returns true if the route was able to be located. The route must be released using ecm_interface_route_release().
905 */
906bool ecm_interface_find_route_by_addr(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
907{
908 char __attribute__((unused)) addr_str[40];
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530909
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100910 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
Ben Menchaca84f36632014-02-28 20:57:38 +0000911 DEBUG_TRACE("Locate route to: %s\n", addr_str);
912
913 if (ECM_IP_ADDR_IS_V4(addr)) {
914 return ecm_interface_find_route_by_addr_ipv4(addr, ecm_rt);
915 }
916
Gareth Williams8ac34292015-03-17 14:06:58 +0000917#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000918 return ecm_interface_find_route_by_addr_ipv6(addr, ecm_rt);
Murat Sezgin49465a42014-11-24 15:37:48 -0800919#else
920 return false;
921#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000922}
923EXPORT_SYMBOL(ecm_interface_find_route_by_addr);
924
925/*
926 * ecm_interface_route_release()
927 * Release an ecm route
928 */
929void ecm_interface_route_release(struct ecm_interface_route *rt)
930{
931 dst_release(rt->dst);
932}
933EXPORT_SYMBOL(ecm_interface_route_release);
934
Murat Sezgin188b4a32015-06-03 10:58:59 -0700935#ifdef ECM_IPV6_ENABLE
936/*
937 * ecm_interface_send_neighbour_solicitation()
938 * Issue an IPv6 Neighbour soliciation request.
939 */
940void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t addr)
941{
942 struct in6_addr dst_addr, src_addr;
943 struct in6_addr mc_dst_addr;
944 struct rt6_info *rt6i;
945 struct neighbour *neigh;
Murat Sezgin188b4a32015-06-03 10:58:59 -0700946 struct net *netf = dev_net(dev);
947 int ret;
948
Murat Sezgin188b4a32015-06-03 10:58:59 -0700949 /*
950 * Find source and destination addresses in Linux format. We need
951 * mcast destination address as well.
952 */
953 ECM_IP_ADDR_TO_NIN6_ADDR(dst_addr, addr);
954 addrconf_addr_solict_mult(&dst_addr, &mc_dst_addr);
Murat Sezgin96ed0342017-05-19 09:48:57 -0700955 ret = ipv6_dev_get_saddr(netf, dev, &mc_dst_addr, 0, &src_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -0700956
957 /*
Murat Sezgin188b4a32015-06-03 10:58:59 -0700958 * Find the route entry
959 */
960 rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0);
961 if (!rt6i) {
Murat Sezginf21210e2016-04-04 13:58:20 -0700962 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 -0700963 return;
964 }
965
966 /*
967 * Find the neighbor entry
968 */
969#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
970 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, &dst_addr);
971#else
972 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr);
973#endif
974 if (neigh == NULL) {
Murat Sezginf21210e2016-04-04 13:58:20 -0700975 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 -0700976 dst_release(&rt6i->dst);
977 return;
978 }
979
980 /*
981 * Issue a Neighbour soliciation request
982 */
983 DEBUG_TRACE("Issue Neighbour solicitation request\n");
Murat Sezgine1c51d82016-02-10 16:42:58 -0800984#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
Murat Sezgin188b4a32015-06-03 10:58:59 -0700985 ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr);
Murat Sezgine1c51d82016-02-10 16:42:58 -0800986#else
987 ndisc_send_ns(dev, &dst_addr, &mc_dst_addr, &src_addr);
988#endif
Murat Sezgin188b4a32015-06-03 10:58:59 -0700989 neigh_release(neigh);
990 dst_release(&rt6i->dst);
991}
992EXPORT_SYMBOL(ecm_interface_send_neighbour_solicitation);
993#endif
994
995/*
996 * ecm_interface_send_arp_request()
997 * Issue and ARP request.
998 */
999void ecm_interface_send_arp_request(struct net_device *dest_dev, ip_addr_t dest_addr, bool on_link, ip_addr_t gw_addr)
1000{
1001 /*
1002 * Possible ARP does not know the address yet
1003 */
Murat Sezgin4c093212016-03-24 14:59:02 -07001004 struct neighbour *neigh;
Murat Sezgin188b4a32015-06-03 10:58:59 -07001005 __be32 ipv4_addr;
Murat Sezgin188b4a32015-06-03 10:58:59 -07001006
1007 /*
Murat Sezgin987493e2016-04-15 12:33:47 -07001008 * Convert the ECM IP address type to network order IPv4 address.
Murat Sezgin188b4a32015-06-03 10:58:59 -07001009 */
1010 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07001011
1012 /*
1013 * If we have a GW for this address, then we have to send ARP request to the GW
1014 */
1015 if (!on_link && !ECM_IP_ADDR_IS_NULL(gw_addr)) {
1016 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, gw_addr);
1017 }
1018
Murat Sezgin4c093212016-03-24 14:59:02 -07001019 /*
1020 * If we don't have this neighbor, create it before sending the arp request,
1021 * so that when we receive the arp reply we update the neigh entry.
1022 */
1023 neigh = neigh_lookup(&arp_tbl, &ipv4_addr, dest_dev);
1024 if (!neigh) {
Murat Sezgin987493e2016-04-15 12:33:47 -07001025 neigh = neigh_create(&arp_tbl, &ipv4_addr, dest_dev);
1026 if (IS_ERR(neigh)) {
1027 DEBUG_WARN("Unable to create ARP request neigh for %pI4\n", &ipv4_addr);
1028 return;
1029 }
Murat Sezgin4c093212016-03-24 14:59:02 -07001030 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07001031
Murat Sezgin987493e2016-04-15 12:33:47 -07001032 DEBUG_TRACE("Send ARP for %pI4\n", &ipv4_addr);
1033 neigh_event_send(neigh, NULL);
1034 neigh_release(neigh);
Murat Sezgin188b4a32015-06-03 10:58:59 -07001035}
1036EXPORT_SYMBOL(ecm_interface_send_arp_request);
1037
Xiaoping Fanc7735462015-08-09 18:57:26 -07001038/*
1039 * ecm_interface_ipv4_neigh_get()
1040 * Returns neighbour reference for a given IP address which must be released when you are done with it.
1041 *
1042 * Returns NULL on fail.
1043 */
1044struct neighbour *ecm_interface_ipv4_neigh_get(ip_addr_t addr)
1045{
1046 struct neighbour *neigh;
1047 struct rtable *rt;
1048 struct dst_entry *dst;
1049 __be32 ipv4_addr;
1050
1051 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
1052 rt = ip_route_output(&init_net, ipv4_addr, 0, 0, 0);
1053 if (IS_ERR(rt)) {
1054 return NULL;
1055 }
1056 dst = (struct dst_entry *)rt;
1057 neigh = dst_neigh_lookup(dst, &ipv4_addr);
1058 ip_rt_put(rt);
1059 return neigh;
1060}
1061
1062#ifdef ECM_IPV6_ENABLE
1063/*
1064 * ecm_interface_ipv6_neigh_get()
1065 * Returns neighbour reference for a given IP address which must be released when you are done with it.
1066 *
1067 * Returns NULL on fail.
1068 */
1069struct neighbour *ecm_interface_ipv6_neigh_get(ip_addr_t addr)
1070{
1071 struct neighbour *neigh;
1072 struct rt6_info *rt;
1073 struct dst_entry *dst;
1074 struct in6_addr ipv6_addr;
1075
1076 ECM_IP_ADDR_TO_NIN6_ADDR(ipv6_addr, addr);
1077 rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0);
1078 if (!rt) {
1079 return NULL;
1080 }
1081 dst = (struct dst_entry *)rt;
1082 neigh = dst_neigh_lookup(dst, &ipv6_addr);
1083 dst_release(dst);
1084 return neigh;
1085}
1086#endif
1087
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301088/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301089 * ecm_interface_is_pptp()
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301090 * skip pptp tunnel encapsulated traffic
1091 *
Shyam Sunder23f2e542015-09-28 14:56:49 +05301092 * ECM does not handle PPTP,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301093 * this function detects packets of that type so they can be skipped over to improve their throughput.
1094 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301095bool ecm_interface_is_pptp(struct sk_buff *skb, const struct net_device *out)
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301096{
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301097 struct net_device *in;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301098
ratheesh kannothf4801a02016-12-09 22:46:39 +05301099 /*
1100 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1101 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301102 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301103 if (out->priv_flags & IFF_PPP_PPTP) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301104 return true;
1105 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301106 }
1107
1108 in = dev_get_by_index(&init_net, skb->skb_iif);
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301109 if (!in) {
1110 return true;
1111 }
1112
1113 if (in->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301114 if (in->priv_flags & IFF_PPP_PPTP) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301115 dev_put(in);
1116 return true;
1117 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05301118 }
1119
1120 dev_put(in);
1121 return false;
1122}
1123
Shyam Sunder2ca02492016-08-05 20:55:12 +05301124#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder23f2e542015-09-28 14:56:49 +05301125/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301126 * ecm_interface_is_l2tp_packet_by_version()
Shyam Sunder23f2e542015-09-28 14:56:49 +05301127 * Check version of l2tp tunnel encapsulated traffic
1128 *
1129 * ECM does not handle l2tp,
1130 * this function detects packets of that type so they can be skipped over to improve their throughput.
1131 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301132bool 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 +05301133{
ratheesh kannothf4801a02016-12-09 22:46:39 +05301134 uint32_t flag = 0;
Shyam Sunder23f2e542015-09-28 14:56:49 +05301135 struct net_device *in;
1136
ratheesh kannothf4801a02016-12-09 22:46:39 +05301137 switch (ver) {
1138 case 2:
1139 flag = IFF_PPP_L2TPV2;
1140 break;
1141 case 3:
1142 flag = IFF_PPP_L2TPV3;
1143 break;
1144 default:
1145 break;
1146 }
1147
1148 /*
1149 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1150 */
Shyam Sunder23f2e542015-09-28 14:56:49 +05301151 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301152 if (out->priv_flags & flag) {
Shyam Sunder23f2e542015-09-28 14:56:49 +05301153 return true;
1154 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05301155 }
1156
1157 in = dev_get_by_index(&init_net, skb->skb_iif);
1158 if (!in) {
1159 return true;
1160 }
1161
1162 if (in->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301163 if (in->priv_flags & flag) {
Shyam Sunder23f2e542015-09-28 14:56:49 +05301164 dev_put(in);
1165 return true;
1166 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301167 }
1168
ratheesh kannoth08b8e442015-10-02 00:24:55 +05301169 dev_put(in);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301170 return false;
1171}
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301172
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001173/*
Shyam Sunder2ca02492016-08-05 20:55:12 +05301174 * ecm_interface_is_l2tp_pptp()
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001175 * skip l2tp/pptp tunnel encapsulated traffic
1176 *
1177 * ECM does not handle L2TP or PPTP encapsulated packets,
1178 * this function detects packets of that type so they can be skipped over to improve their throughput.
1179 */
Shyam Sunder2ca02492016-08-05 20:55:12 +05301180bool ecm_interface_is_l2tp_pptp(struct sk_buff *skb, const struct net_device *out)
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001181{
ratheesh kannothf4801a02016-12-09 22:46:39 +05301182 struct net_device *in;
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001183
1184 /*
1185 * skip first pass of l2tp/pptp tunnel encapsulated traffic
1186 */
1187 if (out->type == ARPHRD_PPP) {
ratheesh kannothf4801a02016-12-09 22:46:39 +05301188 if (out->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 |
1189 IFF_PPP_PPTP)) {
1190 return true;
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001191 }
1192 }
1193
ratheesh kannothf4801a02016-12-09 22:46:39 +05301194 in = dev_get_by_index(&init_net, skb->skb_iif);
1195 if (!in) {
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001196 return true;
1197 }
1198
ratheesh kannothf4801a02016-12-09 22:46:39 +05301199 if (in->type == ARPHRD_PPP) {
1200 if (in->priv_flags & (IFF_PPP_L2TPV2 | IFF_PPP_L2TPV3 |
1201 IFF_PPP_PPTP)) {
1202 dev_put(in);
1203 return true;
1204 }
1205 }
1206
1207 dev_put(in);
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001208 return false;
ratheesh kannothf4801a02016-12-09 22:46:39 +05301209
Xiaoping Fan80e406b2015-01-29 16:15:31 -08001210}
1211#endif
1212
Gareth Williams141d2382014-11-25 11:35:19 -08001213#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001214/*
Ben Menchaca84f36632014-02-28 20:57:38 +00001215 * ecm_interface_vlan_interface_establish()
1216 * Returns a reference to a iface of the VLAN type, possibly creating one if necessary.
1217 * Returns NULL on failure or a reference to interface.
1218 */
1219static 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 -07001220 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001221{
1222 struct ecm_db_iface_instance *nii;
1223 struct ecm_db_iface_instance *ii;
1224
Murat Sezgin91c5d712015-06-12 15:16:22 -07001225 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",
1226 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 +00001227
1228 /*
1229 * Locate the iface
1230 */
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301231 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 +00001232 if (ii) {
1233 DEBUG_TRACE("%p: iface established\n", ii);
1234 return ii;
1235 }
1236
1237 /*
1238 * No iface - create one
1239 */
1240 nii = ecm_db_iface_alloc();
1241 if (!nii) {
1242 DEBUG_WARN("Failed to establish iface\n");
1243 return NULL;
1244 }
1245
1246 /*
1247 * Add iface into the database, atomically to avoid races creating the same thing
1248 */
1249 spin_lock_bh(&ecm_interface_lock);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301250 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 +00001251 if (ii) {
1252 spin_unlock_bh(&ecm_interface_lock);
1253 ecm_db_iface_deref(nii);
1254 return ii;
1255 }
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301256 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 -07001257 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001258 spin_unlock_bh(&ecm_interface_lock);
1259
1260 DEBUG_TRACE("%p: vlan iface established\n", nii);
1261 return nii;
1262}
Gareth Williams141d2382014-11-25 11:35:19 -08001263#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001264
1265/*
1266 * ecm_interface_bridge_interface_establish()
1267 * Returns a reference to a iface of the BRIDGE type, possibly creating one if necessary.
1268 * Returns NULL on failure or a reference to interface.
1269 */
1270static 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 -07001271 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001272{
1273 struct ecm_db_iface_instance *nii;
1274 struct ecm_db_iface_instance *ii;
1275
Murat Sezgin91c5d712015-06-12 15:16:22 -07001276 DEBUG_INFO("Establish BRIDGE iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1277 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001278
1279 /*
1280 * Locate the iface
1281 */
1282 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1283 if (ii) {
1284 DEBUG_TRACE("%p: iface established\n", ii);
1285 return ii;
1286 }
1287
1288 /*
1289 * No iface - create one
1290 */
1291 nii = ecm_db_iface_alloc();
1292 if (!nii) {
1293 DEBUG_WARN("Failed to establish iface\n");
1294 return NULL;
1295 }
1296
1297 /*
1298 * Add iface into the database, atomically to avoid races creating the same thing
1299 */
1300 spin_lock_bh(&ecm_interface_lock);
1301 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1302 if (ii) {
1303 spin_unlock_bh(&ecm_interface_lock);
1304 ecm_db_iface_deref(nii);
1305 return ii;
1306 }
1307 ecm_db_iface_add_bridge(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001308 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001309 spin_unlock_bh(&ecm_interface_lock);
1310
1311 DEBUG_TRACE("%p: bridge iface established\n", nii);
1312 return nii;
1313}
1314
Murat Sezgin910c9662015-03-11 16:15:06 -07001315#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001316/*
1317 * ecm_interface_lag_interface_establish()
1318 * Returns a reference to a iface of the LAG type, possibly creating one if necessary.
1319 * Returns NULL on failure or a reference to interface.
1320 */
1321static 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 -07001322 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001323{
1324 struct ecm_db_iface_instance *nii;
1325 struct ecm_db_iface_instance *ii;
1326
Murat Sezgin91c5d712015-06-12 15:16:22 -07001327 DEBUG_INFO("Establish LAG iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1328 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001329
1330 /*
1331 * Locate the iface
1332 */
1333 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1334 if (ii) {
1335 DEBUG_TRACE("%p: iface established\n", ii);
1336 return ii;
1337 }
1338
1339 /*
1340 * No iface - create one
1341 */
1342 nii = ecm_db_iface_alloc();
1343 if (!nii) {
1344 DEBUG_WARN("Failed to establish iface\n");
1345 return NULL;
1346 }
1347
1348 /*
1349 * Add iface into the database, atomically to avoid races creating the same thing
1350 */
1351 spin_lock_bh(&ecm_interface_lock);
1352 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1353 if (ii) {
1354 spin_unlock_bh(&ecm_interface_lock);
1355 ecm_db_iface_deref(nii);
1356 return ii;
1357 }
1358 ecm_db_iface_add_lag(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001359 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001360 spin_unlock_bh(&ecm_interface_lock);
1361
1362 DEBUG_TRACE("%p: lag iface established\n", nii);
1363 return nii;
1364}
Murat Sezgin910c9662015-03-11 16:15:06 -07001365#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001366
1367/*
1368 * ecm_interface_ethernet_interface_establish()
1369 * Returns a reference to a iface of the ETHERNET type, possibly creating one if necessary.
1370 * Returns NULL on failure or a reference to interface.
1371 */
1372static 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 -07001373 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001374{
1375 struct ecm_db_iface_instance *nii;
1376 struct ecm_db_iface_instance *ii;
1377
Murat Sezgin91c5d712015-06-12 15:16:22 -07001378 DEBUG_INFO("Establish ETHERNET iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1379 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001380
1381 /*
1382 * Locate the iface
1383 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301384 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
1385
Ben Menchaca84f36632014-02-28 20:57:38 +00001386 if (ii) {
1387 DEBUG_TRACE("%p: iface established\n", ii);
Murat Sezgin5f2947a2016-06-28 12:09:33 -07001388 /*
1389 * Update the accel engine interface identifier, just in case it was changed.
1390 */
1391 ecm_db_iface_ae_interface_identifier_set(ii, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001392 return ii;
1393 }
1394
1395 /*
1396 * No iface - create one
1397 */
1398 nii = ecm_db_iface_alloc();
1399 if (!nii) {
1400 DEBUG_WARN("Failed to establish iface\n");
1401 return NULL;
1402 }
1403
1404 /*
1405 * Add iface into the database, atomically to avoid races creating the same thing
1406 */
1407 spin_lock_bh(&ecm_interface_lock);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301408 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001409 if (ii) {
1410 spin_unlock_bh(&ecm_interface_lock);
1411 ecm_db_iface_deref(nii);
1412 return ii;
1413 }
1414 ecm_db_iface_add_ethernet(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001415 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001416 spin_unlock_bh(&ecm_interface_lock);
1417
1418 DEBUG_TRACE("%p: ethernet iface established\n", nii);
1419 return nii;
1420}
1421
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301422#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001423/*
1424 * ecm_interface_pppoe_interface_establish()
1425 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1426 * Returns NULL on failure or a reference to interface.
1427 */
1428static 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 -07001429 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001430{
1431 struct ecm_db_iface_instance *nii;
1432 struct ecm_db_iface_instance *ii;
1433
Murat Sezgin91c5d712015-06-12 15:16:22 -07001434 DEBUG_INFO("Establish PPPoE iface: %s with session id: %u, remote mac: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1435 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 +00001436
1437 /*
1438 * Locate the iface
1439 */
1440 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1441 if (ii) {
1442 DEBUG_TRACE("%p: iface established\n", ii);
1443 return ii;
1444 }
1445
1446 /*
1447 * No iface - create one
1448 */
1449 nii = ecm_db_iface_alloc();
1450 if (!nii) {
1451 DEBUG_WARN("Failed to establish iface\n");
1452 return NULL;
1453 }
1454
1455 /*
1456 * Add iface into the database, atomically to avoid races creating the same thing
1457 */
1458 spin_lock_bh(&ecm_interface_lock);
1459 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1460 if (ii) {
1461 spin_unlock_bh(&ecm_interface_lock);
1462 ecm_db_iface_deref(nii);
1463 return ii;
1464 }
1465 ecm_db_iface_add_pppoe(nii, type_info->pppoe_session_id, type_info->remote_mac, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001466 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001467 spin_unlock_bh(&ecm_interface_lock);
1468
1469 DEBUG_TRACE("%p: pppoe iface established\n", nii);
1470 return nii;
1471}
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001472#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001473
ratheesh kannothcfdcb332015-12-24 07:19:18 +05301474#ifdef ECM_INTERFACE_MAP_T_ENABLE
1475/*
1476 * ecm_interface_map_t_interface_establish()
1477 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1478 * Returns NULL on failure or a reference to interface.
1479 */
1480static struct ecm_db_iface_instance *ecm_interface_map_t_interface_establish(struct ecm_db_interface_info_map_t *type_info,
1481 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1482{
1483 struct ecm_db_iface_instance *nii;
1484 struct ecm_db_iface_instance *ii;
1485
1486 DEBUG_TRACE("Establish MAP-T iface: %s MTU: %d, if num: %d, accel engine if id: %d\n",
1487 dev_name, mtu, dev_interface_num, ae_interface_num);
1488
1489 /*
1490 * Locate the iface
1491 */
1492 ii = ecm_db_iface_find_and_ref_map_t(type_info->if_index);
1493 if (ii) {
1494 DEBUG_TRACE("%p: iface established\n", ii);
1495 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1496 return ii;
1497 }
1498
1499 /*
1500 * No iface - create one
1501 */
1502 nii = ecm_db_iface_alloc();
1503 if (!nii) {
1504 DEBUG_WARN("Failed to establish iface\n");
1505 return NULL;
1506 }
1507
1508 /*
1509 * Add iface into the database, atomically to avoid races creating the same thing
1510 */
1511 spin_lock_bh(&ecm_interface_lock);
1512 ii = ecm_db_iface_find_and_ref_map_t(type_info->if_index);
1513 if (ii) {
1514 spin_unlock_bh(&ecm_interface_lock);
1515 ecm_db_iface_deref(nii);
1516 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1517 return ii;
1518 }
1519 ecm_db_iface_add_map_t(nii, type_info, dev_name,
1520 mtu, dev_interface_num, ae_interface_num, NULL, nii);
1521 spin_unlock_bh(&ecm_interface_lock);
1522
1523 DEBUG_TRACE("%p: map_t iface established\n", nii);
1524 return nii;
1525}
1526#endif
1527
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301528#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1529/*
1530 * ecm_interface_pppol2tpv2_interface_establish()
1531 * Returns a reference to a iface of the PPPoL2TPV2 type, possibly creating one if necessary.
1532 * Returns NULL on failure or a reference to interface.
1533 */
1534static struct ecm_db_iface_instance *ecm_interface_pppol2tpv2_interface_establish(struct ecm_db_interface_info_pppol2tpv2 *type_info,
1535 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1536{
1537 struct ecm_db_iface_instance *nii;
1538 struct ecm_db_iface_instance *ii;
1539
1540 DEBUG_INFO("Establish PPPol2tp iface: %s with tunnel id=%u session id %u\n", dev_name, type_info->l2tp.tunnel.tunnel_id,
1541 type_info->l2tp.session.session_id);
1542 /*
1543 * Locate the iface
1544 */
1545 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1546 if (ii) {
1547 DEBUG_TRACE("%p: iface established\n", ii);
ratheesh kannothed721852015-09-28 12:39:52 +05301548 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301549 return ii;
1550 }
1551
1552 /*
1553 * No iface - create one
1554 */
1555 nii = ecm_db_iface_alloc();
1556 if (!nii) {
1557 DEBUG_WARN("Failed to establish iface\n");
1558 return NULL;
1559 }
1560
1561 /*
1562 * Add iface into the database, atomically to avoid races creating the same thing
1563 */
1564 spin_lock_bh(&ecm_interface_lock);
1565 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1566 if (ii) {
1567 spin_unlock_bh(&ecm_interface_lock);
1568 ecm_db_iface_deref(nii);
ratheesh kannothed721852015-09-28 12:39:52 +05301569 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301570 return ii;
1571 }
1572
1573 ecm_db_iface_add_pppol2tpv2(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1574 spin_unlock_bh(&ecm_interface_lock);
1575
1576 DEBUG_TRACE("%p: pppol2tpv2 iface established\n", nii);
1577 return nii;
1578}
1579
1580#endif
1581
Shyam Sunder23f2e542015-09-28 14:56:49 +05301582#ifdef ECM_INTERFACE_PPTP_ENABLE
1583/*
1584 * ecm_interface_pptp_interface_establish()
1585 * Returns a reference to a iface of the PPTP type, possibly creating one if necessary.
1586 * Returns NULL on failure or a reference to interface.
1587 */
1588static struct ecm_db_iface_instance *ecm_interface_pptp_interface_establish(struct ecm_db_interface_info_pptp *type_info,
1589 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1590{
1591 struct ecm_db_iface_instance *nii;
1592 struct ecm_db_iface_instance *ii;
1593
1594 DEBUG_INFO("Establish PPTP iface: %s with local call id %u peer call id %u\n", dev_name, type_info->src_call_id,
1595 type_info->dst_call_id);
1596 /*
1597 * Locate the iface
1598 */
1599 ii = ecm_db_iface_find_and_ref_pptp(type_info->src_call_id, type_info->dst_call_id);
1600 if (ii) {
1601 DEBUG_TRACE("%p: iface established\n", ii);
1602 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1603 return ii;
1604 }
1605
1606 /*
1607 * No iface - create one
1608 */
1609 nii = ecm_db_iface_alloc();
1610 if (!nii) {
1611 DEBUG_WARN("Failed to establish iface\n");
1612 return NULL;
1613 }
1614
1615 /*
1616 * Add iface into the database, atomically to avoid races creating the same thing
1617 */
1618 spin_lock_bh(&ecm_interface_lock);
1619 ii = ecm_db_iface_find_and_ref_pptp(type_info->src_call_id, type_info->dst_call_id);
1620 if (ii) {
1621 spin_unlock_bh(&ecm_interface_lock);
1622 ecm_db_iface_deref(nii);
1623 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
1624 return ii;
1625 }
1626
1627 ecm_db_iface_add_pptp(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1628 spin_unlock_bh(&ecm_interface_lock);
1629
1630 DEBUG_TRACE("%p: pptp iface established\n", nii);
1631 return nii;
1632}
1633#endif
1634
Ben Menchaca84f36632014-02-28 20:57:38 +00001635/*
1636 * ecm_interface_unknown_interface_establish()
1637 * Returns a reference to a iface of the UNKNOWN type, possibly creating one if necessary.
1638 * Returns NULL on failure or a reference to interface.
1639 */
1640static 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 -07001641 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001642{
1643 struct ecm_db_iface_instance *nii;
1644 struct ecm_db_iface_instance *ii;
1645
Murat Sezgin91c5d712015-06-12 15:16:22 -07001646 DEBUG_INFO("Establish UNKNOWN iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1647 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001648
1649 /*
1650 * Locate the iface
1651 */
1652 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1653 if (ii) {
1654 DEBUG_TRACE("%p: iface established\n", ii);
1655 return ii;
1656 }
1657
1658 /*
1659 * No iface - create one
1660 */
1661 nii = ecm_db_iface_alloc();
1662 if (!nii) {
1663 DEBUG_WARN("Failed to establish iface\n");
1664 return NULL;
1665 }
1666
1667 /*
1668 * Add iface into the database, atomically to avoid races creating the same thing
1669 */
1670 spin_lock_bh(&ecm_interface_lock);
1671 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1672 if (ii) {
1673 spin_unlock_bh(&ecm_interface_lock);
1674 ecm_db_iface_deref(nii);
1675 return ii;
1676 }
1677 ecm_db_iface_add_unknown(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001678 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001679 spin_unlock_bh(&ecm_interface_lock);
1680
1681 DEBUG_TRACE("%p: unknown iface established\n", nii);
1682 return nii;
1683}
1684
1685/*
1686 * ecm_interface_loopback_interface_establish()
1687 * Returns a reference to a iface of the LOOPBACK type, possibly creating one if necessary.
1688 * Returns NULL on failure or a reference to interface.
1689 */
1690static 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 -07001691 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001692{
1693 struct ecm_db_iface_instance *nii;
1694 struct ecm_db_iface_instance *ii;
1695
Murat Sezgin91c5d712015-06-12 15:16:22 -07001696 DEBUG_INFO("Establish LOOPBACK iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1697 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001698
1699 /*
1700 * Locate the iface
1701 */
1702 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1703 if (ii) {
1704 DEBUG_TRACE("%p: iface established\n", ii);
1705 return ii;
1706 }
1707
1708 /*
1709 * No iface - create one
1710 */
1711 nii = ecm_db_iface_alloc();
1712 if (!nii) {
1713 DEBUG_WARN("Failed to establish iface\n");
1714 return NULL;
1715 }
1716
1717 /*
1718 * Add iface into the database, atomically to avoid races creating the same thing
1719 */
1720 spin_lock_bh(&ecm_interface_lock);
1721 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1722 if (ii) {
1723 spin_unlock_bh(&ecm_interface_lock);
1724 ecm_db_iface_deref(nii);
1725 return ii;
1726 }
1727 ecm_db_iface_add_loopback(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001728 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001729 spin_unlock_bh(&ecm_interface_lock);
1730
1731 DEBUG_TRACE("%p: loopback iface established\n", nii);
1732 return nii;
1733}
1734
Murat Sezgin69a27532015-03-12 14:09:40 -07001735#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001736/*
1737 * ecm_interface_ipsec_tunnel_interface_establish()
1738 * Returns a reference to a iface of the IPSEC_TUNNEL type, possibly creating one if necessary.
1739 * Returns NULL on failure or a reference to interface.
1740 *
1741 * NOTE: GGG TODO THIS NEEDS TO TAKE A PROPER APPROACH TO IPSEC TUNNELS USING ENDPOINT ADDRESSING AS THE TYPE INFO KEYS
1742 */
1743static 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 -07001744 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001745{
1746 struct ecm_db_iface_instance *nii;
1747 struct ecm_db_iface_instance *ii;
1748
Murat Sezgin91c5d712015-06-12 15:16:22 -07001749 DEBUG_INFO("Establish IPSEC_TUNNEL iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1750 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001751
1752 /*
1753 * Locate the iface
1754 */
1755 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1756 if (ii) {
1757 DEBUG_TRACE("%p: iface established\n", ii);
1758 return ii;
1759 }
1760
1761 /*
1762 * No iface - create one
1763 */
1764 nii = ecm_db_iface_alloc();
1765 if (!nii) {
1766 DEBUG_WARN("Failed to establish iface\n");
1767 return NULL;
1768 }
1769
1770 /*
1771 * Add iface into the database, atomically to avoid races creating the same thing
1772 */
1773 spin_lock_bh(&ecm_interface_lock);
1774 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1775 if (ii) {
1776 spin_unlock_bh(&ecm_interface_lock);
1777 ecm_db_iface_deref(nii);
1778 return ii;
1779 }
1780 ecm_db_iface_add_ipsec_tunnel(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001781 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001782 spin_unlock_bh(&ecm_interface_lock);
1783
1784 DEBUG_TRACE("%p: ipsec_tunnel iface established\n", nii);
1785 return nii;
1786}
Murat Sezgin69a27532015-03-12 14:09:40 -07001787#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001788
Murat Sezginb3731e82014-11-26 12:20:59 -08001789#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07001790#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00001791/*
1792 * ecm_interface_sit_interface_establish()
1793 * Returns a reference to a iface of the SIT type, possibly creating one if necessary.
1794 * Returns NULL on failure or a reference to interface.
1795 */
1796static 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 -07001797 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001798{
1799 struct ecm_db_iface_instance *nii;
1800 struct ecm_db_iface_instance *ii;
1801
Murat Sezgin91c5d712015-06-12 15:16:22 -07001802 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",
1803 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 +00001804
1805 /*
1806 * Locate the iface
1807 */
Murat Sezgined9c1c62017-07-14 16:57:23 -07001808 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001809 if (ii) {
1810 DEBUG_TRACE("%p: iface established\n", ii);
1811 return ii;
1812 }
1813
1814 /*
1815 * No iface - create one
1816 */
1817 nii = ecm_db_iface_alloc();
1818 if (!nii) {
1819 DEBUG_WARN("Failed to establish iface\n");
1820 return NULL;
1821 }
1822
1823 /*
1824 * Add iface into the database, atomically to avoid races creating the same thing
1825 */
1826 spin_lock_bh(&ecm_interface_lock);
Murat Sezgined9c1c62017-07-14 16:57:23 -07001827 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001828 if (ii) {
1829 spin_unlock_bh(&ecm_interface_lock);
1830 ecm_db_iface_deref(nii);
1831 return ii;
1832 }
1833 ecm_db_iface_add_sit(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001834 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001835 spin_unlock_bh(&ecm_interface_lock);
1836
1837 DEBUG_TRACE("%p: sit iface established\n", nii);
1838 return nii;
1839}
Murat Sezgincc6eedf2014-05-09 23:59:19 -07001840#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08001841#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001842
Murat Sezginc1402562015-03-12 12:32:20 -07001843#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001844#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001845/*
1846 * ecm_interface_tunipip6_interface_establish()
1847 * Returns a reference to a iface of the TUNIPIP6 type, possibly creating one if necessary.
1848 * Returns NULL on failure or a reference to interface.
1849 */
1850static 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 -07001851 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001852{
1853 struct ecm_db_iface_instance *nii;
1854 struct ecm_db_iface_instance *ii;
1855
Murat Sezgin91c5d712015-06-12 15:16:22 -07001856 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",
1857 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 +00001858
1859 /*
1860 * Locate the iface
1861 */
1862 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1863 if (ii) {
1864 DEBUG_TRACE("%p: iface established\n", ii);
1865 return ii;
1866 }
1867
1868 /*
1869 * No iface - create one
1870 */
1871 nii = ecm_db_iface_alloc();
1872 if (!nii) {
1873 DEBUG_WARN("Failed to establish iface\n");
1874 return NULL;
1875 }
1876
1877 /*
1878 * Add iface into the database, atomically to avoid races creating the same thing
1879 */
1880 spin_lock_bh(&ecm_interface_lock);
1881 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1882 if (ii) {
1883 spin_unlock_bh(&ecm_interface_lock);
1884 ecm_db_iface_deref(nii);
1885 return ii;
1886 }
1887 ecm_db_iface_add_tunipip6(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001888 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001889 spin_unlock_bh(&ecm_interface_lock);
1890
1891 DEBUG_TRACE("%p: tunipip6 iface established\n", nii);
1892 return nii;
1893}
Murat Sezginc1402562015-03-12 12:32:20 -07001894#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001895#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001896
1897/*
1898 * ecm_interface_establish_and_ref()
1899 * Establish an interface instance for the given interface detail.
1900 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001901struct ecm_db_iface_instance *ecm_interface_establish_and_ref(struct ecm_front_end_connection_instance *feci,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301902 struct net_device *dev, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00001903{
1904 int32_t dev_interface_num;
1905 char *dev_name;
1906 int32_t dev_type;
1907 int32_t dev_mtu;
Murat Sezgin91c5d712015-06-12 15:16:22 -07001908 int32_t ae_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00001909 struct ecm_db_iface_instance *ii;
1910 union {
1911 struct ecm_db_interface_info_ethernet ethernet; /* type == ECM_DB_IFACE_TYPE_ETHERNET */
Gareth Williams141d2382014-11-25 11:35:19 -08001912#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001913 struct ecm_db_interface_info_vlan vlan; /* type == ECM_DB_IFACE_TYPE_VLAN */
Gareth Williams141d2382014-11-25 11:35:19 -08001914#endif
Murat Sezgin910c9662015-03-11 16:15:06 -07001915#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001916 struct ecm_db_interface_info_lag lag; /* type == ECM_DB_IFACE_TYPE_LAG */
Murat Sezgin910c9662015-03-11 16:15:06 -07001917#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001918 struct ecm_db_interface_info_bridge bridge; /* type == ECM_DB_IFACE_TYPE_BRIDGE */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301919#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001920 struct ecm_db_interface_info_pppoe pppoe; /* type == ECM_DB_IFACE_TYPE_PPPOE */
Murat Sezginaad635c2015-03-06 16:11:41 -08001921#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301922#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1923 struct ecm_db_interface_info_pppol2tpv2 pppol2tpv2; /* type == ECM_DB_IFACE_TYPE_PPPOL2TPV2 */
1924#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301925#ifdef ECM_INTERFACE_PPTP_ENABLE
1926 struct ecm_db_interface_info_pptp pptp; /* type == ECM_DB_IFACE_TYPE_PPTP */
1927#endif
ratheesh kannothcfdcb332015-12-24 07:19:18 +05301928#ifdef ECM_INTERFACE_MAP_T_ENABLE
1929 struct ecm_db_interface_info_map_t map_t; /* type == ECM_DB_IFACE_TYPE_MAP_T */
1930#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001931 struct ecm_db_interface_info_unknown unknown; /* type == ECM_DB_IFACE_TYPE_UNKNOWN */
1932 struct ecm_db_interface_info_loopback loopback; /* type == ECM_DB_IFACE_TYPE_LOOPBACK */
Murat Sezgin69a27532015-03-12 14:09:40 -07001933#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001934 struct ecm_db_interface_info_ipsec_tunnel ipsec_tunnel; /* type == ECM_DB_IFACE_TYPE_IPSEC_TUNNEL */
Murat Sezgin69a27532015-03-12 14:09:40 -07001935#endif
Murat Sezginbde55f92015-03-11 16:44:11 -07001936#ifdef ECM_INTERFACE_SIT_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001937 struct ecm_db_interface_info_sit sit; /* type == ECM_DB_IFACE_TYPE_SIT */
Murat Sezginbde55f92015-03-11 16:44:11 -07001938#endif
Murat Sezginc1402562015-03-12 12:32:20 -07001939#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001940#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001941 struct ecm_db_interface_info_tunipip6 tunipip6; /* type == ECM_DB_IFACE_TYPE_TUNIPIP6 */
Murat Sezginc1402562015-03-12 12:32:20 -07001942#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001943#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001944 } type_info;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001945
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08001946#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001947 int channel_count;
1948 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00001949 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301950#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001951 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001952#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301953#ifdef ECM_INTERFACE_PPTP_ENABLE
1954 int protocol = IPPROTO_IP;
1955 struct pptp_opt opt;
1956 struct iphdr *v4_hdr = NULL;
1957 if (skb) {
1958 v4_hdr = ip_hdr(skb);
1959 protocol = v4_hdr->protocol;
1960 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301961#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05301962#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001963 /*
1964 * Get basic information about the given device
1965 */
1966 dev_interface_num = dev->ifindex;
1967 dev_name = dev->name;
1968 dev_type = dev->type;
1969 dev_mtu = dev->mtu;
1970
1971 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07001972 * Does the accel engine recognise this interface?
Ben Menchaca84f36632014-02-28 20:57:38 +00001973 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001974 ae_interface_num = feci->ae_interface_number_by_dev_get(dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00001975
Murat Sezgin91c5d712015-06-12 15:16:22 -07001976 DEBUG_TRACE("Establish interface instance for device: %p is type: %d, name: %s, ifindex: %d, ae_if: %d, mtu: %d\n",
1977 dev, dev_type, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00001978
1979 /*
1980 * Extract from the device more type-specific information
1981 */
1982 if (dev_type == ARPHRD_ETHER) {
Shyam Sunder39e25672015-09-03 14:28:09 +05301983
Ben Menchaca84f36632014-02-28 20:57:38 +00001984 /*
1985 * Ethernet - but what sub type?
1986 */
1987
Gareth Williams141d2382014-11-25 11:35:19 -08001988#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001989 /*
1990 * VLAN?
1991 */
1992 if (is_vlan_dev(dev)) {
1993 /*
1994 * VLAN master
1995 * GGG No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
1996 */
1997 memcpy(type_info.vlan.address, dev->dev_addr, 6);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301998 type_info.vlan.vlan_tag = vlan_dev_vlan_id(dev);
Amit Gupta8975f9d2017-07-12 20:34:36 +05301999#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
Murat Sezginb2676062015-06-12 17:05:31 -07002000 type_info.vlan.vlan_tpid = ETH_P_8021Q;
Amit Gupta8975f9d2017-07-12 20:34:36 +05302001#else
2002 type_info.vlan.vlan_tpid = ntohs(vlan_dev_vlan_proto(dev));
2003#endif
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05302004 DEBUG_TRACE("Net device: %p is VLAN, mac: %pM, vlan_id: %x vlan_tpid: %x\n",
2005 dev, type_info.vlan.address, type_info.vlan.vlan_tag, type_info.vlan.vlan_tpid);
Ben Menchaca84f36632014-02-28 20:57:38 +00002006
2007 /*
2008 * Establish this type of interface
2009 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002010 ii = ecm_interface_vlan_interface_establish(&type_info.vlan, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder39e25672015-09-03 14:28:09 +05302011 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00002012 }
Gareth Williams141d2382014-11-25 11:35:19 -08002013#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002014
2015 /*
2016 * BRIDGE?
2017 */
2018 if (ecm_front_end_is_bridge_device(dev)) {
2019 /*
2020 * Bridge
2021 */
2022 memcpy(type_info.bridge.address, dev->dev_addr, 6);
2023
2024 DEBUG_TRACE("Net device: %p is BRIDGE, mac: %pM\n",
2025 dev, type_info.bridge.address);
2026
2027 /*
2028 * Establish this type of interface
2029 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002030 ii = ecm_interface_bridge_interface_establish(&type_info.bridge, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder39e25672015-09-03 14:28:09 +05302031 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00002032 }
2033
Murat Sezgin910c9662015-03-11 16:15:06 -07002034#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002035 /*
2036 * LAG?
2037 */
2038 if (ecm_front_end_is_lag_master(dev)) {
2039 /*
2040 * Link aggregation
2041 */
2042 memcpy(type_info.lag.address, dev->dev_addr, 6);
2043
2044 DEBUG_TRACE("Net device: %p is LAG, mac: %pM\n",
2045 dev, type_info.lag.address);
2046
2047 /*
2048 * Establish this type of interface
2049 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002050 ii = ecm_interface_lag_interface_establish(&type_info.lag, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Shyam Sunder39e25672015-09-03 14:28:09 +05302051 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00002052 }
Murat Sezgin910c9662015-03-11 16:15:06 -07002053#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002054
Murat Sezgin31effef2017-11-13 15:09:34 -08002055#ifdef ECM_INTERFACE_GRE_ENABLE
2056 /*
2057 * GRE TAP?
2058 */
2059 if (dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)) {
2060 /*
2061 * GRE TAP interface is handled as ethernet interface, however it is possible
2062 * that the acceleration engine may not be ready yet to handle the connection.
2063 * In this case the acceleration engine interface is not found for this type and
2064 * we should wait until it is ready.
2065 */
2066 if (ae_interface_num < 0) {
2067 DEBUG_TRACE("GRE interface is not ready yet\n");
2068 return NULL;
2069 }
2070 }
2071#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002072 /*
2073 * ETHERNET!
2074 * Just plain ethernet it seems
2075 */
2076 memcpy(type_info.ethernet.address, dev->dev_addr, 6);
2077 DEBUG_TRACE("Net device: %p is ETHERNET, mac: %pM\n",
2078 dev, type_info.ethernet.address);
2079
2080 /*
2081 * Establish this type of interface
2082 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002083 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 +05302084
2085identifier_update:
2086 if (ii) {
2087 /*
2088 * An interface identifier/ifindex can be change after network restart. Below
2089 * functtion will check interface_identifier present in 'ii' with new dev_interface_num.
2090 * If differ then update new ifindex and update the interface identifier hash table.
2091 */
2092 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2093 }
2094
Ben Menchaca84f36632014-02-28 20:57:38 +00002095 return ii;
2096 }
2097
2098 /*
2099 * LOOPBACK?
2100 */
2101 if (dev_type == ARPHRD_LOOPBACK) {
2102 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dev, dev_type);
2103 type_info.loopback.os_specific_ident = dev_interface_num;
Murat Sezgin91c5d712015-06-12 15:16:22 -07002104 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 +00002105 return ii;
2106 }
2107
Murat Sezgin69a27532015-03-12 14:09:40 -07002108#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002109 /*
2110 * IPSEC?
2111 */
2112 if (dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2113 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dev, dev_type);
2114 type_info.ipsec_tunnel.os_specific_ident = dev_interface_num;
Ankit Dhanuka6d5014a2014-06-22 17:21:44 +05302115
Ben Menchaca84f36632014-02-28 20:57:38 +00002116 // GGG TODO Flesh this out with tunnel endpoint addressing detail
Murat Sezgin91c5d712015-06-12 15:16:22 -07002117 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 +00002118 return ii;
2119 }
Murat Sezgin69a27532015-03-12 14:09:40 -07002120#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002121
ratheesh kannothcfdcb332015-12-24 07:19:18 +05302122#ifdef ECM_INTERFACE_MAP_T_ENABLE
2123 if (dev_type == ARPHRD_NONE) {
2124 if (is_map_t_dev(dev)) {
2125 type_info.map_t.if_index = dev_interface_num;
2126 ii = ecm_interface_map_t_interface_establish(&type_info.map_t, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2127 return ii;
2128 }
2129
2130 }
2131#endif
2132
Murat Sezginb3731e82014-11-26 12:20:59 -08002133#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07002134#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00002135 /*
2136 * SIT (6-in-4)?
2137 */
2138 if (dev_type == ARPHRD_SIT) {
2139 struct ip_tunnel *tunnel;
2140 struct ip_tunnel_6rd_parm *ip6rd;
2141 const struct iphdr *tiph;
Murat Sezgined9c1c62017-07-14 16:57:23 -07002142 int interface_type;
Ben Menchaca84f36632014-02-28 20:57:38 +00002143
2144 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dev, dev_type);
2145
2146 tunnel = (struct ip_tunnel*)netdev_priv(dev);
2147 ip6rd = &tunnel->ip6rd;
2148
2149 /*
2150 * Get the Tunnel device IP header info
2151 */
2152 tiph = &tunnel->parms.iph ;
2153
2154 type_info.sit.prefixlen = ip6rd->prefixlen;
2155 type_info.sit.relay_prefix = ip6rd->relay_prefix;
2156 type_info.sit.relay_prefixlen = ip6rd->relay_prefixlen;
2157 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.saddr, tiph->saddr);
2158 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.daddr, tiph->daddr);
2159 type_info.sit.prefix[0] = ntohl(ip6rd->prefix.s6_addr32[0]);
2160 type_info.sit.prefix[1] = ntohl(ip6rd->prefix.s6_addr32[1]);
2161 type_info.sit.prefix[2] = ntohl(ip6rd->prefix.s6_addr32[2]);
2162 type_info.sit.prefix[3] = ntohl(ip6rd->prefix.s6_addr32[3]);
2163 type_info.sit.ttl = tiph->ttl;
2164 type_info.sit.tos = tiph->tos;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05302165
Murat Sezgined9c1c62017-07-14 16:57:23 -07002166 interface_type = feci->ae_interface_type_get(feci, dev_type);
2167 ae_interface_num = feci->ae_interface_number_by_dev_type_get(dev, interface_type);
2168
Murat Sezgin91c5d712015-06-12 15:16:22 -07002169 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 +00002170 return ii;
2171 }
Murat Sezgincc6eedf2014-05-09 23:59:19 -07002172#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08002173#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002174
Murat Sezginc1402562015-03-12 12:32:20 -07002175#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00002176#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00002177 /*
2178 * IPIP6 Tunnel?
2179 */
2180 if (dev_type == ARPHRD_TUNNEL6) {
2181 struct ip6_tnl *tunnel;
2182 struct flowi6 *fl6;
2183
2184 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dev, dev_type);
2185
2186 /*
2187 * Get the tunnel device flow information (discover the output path of the tunnel)
2188 */
2189 tunnel = (struct ip6_tnl *)netdev_priv(dev);
2190 fl6 = &tunnel->fl.u.ip6;
2191
2192 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.saddr, fl6->saddr);
2193 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.daddr, fl6->daddr);
2194 type_info.tunipip6.hop_limit = tunnel->parms.hop_limit;
2195 type_info.tunipip6.flags = ntohl(tunnel->parms.flags);
2196 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 +05302197
Murat Sezgin91c5d712015-06-12 15:16:22 -07002198 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 +00002199 return ii;
2200 }
Murat Sezginc1402562015-03-12 12:32:20 -07002201#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00002202#endif
2203
Ben Menchaca84f36632014-02-28 20:57:38 +00002204 /*
2205 * If this is NOT PPP then it is unknown to the ecm
2206 */
2207 if (dev_type != ARPHRD_PPP) {
2208 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dev, dev_type);
2209 type_info.unknown.os_specific_ident = dev_interface_num;
2210
2211 /*
2212 * Establish this type of interface
2213 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002214 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 +00002215 return ii;
2216 }
2217
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08002218#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002219 /*
ratheesh kannothf4801a02016-12-09 22:46:39 +05302220 * PPP Support is NOT provided for.
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002221 * Interface is therefore unknown
2222 */
2223 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dev, dev_type);
2224 type_info.unknown.os_specific_ident = dev_interface_num;
2225
2226 /*
2227 * Establish this type of interface
2228 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002229 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 +01002230 return ii;
2231#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302232
2233#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2234 /*
2235 * ppp_xmit lock is held by linux kernel for l2tp packet in transmit
2236 * direction. we need to check for l2tp packet and avoid calls to
2237 * ppp_is_multilink() and ppp_hold_channels() which acquire same lock
2238 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05302239
2240 if ((dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(dev)) {
Murat Sezgindb0c5d82017-02-22 11:43:03 -08002241 if (skb && (skb->skb_iif == dev->ifindex)) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302242 struct pppol2tp_common_addr info;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302243
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302244 if (__ppp_is_multilink(dev) > 0) {
2245 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
2246 type_info.unknown.os_specific_ident = dev_interface_num;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302247
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302248 /*
2249 * Establish this type of interface
2250 */
2251 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2252 return ii;
2253 }
2254 channel_count = __ppp_hold_channels(dev, ppp_chan, 1);
2255 if (channel_count != 1) {
2256 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
2257 dev, channel_count);
2258 type_info.unknown.os_specific_ident = dev_interface_num;
2259
2260 /*
2261 * Establish this type of interface
2262 */
2263 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2264 return ii;
2265 }
2266
2267 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
2268 ppp_release_channels(ppp_chan, 1);
ratheesh kannothed721852015-09-28 12:39:52 +05302269 return NULL;
2270 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302271
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302272 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = info.local_tunnel_id;
2273 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = info.remote_tunnel_id;
2274 type_info.pppol2tpv2.l2tp.session.session_id = info.local_session_id;
2275 type_info.pppol2tpv2.l2tp.session.peer_session_id = info.remote_session_id;
2276 type_info.pppol2tpv2.udp.sport = ntohs(info.local_addr.sin_port);
2277 type_info.pppol2tpv2.udp.dport = ntohs(info.remote_addr.sin_port);
2278 type_info.pppol2tpv2.ip.saddr = ntohl(info.local_addr.sin_addr.s_addr);
2279 type_info.pppol2tpv2.ip.daddr = ntohl(info.remote_addr.sin_addr.s_addr);
ratheesh kannothed721852015-09-28 12:39:52 +05302280
2281 /*
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302282 * Release the channel. Note that next_dev is still (correctly) held.
ratheesh kannothed721852015-09-28 12:39:52 +05302283 */
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302284 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302285
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302286 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 +05302287
2288 /*
2289 * Establish this type of interface
2290 */
2291 ii = ecm_interface_pppol2tpv2_interface_establish(&type_info.pppol2tpv2, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2292 return ii;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302293 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302294 }
2295#endif
2296
Shyam Sunder23f2e542015-09-28 14:56:49 +05302297#ifdef ECM_INTERFACE_PPTP_ENABLE
2298 if ((protocol == IPPROTO_GRE) && skb && v4_hdr) {
2299 struct gre_hdr_pptp *gre_hdr;
2300 uint16_t proto;
2301 int ret;
2302
2303 skb_pull(skb, sizeof(struct iphdr));
2304 gre_hdr = (struct gre_hdr_pptp *)(skb->data);
2305 proto = ntohs(gre_hdr->protocol);
2306 if ((gre_hdr->version == GRE_VERSION_PPTP) && (proto == GRE_PROTOCOL_PPTP)) {
2307 ret = pptp_session_find(&opt, gre_hdr->call_id, v4_hdr->daddr);
2308 if (ret < 0) {
2309 skb_push(skb, sizeof(struct iphdr));
2310 DEBUG_WARN("PPTP session info not found\n");
2311 return NULL;
2312 }
2313
2314 /*
2315 * Get PPTP session info
2316 */
2317 type_info.pptp.src_call_id = ntohs(opt.src_addr.call_id);
2318 type_info.pptp.dst_call_id = ntohs(opt.dst_addr.call_id);
2319 type_info.pptp.src_ip = ntohl(opt.src_addr.sin_addr.s_addr);
2320 type_info.pptp.dst_ip = ntohl(opt.dst_addr.sin_addr.s_addr);
2321
2322 skb_push(skb, sizeof(struct iphdr));
2323
2324 /*
2325 * Establish this type of interface
2326 */
2327 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 +05302328 if (ii) {
2329 /*
2330 * The ifindex of a virtual netdevice like a PPTP session can change if it is destroyed
2331 * and comes up again. Detect if the ifindex has changed and update it if required
2332 */
2333 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2334 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05302335 return ii;
2336 }
2337
2338 skb_push(skb, sizeof(struct iphdr));
2339
2340 DEBUG_TRACE("Unknown GRE protocol \n");
2341 type_info.unknown.os_specific_ident = dev_interface_num;
2342
2343 /*
2344 * Establish this type of interface
2345 */
2346 ii = ecm_interface_unknown_interface_establish(&type_info.unknown, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2347 return ii;
2348 }
2349#endif
2350
Ben Menchaca84f36632014-02-28 20:57:38 +00002351 /*
2352 * PPP - but what is the channel type?
2353 * First: If this is multi-link then we do not support it
2354 */
2355 if (ppp_is_multilink(dev) > 0) {
2356 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
2357 type_info.unknown.os_specific_ident = dev_interface_num;
2358
2359 /*
2360 * Establish this type of interface
2361 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002362 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 +00002363 return ii;
2364 }
2365
2366 DEBUG_TRACE("Net device: %p is PPP\n", dev);
2367
2368 /*
2369 * Get the PPP channel and then enquire what kind of channel it is
2370 * NOTE: Not multilink so only one channel to get.
2371 */
2372 channel_count = ppp_hold_channels(dev, ppp_chan, 1);
2373 if (channel_count != 1) {
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002374 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
2375 dev, channel_count);
Ben Menchaca84f36632014-02-28 20:57:38 +00002376 type_info.unknown.os_specific_ident = dev_interface_num;
2377
2378 /*
2379 * Establish this type of interface
2380 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002381 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 +00002382 return ii;
2383 }
2384
2385 /*
2386 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002387 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00002388 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01002389 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302390
2391#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2392 if (channel_protocol == PX_PROTO_OL2TP) {
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302393 struct pppol2tp_common_addr info;
Ben Menchaca84f36632014-02-28 20:57:38 +00002394
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302395 if (pppol2tp_channel_addressing_get(ppp_chan[0], &info)) {
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302396 ppp_release_channels(ppp_chan, 1);
2397 return NULL;
2398 }
2399
ratheesh kannoth08b8e442015-10-02 00:24:55 +05302400 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = info.local_tunnel_id;
2401 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = info.remote_tunnel_id;
2402 type_info.pppol2tpv2.l2tp.session.session_id = info.local_session_id;
2403 type_info.pppol2tpv2.l2tp.session.peer_session_id = info.remote_session_id;
2404 type_info.pppol2tpv2.udp.sport = ntohs(info.local_addr.sin_port);
2405 type_info.pppol2tpv2.udp.dport = ntohs(info.remote_addr.sin_port);
2406 type_info.pppol2tpv2.ip.saddr = ntohl(info.local_addr.sin_addr.s_addr);
2407 type_info.pppol2tpv2.ip.daddr = ntohl(info.remote_addr.sin_addr.s_addr);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302408
2409 /*
2410 * Release the channel. Note that next_dev is still (correctly) held.
Ben Menchaca84f36632014-02-28 20:57:38 +00002411 */
2412 ppp_release_channels(ppp_chan, 1);
2413
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302414 DEBUG_TRACE("Net device: %p PPPo2L2TP session: %d,n", dev, type_info.pppol2tpv2.l2tp.session.peer_session_id);
2415
Ben Menchaca84f36632014-02-28 20:57:38 +00002416 /*
2417 * Establish this type of interface
2418 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302419 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 +00002420 return ii;
2421 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302422#endif
2423#ifdef ECM_INTERFACE_PPPOE_ENABLE
2424 if (channel_protocol == PX_PROTO_OE) {
2425
2426 /*
2427 * PPPoE channel
2428 */
2429 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dev);
2430
2431 /*
2432 * Get PPPoE session information and the underlying device it is using.
2433 */
2434 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2435 type_info.pppoe.pppoe_session_id = (uint16_t)ntohs((uint16_t)addressing.pa.sid);
2436 memcpy(type_info.pppoe.remote_mac, addressing.pa.remote, ETH_ALEN);
2437 dev_put(addressing.dev);
2438
2439 /*
2440 * Release the channel. Note that next_dev is still (correctly) held.
2441 */
2442 ppp_release_channels(ppp_chan, 1);
2443
2444 DEBUG_TRACE("Net device: %p PPPoE session: %x, remote mac: %pM\n",
2445 dev, type_info.pppoe.pppoe_session_id, type_info.pppoe.remote_mac);
2446
2447 /*
2448 * Establish this type of interface
2449 */
2450 ii = ecm_interface_pppoe_interface_establish(&type_info.pppoe, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2451 return ii;
2452 }
2453#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05302454
2455#ifdef ECM_INTERFACE_PPTP_ENABLE
2456 if (channel_protocol == PX_PROTO_PPTP) {
2457 pptp_channel_addressing_get(&opt, ppp_chan[0]);
2458
2459 /*
2460 * Get PPTP session info
2461 */
2462 type_info.pptp.src_call_id = ntohs(opt.src_addr.call_id);
2463 type_info.pptp.dst_call_id = ntohs(opt.dst_addr.call_id);
2464 type_info.pptp.src_ip = ntohl(opt.src_addr.sin_addr.s_addr);
2465 type_info.pptp.dst_ip = ntohl(opt.dst_addr.sin_addr.s_addr);
2466
2467 DEBUG_TRACE("Net device: %p PPTP source call id: %d,n", dev, type_info.pptp.src_call_id);
2468 ppp_release_channels(ppp_chan, 1);
2469
2470 /*
2471 * Establish this type of interface
2472 */
2473 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 +05302474 if (ii) {
2475 /*
2476 * The ifindex of a virtual netdevice like a PPTP session can change if it is destroyed
2477 * and comes up again. Detect if the ifindex has changed and update it if required
2478 */
2479 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
2480 }
Shyam Sunder23f2e542015-09-28 14:56:49 +05302481 return ii;
2482 }
2483#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302484 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n", dev, channel_protocol);
2485 type_info.unknown.os_specific_ident = dev_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00002486
2487 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302488 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00002489 */
2490 ppp_release_channels(ppp_chan, 1);
2491
Ben Menchaca84f36632014-02-28 20:57:38 +00002492 /*
2493 * Establish this type of interface
2494 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302495 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 +00002496 return ii;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002497#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002498}
2499EXPORT_SYMBOL(ecm_interface_establish_and_ref);
2500
Shyam Sunder6358b862015-05-04 15:06:24 +05302501#ifdef ECM_MULTICAST_ENABLE
2502/*
2503 * ecm_interface_multicast_heirarchy_construct_single()
2504 * Create and return an interface heirarchy for a single interface for a multicast connection
2505 *
2506 * src_addr IP source address
2507 * dest_addr IP Destination address/Group Address
2508 * interface Pointer to a single multicast interface heirarchy
2509 * given_dest_dev Netdev pointer for destination interface
2510 * br_slave_dev Netdev pointer to a bridge slave device. It could be NULL in case of pure
2511 * routed flow without any bridge interface in destination dev list.
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302512 * skb sk_buff
Shyam Sunder6358b862015-05-04 15:06:24 +05302513 */
Shyam Sunder81836832015-07-09 19:18:25 +05302514static uint32_t ecm_interface_multicast_heirarchy_construct_single(struct ecm_front_end_connection_instance *feci, ip_addr_t src_addr,
2515 ip_addr_t dest_addr, struct ecm_db_iface_instance *interface,
2516 struct net_device *given_dest_dev, struct net_device *br_slave_dev,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302517 uint8_t *src_node_addr, bool is_routed, __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302518{
2519 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2520 struct ecm_db_iface_instance **ifaces;
2521 struct ecm_db_iface_instance *ii_temp;
2522 struct net_device *dest_dev;
2523 int32_t current_interface_index;
2524 int32_t interfaces_cnt = 0;
2525 int32_t dest_dev_type;
2526
2527 dest_dev = given_dest_dev;
2528 dev_hold(dest_dev);
2529 dest_dev_type = dest_dev->type;
2530 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
2531
2532 while (current_interface_index > 0) {
2533 struct ecm_db_iface_instance *ii;
2534 struct net_device *next_dev;
2535
2536 /*
2537 * Get the ecm db interface instance for the device at hand
2538 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302539 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Shyam Sunder6358b862015-05-04 15:06:24 +05302540 interfaces_cnt++;
2541
2542 /*
2543 * If the interface could not be established then we abort
2544 */
2545 if (!ii) {
2546 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev->name);
2547 dev_put(dest_dev);
2548
2549 /*
2550 * Release the interfaces heirarchy we constructed to this point.
2551 */
2552 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2553 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2554 return ECM_DB_IFACE_HEIRARCHY_MAX;
2555 }
2556
2557 /*
2558 * Record the interface instance into the *ifaces
2559 */
2560 current_interface_index--;
2561 ii_temp = ecm_db_multicast_if_instance_get_at_index(interface, current_interface_index);
2562 ifaces = (struct ecm_db_iface_instance **)ii_temp;
2563 *ifaces = ii;
2564
2565 /*
2566 * Now we have to figure out what the next device will be (in the transmission path)
2567 */
2568 do {
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302569#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302570 int channel_count;
2571 struct ppp_channel *ppp_chan[1];
2572 int channel_protocol;
2573 struct pppoe_opt addressing;
2574#endif
2575 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev->name);
2576 next_dev = NULL;
2577
2578 if (dest_dev_type == ARPHRD_ETHER) {
2579 /*
2580 * Ethernet - but what sub type?
2581 */
2582
2583 /*
2584 * VLAN?
2585 */
2586 if (is_vlan_dev(dest_dev)) {
2587 /*
2588 * VLAN master
2589 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
2590 */
Shyam Sunder9db20852016-03-09 19:04:49 +05302591 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Shyam Sunder6358b862015-05-04 15:06:24 +05302592 dev_hold(next_dev);
2593 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
2594 dest_dev, next_dev, next_dev->name);
2595 break;
2596 }
2597
2598 /*
2599 * BRIDGE?
2600 */
2601 if (ecm_front_end_is_bridge_device(dest_dev)) {
2602 if (!ecm_front_end_is_bridge_port(br_slave_dev)) {
2603 DEBUG_ASSERT(NULL, "%p: expected only bridge slave here\n", interface);
2604
2605 /*
2606 * Release the interfaces heirarchy we constructed to this point.
2607 */
2608 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2609 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2610 dev_put(dest_dev);
2611 return ECM_DB_IFACE_HEIRARCHY_MAX;
2612 }
2613
2614 next_dev = br_slave_dev;
2615 if (!next_dev) {
2616 DEBUG_WARN("Unable to obtain output port \n");
2617
2618 /*
2619 * Release the interfaces heirarchy we constructed to this point.
2620 */
2621 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2622 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2623 dev_put(dest_dev);
2624 return ECM_DB_IFACE_HEIRARCHY_MAX;
2625 }
2626 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2627 dev_hold(next_dev);
2628 break;
2629 }
2630
Shyam Sunder81836832015-07-09 19:18:25 +05302631#ifdef ECM_INTERFACE_BOND_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302632 /*
2633 * LAG?
2634 */
2635 if (ecm_front_end_is_lag_master(dest_dev)) {
2636 /*
2637 * Link aggregation
2638 * Figure out which slave device of the link aggregation will be used to reach the destination.
2639 */
2640 uint32_t src_addr_32 = 0;
2641 uint32_t dest_addr_32 = 0;
Suman Ghoshf14d2172015-07-31 14:38:10 +05302642 struct in6_addr src_addr6;
2643 struct in6_addr dest_addr6;
Shyam Sunder6358b862015-05-04 15:06:24 +05302644 uint8_t src_mac_addr[ETH_ALEN];
2645 uint8_t dest_mac_addr[ETH_ALEN];
2646
2647 memset(src_mac_addr, 0, ETH_ALEN);
2648 memset(dest_mac_addr, 0, ETH_ALEN);
2649
Shyam Sunder81836832015-07-09 19:18:25 +05302650 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2651 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
2652 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
2653 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302654
Shyam Sunder81836832015-07-09 19:18:25 +05302655 if (!is_routed) {
2656 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
Shyam Sunder6358b862015-05-04 15:06:24 +05302657 } else {
Shyam Sunder81836832015-07-09 19:18:25 +05302658 struct net_device *dest_dev_master;
2659
2660 /*
2661 * Use appropriate source MAC address for routed packets
2662 */
2663 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
2664 if (dest_dev_master) {
2665 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
2666 dev_put(dest_dev_master);
2667 } else {
2668 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
2669 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302670 }
2671
2672 /*
2673 * Create Destination MAC address using IP multicast destination address
2674 */
2675 ecm_translate_multicast_mac(dest_addr, dest_mac_addr);
2676
Shyam Sunder81836832015-07-09 19:18:25 +05302677 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2678 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
2679 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302680 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302681 } else {
Suman Ghoshf14d2172015-07-31 14:38:10 +05302682 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
2683 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, dest_addr);
Shyam Sunder81836832015-07-09 19:18:25 +05302684 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
Suman Ghoshf14d2172015-07-31 14:38:10 +05302685 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05302686 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302687 }
2688
Shyam Sunder6358b862015-05-04 15:06:24 +05302689 if (!(next_dev && netif_carrier_ok(next_dev))) {
2690 DEBUG_WARN("Unable to obtain LAG output slave device\n");
2691 dev_put(dest_dev);
2692
2693 /*
2694 * Release the interfaces heirarchy we constructed to this point.
2695 */
2696 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2697 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2698 return ECM_DB_IFACE_HEIRARCHY_MAX;
2699 }
2700
2701 dev_hold(next_dev);
2702 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2703 break;
2704 }
2705#endif
2706
2707 /*
2708 * ETHERNET!
2709 * Just plain ethernet it seems.
2710 */
2711 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
2712 break;
2713 }
2714
2715 /*
2716 * LOOPBACK?
2717 */
2718 if (dest_dev_type == ARPHRD_LOOPBACK) {
2719 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
2720 break;
2721 }
2722
2723 /*
2724 * IPSEC?
2725 */
2726 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2727 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
2728 /*
2729 * TODO Figure out the next device the tunnel is using...
2730 */
2731 break;
2732 }
2733
2734 /*
2735 * SIT (6-in-4)?
2736 */
2737 if (dest_dev_type == ARPHRD_SIT) {
2738 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
2739 /*
2740 * TODO Figure out the next device the tunnel is using...
2741 */
2742 break;
2743 }
2744
2745 /*
2746 * IPIP6 Tunnel?
2747 */
2748 if (dest_dev_type == ARPHRD_TUNNEL6) {
2749 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
2750 /*
2751 * TODO Figure out the next device the tunnel is using...
2752 */
2753 break;
2754 }
2755
2756 /*
2757 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
2758 */
2759 if (dest_dev_type != ARPHRD_PPP) {
2760 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
2761 break;
2762 }
2763
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302764#ifndef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302765 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
2766#else
2767 /*
2768 * PPP - but what is the channel type?
2769 * First: If this is multi-link then we do not support it
2770 */
2771 if (ppp_is_multilink(dest_dev) > 0) {
2772 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
2773 break;
2774 }
2775
2776 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
2777
2778 /*
2779 * Get the PPP channel and then enquire what kind of channel it is
2780 * NOTE: Not multilink so only one channel to get.
2781 */
2782 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
2783 if (channel_count != 1) {
2784 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
2785 dest_dev, channel_count);
2786 break;
2787 }
2788
2789 /*
2790 * Get channel protocol type
2791 * NOTE: Not all PPP channels support channel specific methods.
2792 */
2793 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
2794 if (channel_protocol != PX_PROTO_OE) {
2795 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
2796 dest_dev, channel_protocol);
2797
2798 /*
2799 * Release the channel
2800 */
2801 ppp_release_channels(ppp_chan, 1);
2802
2803 break;
2804 }
2805
2806 /*
2807 * PPPoE channel
2808 */
2809 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
2810
2811 /*
2812 * Get PPPoE session information and the underlying device it is using.
2813 */
2814 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2815
2816 /*
2817 * Copy the dev hold into this, we will release the hold later
2818 */
2819 next_dev = addressing.dev;
2820
Shyam Sunder6358b862015-05-04 15:06:24 +05302821 /*
2822 * Release the channel. Note that next_dev is still (correctly) held.
2823 */
2824 ppp_release_channels(ppp_chan, 1);
2825#endif
2826 } while (false);
2827
2828 /*
2829 * No longer need dest_dev as it may become next_dev
2830 */
2831 dev_put(dest_dev);
2832
2833 /*
2834 * Check out the next_dev, if any
2835 */
2836 if (!next_dev) {
2837 int32_t i __attribute__((unused));
2838 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
2839#if DEBUG_LEVEL > 1
2840 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2841 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
2842 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n", \
2843 i, to_list_single[i], ecm_db_connection_iface_type_get(to_list_single[i]), \
2844 ecm_db_interface_type_to_string(ecm_db_connection_iface_type_get(to_list_single[i])));
2845 }
2846#endif
2847 return current_interface_index;
2848 }
2849
2850 /*
2851 * dest_dev becomes next_dev
2852 */
2853 dest_dev = next_dev;
2854 dest_dev_type = dest_dev->type;
2855 }
2856
2857 dev_put(dest_dev);
2858
2859 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2860 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2861 return ECM_DB_IFACE_HEIRARCHY_MAX;
2862}
2863
2864/*
2865 * ecm_interface_multicast_heirarchy_construct_routed()
2866 * Create destination interface heirarchy for a routed multicast connectiona
2867 *
2868 * interfaces Pointer to the 2-D array of multicast interface heirarchies
2869 * in_dev Pointer to the source netdev
2870 * packet_src_addr Source IP of the multicast flow
2871 * packet_dest_addr Group(dest) IP of the multicast flow
2872 * max_dst Maximum number of netdev joined the multicast group
2873 * dst_if_index_base An array of if index joined the multicast group
2874 * interface_first_base An array of the index of the first interface in the list
2875 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002876int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_connection_instance *feci,
2877 struct ecm_db_iface_instance *interfaces,
2878 struct net_device *in_dev,
2879 ip_addr_t packet_src_addr,
2880 ip_addr_t packet_dest_addr, uint8_t max_if,
2881 uint32_t *dst_if_index_base,
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302882 uint32_t *interface_first_base, bool mfc_update,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302883 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302884{
2885 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2886 struct ecm_db_iface_instance *ifaces;
2887 struct net_device *dest_dev = NULL;
2888 struct net_device *br_dev_src = NULL;
2889 uint32_t *dst_if_index;
2890 uint32_t *interface_first;
2891 uint32_t br_if;
2892 uint32_t valid_if;
Shyam Sunder41637872015-06-11 21:19:05 +05302893 int32_t if_num;
Shyam Sunder6358b862015-05-04 15:06:24 +05302894 int32_t dest_dev_type;
2895 int if_index;
2896 int ii_cnt;
2897 int total_ii_count = 0;
2898 bool src_dev_is_bridge = false;
2899
2900 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",
2901 ECM_IP_ADDR_TO_DOT(packet_dest_addr), ECM_IP_ADDR_TO_DOT(packet_src_addr), max_if);
2902
2903 /*
2904 * Check if the source net_dev is a bridge slave.
2905 */
Shyam Sundera2e08ee2015-06-18 21:32:13 +05302906 if (in_dev && !mfc_update) {
Shyam Sunder6358b862015-05-04 15:06:24 +05302907 if (ecm_front_end_is_bridge_port(in_dev)) {
2908 src_dev_is_bridge = true;
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302909 br_dev_src = ecm_interface_get_and_hold_dev_master(in_dev);
2910 DEBUG_ASSERT(br_dev_src, "Expected a master\n");
Shyam Sunder6358b862015-05-04 15:06:24 +05302911
2912 /*
2913 * The source net_dev found as bridge slave. In case of routed interface
2914 * heirarchy MFC is not aware of any other bridge slave has joined the same
2915 * multicast group as a destination interface. Therfore we assume there
2916 * are bridge slaves present in multicast destination interface list
2917 * and increase the max_if by one.
2918 */
2919 max_if++;
2920 }
2921 }
2922
2923 ii_cnt = 0;
2924 br_if = if_num = 0;
2925
2926 /*
2927 * This loop is for creating the destination interface hierarchy list.
2928 * We take the destination interface array we got from MFC (in form of ifindex array)
2929 * as input for this.
2930 */
2931 for (if_index = 0, valid_if = 0; if_index < max_if; if_index++) {
2932 dst_if_index = ecm_db_multicast_if_first_get_at_index(dst_if_index_base, if_index);
2933
2934 if (*dst_if_index == ECM_INTERFACE_LOOPBACK_DEV_INDEX) {
2935 continue;
2936 }
2937
2938 dest_dev = dev_get_by_index(&init_net, *dst_if_index);
2939 if (!dest_dev) {
2940 if (!src_dev_is_bridge) {
2941 int i;
2942
2943 /*
2944 * If already constructed any interface heirarchies before hitting
2945 * this error condition then Deref all interface heirarchies.
2946 */
2947 if (valid_if > 0) {
2948 for (i = 0; i < valid_if; i++) {
2949 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2950 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2951 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2952 }
2953 }
2954
2955 /*
2956 * If valid netdev not found, Return 0
2957 */
2958 return 0;
2959 }
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302960
Shyam Sunder6358b862015-05-04 15:06:24 +05302961 dest_dev = br_dev_src;
Karthik Hariharan3e964a32015-09-22 21:40:52 +05302962
Shyam Sunder6358b862015-05-04 15:06:24 +05302963 }
2964
2965 dest_dev_type = dest_dev->type;
2966
2967 if (ecm_front_end_is_bridge_device(dest_dev)) {
2968 struct net_device *mc_br_slave_dev = NULL;
2969 uint32_t mc_max_dst = ECM_DB_MULTICAST_IF_MAX;
2970 uint32_t mc_dst_if_index[ECM_DB_MULTICAST_IF_MAX];
2971
2972 if (ECM_IP_ADDR_IS_V4(packet_src_addr)) {
2973 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);
2974 } else {
2975 struct in6_addr origin6;
2976 struct in6_addr group6;
2977 ECM_IP_ADDR_TO_NIN6_ADDR(origin6, packet_src_addr);
2978 ECM_IP_ADDR_TO_NIN6_ADDR(group6, packet_dest_addr);
2979 if_num = mc_bridge_ipv6_get_if(dest_dev, &origin6, &group6, mc_max_dst, mc_dst_if_index);
2980 }
2981
Shyam Sunder81836832015-07-09 19:18:25 +05302982 if ((if_num < 0) || (if_num > ECM_DB_MULTICAST_IF_MAX)) {
2983 int i;
2984 DEBUG_WARN("MCS is not ready\n");
2985
2986 /*
2987 * If already constructed any interface heirarchies before hitting
2988 * this error condition then Deref all interface heirarchies.
2989 */
2990 if (valid_if > 0) {
2991 for (i = 0; i < valid_if; i++) {
2992 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2993 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2994 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2995 }
2996 }
2997
Shyam Sunder41637872015-06-11 21:19:05 +05302998 dev_put(dest_dev);
2999 return 0;
3000 }
3001
Shyam Sundera450b582016-07-22 14:44:14 +05303002 if (in_dev && !mfc_update) {
Shyam Sunder06588292016-04-18 19:57:39 +05303003 if_num = ecm_interface_multicast_check_for_src_ifindex(mc_dst_if_index, if_num, in_dev->ifindex);
3004 }
Shyam Sundera2e08ee2015-06-18 21:32:13 +05303005
Shyam Sunder6358b862015-05-04 15:06:24 +05303006 for (br_if = 0; br_if < if_num; br_if++) {
3007 mc_br_slave_dev = dev_get_by_index(&init_net, mc_dst_if_index[br_if]);
3008 if (!mc_br_slave_dev) {
3009 continue;
3010 }
3011
3012 if ((valid_if + br_if) > ECM_DB_MULTICAST_IF_MAX) {
3013 int i;
3014
3015 /*
3016 * If already constructed any interface heirarchies before hitting
3017 * this error condition then Deref all interface heirarchies.
3018 */
3019 for (i = 0; i < (valid_if + br_if); i++) {
3020 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3021 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3022 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3023 }
3024
3025 dev_put(dest_dev);
3026 dev_put(mc_br_slave_dev);
3027 return 0;
3028 }
3029
3030 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if + br_if);
3031 /*
3032 * Construct a single interface heirarchy of a multicast dev.
3033 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303034 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 +05303035 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3036
3037 /*
3038 * If already constructed any interface heirarchies before hitting
3039 * this error condition then Deref all interface heirarchies.
3040 */
3041 if ((valid_if + br_if) > 0) {
3042 int i;
3043 for (i = 0; i < (valid_if + br_if); i++) {
3044 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3045 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3046 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3047 }
3048 }
3049
3050 dev_put(dest_dev);
3051 dev_put(mc_br_slave_dev);
3052 return 0;
3053 }
3054
3055 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, (valid_if + br_if));
3056 *interface_first = ii_cnt;
3057 total_ii_count += ii_cnt;
3058 dev_put(mc_br_slave_dev);
3059 }
3060
3061 valid_if += br_if;
3062
3063 } else {
3064
3065 DEBUG_ASSERT(valid_if < ECM_DB_MULTICAST_IF_MAX, "Bad array index size %d\n", valid_if);
3066 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
3067 /*
3068 * Construct a single interface heirarchy of a multicast dev.
3069 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303070 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 +05303071 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3072
3073 /*
3074 * If already constructed any interface heirarchies before hitting
3075 * this error condition then Deref all interface heirarchies.
3076 */
3077 if (valid_if > 0) {
3078 int i;
3079 for (i = 0; i < valid_if; i++) {
3080 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3081 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3082 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3083 }
3084 }
3085
3086 dev_put(dest_dev);
3087 return 0;
3088 }
3089
3090 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
3091 *interface_first = ii_cnt;
3092 total_ii_count += ii_cnt;
3093 valid_if++;
3094 }
3095
3096 dev_put(dest_dev);
3097 }
3098 return total_ii_count;
3099}
3100EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed);
3101
3102/*
3103 * ecm_interface_multicast_heirarchy_construct_bridged()
3104 * This function called when the Hyfi bridge snooper has IGMP/IMLD updates, this function
3105 * creates destination interface heirarchy for a bridged multicast connection.
3106 *
3107 * interfaces Pointer to the 2-D array of multicast interface heirarchies
3108 * dest_dev Pointer to the destination dev, here dest_dev is always a bridge type
3109 * packet_src_addr Source IP of the multicast flow
3110 * packet_dest_addr Group(dest) IP of the multicast flow
3111 * mc_max_dst Maximum number of bridge slaves joined the multicast group
3112 * mc_dst_if_index_base An array of if index joined the multicast group
3113 * interface_first_base An array of the index of the first interface in the list
3114 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003115int32_t ecm_interface_multicast_heirarchy_construct_bridged(struct ecm_front_end_connection_instance *feci,
Shyam Sunder81836832015-07-09 19:18:25 +05303116 struct ecm_db_iface_instance *interfaces, struct net_device *dest_dev,
3117 ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, uint8_t mc_max_dst,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05303118 int *mc_dst_if_index_base, uint32_t *interface_first_base, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303119 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05303120{
3121 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
3122 struct ecm_db_iface_instance *ifaces;
3123 struct net_device *mc_br_slave_dev = NULL;
3124 uint32_t *interface_first;
3125 int *mc_dst_if_index;
3126 int valid_if;
3127 int ii_cnt = 0;
3128 int br_if;
3129 int total_ii_cnt = 0;
3130
3131 /*
3132 * Go through the newly joined interface index one by one and
3133 * create an interface heirarchy for each valid interface.
3134 */
3135 for (br_if = 0, valid_if = 0; br_if < mc_max_dst; br_if++) {
3136 mc_dst_if_index = (int *)ecm_db_multicast_if_num_get_at_index(mc_dst_if_index_base, br_if);
3137 mc_br_slave_dev = dev_get_by_index(&init_net, *mc_dst_if_index);
3138 if (!mc_br_slave_dev) {
3139
3140 /*
3141 * If already constructed any interface heirarchies before hitting
3142 * this error condition then Deref all interface heirarchies.
3143 */
3144 if (valid_if > 0) {
3145 int i;
3146 for (i = 0; i < valid_if; i++) {
3147 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3148 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3149 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3150 }
3151 }
3152
3153 /*
3154 * If valid netdev not found, Return 0
3155 */
3156 return 0;
3157 }
3158
3159 if (valid_if > ECM_DB_MULTICAST_IF_MAX) {
3160 int i;
3161
3162 /*
3163 * If already constructed any interface heirarchies before hitting
3164 * this error condition then Deref all interface heirarchies.
3165 */
3166 for (i = 0; i < valid_if; i++) {
3167 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3168 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3169 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3170 }
3171
3172 dev_put(mc_br_slave_dev);
3173 return 0;
3174 }
3175
3176 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
3177
3178 /*
3179 * Construct a single interface heirarchy of a multicast dev.
3180 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303181 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 +05303182 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
3183
3184 /*
3185 * If already constructed any interface heirarchies before hitting
3186 * this error condition then Deref all interface heirarchies.
3187 */
3188 if (valid_if > 0) {
3189 int i;
3190 for (i = 0; i < valid_if; i++) {
3191 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
3192 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
3193 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
3194 }
3195 }
3196
3197 dev_put(mc_br_slave_dev);
3198 return 0;
3199 }
3200
3201 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
3202 *interface_first = ii_cnt;
3203 total_ii_cnt += ii_cnt;
3204 valid_if++;
3205 dev_put(mc_br_slave_dev);
3206 }
3207
Shyam Sunder280b34a2016-06-22 19:30:22 +05303208 return valid_if;
Shyam Sunder6358b862015-05-04 15:06:24 +05303209}
3210EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_bridged);
Shyam Sunder6358b862015-05-04 15:06:24 +05303211
Ben Menchaca84f36632014-02-28 20:57:38 +00003212/*
Murat Sezgin5dae8832015-12-03 14:23:19 -08003213 * ecm_interface_multicast_get_next_node_mac_address()
3214 * Get the MAC address of the next node for multicast flows
3215 *
3216 * TODO: This function will be removed when the multicast flow code
3217 * is fixed to use the new interface hierarchy construction model.
3218 *
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003219 */
Murat Sezgin5dae8832015-12-03 14:23:19 -08003220static bool ecm_interface_multicast_get_next_node_mac_address(
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003221 ip_addr_t dest_addr, struct net_device *dest_dev, int ip_version,
3222 uint8_t *mac_addr)
3223{
3224 bool on_link;
3225 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3226
3227 if (!ecm_interface_mac_addr_get(dest_addr, mac_addr, &on_link, gw_addr)) {
3228 if (ip_version == 4) {
3229 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n",
3230 ECM_IP_ADDR_TO_DOT(dest_addr));
3231 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
3232 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003233#ifdef ECM_IPV6_ENABLE
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003234 if (ip_version == 6) {
3235 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n",
3236 ECM_IP_ADDR_TO_OCTAL(dest_addr));
3237 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
3238 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003239#endif
3240 return false;
3241 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003242
Murat Sezgin5dae8832015-12-03 14:23:19 -08003243 return true;
3244}
Murat Sezgin8f70b312016-02-02 23:33:10 -08003245#endif
Murat Sezgin5dae8832015-12-03 14:23:19 -08003246
3247/*
3248 * ecm_interface_get_next_node_mac_address()
3249 * Get the MAC address of the next node
3250 */
3251static bool ecm_interface_get_next_node_mac_address(
3252 ip_addr_t dest_addr, struct net_device *dest_dev, int ip_version,
3253 uint8_t *mac_addr)
3254{
3255 if (!ecm_interface_mac_addr_get_no_route(dest_dev, dest_addr, mac_addr)) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003256 /*
3257 * MAC address look up failed. The host IP address may not be in the
3258 * neighbour table. So, let's send an ARP or neighbour solicitation
3259 * request to this host IP address, so in the subsequent lookups it can be
3260 * found.
3261 */
Murat Sezgin5dae8832015-12-03 14:23:19 -08003262 if (ip_version == 4) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003263 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3264 bool on_link = true;
3265
3266 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT " send ARP request\n",
Murat Sezgin5dae8832015-12-03 14:23:19 -08003267 ECM_IP_ADDR_TO_DOT(dest_addr));
Murat Sezgin00627c12016-02-05 16:53:21 -08003268
3269 if (ecm_interface_find_gateway(dest_addr, gw_addr)) {
3270 on_link = false;
3271 }
Shyam Sunder9ac555d2016-09-16 17:58:15 +05303272
3273 if (ecm_interface_mac_addr_get_no_route(dest_dev, gw_addr, mac_addr)) {
3274 DEBUG_TRACE("Found the mac address for gateway\n");
3275 return true;
3276 }
3277
Murat Sezgin00627c12016-02-05 16:53:21 -08003278 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003279 }
3280#ifdef ECM_IPV6_ENABLE
3281 if (ip_version == 6) {
Murat Sezgin00627c12016-02-05 16:53:21 -08003282 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 -08003283 ECM_IP_ADDR_TO_OCTAL(dest_addr));
Murat Sezgin00627c12016-02-05 16:53:21 -08003284 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003285 }
3286#endif
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003287 return false;
3288 }
3289
3290 return true;
3291}
3292
3293/*
3294 * ecm_interface_should_update_egress_device_bridged()
3295 * Determine if the egress port should be re-evaluated in the bridged case
3296 *
3297 * This will be done if:
3298 * - The egress port is the one provided from the front-end
3299 * - The egress port is not a bridge, but is a slave of the bridge
3300 * - Not routed
3301 *
3302 * If these conditions hold, this function will hold a reference to the bridge
3303 * port and return it to the caller. Otherwise no reference will be held and
3304 * it will return NULL.
3305 */
3306static struct net_device *ecm_interface_should_update_egress_device_bridged(
3307 struct net_device *given_dest_dev, struct net_device *dest_dev,
3308 bool is_routed)
3309{
3310 struct net_device *bridge;
3311
3312 /*
3313 * Determine if we should attempt to fetch the bridge device
3314 */
3315 if (!given_dest_dev || is_routed || (dest_dev != given_dest_dev) ||
3316 ecm_front_end_is_bridge_device(given_dest_dev))
3317 return NULL;
3318
3319 bridge = ecm_interface_get_and_hold_dev_master(given_dest_dev);
3320
3321 if (!bridge)
3322 return NULL;
3323
Murat Sezgin3aea6c92015-11-13 13:14:12 -08003324 if (!ecm_front_end_is_bridge_device(bridge)) {
3325 /*
3326 * Master is not a bridge - free the reference and return
3327 */
3328 dev_put(bridge);
3329 return NULL;
3330 }
3331
3332 /*
3333 * Reference is held to bridge and must be freed by caller
3334 */
3335 return bridge;
3336}
3337
3338/*
Ben Menchaca84f36632014-02-28 20:57:38 +00003339 * ecm_interface_heirarchy_construct()
3340 * Construct an interface heirarchy.
3341 *
3342 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
3343 * This is the heirarchy of interfaces a packet would transit to emit from the device.
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003344 *
3345 * We will use the given src/dest devices when is_routed is false.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003346 * When is_routed is true we will use the construct and the other devices (which is the src device of the
3347 * construct device) whcih were obtained from the skb's route field and passed to this function..
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003348 *
Ben Menchaca84f36632014-02-28 20:57:38 +00003349 * For example, with this network arrangement:
3350 *
3351 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
3352 *
Gareth Williams43fc0852014-05-26 19:10:00 +01003353 * 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 +00003354 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
3355 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
3356 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
3357 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
3358 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
3359 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
3360 *
3361 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
3362 * they will be created and added automatically to the database.
Ben Menchaca84f36632014-02-28 20:57:38 +00003363 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003364int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
3365 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin5dae8832015-12-03 14:23:19 -08003366 struct net_device *const_if, struct net_device *other_if,
Murat Sezginf92db492016-07-15 11:33:15 -07003367 ip_addr_t lookup_src_addr,
3368 ip_addr_t lookup_dest_addr,
3369 ip_addr_t real_dest_addr,
Murat Sezgin5dae8832015-12-03 14:23:19 -08003370 int ip_version, int packet_protocol,
3371 struct net_device *given_dest_dev,
3372 bool is_routed, struct net_device *given_src_dev,
3373 uint8_t *dest_node_addr, uint8_t *src_node_addr,
3374 __be16 *layer4hdr, struct sk_buff *skb)
3375{
3376 int protocol;
3377 ip_addr_t src_addr;
3378 ip_addr_t dest_addr;
3379 struct net_device *dest_dev;
3380 char *dest_dev_name;
3381 int32_t dest_dev_type;
3382 struct net_device *src_dev;
3383 char *src_dev_name;
3384 int32_t src_dev_type;
3385 int32_t current_interface_index;
3386 bool from_local_addr;
3387 bool next_dest_addr_valid;
3388 bool next_dest_node_addr_valid = false;
3389 ip_addr_t next_dest_addr;
3390 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003391 struct net_device *bridge;
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303392 struct net_device *top_dev_vlan = NULL;
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003393 uint32_t serial = ecm_db_connection_serial_get(feci->ci);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003394
3395 /*
3396 * Get a big endian of the IPv4 address we have been given as our starting point.
3397 */
3398 protocol = packet_protocol;
Murat Sezginf92db492016-07-15 11:33:15 -07003399 ECM_IP_ADDR_COPY(src_addr, lookup_src_addr);
3400 ECM_IP_ADDR_COPY(dest_addr, lookup_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003401
3402 if (ip_version == 4) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003403 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",
3404 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol,
3405 serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003406#ifdef ECM_IPV6_ENABLE
3407 } else if (ip_version == 6) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003408 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",
3409 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol,
3410 serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003411#endif
3412 } else {
3413 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
3414 return ECM_DB_IFACE_HEIRARCHY_MAX;
3415 }
3416
3417 /*
3418 * Get device to reach the given destination address.
3419 * If the heirarchy is for a routed connection we must use the devices obtained from the skb's route information..
3420 * If the heirarchy is NOT for a routed connection we try the given_dest_dev.
3421 */
3422 from_local_addr = false;
3423 if (!is_routed) {
3424 dest_dev = given_dest_dev;
3425 dev_hold(dest_dev);
3426 } else {
3427 dest_dev = ecm_interface_dev_find_by_local_addr(dest_addr);
3428 if (dest_dev) {
3429 from_local_addr = true;
3430 } else {
3431 dest_dev = const_if;
3432 dev_hold(dest_dev);
3433 }
3434 }
3435
3436 /*
3437 * If the address is a local address and protocol is an IP tunnel
3438 * then this connection is a tunnel endpoint made to this device.
3439 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
3440 *
3441 * TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
3442 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
3443 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
3444 */
3445 if (dest_dev && from_local_addr) {
3446 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
Murat Sezgin31effef2017-11-13 15:09:34 -08003447 ((ip_version == 6) && (protocol == IPPROTO_IPIP))
3448#ifdef ECM_INTERFACE_GRE_ENABLE
3449 || ((protocol == IPPROTO_GRE) && (given_dest_dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)))) {
3450#else
3451 {
3452#endif
Murat Sezgin5dae8832015-12-03 14:23:19 -08003453 dev_put(dest_dev);
3454 dest_dev = given_dest_dev;
3455 if (dest_dev) {
3456 dev_hold(dest_dev);
3457 if (ip_version == 4) {
3458 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);
3459 } else {
3460 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);
3461 }
3462 }
3463 }
3464 }
3465
3466#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05303467
Murat Sezgin5dae8832015-12-03 14:23:19 -08003468 /*
3469 * if the address is a local address and indev=l2tp.
3470 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05303471 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 -08003472 dev_put(dest_dev);
3473 dest_dev = given_dest_dev;
3474 if (dest_dev) {
3475 dev_hold(dest_dev);
3476 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);
3477 }
3478 }
3479#endif
3480
3481#ifdef ECM_INTERFACE_PPTP_ENABLE
3482 /*
3483 * if the address is a local address and indev=PPTP.
3484 */
3485 if (protocol == IPPROTO_GRE && given_dest_dev && given_dest_dev->type == ARPHRD_PPP) {
3486 dev_put(dest_dev);
3487 dest_dev = given_dest_dev;
3488 if (dest_dev) {
3489 dev_hold(dest_dev);
3490 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);
3491 }
3492 }
3493#endif
3494
3495 if (!dest_dev) {
3496 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
3497 return ECM_DB_IFACE_HEIRARCHY_MAX;
3498 }
3499 dest_dev_name = dest_dev->name;
3500 dest_dev_type = dest_dev->type;
3501
3502 /*
3503 * Get device to reach the given source address.
3504 * If the heirarchy is for a routed connection we must use the devices obtained from the skb's route information..
3505 * If the heirarchy is NOT for a routed connection we try the given_src_dev.
3506 */
3507 from_local_addr = false;
3508 if (!is_routed) {
3509 src_dev = given_src_dev;
3510 dev_hold(src_dev);
3511 } else {
3512 src_dev = ecm_interface_dev_find_by_local_addr(src_addr);
3513 if (src_dev) {
3514 from_local_addr = true;
3515 } else {
3516 src_dev = other_if;
3517 dev_hold(src_dev);
3518 }
3519 }
3520
3521 /*
3522 * If the address is a local address and protocol is an IP tunnel
3523 * then this connection is a tunnel endpoint made to this device.
3524 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
3525 *
3526 * TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
3527 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
3528 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
3529 */
3530 if (src_dev && from_local_addr) {
3531 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
Murat Sezgin31effef2017-11-13 15:09:34 -08003532 ((ip_version == 6) && (protocol == IPPROTO_IPIP))
3533#ifdef ECM_INTERFACE_GRE_ENABLE
3534 || ((protocol == IPPROTO_GRE) && (given_src_dev->priv_flags & (IFF_GRE_V4_TAP | IFF_GRE_V6_TAP)))) {
3535#else
3536 {
3537#endif
Murat Sezgin5dae8832015-12-03 14:23:19 -08003538 dev_put(src_dev);
3539 src_dev = given_src_dev;
3540 if (src_dev) {
3541 dev_hold(src_dev);
3542 if (ip_version == 4) {
3543 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);
3544 } else {
3545 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);
3546 }
3547 }
3548 }
3549 }
3550
3551 if (!src_dev) {
3552 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
3553 dev_put(dest_dev);
3554 return ECM_DB_IFACE_HEIRARCHY_MAX;
3555 }
3556 src_dev_name = src_dev->name;
3557 src_dev_type = src_dev->type;
3558
3559 /*
3560 * Check if source and dest dev are same.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003561 */
3562 if (src_dev == dest_dev) {
ratheesh kannotha6d25952016-04-11 12:23:26 +05303563 bool skip = false;
3564
Murat Sezgin5dae8832015-12-03 14:23:19 -08003565 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
ratheesh kannotha6d25952016-04-11 12:23:26 +05303566
3567 switch (ip_version) {
3568 case 4:
3569 if ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)) {
3570 skip = true;
3571 break;
3572 }
3573
3574 if ((protocol == IPPROTO_UDP) && (udp_hdr(skb)->dest == htons(4500))) {
3575 skip = true;
3576 break;
3577 }
3578
3579 break;
3580
3581 case 6:
ratheesh kannotha6d25952016-04-11 12:23:26 +05303582 if ((protocol == IPPROTO_IPIP) || (protocol == IPPROTO_ESP)) {
3583 skip = true;
3584 break;
3585 }
3586
3587 break;
3588
3589 default:
3590 DEBUG_WARN("IP version = %d, Protocol = %d: Corrupted packet entered ecm\n", ip_version, protocol);
3591 skip = true;
3592 break;
3593 }
3594
3595 if (skip) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003596 /*
3597 * This happens from the input hook
3598 * We do not want to create a connection entry for this
3599 * TODO YES WE DO.
3600 * TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
3601 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
3602 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
3603 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
3604 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
3605 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
3606 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
3607 */
3608 dev_put(src_dev);
3609 dev_put(dest_dev);
3610 return ECM_DB_IFACE_HEIRARCHY_MAX;
3611 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003612 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003613
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003614 bridge = ecm_interface_should_update_egress_device_bridged(
3615 given_dest_dev, dest_dev, is_routed);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003616
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003617 if (bridge) {
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003618 struct net_device *new_dest_dev;
Murat Sezginb9bd5e02016-08-05 14:55:07 -07003619 new_dest_dev = br_port_dev_get(bridge, dest_node_addr, skb, serial);
3620 if (new_dest_dev) {
3621 dev_put(dest_dev);
3622 if (new_dest_dev != given_dest_dev) {
3623 DEBUG_INFO("Adjusted port for %pM is %s (given was %s)\n",
3624 dest_node_addr, new_dest_dev->name,
3625 given_dest_dev->name);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003626
Murat Sezginb9bd5e02016-08-05 14:55:07 -07003627 dest_dev = new_dest_dev;
3628 dest_dev_name = dest_dev->name;
3629 dest_dev_type = dest_dev->type;
Murat Sezgin5dae8832015-12-03 14:23:19 -08003630 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003631 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08003632 dev_put(bridge);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003633 }
3634
3635 next_dest_addr_valid = true;
3636 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
3637
3638 /*
3639 * Iterate until we are done or get to the max number of interfaces we can record.
3640 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
3641 * because we add from the end first_interface grows downwards.
3642 */
3643 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
3644 while (current_interface_index > 0) {
3645 struct ecm_db_iface_instance *ii;
3646 struct net_device *next_dev;
3647 /*
3648 * Get the ecm db interface instance for the device at hand
3649 */
3650 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
3651
3652 /*
3653 * If the interface could not be established then we abort
3654 */
3655 if (!ii) {
3656 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
3657 dev_put(src_dev);
3658 dev_put(dest_dev);
3659
3660 /*
3661 * Release the interfaces heirarchy we constructed to this point.
3662 */
3663 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3664 return ECM_DB_IFACE_HEIRARCHY_MAX;
3665 }
3666
3667 /*
3668 * Record the interface instance into the interfaces[]
3669 */
3670 current_interface_index--;
3671 interfaces[current_interface_index] = ii;
3672
3673 /*
3674 * Now we have to figure out what the next device will be (in the transmission path) the skb
3675 * will use to emit to the destination address.
3676 */
3677 do {
3678#ifdef ECM_INTERFACE_PPP_ENABLE
3679 int channel_count;
3680 struct ppp_channel *ppp_chan[1];
3681 int channel_protocol;
3682#ifdef ECM_INTERFACE_PPPOE_ENABLE
3683 struct pppoe_opt addressing;
3684#endif
3685#endif
3686
3687 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
3688 next_dev = NULL;
3689
3690 if (dest_dev_type == ARPHRD_ETHER) {
3691 /*
3692 * Ethernet - but what sub type?
3693 */
3694
3695#ifdef ECM_INTERFACE_VLAN_ENABLE
3696 /*
3697 * VLAN?
3698 */
3699 if (is_vlan_dev(dest_dev)) {
3700 /*
3701 * VLAN master
3702 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
3703 */
Shyam Sunder9db20852016-03-09 19:04:49 +05303704 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003705 dev_hold(next_dev);
3706 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
3707 dest_dev, next_dev, next_dev->name);
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303708 if (current_interface_index == (ECM_DB_IFACE_HEIRARCHY_MAX - 1)) {
3709 top_dev_vlan = dest_dev;
3710 }
Murat Sezgin5dae8832015-12-03 14:23:19 -08003711 break;
3712 }
3713#endif
3714
3715 /*
3716 * BRIDGE?
3717 */
3718 if (ecm_front_end_is_bridge_device(dest_dev)) {
3719 /*
3720 * Bridge
3721 * Figure out which port device the skb will go to using the dest_addr.
3722 */
3723 uint8_t mac_addr[ETH_ALEN];
3724
3725 if (next_dest_node_addr_valid) {
3726 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
3727 } else if (!next_dest_addr_valid) {
3728 dev_put(src_dev);
3729 dev_put(dest_dev);
3730
3731 /*
3732 * Release the interfaces heirarchy we constructed to this point.
3733 */
3734 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3735 return ECM_DB_IFACE_HEIRARCHY_MAX;
3736 } else {
3737 if (!ecm_interface_get_next_node_mac_address(dest_addr, dest_dev, ip_version, mac_addr)) {
3738 dev_put(src_dev);
3739 dev_put(dest_dev);
3740
3741 /*
3742 * Release the interfaces heirarchy we constructed to this point.
3743 */
3744 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3745 return ECM_DB_IFACE_HEIRARCHY_MAX;
3746 }
3747 }
3748
Murat Sezgin545cf7d2016-03-04 09:48:21 -08003749 next_dev = br_port_dev_get(dest_dev,
3750 mac_addr, skb, serial);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003751
3752 if (!next_dev) {
3753 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
3754 dev_put(src_dev);
3755 dev_put(dest_dev);
3756
3757 /*
3758 * Release the interfaces heirarchy we constructed to this point.
3759 */
3760 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3761 return ECM_DB_IFACE_HEIRARCHY_MAX;
3762 }
3763 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3764 break;
3765 }
3766
3767#ifdef ECM_INTERFACE_BOND_ENABLE
3768 /*
3769 * LAG?
3770 */
3771 if (ecm_front_end_is_lag_master(dest_dev)) {
3772 /*
3773 * Link aggregation
3774 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
3775 */
3776 uint32_t src_addr_32 = 0;
3777 uint32_t dest_addr_32 = 0;
3778 struct in6_addr src_addr6;
3779 struct in6_addr dest_addr6;
3780 uint8_t src_mac_addr[ETH_ALEN];
3781 uint8_t dest_mac_addr[ETH_ALEN];
3782
3783 memset(src_mac_addr, 0, ETH_ALEN);
3784 memset(dest_mac_addr, 0, ETH_ALEN);
3785
3786 if (ip_version == 4) {
3787 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
Murat Sezginf92db492016-07-15 11:33:15 -07003788 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, real_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003789 }
3790
3791 if (!is_routed) {
3792 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
3793 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
3794 } else {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003795 struct net_device *master_dev;
Murat Sezgin5dae8832015-12-03 14:23:19 -08003796
3797 /*
Murat Sezgin7be87d22016-01-29 17:41:37 -08003798 * Use appropriate source MAC address for routed packets and
3799 * find proper interface to find the destination mac address and
3800 * from which to issue ARP or neighbour solicitation packet.
Murat Sezgin5dae8832015-12-03 14:23:19 -08003801 */
Murat Sezgin7be87d22016-01-29 17:41:37 -08003802 master_dev = ecm_interface_get_and_hold_dev_master(dest_dev);
3803 if (master_dev) {
3804 memcpy(src_mac_addr, master_dev->dev_addr, ETH_ALEN);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003805 } else {
3806 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003807 master_dev = dest_dev;
Shyam Sunder2e9528b2016-07-05 14:45:55 +05303808 if (top_dev_vlan) {
3809 master_dev = top_dev_vlan;
3810 }
Murat Sezgin7be87d22016-01-29 17:41:37 -08003811 dev_hold(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003812 }
3813
3814 /*
3815 * Determine destination MAC address for this routed packet
3816 */
3817 if (next_dest_node_addr_valid) {
3818 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
3819 } else if (!next_dest_addr_valid) {
3820 dev_put(src_dev);
3821 dev_put(dest_dev);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003822 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003823 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3824 return ECM_DB_IFACE_HEIRARCHY_MAX;
3825 } else {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003826 if (!ecm_interface_mac_addr_get_no_route(master_dev, dest_addr, dest_mac_addr)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003827 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
3828 /*
3829 * Try one more time with gateway ip address if it exists.
3830 */
3831 if (!ecm_interface_find_gateway(dest_addr, gw_addr)) {
3832 goto lag_fail;
3833 }
3834
3835 if (ip_version == 4) {
3836 DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(gw_addr));
3837 }
3838#ifdef ECM_IPV6_ENABLE
3839
3840 if (ip_version == 6) {
3841 DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr));
3842 }
3843#endif
Murat Sezgin7be87d22016-01-29 17:41:37 -08003844 if (ecm_interface_mac_addr_get_no_route(master_dev, gw_addr, dest_mac_addr)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003845 DEBUG_TRACE("Found the mac address for gateway\n");
Murat Sezgin7be87d22016-01-29 17:41:37 -08003846 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003847 goto lag_success;
3848 }
3849
3850 if (ip_version == 4) {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003851 ecm_interface_send_arp_request(master_dev, dest_addr, false, gw_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003852
3853 DEBUG_WARN("Unable to obtain any MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
3854 }
3855#ifdef ECM_IPV6_ENABLE
3856 if (ip_version == 6) {
Murat Sezgin7be87d22016-01-29 17:41:37 -08003857 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003858
3859 DEBUG_WARN("Unable to obtain any MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
3860 }
3861#endif
3862lag_fail:
3863 dev_put(src_dev);
3864 dev_put(dest_dev);
Murat Sezgin7be87d22016-01-29 17:41:37 -08003865 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003866
3867 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3868 return ECM_DB_IFACE_HEIRARCHY_MAX;
3869 }
3870 }
Suman Ghosh11c6f9e2018-03-01 20:40:39 +05303871 dev_put(master_dev);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003872 }
3873lag_success:
3874 if (ip_version == 4) {
3875 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3876 &src_addr_32, &dest_addr_32,
3877 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
3878 } else if (ip_version == 6) {
3879 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
Murat Sezginf92db492016-07-15 11:33:15 -07003880 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, real_dest_addr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003881 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3882 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05303883 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Murat Sezgin5dae8832015-12-03 14:23:19 -08003884 }
3885
3886 if (next_dev && netif_carrier_ok(next_dev)) {
3887 dev_hold(next_dev);
3888 } else {
3889 DEBUG_WARN("Unable to obtain LAG output slave device\n");
3890 dev_put(src_dev);
3891 dev_put(dest_dev);
3892
3893 /*
3894 * Release the interfaces heirarchy we constructed to this point.
3895 */
3896 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3897 return ECM_DB_IFACE_HEIRARCHY_MAX;
3898 }
3899
3900 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3901 break;
3902 }
3903#endif
3904
3905 /*
3906 * ETHERNET!
3907 * Just plain ethernet it seems.
3908 */
3909 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
3910 break;
3911 }
3912
3913 /*
3914 * LOOPBACK?
3915 */
3916 if (dest_dev_type == ARPHRD_LOOPBACK) {
3917 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
3918 break;
3919 }
3920
3921 /*
3922 * IPSEC?
3923 */
3924 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
3925 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
3926 /* TODO Figure out the next device the tunnel is using... */
3927 break;
3928 }
3929
3930 /*
3931 * SIT (6-in-4)?
3932 */
3933 if (dest_dev_type == ARPHRD_SIT) {
3934 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
3935 /* TODO Figure out the next device the tunnel is using... */
3936 break;
3937 }
3938
3939 /*
3940 * IPIP6 Tunnel?
3941 */
3942 if (dest_dev_type == ARPHRD_TUNNEL6) {
3943 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
3944 /* TODO Figure out the next device the tunnel is using... */
3945 break;
3946 }
3947
ratheesh kannothcfdcb332015-12-24 07:19:18 +05303948#ifdef ECM_INTERFACE_MAP_T_ENABLE
3949 /*
3950 * MAP-T xlate ?
3951 */
3952 if (dest_dev_type == ARPHRD_NONE) {
3953 if (is_map_t_dev(dest_dev)) {
3954 DEBUG_TRACE("Net device: %p is MAP-T type: %d\n", dest_dev, dest_dev_type);
3955 break;
3956 }
3957 }
3958#endif
3959
Murat Sezgin5dae8832015-12-03 14:23:19 -08003960 /*
3961 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
3962 */
3963 if (dest_dev_type != ARPHRD_PPP) {
3964 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
3965 break;
3966 }
3967
3968#ifndef ECM_INTERFACE_PPP_ENABLE
3969 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
3970#else
3971 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
3972
3973#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05303974 if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08003975 if (skb->skb_iif == dest_dev->ifindex) {
3976 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
3977 break;
3978 }
3979 }
3980#endif
3981
3982#ifdef ECM_INTERFACE_PPTP_ENABLE
3983 if (protocol == IPPROTO_GRE && dest_dev && dest_dev->type == ARPHRD_PPP) {
3984 DEBUG_TRACE("Net device: %p PPP channel is PPTP\n", dest_dev);
3985 break;
3986 }
3987#endif
3988 /*
3989 * PPP - but what is the channel type?
3990 * First: If this is multi-link then we do not support it
3991 */
3992 if (ppp_is_multilink(dest_dev) > 0) {
3993 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
3994 break;
3995 }
3996
3997 /*
3998 * Get the PPP channel and then enquire what kind of channel it is
3999 * NOTE: Not multilink so only one channel to get.
4000 */
4001 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
4002 if (channel_count != 1) {
4003 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
4004 dest_dev, channel_count);
4005 break;
4006 }
4007
4008 /*
4009 * Get channel protocol type
4010 * NOTE: Not all PPP channels support channel specific methods.
4011 */
4012 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
4013
4014#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4015 if (channel_protocol == PX_PROTO_OL2TP) {
4016
4017 /*
4018 * PPPoL2TPV2 channel
4019 */
4020 ppp_release_channels(ppp_chan, 1);
4021 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
4022
4023 /*
4024 * Release the channel. Note that next_dev not held.
4025 */
4026 break;
4027 }
4028#endif
4029#ifdef ECM_INTERFACE_PPPOE_ENABLE
4030 if (channel_protocol == PX_PROTO_OE) {
4031 /*
4032 * PPPoE channel
4033 */
4034 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
4035
4036 /*
4037 * Get PPPoE session information and the underlying device it is using.
4038 */
4039 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
4040
4041 /*
4042 * Copy the dev hold into this, we will release the hold later
4043 */
4044 next_dev = addressing.dev;
4045 next_dest_addr_valid = false;
4046 next_dest_node_addr_valid = true;
4047 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
4048
4049 /*
4050 * Release the channel. Note that next_dev is still (correctly) held.
4051 */
4052 ppp_release_channels(ppp_chan, 1);
4053 break;
4054 }
4055#endif
4056
4057 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
4058 dest_dev, channel_protocol);
4059
4060 /*
4061 * Release the channel
4062 */
4063 ppp_release_channels(ppp_chan, 1);
4064
4065#endif
4066 } while (false);
4067
4068 /*
4069 * No longer need dest_dev as it may become next_dev
4070 */
4071 dev_put(dest_dev);
4072
4073 /*
4074 * Check out the next_dev, if any
4075 */
4076 if (!next_dev) {
4077 int32_t i __attribute__((unused));
4078 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
4079#if DEBUG_LEVEL > 1
4080 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
4081 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
4082 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])));
4083
4084 }
4085#endif
4086
4087 /*
4088 * Release src_dev now
4089 */
4090 dev_put(src_dev);
4091 return current_interface_index;
4092 }
4093
4094 /*
4095 * dest_dev becomes next_dev
4096 */
4097 dest_dev = next_dev;
4098 dest_dev_name = dest_dev->name;
4099 dest_dev_type = dest_dev->type;
4100 }
4101
4102 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
4103 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
4104 dev_put(src_dev);
4105 dev_put(dest_dev);
4106
4107 /*
4108 * Release the interfaces heirarchy we constructed to this point.
4109 */
4110 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4111 return ECM_DB_IFACE_HEIRARCHY_MAX;
4112}
4113EXPORT_SYMBOL(ecm_interface_heirarchy_construct);
4114
4115#ifdef ECM_MULTICAST_ENABLE
4116/*
4117 * ecm_interface_multicast_from_heirarchy_construct()
4118 * Construct an interface heirarchy.
4119 *
4120 * TODO: This function will be removed later and ecm_interface_heirarchy_construct() function
4121 * will be used when the multicast code is fixed to use the new interface hierarchy
4122 * construction model which uses the skb's route information instead of doing
4123 * the route lookup based on the IP addresses.
4124 *
4125 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
4126 * This is the heirarchy of interfaces a packet would transit to emit from the device.
4127 *
4128 * We will use the given src/dest devices when is_routed is false.
4129 * When is_routed is true we will try routing tables first, failing back to any given.
4130 *
4131 * For example, with this network arrangement:
4132 *
4133 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
4134 *
4135 * Given the packet_dest_addr IP address 10.22.33.11 this will create an interface heirarchy (in interracfes[]) of:
4136 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
4137 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
4138 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
4139 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
4140 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
4141 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
4142 *
4143 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
4144 * they will be created and added automatically to the database.
4145 */
4146int32_t ecm_interface_multicast_from_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
4147 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin188b4a32015-06-03 10:58:59 -07004148 ip_addr_t packet_src_addr,
4149 ip_addr_t packet_dest_addr,
4150 int ip_version, int packet_protocol,
4151 struct net_device *given_dest_dev,
4152 bool is_routed, struct net_device *given_src_dev,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05304153 uint8_t *dest_node_addr, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304154 __be16 *layer4hdr, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00004155{
Ben Menchaca84f36632014-02-28 20:57:38 +00004156 int protocol;
4157 ip_addr_t src_addr;
4158 ip_addr_t dest_addr;
Ben Menchaca84f36632014-02-28 20:57:38 +00004159 struct net_device *dest_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00004160 char *dest_dev_name;
Ben Menchaca84f36632014-02-28 20:57:38 +00004161 int32_t dest_dev_type;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004162 struct net_device *src_dev;
4163 char *src_dev_name;
4164 int32_t src_dev_type;
Ben Menchaca84f36632014-02-28 20:57:38 +00004165 int32_t current_interface_index;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004166 bool from_local_addr;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004167 bool next_dest_addr_valid;
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004168 bool next_dest_node_addr_valid = false;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004169 ip_addr_t next_dest_addr;
4170 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004171 struct net_device *bridge;
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004172 uint32_t serial = ecm_db_connection_serial_get(feci->ci);
Ben Menchaca84f36632014-02-28 20:57:38 +00004173
4174 /*
4175 * Get a big endian of the IPv4 address we have been given as our starting point.
4176 */
4177 protocol = packet_protocol;
4178 ECM_IP_ADDR_COPY(src_addr, packet_src_addr);
4179 ECM_IP_ADDR_COPY(dest_addr, packet_dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004180
4181 if (ip_version == 4) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004182 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",
4183 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol,
4184 serial);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004185#ifdef ECM_IPV6_ENABLE
4186 } else if (ip_version == 6) {
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004187 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",
4188 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol,
4189 serial);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004190#endif
4191 } else {
4192 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
4193 return ECM_DB_IFACE_HEIRARCHY_MAX;
4194 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004195
4196 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004197 * Get device to reach the given destination address.
4198 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_dest_dev.
4199 * 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 +00004200 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004201 from_local_addr = false;
4202 if (is_routed) {
4203 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
4204 if (!dest_dev && given_dest_dev) {
4205 /*
4206 * Fall back to any given
4207 */
4208 dest_dev = given_dest_dev;
4209 dev_hold(dest_dev);
Gareth Williams43fc0852014-05-26 19:10:00 +01004210 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004211 } else if (given_dest_dev) {
4212 dest_dev = given_dest_dev;
4213 dev_hold(dest_dev);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304214 } else {
4215 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004216 * Fall back to routed look up
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304217 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004218 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
Gareth Williams43fc0852014-05-26 19:10:00 +01004219 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304220
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004221 /*
4222 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
4223 * then this connection is a tunnel endpoint made to this device.
4224 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
4225 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
4226 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
4227 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
4228 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07004229 if (dest_dev && from_local_addr) {
4230 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
4231 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
4232 dev_put(dest_dev);
4233 dest_dev = given_dest_dev;
4234 if (dest_dev) {
4235 dev_hold(dest_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05304236 if (ip_version == 4) {
4237 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);
4238 } else {
4239 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);
4240 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004241 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304242 }
Gareth Williams43fc0852014-05-26 19:10:00 +01004243 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304244
4245#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4246 /*
4247 * if the address is a local address and indev=l2tp.
4248 */
ratheesh kannothf4801a02016-12-09 22:46:39 +05304249 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 +05304250 dev_put(dest_dev);
4251 dest_dev = given_dest_dev;
4252 if (dest_dev) {
4253 dev_hold(dest_dev);
4254 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);
4255 }
4256 }
4257#endif
4258
Shyam Sunder23f2e542015-09-28 14:56:49 +05304259#ifdef ECM_INTERFACE_PPTP_ENABLE
4260 /*
4261 * if the address is a local address and indev=PPTP.
4262 */
4263 if (protocol == IPPROTO_GRE && given_dest_dev && given_dest_dev->type == ARPHRD_PPP) {
4264 dev_put(dest_dev);
4265 dest_dev = given_dest_dev;
4266 if (dest_dev) {
4267 dev_hold(dest_dev);
4268 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);
4269 }
4270 }
4271#endif
4272
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004273 if (!dest_dev) {
4274 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
4275 return ECM_DB_IFACE_HEIRARCHY_MAX;
4276 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004277 dest_dev_name = dest_dev->name;
4278 dest_dev_type = dest_dev->type;
4279
4280 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004281 * Get device to reach the given source address.
4282 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_src_dev.
4283 * If the heirarchy is NOT for a routed connection we try the given_src_dev first, followed by routed lookup.
4284 */
4285 from_local_addr = false;
4286 if (is_routed) {
4287 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
4288 if (!src_dev && given_src_dev) {
4289 /*
4290 * Fall back to any given
4291 */
4292 src_dev = given_src_dev;
4293 dev_hold(src_dev);
4294 }
4295 } else if (given_src_dev) {
4296 src_dev = given_src_dev;
4297 dev_hold(src_dev);
4298 } else {
4299 /*
4300 * Fall back to routed look up
4301 */
4302 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
4303 }
4304
4305 /*
4306 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
4307 * then this connection is a tunnel endpoint made to this device.
4308 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
4309 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
4310 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
4311 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
4312 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07004313 if (src_dev && from_local_addr) {
4314 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
4315 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
4316 dev_put(src_dev);
4317 src_dev = given_src_dev;
4318 if (src_dev) {
4319 dev_hold(src_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05304320 if (ip_version == 4) {
4321 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);
4322 } else {
4323 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);
4324 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004325 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004326 }
4327 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07004328
ratheesh kannothed721852015-09-28 12:39:52 +05304329#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4330 /*
4331 * if the address is a local address and indev=l2tp.
4332 */
4333 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
4334 if (dest_dev != given_src_dev) {
4335 dev_put(src_dev);
4336 src_dev = given_src_dev;
4337 if (src_dev) {
4338 dev_hold(src_dev);
4339 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);
4340 }
4341 }
4342 }
4343#endif
4344
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004345 if (!src_dev) {
4346 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
4347 dev_put(dest_dev);
4348 return ECM_DB_IFACE_HEIRARCHY_MAX;
4349 }
4350 src_dev_name = src_dev->name;
4351 src_dev_type = src_dev->type;
4352
4353 /*
4354 * Check if source and dest dev are same.
4355 * For the forwarded flows which involve tunnels this will happen when called from input hook.
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304356 */
4357 if (src_dev == dest_dev) {
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004358 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004359 if (((ip_version == 4) && ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)))
4360 || ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304361 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004362 * This happens from the input hook
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304363 * We do not want to create a connection entry for this
Gareth Williams46f4b5f2014-06-01 23:35:23 +01004364 * GGG TODO YES WE DO.
4365 * GGG TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
4366 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
4367 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
4368 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
4369 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
4370 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
4371 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304372 */
4373 dev_put(src_dev);
4374 dev_put(dest_dev);
4375 return ECM_DB_IFACE_HEIRARCHY_MAX;
4376 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004377 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004378
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004379 bridge = ecm_interface_should_update_egress_device_bridged(
4380 given_dest_dev, dest_dev, is_routed);
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004381
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004382 if (bridge) {
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004383 struct net_device *new_dest_dev;
Murat Sezginb9bd5e02016-08-05 14:55:07 -07004384 new_dest_dev = br_port_dev_get(bridge, dest_node_addr, skb, serial);
4385 if (new_dest_dev) {
4386 dev_put(dest_dev);
4387 if (new_dest_dev != given_dest_dev) {
4388 DEBUG_INFO("Adjusted port for %pM is %s (given was %s)\n",
4389 dest_node_addr, new_dest_dev->name,
4390 given_dest_dev->name);
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004391
Murat Sezginb9bd5e02016-08-05 14:55:07 -07004392 dest_dev = new_dest_dev;
4393 dest_dev_name = dest_dev->name;
4394 dest_dev_type = dest_dev->type;
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004395 }
Murat Sezgin3aea6c92015-11-13 13:14:12 -08004396 }
Murat Sezgin70c44cd2016-03-02 11:32:10 -08004397 dev_put(bridge);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304398 }
4399
Murat Sezgin7ef29962015-08-14 10:53:24 -07004400 next_dest_addr_valid = true;
Murat Sezgin5dae8832015-12-03 14:23:19 -08004401 next_dest_node_addr_valid = false;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004402 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
4403
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304404 /*
Ben Menchaca84f36632014-02-28 20:57:38 +00004405 * Iterate until we are done or get to the max number of interfaces we can record.
4406 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
4407 * because we add from the end first_interface grows downwards.
4408 */
4409 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
4410 while (current_interface_index > 0) {
4411 struct ecm_db_iface_instance *ii;
4412 struct net_device *next_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00004413 /*
4414 * Get the ecm db interface instance for the device at hand
4415 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304416 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Ben Menchaca84f36632014-02-28 20:57:38 +00004417
4418 /*
4419 * If the interface could not be established then we abort
4420 */
4421 if (!ii) {
4422 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
4423 dev_put(src_dev);
4424 dev_put(dest_dev);
4425
4426 /*
4427 * Release the interfaces heirarchy we constructed to this point.
4428 */
4429 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4430 return ECM_DB_IFACE_HEIRARCHY_MAX;
4431 }
4432
4433 /*
4434 * Record the interface instance into the interfaces[]
4435 */
4436 current_interface_index--;
4437 interfaces[current_interface_index] = ii;
4438
4439 /*
4440 * Now we have to figure out what the next device will be (in the transmission path) the skb
4441 * will use to emit to the destination address.
4442 */
4443 do {
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08004444#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004445 int channel_count;
4446 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00004447 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304448#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004449 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004450#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304451#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004452
4453 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
4454 next_dev = NULL;
4455
4456 if (dest_dev_type == ARPHRD_ETHER) {
4457 /*
4458 * Ethernet - but what sub type?
4459 */
4460
Gareth Williams141d2382014-11-25 11:35:19 -08004461#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004462 /*
4463 * VLAN?
4464 */
4465 if (is_vlan_dev(dest_dev)) {
4466 /*
4467 * VLAN master
4468 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
4469 */
Shyam Sunder9db20852016-03-09 19:04:49 +05304470 next_dev = ecm_interface_vlan_real_dev(dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004471 dev_hold(next_dev);
4472 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
4473 dest_dev, next_dev, next_dev->name);
4474 break;
4475 }
Gareth Williams141d2382014-11-25 11:35:19 -08004476#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004477
4478 /*
4479 * BRIDGE?
4480 */
4481 if (ecm_front_end_is_bridge_device(dest_dev)) {
4482 /*
4483 * Bridge
4484 * Figure out which port device the skb will go to using the dest_addr.
4485 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004486 uint8_t mac_addr[ETH_ALEN];
Murat Sezgin7ef29962015-08-14 10:53:24 -07004487
4488 if (next_dest_node_addr_valid) {
4489 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
4490 } else if (!next_dest_addr_valid) {
Ben Menchaca84f36632014-02-28 20:57:38 +00004491 dev_put(src_dev);
4492 dev_put(dest_dev);
4493
4494 /*
4495 * Release the interfaces heirarchy we constructed to this point.
4496 */
4497 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4498 return ECM_DB_IFACE_HEIRARCHY_MAX;
Murat Sezgin7ef29962015-08-14 10:53:24 -07004499 } else {
Murat Sezgin5dae8832015-12-03 14:23:19 -08004500 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 -07004501 dev_put(src_dev);
4502 dev_put(dest_dev);
4503
4504 /*
4505 * Release the interfaces heirarchy we constructed to this point.
4506 */
4507 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4508 return ECM_DB_IFACE_HEIRARCHY_MAX;
4509 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004510 }
Murat Sezgin545cf7d2016-03-04 09:48:21 -08004511 next_dev = br_port_dev_get(dest_dev,
4512 mac_addr, skb, serial);
Ben Menchaca84f36632014-02-28 20:57:38 +00004513 if (!next_dev) {
4514 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
4515 dev_put(src_dev);
4516 dev_put(dest_dev);
4517
4518 /*
4519 * Release the interfaces heirarchy we constructed to this point.
4520 */
4521 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4522 return ECM_DB_IFACE_HEIRARCHY_MAX;
4523 }
4524 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
4525 break;
4526 }
Gareth Williams8ac34292015-03-17 14:06:58 +00004527
Murat Sezginb3731e82014-11-26 12:20:59 -08004528#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00004529 /*
4530 * LAG?
4531 */
4532 if (ecm_front_end_is_lag_master(dest_dev)) {
4533 /*
4534 * Link aggregation
Murat Sezginb3731e82014-11-26 12:20:59 -08004535 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
Ben Menchaca84f36632014-02-28 20:57:38 +00004536 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304537 bool dest_on_link = false;
4538 ip_addr_t dest_gw_addr = ECM_IP_ADDR_NULL;
4539 uint32_t src_addr_32 = 0;
4540 uint32_t dest_addr_32 = 0;
Suman Ghoshf14d2172015-07-31 14:38:10 +05304541 struct in6_addr src_addr6;
4542 struct in6_addr dest_addr6;
Ben Menchaca84f36632014-02-28 20:57:38 +00004543 uint8_t src_mac_addr[ETH_ALEN];
4544 uint8_t dest_mac_addr[ETH_ALEN];
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304545 struct net_device *master_dev = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00004546
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304547 memset(src_mac_addr, 0, ETH_ALEN);
4548 memset(dest_mac_addr, 0, ETH_ALEN);
Ben Menchaca84f36632014-02-28 20:57:38 +00004549
Gareth Williams341df382015-07-20 16:44:17 +01004550 if (ip_version == 4) {
4551 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
4552 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
4553 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304554
4555 if (!is_routed) {
4556 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
4557 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
4558 } else {
Murat Sezginb3731e82014-11-26 12:20:59 -08004559 struct net_device *dest_dev_master;
4560
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304561 /*
4562 * Use appropriate source MAC address for routed packets
4563 */
Murat Sezginb3731e82014-11-26 12:20:59 -08004564 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
4565 if (dest_dev_master) {
4566 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304567 } else {
4568 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
4569 }
4570
4571 /*
4572 * Determine destination MAC address for this routed packet
4573 */
Tushar Mathur78b5f432015-09-18 20:13:31 +05304574 if (next_dest_node_addr_valid) {
4575 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
4576 } else if (!next_dest_addr_valid) {
4577 dev_put(src_dev);
4578 dev_put(dest_dev);
Murat Sezginb3731e82014-11-26 12:20:59 -08004579 if (dest_dev_master) {
4580 dev_put(dest_dev_master);
4581 }
4582
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304583 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4584 return ECM_DB_IFACE_HEIRARCHY_MAX;
Tushar Mathur78b5f432015-09-18 20:13:31 +05304585 } else {
4586 if (!ecm_interface_mac_addr_get(dest_addr, dest_mac_addr,
4587 &dest_on_link, dest_gw_addr)) {
4588
4589 /*
4590 * Find proper interfce from which to issue ARP
4591 * or neighbour solicitation packet.
4592 */
4593 if (dest_dev_master) {
4594 master_dev = dest_dev_master;
4595 } else {
4596 master_dev = dest_dev;
4597 }
4598
4599 dev_hold(master_dev);
4600
4601 if (dest_dev_master) {
4602 dev_put(dest_dev_master);
4603 }
4604
4605 if (ip_version == 4) {
4606 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
4607 ecm_interface_send_arp_request(dest_dev, dest_addr, dest_on_link, dest_gw_addr);
4608 }
4609#ifdef ECM_IPV6_ENABLE
4610 if (ip_version == 6) {
Murat Sezgin5dae8832015-12-03 14:23:19 -08004611 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 +05304612 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
4613 }
4614#endif
4615 dev_put(src_dev);
4616 dev_put(dest_dev);
4617 dev_put(master_dev);
4618 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4619 return ECM_DB_IFACE_HEIRARCHY_MAX;
4620 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304621 }
Murat Sezginb3731e82014-11-26 12:20:59 -08004622
4623 if (dest_dev_master) {
4624 dev_put(dest_dev_master);
4625 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05304626 }
4627
Murat Sezgin188b4a32015-06-03 10:58:59 -07004628 if (ip_version == 4) {
4629 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
4630 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05304631 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004632 } else if (ip_version == 6) {
Suman Ghoshf14d2172015-07-31 14:38:10 +05304633 ECM_IP_ADDR_TO_NIN6_ADDR(src_addr6, src_addr);
4634 ECM_IP_ADDR_TO_NIN6_ADDR(dest_addr6, dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004635 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
Suman Ghoshf14d2172015-07-31 14:38:10 +05304636 src_addr6.s6_addr, dest_addr6.s6_addr,
Shyam Sundere60540c2016-04-29 15:06:35 +05304637 htons((uint16_t)ETH_P_IPV6), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07004638 }
4639
Tushar Mathur933907c2014-06-24 17:06:14 +05304640 if (next_dev && netif_carrier_ok(next_dev)) {
Ben Menchaca84f36632014-02-28 20:57:38 +00004641 dev_hold(next_dev);
4642 } else {
4643 DEBUG_WARN("Unable to obtain LAG output slave device\n");
4644 dev_put(src_dev);
4645 dev_put(dest_dev);
4646
4647 /*
4648 * Release the interfaces heirarchy we constructed to this point.
4649 */
4650 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4651 return ECM_DB_IFACE_HEIRARCHY_MAX;
4652 }
4653
4654 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 +00004655 break;
4656 }
Murat Sezginb3731e82014-11-26 12:20:59 -08004657#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004658
4659 /*
4660 * ETHERNET!
4661 * Just plain ethernet it seems.
4662 */
4663 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
4664 break;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05304665 }
Ben Menchaca84f36632014-02-28 20:57:38 +00004666
4667 /*
4668 * LOOPBACK?
4669 */
4670 if (dest_dev_type == ARPHRD_LOOPBACK) {
4671 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
4672 break;
4673 }
4674
4675 /*
4676 * IPSEC?
4677 */
4678 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
4679 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004680 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004681 break;
4682 }
4683
4684 /*
4685 * SIT (6-in-4)?
4686 */
4687 if (dest_dev_type == ARPHRD_SIT) {
4688 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 -08004689 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004690 break;
4691 }
4692
4693 /*
4694 * IPIP6 Tunnel?
4695 */
4696 if (dest_dev_type == ARPHRD_TUNNEL6) {
4697 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
Murat Sezgin5dae8832015-12-03 14:23:19 -08004698 /* TODO Figure out the next device the tunnel is using... */
Ben Menchaca84f36632014-02-28 20:57:38 +00004699 break;
4700 }
4701
4702 /*
4703 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
4704 */
4705 if (dest_dev_type != ARPHRD_PPP) {
4706 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
4707 break;
4708 }
4709
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08004710#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004711 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
4712#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304713 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
4714
4715#ifdef ECM_INTERFACE_L2TPV2_ENABLE
ratheesh kannothf4801a02016-12-09 22:46:39 +05304716 if ((given_src_dev->priv_flags & IFF_PPP_L2TPV2) && ppp_is_xmit_locked(given_src_dev)) {
ratheesh kannothed721852015-09-28 12:39:52 +05304717 if (skb->skb_iif == dest_dev->ifindex) {
4718 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
4719 break;
4720 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304721 }
4722#endif
Shyam Sunder23f2e542015-09-28 14:56:49 +05304723
4724#ifdef ECM_INTERFACE_PPTP_ENABLE
4725 if (protocol == IPPROTO_GRE && dest_dev && dest_dev->type == ARPHRD_PPP) {
4726 DEBUG_TRACE("Net device: %p PPP channel is PPTP\n", dest_dev);
4727 break;
4728 }
4729#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004730 /*
4731 * PPP - but what is the channel type?
4732 * First: If this is multi-link then we do not support it
4733 */
4734 if (ppp_is_multilink(dest_dev) > 0) {
4735 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
4736 break;
4737 }
4738
Ben Menchaca84f36632014-02-28 20:57:38 +00004739 /*
4740 * Get the PPP channel and then enquire what kind of channel it is
4741 * NOTE: Not multilink so only one channel to get.
4742 */
4743 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
4744 if (channel_count != 1) {
4745 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
4746 dest_dev, channel_count);
4747 break;
4748 }
4749
4750 /*
4751 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01004752 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00004753 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01004754 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304755
4756#ifdef ECM_INTERFACE_L2TPV2_ENABLE
4757 if (channel_protocol == PX_PROTO_OL2TP) {
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05304758
Ben Menchaca84f36632014-02-28 20:57:38 +00004759 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304760 * PPPoL2TPV2 channel
Ben Menchaca84f36632014-02-28 20:57:38 +00004761 */
4762 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304763 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004764
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304765 /*
4766 * Release the channel. Note that next_dev not held.
4767 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004768 break;
4769 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304770#endif
4771#ifdef ECM_INTERFACE_PPPOE_ENABLE
4772 if (channel_protocol == PX_PROTO_OE) {
4773 /*
4774 * PPPoE channel
4775 */
4776 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
4777
4778 /*
4779 * Get PPPoE session information and the underlying device it is using.
4780 */
4781 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
4782
4783 /*
4784 * Copy the dev hold into this, we will release the hold later
4785 */
4786 next_dev = addressing.dev;
4787 next_dest_addr_valid = false;
4788 next_dest_node_addr_valid = true;
4789 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
4790
4791 /*
4792 * Release the channel. Note that next_dev is still (correctly) held.
4793 */
4794 ppp_release_channels(ppp_chan, 1);
4795 break;
4796 }
4797#endif
4798
4799 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
4800 dest_dev, channel_protocol);
Ben Menchaca84f36632014-02-28 20:57:38 +00004801
4802 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304803 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00004804 */
4805 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304806
Gareth Williamsc5b9d712014-05-09 20:40:07 +01004807#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004808 } while (false);
4809
4810 /*
Gareth Williamsa11d4352014-05-14 18:25:49 +01004811 * No longer need dest_dev as it may become next_dev
Ben Menchaca84f36632014-02-28 20:57:38 +00004812 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004813 dev_put(dest_dev);
4814
4815 /*
4816 * Check out the next_dev, if any
4817 */
4818 if (!next_dev) {
4819 int32_t i __attribute__((unused));
4820 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
4821#if DEBUG_LEVEL > 1
4822 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
4823 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
4824 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 +05304825
Ben Menchaca84f36632014-02-28 20:57:38 +00004826 }
4827#endif
Gareth Williamsa11d4352014-05-14 18:25:49 +01004828
4829 /*
4830 * Release src_dev now
4831 */
4832 dev_put(src_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00004833 return current_interface_index;
4834 }
4835
Gareth Williamsa11d4352014-05-14 18:25:49 +01004836 /*
4837 * dest_dev becomes next_dev
4838 */
Ben Menchaca84f36632014-02-28 20:57:38 +00004839 dest_dev = next_dev;
4840 dest_dev_name = dest_dev->name;
4841 dest_dev_type = dest_dev->type;
4842 }
4843
4844 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
4845 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
4846 dev_put(src_dev);
4847 dev_put(dest_dev);
4848
4849 /*
4850 * Release the interfaces heirarchy we constructed to this point.
4851 */
4852 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
4853 return ECM_DB_IFACE_HEIRARCHY_MAX;
4854}
Murat Sezgin5dae8832015-12-03 14:23:19 -08004855EXPORT_SYMBOL(ecm_interface_multicast_from_heirarchy_construct);
4856#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004857
4858/*
Gareth Williamsadf425f2014-05-26 19:29:02 +01004859 * ecm_interface_list_stats_update()
4860 * Given an interface list, walk the interfaces and update the stats for certain types.
4861 */
4862static 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 +05304863 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 +01004864{
4865 int list_index;
4866
4867 for (list_index = iface_list_first; (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) {
4868 struct ecm_db_iface_instance *ii;
4869 ecm_db_iface_type_t ii_type;
4870 char *ii_name;
4871 struct net_device *dev;
4872
4873 ii = iface_list[list_index];
4874 ii_type = ecm_db_connection_iface_type_get(ii);
4875 ii_name = ecm_db_interface_type_to_string(ii_type);
4876 DEBUG_TRACE("list_index: %d, ii: %p, type: %d (%s)\n", list_index, ii, ii_type, ii_name);
4877
4878 /*
4879 * Locate real device in system
4880 */
4881 dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii));
4882 if (!dev) {
4883 DEBUG_WARN("Could not locate interface\n");
4884 continue;
4885 }
4886 DEBUG_TRACE("found dev: %p (%s)\n", dev, dev->name);
4887
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304888 if (likely(!is_mcast_flow)) {
4889 /*
4890 * Refresh the bridge forward table entry if the port is a bridge port
4891 * Note: A bridge port can be of different interface type, e.g VLAN, ethernet.
4892 * This check, therefore, should be performed for all interface types.
4893 */
4894 if (is_valid_ether_addr(mac_addr) && ecm_front_end_is_bridge_port(dev) && rx_packets) {
4895 DEBUG_TRACE("Update bridge fdb entry for mac: %pM\n", mac_addr);
4896 br_refresh_fdb_entry(dev, mac_addr);
4897 }
Selin Dag1af781a2014-06-10 10:37:54 -07004898 }
4899
Gareth Williamsadf425f2014-05-26 19:29:02 +01004900 switch (ii_type) {
4901 struct rtnl_link_stats64 stats;
4902
Gareth Williams141d2382014-11-25 11:35:19 -08004903#ifdef ECM_INTERFACE_VLAN_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +01004904 case ECM_DB_IFACE_TYPE_VLAN:
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05304905 DEBUG_INFO("VLAN\n");
Gareth Williamsadf425f2014-05-26 19:29:02 +01004906 stats.rx_packets = rx_packets;
4907 stats.rx_bytes = rx_bytes;
4908 stats.tx_packets = tx_packets;
4909 stats.tx_bytes = tx_bytes;
4910 __vlan_dev_update_accel_stats(dev, &stats);
4911 break;
Gareth Williams141d2382014-11-25 11:35:19 -08004912#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01004913 case ECM_DB_IFACE_TYPE_BRIDGE:
4914 DEBUG_INFO("BRIDGE\n");
4915 stats.rx_packets = rx_packets;
4916 stats.rx_bytes = rx_bytes;
4917 stats.tx_packets = tx_packets;
4918 stats.tx_bytes = tx_bytes;
4919 br_dev_update_stats(dev, &stats);
Gareth Williamsadf425f2014-05-26 19:29:02 +01004920 break;
Murat Sezgina683edd2015-01-20 10:48:30 -08004921
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304922#ifdef ECM_INTERFACE_PPPOE_ENABLE
Murat Sezgina683edd2015-01-20 10:48:30 -08004923 case ECM_DB_IFACE_TYPE_PPPOE:
4924 DEBUG_INFO("PPPOE\n");
ratheesh kannothb1b753a2015-09-28 11:17:35 +05304925 ppp_update_stats(dev, rx_packets, rx_bytes, tx_packets, tx_bytes, 0, 0, 0, 0);
Murat Sezgina683edd2015-01-20 10:48:30 -08004926 break;
4927#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01004928 default:
4929 /*
4930 * TODO: Extend it accordingly
4931 */
4932 break;
4933 }
4934
4935 dev_put(dev);
4936 }
4937}
4938
4939/*
4940 * ecm_interface_stats_update()
4941 * Using the interface lists for the given connection, update the interface statistics for each.
4942 *
4943 * 'from' here is wrt the connection 'from' side. Likewise with 'to'.
4944 * TX is wrt what the interface has transmitted. RX is what the interface has received.
4945 */
4946void ecm_interface_stats_update(struct ecm_db_connection_instance *ci,
4947 uint32_t from_tx_packets, uint32_t from_tx_bytes, uint32_t from_rx_packets, uint32_t from_rx_bytes,
4948 uint32_t to_tx_packets, uint32_t to_tx_bytes, uint32_t to_rx_packets, uint32_t to_rx_bytes)
4949{
4950 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
4951 struct ecm_db_iface_instance *to_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
4952 int from_ifaces_first;
4953 int to_ifaces_first;
4954 uint8_t mac_addr[ETH_ALEN];
4955
4956 /*
4957 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
4958 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
4959 * from_rx_packets / bytes: the amount received by the 'from' interface
4960 */
4961 DEBUG_INFO("%p: Update from interface stats\n", ci);
4962 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
4963 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304964 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 +01004965 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
4966
4967 /*
4968 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
4969 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
4970 * to_rx_packets / bytes: the amount received by the 'to' interface
4971 */
4972 DEBUG_INFO("%p: Update to interface stats\n", ci);
4973 to_ifaces_first = ecm_db_connection_to_interfaces_get_and_ref(ci, to_ifaces);
4974 ecm_db_connection_to_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304975 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 +01004976 ecm_db_connection_interfaces_deref(to_ifaces, to_ifaces_first);
4977}
4978EXPORT_SYMBOL(ecm_interface_stats_update);
4979
Shyam Sunder6358b862015-05-04 15:06:24 +05304980#ifdef ECM_MULTICAST_ENABLE
4981/*
Shyam Sunder6358b862015-05-04 15:06:24 +05304982 * ecm_interface_multicast_stats_update()
4983 * Using the interface lists for the given connection, update the interface statistics for each.
4984 *
4985 * 'from interface' here is the connection 'from' side. Likewise with 'to interface'.
4986 * TX is wrt what the interface has transmitted. RX is what the interface has received.
4987 */
4988void ecm_interface_multicast_stats_update(struct ecm_db_connection_instance *ci, uint32_t from_tx_packets, uint32_t from_tx_bytes,
4989 uint32_t from_rx_packets, uint32_t from_rx_bytes, uint32_t to_tx_packets, uint32_t to_tx_bytes,
4990 uint32_t to_rx_packets, uint32_t to_rx_bytes)
4991{
4992 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05304993 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunder6358b862015-05-04 15:06:24 +05304994 struct ecm_db_iface_instance *to_ifaces;
4995 struct ecm_db_iface_instance *ii_temp;
4996 int from_ifaces_first;
4997 int *to_ifaces_first;
4998 int if_index;
4999 int ret;
5000 uint8_t mac_addr[ETH_ALEN];
5001
5002 /*
5003 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
5004 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
5005 * from_rx_packets / bytes: the amount received by the 'from' interface
5006 */
5007 DEBUG_INFO("%p: Update from interface stats\n", ci);
5008 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
5009 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05305010 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 +05305011 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
5012
5013 /*
5014 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
5015 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
5016 * to_rx_packets / bytes: the amount received by the 'to' interface
5017 */
5018 DEBUG_INFO("%p: Update to interface stats\n", ci);
5019
5020 /*
5021 * This function allocates the memory for temporary destination interface heirarchies.
5022 * This memory needs to be free at the end.
5023 */
5024 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &to_ifaces, &to_ifaces_first);
5025 if (ret == 0) {
5026 DEBUG_WARN("%p: Get and ref to all multicast detination interface heirarchies failed\n", ci);
5027 return;
5028 }
5029
5030 for (if_index = 0; if_index < ECM_DB_MULTICAST_IF_MAX; if_index++) {
5031 if (to_ifaces_first[if_index] < ECM_DB_IFACE_HEIRARCHY_MAX) {
5032 ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, if_index);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05305033 ecm_db_multicast_copy_if_heirarchy(to_list_single, ii_temp);
5034 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 +05305035 }
5036 }
5037
5038 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
5039}
5040EXPORT_SYMBOL(ecm_interface_multicast_stats_update);
5041#endif
5042
Gareth Williamsadf425f2014-05-26 19:29:02 +01005043/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005044 * ecm_interface_regenerate_connections()
5045 * Cause regeneration of all connections that are using the specified interface.
5046 */
5047static void ecm_interface_regenerate_connections(struct ecm_db_iface_instance *ii)
5048{
Gareth Williamsb5903892015-03-20 15:13:07 +00005049#ifdef ECM_DB_XREF_ENABLE
Gareth Williamsa4390962015-08-26 12:51:31 +01005050 struct ecm_db_connection_instance *ci_from;
5051 struct ecm_db_connection_instance *ci_to;
5052 struct ecm_db_connection_instance *ci_from_nat;
5053 struct ecm_db_connection_instance *ci_to_nat;
5054 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
Gareth Williamsb5903892015-03-20 15:13:07 +00005055#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005056
5057 DEBUG_TRACE("Regenerate connections using interface: %p\n", ii);
5058
Gareth Williamsb5903892015-03-20 15:13:07 +00005059#ifndef ECM_DB_XREF_ENABLE
5060 /*
5061 * An interface has changed, re-generate the connections to ensure all state is updated.
5062 */
Tushar Mathurd38cacd2015-07-28 12:19:10 +05305063 ecm_db_regeneration_needed();
Gareth Williamsb5903892015-03-20 15:13:07 +00005064#else
Ben Menchaca84f36632014-02-28 20:57:38 +00005065 /*
Gareth Williamsa4390962015-08-26 12:51:31 +01005066 * If the interface has NO connections then we re-generate all.
5067 */
5068 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
5069 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
5070 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
5071 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
5072 if (!ci_from && !ci_to && !ci_from_nat && !ci_to_nat) {
5073 ecm_db_regeneration_needed();
5074 DEBUG_TRACE("%p: Regenerate (ALL) COMPLETE\n", ii);
5075 return;
5076 }
5077
5078 /*
5079 * Re-generate all connections associated with this interface
Ben Menchaca84f36632014-02-28 20:57:38 +00005080 */
5081 DEBUG_TRACE("%p: Regenerate 'from' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005082 while (ci_from) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005083 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005084 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
Ben Menchaca84f36632014-02-28 20:57:38 +00005085
Gareth Williamsa4390962015-08-26 12:51:31 +01005086 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005087 ecm_db_connection_regenerate(ci_from);
Gareth Williamsa4390962015-08-26 12:51:31 +01005088 ecm_db_connection_deref(ci_from);
5089 ci_from = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005090 }
5091
5092 DEBUG_TRACE("%p: Regenerate 'to' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005093 while (ci_to) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005094 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005095 cin = ecm_db_connection_iface_to_get_and_ref_next(ci_to);
Ben Menchaca84f36632014-02-28 20:57:38 +00005096
Gareth Williamsa4390962015-08-26 12:51:31 +01005097 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005098 ecm_db_connection_regenerate(ci_to);
Gareth Williamsa4390962015-08-26 12:51:31 +01005099 ecm_db_connection_deref(ci_to);
5100 ci_to = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005101 }
5102
Gareth Williamsa4390962015-08-26 12:51:31 +01005103 /*
5104 * GGG TODO These deprecated lists _nat_ lists will eventually be removed
5105 */
Ben Menchaca84f36632014-02-28 20:57:38 +00005106 DEBUG_TRACE("%p: Regenerate 'from_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005107 while (ci_from_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005108 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005109 cin = ecm_db_connection_iface_nat_from_get_and_ref_next(ci_from_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00005110
Gareth Williamsa4390962015-08-26 12:51:31 +01005111 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005112 ecm_db_connection_regenerate(ci_from_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01005113 ecm_db_connection_deref(ci_from_nat);
5114 ci_from_nat = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005115 }
5116
5117 DEBUG_TRACE("%p: Regenerate 'to_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01005118 while (ci_to_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00005119 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01005120 cin = ecm_db_connection_iface_nat_to_get_and_ref_next(ci_to_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00005121
Gareth Williamsa4390962015-08-26 12:51:31 +01005122 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005123 ecm_db_connection_regenerate(ci_to_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01005124 ecm_db_connection_deref(ci_to_nat);
5125 ci_to_nat = cin;
5126 }
5127
5128#ifdef ECM_MULTICAST_ENABLE
5129 /*
5130 * Multicasts would not have recorded in the lists above.
5131 * Our only way to re-gen those is to iterate all multicasts.
5132 * GGG TODO This will be optimised in a future release.
5133 */
5134 ci_mcast = ecm_db_connections_get_and_ref_first();
5135 while (ci_mcast) {
5136 struct ecm_db_connection_instance *cin;
5137
5138 /*
5139 * Multicast and NOT flagged for re-gen?
5140 */
5141 if (ecm_db_multicast_connection_to_interfaces_set_check(ci_mcast)
5142 && ecm_db_connection_regeneration_required_peek(ci_mcast)) {
Xiaoping Faned6d37e2015-09-17 14:13:47 -07005143 ecm_db_connection_regenerate(ci_mcast);
Gareth Williamsa4390962015-08-26 12:51:31 +01005144 }
5145
5146 cin = ecm_db_connection_get_and_ref_next(ci_mcast);
5147 ecm_db_connection_deref(ci_mcast);
5148 ci_mcast = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00005149 }
Gareth Williamsb5903892015-03-20 15:13:07 +00005150#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005151
Gareth Williamsa4390962015-08-26 12:51:31 +01005152#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00005153 DEBUG_TRACE("%p: Regenerate COMPLETE\n", ii);
5154}
5155
5156/*
5157 * ecm_interface_dev_regenerate_connections()
5158 * Cause regeneration of all connections that are using the specified interface.
5159 */
Tushar Mathurcccbf282015-01-13 01:22:44 +05305160void ecm_interface_dev_regenerate_connections(struct net_device *dev)
Ben Menchaca84f36632014-02-28 20:57:38 +00005161{
5162 struct ecm_db_iface_instance *ii;
5163
5164 DEBUG_INFO("Regenerate connections for: %p (%s)\n", dev, dev->name);
5165
5166 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07005167 * If the interface is known to us then we will get it returned by this
5168 * function and process it accordingly.
Ben Menchaca84f36632014-02-28 20:57:38 +00005169 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07005170 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00005171 if (!ii) {
5172 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5173 return;
5174 }
5175 ecm_interface_regenerate_connections(ii);
5176 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
5177 ecm_db_iface_deref(ii);
5178}
5179
5180/*
Suman Ghosh7a261712016-01-12 21:42:55 +05305181 * ecm_interface_defunct_connections()
5182 * Cause defunct of all connections that are using the specified interface.
5183 */
5184static void ecm_interface_defunct_connections(struct ecm_db_iface_instance *ii)
5185{
5186#ifndef ECM_DB_XREF_ENABLE
5187 ecm_db_connection_defunct_all();
5188#else
5189 struct ecm_db_connection_instance *ci_from;
5190 struct ecm_db_connection_instance *ci_to;
5191 struct ecm_db_connection_instance *ci_from_nat;
5192 struct ecm_db_connection_instance *ci_to_nat;
5193 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
5194
5195 DEBUG_TRACE("defunct connections using interface: %p\n", ii);
5196
5197 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
5198 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
5199 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
5200 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
5201
5202 /*
Bhaskar Valaboju35d2a8b2018-01-16 18:35:10 +05305203 * Defunct ALL if all the four connection instances are NULL
5204 */
5205 if (!ci_from && !ci_to && !ci_from_nat && !ci_to_nat) {
5206 ecm_db_connection_defunct_all();
5207 DEBUG_TRACE("%p: Defunct (ALL) COMPLETE\n", ii);
5208 return;
5209 }
5210
5211 /*
Suman Ghosh7a261712016-01-12 21:42:55 +05305212 * Defunct all connections associated with this interface
5213 */
5214 DEBUG_TRACE("%p: Defunct 'from' connections\n", ii);
5215 while (ci_from) {
5216 struct ecm_db_connection_instance *cin;
5217 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
5218
5219 DEBUG_TRACE("%p: Defunct: %p", ii, ci_from);
5220 ecm_db_connection_make_defunct(ci_from);
5221 ecm_db_connection_deref(ci_from);
5222 ci_from = cin;
5223 }
5224
5225 DEBUG_TRACE("%p: Defunct 'to' connections\n", ii);
5226 while (ci_to) {
5227 struct ecm_db_connection_instance *cin;
5228 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to);
5229
5230 DEBUG_TRACE("%p: Defunct: %p", ii, ci_to);
5231 ecm_db_connection_make_defunct(ci_to);
5232 ecm_db_connection_deref(ci_to);
5233 ci_to = cin;
5234 }
5235
5236 DEBUG_TRACE("%p: Defunct 'from_nat' connections\n", ii);
5237 while (ci_from_nat) {
5238 struct ecm_db_connection_instance *cin;
5239 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from_nat);
5240
5241 DEBUG_TRACE("%p: Defunct: %p", ii, ci_from_nat);
5242 ecm_db_connection_make_defunct(ci_from_nat);
5243 ecm_db_connection_deref(ci_from_nat);
5244 ci_from_nat = cin;
5245 }
5246
5247 DEBUG_TRACE("%p: Defunct 'to_nat' connections\n", ii);
5248 while (ci_to_nat) {
5249 struct ecm_db_connection_instance *cin;
5250 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_to_nat);
5251
5252 DEBUG_TRACE("%p: Defunct: %p", ii, ci_to_nat);
5253 ecm_db_connection_make_defunct(ci_to_nat);
5254 ecm_db_connection_deref(ci_to_nat);
5255 ci_to_nat = cin;
5256 }
5257#endif
5258 DEBUG_TRACE("%p: Defunct COMPLETE\n", ii);
5259}
5260
5261/*
5262 * ecm_interface_dev_defunct_connections()
5263 * Cause defunct of all connections that are using the specified interface.
5264 */
5265void ecm_interface_dev_defunct_connections(struct net_device *dev)
5266{
5267 struct ecm_db_iface_instance *ii;
5268
5269 DEBUG_INFO("defunct connections for: %p (%s)\n", dev, dev->name);
5270
5271 /*
5272 * If the interface is known to us then we will get it returned by this
5273 * function and process it accordingly.
5274 */
5275 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
5276 if (!ii) {
5277 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5278 return;
5279 }
5280 ecm_interface_defunct_connections(ii);
5281 DEBUG_TRACE("%p: defunct for %p: COMPLETE\n", dev, ii);
5282 ecm_db_iface_deref(ii);
5283}
5284
5285/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005286 * ecm_interface_mtu_change()
5287 * MTU of interface has changed
5288 */
5289static void ecm_interface_mtu_change(struct net_device *dev)
5290{
5291 int mtu;
5292 struct ecm_db_iface_instance *ii;
5293
5294 mtu = dev->mtu;
5295 DEBUG_INFO("%p (%s): MTU Change to: %d\n", dev, dev->name, mtu);
5296
5297 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07005298 * Find the interface for the given device.
Ben Menchaca84f36632014-02-28 20:57:38 +00005299 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07005300 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00005301 if (!ii) {
5302 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
5303 return;
5304 }
5305
5306 /*
5307 * Change the mtu
5308 */
5309 ecm_db_iface_mtu_reset(ii, mtu);
5310 DEBUG_TRACE("%p (%s): MTU Changed to: %d\n", dev, dev->name, mtu);
Tushar Mathurad534d62015-06-10 18:37:52 +05305311 if (netif_is_bond_slave(dev)) {
5312 struct net_device *master = NULL;
5313 master = ecm_interface_get_and_hold_dev_master(dev);
5314 DEBUG_ASSERT(master, "Expected a master\n");
5315 ecm_interface_dev_regenerate_connections(master);
5316 dev_put(master);
5317 } else {
5318 ecm_interface_regenerate_connections(ii);
5319 }
5320
Ben Menchaca84f36632014-02-28 20:57:38 +00005321 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
5322 ecm_db_iface_deref(ii);
5323}
5324
5325/*
5326 * ecm_interface_netdev_notifier_callback()
5327 * Netdevice notifier callback to inform us of change of state of a netdevice
5328 */
5329static int ecm_interface_netdev_notifier_callback(struct notifier_block *this, unsigned long event, void *ptr)
5330{
Stephen Wang69379c32015-02-04 18:37:13 -08005331#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0))
Ben Menchaca84f36632014-02-28 20:57:38 +00005332 struct net_device *dev __attribute__ ((unused)) = (struct net_device *)ptr;
Stephen Wang69379c32015-02-04 18:37:13 -08005333#else
5334 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
5335#endif
Tushar Mathurad534d62015-06-10 18:37:52 +05305336 struct net_device *master = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00005337
5338 DEBUG_INFO("Net device notifier for: %p, name: %s, event: %lx\n", dev, dev->name, event);
5339
5340 switch (event) {
5341 case NETDEV_DOWN:
5342 DEBUG_INFO("Net device: %p, DOWN\n", dev);
Tushar Mathurad534d62015-06-10 18:37:52 +05305343 if (netif_is_bond_slave(dev)) {
5344 master = ecm_interface_get_and_hold_dev_master(dev);
5345 DEBUG_ASSERT(master, "Expected a master\n");
Murat Sezgina52ce612017-11-14 17:08:08 -08005346 ecm_interface_dev_defunct_connections(master);
Tushar Mathurad534d62015-06-10 18:37:52 +05305347 dev_put(master);
5348 } else {
Murat Sezgina52ce612017-11-14 17:08:08 -08005349 ecm_interface_dev_defunct_connections(dev);
Tushar Mathurad534d62015-06-10 18:37:52 +05305350 }
Ben Menchaca84f36632014-02-28 20:57:38 +00005351 break;
5352
5353 case NETDEV_CHANGE:
5354 DEBUG_INFO("Net device: %p, CHANGE\n", dev);
5355 if (!netif_carrier_ok(dev)) {
5356 DEBUG_INFO("Net device: %p, CARRIER BAD\n", dev);
Tushar Mathur933907c2014-06-24 17:06:14 +05305357 if (netif_is_bond_slave(dev)) {
Murat Sezginb3731e82014-11-26 12:20:59 -08005358 master = ecm_interface_get_and_hold_dev_master(dev);
Bhaskar Valaboju5cbdf812018-02-21 09:59:24 +05305359 DEBUG_ASSERT(master, "Expected a master.\n");
5360 ecm_interface_dev_defunct_connections(master);
Murat Sezginb3731e82014-11-26 12:20:59 -08005361 dev_put(master);
Tushar Mathur933907c2014-06-24 17:06:14 +05305362 } else {
Bhaskar Valaboju5cbdf812018-02-21 09:59:24 +05305363 ecm_interface_dev_defunct_connections(dev);
Tushar Mathur933907c2014-06-24 17:06:14 +05305364 }
Ben Menchaca84f36632014-02-28 20:57:38 +00005365 }
5366 break;
5367
5368 case NETDEV_CHANGEMTU:
5369 DEBUG_INFO("Net device: %p, MTU CHANGE\n", dev);
5370 ecm_interface_mtu_change(dev);
5371 break;
5372
5373 default:
5374 DEBUG_TRACE("Net device: %p, UNHANDLED: %lx\n", dev, event);
5375 break;
5376 }
5377
5378 return NOTIFY_DONE;
5379}
5380
5381/*
Murat Sezgin9304d472017-04-14 10:16:52 -07005382 * ecm_interface_node_connections_defunct()
5383 * Defunct the connections on this node.
Murat Sezgina205b042016-07-19 14:18:14 -07005384 */
Murat Sezgin9304d472017-04-14 10:16:52 -07005385void ecm_interface_node_connections_defunct(uint8_t *mac)
Murat Sezgina205b042016-07-19 14:18:14 -07005386{
Murat Sezgina5f3de12016-08-02 17:29:30 -07005387 struct ecm_db_node_instance *ni = NULL;
Murat Sezgina205b042016-07-19 14:18:14 -07005388
5389 if (unlikely(!mac)) {
5390 DEBUG_WARN("mac address is null\n");
5391 return;
5392 }
5393
Murat Sezgina5f3de12016-08-02 17:29:30 -07005394 ni = ecm_db_node_chain_get_and_ref_first(mac);
5395 while (ni) {
5396 struct ecm_db_node_instance *nin;
Murat Sezgina205b042016-07-19 14:18:14 -07005397
Murat Sezgina5f3de12016-08-02 17:29:30 -07005398 if (ecm_db_node_is_mac_addr_equal(ni, mac)) {
Murat Sezgin9304d472017-04-14 10:16:52 -07005399 ecm_db_traverse_node_from_connection_list_and_defunct(ni);
5400 ecm_db_traverse_node_to_connection_list_and_defunct(ni);
5401 ecm_db_traverse_node_from_nat_connection_list_and_defunct(ni);
5402 ecm_db_traverse_node_to_nat_connection_list_and_defunct(ni);
Murat Sezgina5f3de12016-08-02 17:29:30 -07005403 }
5404
5405 /*
5406 * Get next node in the chain
5407 */
5408 nin = ecm_db_node_chain_get_and_ref_next(ni);
5409 ecm_db_node_deref(ni);
5410 ni = nin;
Murat Sezgina205b042016-07-19 14:18:14 -07005411 }
Murat Sezgina205b042016-07-19 14:18:14 -07005412}
Murat Sezgin9304d472017-04-14 10:16:52 -07005413EXPORT_SYMBOL(ecm_interface_node_connections_defunct);
Murat Sezgina205b042016-07-19 14:18:14 -07005414
5415/*
Ben Menchaca84f36632014-02-28 20:57:38 +00005416 * struct notifier_block ecm_interface_netdev_notifier
5417 * Registration for net device changes of state.
5418 */
5419static struct notifier_block ecm_interface_netdev_notifier __read_mostly = {
5420 .notifier_call = ecm_interface_netdev_notifier_callback,
5421};
Murat Sezgina205b042016-07-19 14:18:14 -07005422
Murat Sezgin8c345822015-05-27 15:35:38 -07005423#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
Ben Menchaca84f36632014-02-28 20:57:38 +00005424/*
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305425 * ecm_interfae_node_br_fdb_notify_event()
5426 * This is a call back for "bridge fdb update event/ageing timer expire
5427 * event".
5428 */
5429static int ecm_interface_node_br_fdb_notify_event(struct notifier_block *nb,
5430 unsigned long val,
5431 void *data)
5432{
5433 uint8_t *mac = (uint8_t *)data;
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305434
Murat Sezgin04470032017-07-07 14:53:32 -07005435 if (ECM_FRONT_END_TYPE_NSS == ecm_front_end_type_get()) {
5436 DEBUG_INFO("FDB updated for node %pM\n", mac);
5437 ecm_interface_node_connections_defunct(mac);
5438 }
ratheesh kannoth37e35b02015-03-26 11:25:02 +05305439
5440 return NOTIFY_DONE;
5441}
5442
5443static struct notifier_block ecm_interface_node_br_fdb_update_nb = {
5444 .notifier_call = ecm_interface_node_br_fdb_notify_event,
5445};
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07005446
5447static int ecm_interface_node_br_fdb_delete_event(struct notifier_block *nb,
5448 unsigned long event,
5449 void *ctx)
5450{
5451 struct br_fdb_event *fe = (struct br_fdb_event *)ctx;
5452
5453 if ((event != BR_FDB_EVENT_DEL) || fe->is_local) {
5454 DEBUG_WARN("local fdb or not deleting event, ignore\n");
5455 return NOTIFY_DONE;
5456 }
5457
5458 return ecm_interface_node_br_fdb_notify_event(nb, event, fe->addr);
5459}
5460
5461static struct notifier_block ecm_interface_node_br_fdb_delete_nb = {
5462 .notifier_call = ecm_interface_node_br_fdb_delete_event,
5463};
Murat Sezgin8c345822015-05-27 15:35:38 -07005464#endif
Shyam Sunder6358b862015-05-04 15:06:24 +05305465
5466#ifdef ECM_MULTICAST_ENABLE
5467/*
5468 * ecm_interface_multicast_find_outdated_iface_instances()
5469 *
5470 * Called in the case of Routing/Bridging Multicast update events.
5471 *
5472 * This function takes a list of ifindex for the connection which was received
5473 * from MFC or bridge snooper, compares it against the existing list of interfaces
5474 * in the DB connection, and extracts the list of those interfaces that have left
5475 * the multicast group.
5476 *
5477 * ci A DB connection instance.
5478 * mc_updates Part of return Information. The function will mark the index of those
5479 * interfaces in the DB connection 'to_mcast_interfaces' array that have
5480 * left the group, in the mc_updates->if_leave_idx array. The caller uses this
5481 * information to delete those outdated interface heirarchies from the
5482 * connection.
5483 * is_bridged True if the function called due to bridge multicast snooper update event.
5484 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
5485 * by the update from MFC or Bridge snooper.
5486 * max_to_dev Size of the array 'dst_dev'
5487 *
5488 * Return true if outdated interfaces found
5489 */
5490static bool ecm_interface_multicast_find_outdated_iface_instances(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
5491 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5492{
5493 struct ecm_db_iface_instance *mc_ifaces;
5494 struct ecm_db_iface_instance *ii_temp;
5495 struct ecm_db_iface_instance *ii_single;
5496 struct ecm_db_iface_instance **ifaces;
5497 struct ecm_db_iface_instance *to_iface;
5498 int32_t *to_iface_first;
5499 int32_t *mc_ifaces_first;
5500 uint32_t *dst_if_index;
5501 ecm_db_iface_type_t ii_type;
5502 int32_t heirarchy_index;
5503 int32_t if_index;
5504 int32_t if_cnt = 0;
5505 int found = 0;
5506 int ii;
5507 int ret;
5508 int32_t ifaces_identifier;
5509
5510 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
5511 if (ret == 0) {
5512 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
5513 return false;
5514 }
5515
5516 /*
5517 * Loop through the current interface list in the DB
5518 * connection 'to_mcast_interfaces' array
5519 */
5520 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX; heirarchy_index++) {
5521 found = 0;
5522 to_iface_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5523
5524 /*
5525 * Invalid interface entry, skip
5526 */
5527 if (*to_iface_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5528 continue;
5529 }
5530
5531 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
5532 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ECM_DB_IFACE_HEIRARCHY_MAX - 1);
5533 ifaces = (struct ecm_db_iface_instance **)ii_single;
5534 to_iface = *ifaces;
5535 ii_type = ecm_db_connection_iface_type_get(to_iface);
5536
5537 /*
5538 * If the update was received from bridge snooper, do not consider entries in the
5539 * interface list that are not part of a bridge.
5540 */
5541 if (is_br_snooper && (ii_type != ECM_DB_IFACE_TYPE_BRIDGE)) {
5542 continue;
5543 }
5544
5545 /*
5546 * If the update was received from MFC, do not consider entries in the
5547 * interface list that are part of a bridge. The bridge entries will be
5548 * taken care by the Bridge Snooper Callback
5549 */
5550 if (ii_type == ECM_DB_IFACE_TYPE_BRIDGE) {
5551 if (!is_br_snooper && !(flags & ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG)) {
5552 continue;
5553 }
5554 }
5555
5556 /*
5557 * Try to find a match in the newly received interface list, for any of
5558 * the interface instance in the heirarchy. If found, it means that this
5559 * interface has not left the group. If not found, it means that this
5560 * interface has left the group.
5561 */
5562 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_iface_first; ii--) {
5563 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
5564 ifaces = (struct ecm_db_iface_instance **)ii_single;
5565 to_iface = *ifaces;
5566
5567 ii_type = ecm_db_connection_iface_type_get(to_iface);
5568 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_iface);
5569 for (if_index = 0; if_index < max_to_dev; if_index++) {
5570 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
5571 if (*dst_if_index == ifaces_identifier) {
5572 found = 1;
5573 break;
5574 }
5575 }
5576 if (found) {
5577 break;
5578 }
5579 }
5580
5581 /*
5582 * We did not find a match for the interface in the present list. So mark
5583 * if as one that has left the group.
5584 */
5585 if (!found) {
5586 if_cnt++;
5587 mc_updates->if_leave_idx[heirarchy_index] = 1;
5588 }
5589 }
5590
5591 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
5592 mc_updates->if_leave_cnt = if_cnt;
5593 return (if_cnt > 0);
5594}
5595
5596/*
5597 * ecm_interface_multicast_find_new_iface_instances()
5598 *
5599 * Called in the case of Routing/Bridging Multicast update events.
5600 *
5601 * This function takes a list of ifindex for the connection which was received
5602 * from MFC or bridge snooper, compares it against the existing list of interfaces
5603 * in the DB connection, and extracts the list of the new joinees for the multicast
5604 * group.
5605 *
5606 * ci A DB connection instance.
5607 * mc_updates Part of return Information. The function will mark the index of those
5608 * interfaces in the 'dst_dev' array that have joined the group, in the
5609 * mc_updates->if_join_idx array. The caller uses this information to add the new
5610 * interface heirarchies into the connection.
5611 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
5612 * by the update from MFC or Bridge snooper.
5613 * max_to_dev Size of the array 'dst_dev'
5614 *
5615 * Return true if new joinees found
5616 */
5617static bool ecm_interface_multicast_find_new_iface_instances(struct ecm_db_connection_instance *ci,
5618 struct ecm_multicast_if_update *mc_updates, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5619{
5620 struct ecm_db_iface_instance *mc_ifaces;
5621 struct ecm_db_iface_instance *ii_temp;
5622 struct ecm_db_iface_instance *ii_single;
5623 struct ecm_db_iface_instance **ifaces;
5624 int32_t *mc_ifaces_first;
5625 int32_t *to_list_first;
5626 int32_t heirarchy_index;
5627 int32_t if_index;
5628 int32_t if_cnt = 0;
5629 int found = 0;
5630 int ii;
5631 int ret;
5632 uint32_t *dst_if_index;
5633 int32_t ifaces_identifier;
5634 struct ecm_db_iface_instance *to_list;
5635
5636 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
5637 if (ret == 0) {
5638 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
5639 return false;
5640 }
5641
5642 /*
5643 * Loop through the new interface list 'dst_dev'
5644 */
5645 for (if_index = 0; if_index < max_to_dev; if_index++) {
5646 found = 0;
5647 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
5648 if (*dst_if_index == 0) {
5649 continue;
5650 }
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
5655 /*
5656 * Invalid interface entry, skip
5657 */
5658 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5659 continue;
5660 }
5661
5662 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
5663
5664 /*
5665 * Try to find a match for this ifindex (dst_dev[if_index]), in any of the
5666 * interface instance in the heirarchy. If not found, it means that this
5667 * ifindex has joined the group. If found, it means that this ifindex was
5668 * already part of the list of destination interfaces.
5669 */
5670 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_list_first; ii--) {
5671 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
5672 ifaces = (struct ecm_db_iface_instance **)ii_single;
5673 to_list = *ifaces;
5674 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_list);
5675 if (*dst_if_index == ifaces_identifier) {
5676 found = 1;
5677 break;
5678 }
5679 }
5680
5681 if (found) {
5682 break;
5683 }
5684 }
5685
5686 /*
5687 * We did not find a match for the interface in the present list. So mark
5688 * it as one that has joined the group.
5689 */
5690 if (!found) {
5691
5692 /*
5693 * Store the if index of the new joinee
5694 */
5695 mc_updates->join_dev[if_cnt] = *dst_if_index;
5696
5697 /*
5698 * Identify a new vacant slot in the 'to_mcast_interfaces' to place
5699 * the new interface
5700 */
5701 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
5702 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
5703 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
5704 mc_updates->if_join_idx[heirarchy_index] = 1;
5705 break;
5706 }
5707 }
5708
5709 if_cnt++;
5710 }
5711 }
5712
5713 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
5714 mc_updates->if_join_cnt = if_cnt;
5715
5716 return (if_cnt > 0);
5717}
5718
5719/*
5720 * ecm_interface_multicast_find_updates_to_iface_list()
5721 * Process IGMP/MLD updates either from MFC or bridge snooper. Identity the interfaces
5722 * that have left the group and new interfaces that have joined the group.
5723 *
5724 * The function returns true if there was any update necessary to the current destination
5725 * interface list
5726 */
5727bool ecm_interface_multicast_find_updates_to_iface_list(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
5728 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
5729{
5730 bool join;
5731 bool leave;
5732 /*
5733 * Find destination interfaces that have left the group
5734 */
5735 leave = ecm_interface_multicast_find_outdated_iface_instances(ci, mc_updates, flags, is_br_snooper, mc_dst_if_index, max_to_dev);
5736 /*
5737 * Find new destination interfaces that have joined the group
5738 */
5739 join = ecm_interface_multicast_find_new_iface_instances(ci, mc_updates, mc_dst_if_index, max_to_dev);
5740
5741 return (leave || join);
5742}
5743EXPORT_SYMBOL(ecm_interface_multicast_find_updates_to_iface_list);
5744#endif
5745
Murat Sezgin42a44c22016-05-05 14:06:39 -07005746#ifdef ECM_DB_XREF_ENABLE
5747/*
5748 * ecm_interface_neigh_mac_update_notify_event()
5749 * Neighbour mac address change handler.
5750 */
5751static int ecm_interface_neigh_mac_update_notify_event(struct notifier_block *nb,
5752 unsigned long val,
5753 void *data)
5754{
Murat Sezgin42a44c22016-05-05 14:06:39 -07005755 struct neigh_mac_update *nmu = (struct neigh_mac_update *)data;
5756
5757 /*
5758 * If the old and new mac addresses are equal, do nothing.
5759 * This case shouldn't happen.
5760 */
5761 if (!ecm_mac_addr_equal(nmu->old_mac, nmu->update_mac)) {
5762 DEBUG_TRACE("old and new mac addresses are equal: %pM\n", nmu->old_mac);
5763 return NOTIFY_DONE;
5764 }
5765
5766 /*
5767 * If the old mac is zero, do nothing. When a host joins the arp table first
5768 * time, its old mac comes as zero. We shouldn't handle this case, because
5769 * there is not any connection in ECM db with zero mac.
5770 */
5771 if (is_zero_ether_addr(nmu->old_mac)) {
5772 DEBUG_WARN("old mac is zero\n");
5773 return NOTIFY_DONE;
5774 }
5775
5776 DEBUG_TRACE("old mac: %pM new mac: %pM\n", nmu->old_mac, nmu->update_mac);
5777
Murat Sezgina205b042016-07-19 14:18:14 -07005778 DEBUG_INFO("neigh mac update notify for node %pM\n", nmu->old_mac);
Murat Sezgin9304d472017-04-14 10:16:52 -07005779 ecm_interface_node_connections_defunct((uint8_t *)nmu->old_mac);
Murat Sezgin42a44c22016-05-05 14:06:39 -07005780
5781 return NOTIFY_DONE;
5782}
5783
5784/*
5785 * struct notifier_block ecm_interface_neigh_mac_update_nb
5786 * Registration for neighbour mac address update.
5787 */
5788static struct notifier_block ecm_interface_neigh_mac_update_nb = {
5789 .notifier_call = ecm_interface_neigh_mac_update_notify_event,
5790};
5791#endif
5792
Murat Sezgin1f381852014-11-20 09:51:07 -08005793/*
Murat Sezgina205b042016-07-19 14:18:14 -07005794 * ecm_interface_wifi_event_iwevent
5795 * wireless event handler
5796 */
5797static int ecm_interface_wifi_event_iwevent(int ifindex, unsigned char *buf, size_t len)
5798{
5799 struct iw_event iwe_buf, *iwe = &iwe_buf;
5800 char *pos, *end;
5801
5802 pos = buf;
5803 end = buf + len;
5804 while (pos + IW_EV_LCP_LEN <= end) {
5805
5806 /*
5807 * Copy the base data structure to get iwe->len
5808 */
5809 memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
5810
5811 /*
5812 * Check that len is valid and that we have that much in the buffer.
5813 *
5814 */
5815 if (iwe->len < IW_EV_LCP_LEN) {
5816 return -1;
5817 }
5818
5819 if ((iwe->len > sizeof (struct iw_event)) || (iwe->len + pos) > end) {
5820 return -1;
5821 }
5822
5823 /*
5824 * Do the copy again with the full length.
5825 */
5826 memcpy(&iwe_buf, pos, iwe->len);
5827
5828 if (iwe->cmd == IWEVREGISTERED) {
5829 DEBUG_INFO("STA %pM joining\n", (uint8_t *)iwe->u.addr.sa_data);
5830 } else if (iwe->cmd == IWEVEXPIRED) {
5831 DEBUG_INFO("STA %pM leaving\n", (uint8_t *)iwe->u.addr.sa_data);
Murat Sezgin9304d472017-04-14 10:16:52 -07005832 ecm_interface_node_connections_defunct((uint8_t *)iwe->u.addr.sa_data);
Murat Sezgina205b042016-07-19 14:18:14 -07005833 } else {
5834 DEBUG_INFO("iwe->cmd is %d for STA %pM\n", iwe->cmd, (unsigned char *) iwe->u.addr.sa_data);
5835 }
5836
5837 pos += iwe->len;
5838 }
5839
5840 return 0;
5841}
5842
5843/*
5844 * ecm_interface_wifi_event_newlink
5845 * Link event handler
5846 */
5847static int ecm_interface_wifi_event_newlink(struct ifinfomsg *ifi, unsigned char *buf, size_t len)
5848{
5849 struct rtattr *attr;
5850 int attrlen, rta_len;
5851
5852 DEBUG_TRACE("Event from interface %d\n", ifi->ifi_index);
5853
5854 attrlen = len;
5855 attr = (struct rtattr *) buf;
5856 rta_len = RTA_ALIGN(sizeof(struct rtattr));
5857
5858 while (RTA_OK(attr, attrlen)) {
5859 if (attr->rta_type == IFLA_WIRELESS) {
5860 ecm_interface_wifi_event_iwevent(ifi->ifi_index, ((char *) attr) + rta_len, attr->rta_len - rta_len);
5861 }
5862 attr = RTA_NEXT(attr, attrlen);
5863 }
5864
5865 return 0;
5866}
5867
5868/*
5869 * ecm_interface_wifi_event_handler
5870 * Netlink event handler
5871 */
5872static int ecm_interface_wifi_event_handler(unsigned char *buf, int len)
5873{
5874 struct nlmsghdr *nlh;
5875 struct ifinfomsg *ifi;
5876 int left;
5877
5878 nlh = (struct nlmsghdr *) buf;
5879 left = len;
5880
5881 while (NLMSG_OK(nlh, left)) {
5882 switch (nlh->nlmsg_type) {
5883 case RTM_NEWLINK:
5884 case RTM_DELLINK:
5885 if (NLMSG_PAYLOAD(nlh, 0) < sizeof(struct ifinfomsg)) {
5886 DEBUG_INFO("invalid netlink message\n");
5887 break;
5888 }
5889
5890 ifi = NLMSG_DATA(nlh);
5891 DEBUG_INFO("ifi->ifi_family: %d\n", ifi->ifi_family);
5892 if (ifi->ifi_family != AF_BRIDGE) {
5893 ecm_interface_wifi_event_newlink(ifi, (u8 *)ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
5894 NLMSG_PAYLOAD(nlh, sizeof(struct ifinfomsg)));
5895 }
5896 break;
5897 }
5898
5899 nlh = NLMSG_NEXT(nlh, left);
5900 }
5901
5902 return 0;
5903}
5904
5905/*
5906 * ecm_interface_wifi_event_rx
5907 * Receive netlink message from socket
5908 */
5909static int ecm_interface_wifi_event_rx(struct socket *sock, struct sockaddr_nl *addr, unsigned char *buf, int len)
5910{
5911 struct msghdr msg;
5912 struct iovec iov;
5913 mm_segment_t oldfs;
5914 int size;
5915
5916 iov.iov_base = buf;
5917 iov.iov_len = len;
5918
5919 msg.msg_flags = 0;
5920 msg.msg_name = addr;
5921 msg.msg_namelen = sizeof(struct sockaddr_nl);
5922 msg.msg_control = NULL;
5923 msg.msg_controllen = 0;
5924#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
5925 msg.msg_iov = &iov;
5926 msg.msg_iovlen = 1;
5927#else
5928 iov_iter_init(&msg.msg_iter, READ, &iov, 1, 1);
5929#endif
5930 oldfs = get_fs();
5931 set_fs(KERNEL_DS);
5932 size = sock_recvmsg(sock, &msg, len, msg.msg_flags);
5933 set_fs(oldfs);
5934
5935 return size;
5936}
5937
5938/*
5939 * ecm_interface_wifi_event_thread
5940 */
5941static void ecm_interface_wifi_event_thread(void)
5942{
5943 int err;
5944 int size;
5945 struct sockaddr_nl saddr;
5946 unsigned char buf[512];
5947 int len = sizeof(buf);
5948
5949 allow_signal(SIGKILL|SIGSTOP);
5950 err = sock_create(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE, &__ewn.sock);
5951 if (err < 0) {
5952 DEBUG_ERROR("failed to create sock\n");
5953 goto exit1;
5954 }
5955
Murat Sezginac267642016-11-02 15:55:11 -07005956 memset(&saddr, 0, sizeof(saddr));
Murat Sezgina205b042016-07-19 14:18:14 -07005957 saddr.nl_family = AF_NETLINK;
5958 saddr.nl_groups = RTNLGRP_LINK;
5959 saddr.nl_pid = current->pid;
5960
5961 err = __ewn.sock->ops->bind(__ewn.sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr));
5962 if (err < 0) {
5963 DEBUG_ERROR("failed to bind sock\n");
5964 goto exit2;
5965 }
5966
5967 DEBUG_INFO("ecm_interface_wifi_event thread started\n");
5968 while (!kthread_should_stop()) {
5969 size = ecm_interface_wifi_event_rx(__ewn.sock, &saddr, buf, len);
5970 DEBUG_TRACE("got a netlink msg with len %d\n", size);
5971
5972 if (signal_pending(current))
5973 break;
5974
5975 if (size < 0) {
5976 DEBUG_WARN("netlink rx error\n");
5977 } else {
5978 ecm_interface_wifi_event_handler(buf, size);
5979 }
5980 }
5981
5982 DEBUG_INFO("ecm_interface_wifi_event thread stopped\n");
5983exit2:
5984 sock_release(__ewn.sock);
5985exit1:
5986 __ewn.sock = NULL;
5987
5988 return;
5989}
5990
5991/*
5992 * ecm_interface_wifi_event_start()
5993 */
5994int ecm_interface_wifi_event_start(void)
5995{
5996 if (__ewn.thread) {
5997 return 0;
5998 }
5999
6000 __ewn.thread = kthread_run((void *)ecm_interface_wifi_event_thread, NULL, "ECM_wifi_event");
6001 if (IS_ERR(__ewn.thread)) {
6002 DEBUG_ERROR("Unable to start kernel thread\n");
6003 return -ENOMEM;
6004 }
6005
6006 return 0;
6007}
6008
6009/*
6010 * ecm_interface_wifi_event_stop()
6011 */
6012int ecm_interface_wifi_event_stop(void)
6013{
6014 int err;
6015
6016 if (__ewn.thread == NULL) {
6017 return 0;
6018 }
6019
6020 DEBUG_INFO("kill ecm_interface_wifi_event thread\n");
6021 force_sig(SIGKILL, __ewn.thread);
6022 err = kthread_stop(__ewn.thread);
6023 __ewn.thread = NULL;
6024
6025 return err;
6026}
6027
6028/*
Murat Sezgineebedb92017-11-17 17:14:32 -08006029 * ecm_interface_src_check_handler()
6030 * Source interface check sysctl node handler.
6031 */
6032static int ecm_interface_src_check_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
6033{
6034 int ret;
6035 int current_value;
6036
6037 /*
6038 * Take the current value
6039 */
6040 current_value = ecm_interface_src_check;
6041
6042 /*
6043 * Write the variable with user input
6044 */
6045 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
6046 if (ret || (!write)) {
6047 return ret;
6048 }
6049
6050 if (ECM_FRONT_END_TYPE_NSS != ecm_front_end_type_get()) {
6051 DEBUG_WARN("Source interface check is for NSS only.\n");
6052 return -EINVAL;
6053 }
6054
6055 if ((ecm_interface_src_check != 1) && (ecm_interface_src_check != 0)) {
6056 DEBUG_WARN("Invalid input. Valid values 0/1\n");
6057 ecm_interface_src_check = current_value;
6058 return -EINVAL;
6059 }
6060
6061 return ret;
6062}
6063
6064static struct ctl_table ecm_interface_table[] = {
6065 {
6066 .procname = "src_interface_check",
6067 .data = &ecm_interface_src_check,
6068 .maxlen = sizeof(int),
6069 .mode = 0644,
6070 .proc_handler = &ecm_interface_src_check_handler,
6071 },
6072 { }
6073};
6074
6075static struct ctl_table ecm_interface_root_dir[] = {
6076 {
6077 .procname = "ecm",
6078 .mode = 0555,
6079 .child = ecm_interface_table,
6080 },
6081 { }
6082};
6083
6084static struct ctl_table ecm_interface_root[] = {
6085 {
6086 .procname = "net",
6087 .mode = 0555,
6088 .child = ecm_interface_root_dir,
6089 },
6090 { }
6091};
6092
6093/*
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006094 * ecm_interface_init()
Ben Menchaca84f36632014-02-28 20:57:38 +00006095 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006096int ecm_interface_init(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00006097{
6098 int result;
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006099 DEBUG_INFO("ECM Interface init\n");
Ben Menchaca84f36632014-02-28 20:57:38 +00006100
Murat Sezgineebedb92017-11-17 17:14:32 -08006101 /*
6102 * Register sysctl table.
6103 */
6104 ecm_interface_ctl_table_header = register_sysctl_table(ecm_interface_root);
6105
Ben Menchaca84f36632014-02-28 20:57:38 +00006106 result = register_netdevice_notifier(&ecm_interface_netdev_notifier);
6107 if (result != 0) {
6108 DEBUG_ERROR("Failed to register netdevice notifier %d\n", result);
Murat Sezgineebedb92017-11-17 17:14:32 -08006109 unregister_sysctl_table(ecm_interface_ctl_table_header);
Murat Sezgin908ecb32015-05-10 20:54:36 -07006110 return result;
Ben Menchaca84f36632014-02-28 20:57:38 +00006111 }
Murat Sezgin8c345822015-05-27 15:35:38 -07006112#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05306113 /*
6114 * register for bridge fdb database modificationevents
6115 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05306116 br_fdb_update_register_notify(&ecm_interface_node_br_fdb_update_nb);
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07006117 br_fdb_register_notify(&ecm_interface_node_br_fdb_delete_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07006118#endif
Murat Sezgin42a44c22016-05-05 14:06:39 -07006119#ifdef ECM_DB_XREF_ENABLE
6120 neigh_mac_update_register_notify(&ecm_interface_neigh_mac_update_nb);
6121#endif
Murat Sezgina205b042016-07-19 14:18:14 -07006122 ecm_interface_wifi_event_start();
6123
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006124 return 0;
Ben Menchaca84f36632014-02-28 20:57:38 +00006125}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006126EXPORT_SYMBOL(ecm_interface_init);
Ben Menchaca84f36632014-02-28 20:57:38 +00006127
6128/*
6129 * ecm_interface_exit()
6130 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006131void ecm_interface_exit(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00006132{
6133 DEBUG_INFO("ECM Interface exit\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006134
6135 spin_lock_bh(&ecm_interface_lock);
6136 ecm_interface_terminate_pending = true;
6137 spin_unlock_bh(&ecm_interface_lock);
6138
6139 unregister_netdevice_notifier(&ecm_interface_netdev_notifier);
Murat Sezgin42a44c22016-05-05 14:06:39 -07006140#ifdef ECM_DB_XREF_ENABLE
6141 neigh_mac_update_unregister_notify(&ecm_interface_neigh_mac_update_nb);
6142#endif
6143
Murat Sezgin8c345822015-05-27 15:35:38 -07006144#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05306145 /*
6146 * unregister for bridge fdb update events
6147 */
6148 br_fdb_update_unregister_notify(&ecm_interface_node_br_fdb_update_nb);
Xiaoping Fan8fe3edd2016-06-22 16:03:17 -07006149 br_fdb_unregister_notify(&ecm_interface_node_br_fdb_delete_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07006150#endif
Murat Sezgina205b042016-07-19 14:18:14 -07006151 ecm_interface_wifi_event_stop();
Murat Sezgineebedb92017-11-17 17:14:32 -08006152
6153 /*
6154 * Unregister sysctl table.
6155 */
6156 if (ecm_interface_ctl_table_header) {
6157 unregister_sysctl_table(ecm_interface_ctl_table_header);
6158 }
Ben Menchaca84f36632014-02-28 20:57:38 +00006159}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05006160EXPORT_SYMBOL(ecm_interface_exit);