blob: f61d31d8aa63a408f3f3f5c5c5b1c949a87e0f4a [file] [log] [blame]
Ben Menchaca84f36632014-02-28 20:57:38 +00001/*
2 **************************************************************************
Gareth Williamsd5618a82015-05-20 11:13:32 +01003 * Copyright (c) 2014-2015 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 Sezgin8c345822015-05-27 15:35:38 -070041#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +053042#include <linux/if_bridge.h>
Murat Sezgin8c345822015-05-27 15:35:38 -070043#endif
Ben Menchaca84f36632014-02-28 20:57:38 +000044#include <linux/inetdevice.h>
Murat Sezginc1402562015-03-12 12:32:20 -070045#if defined(ECM_INTERFACE_TUNIPIP6_ENABLE) || defined(ECM_INTERFACE_SIT_ENABLE)
Tushar Mathur39f63f62015-06-19 14:31:14 +053046#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 9, 0))
Ben Menchaca84f36632014-02-28 20:57:38 +000047#include <net/ipip.h>
Tushar Mathur39f63f62015-06-19 14:31:14 +053048#else
49#include <net/ip_tunnels.h>
50#endif
Murat Sezginb3731e82014-11-26 12:20:59 -080051#endif
Ben Menchaca84f36632014-02-28 20:57:38 +000052#include <net/ip6_tunnel.h>
Gareth Williams43fc0852014-05-26 19:10:00 +010053#include <net/addrconf.h>
Ben Menchaca84f36632014-02-28 20:57:38 +000054#include <linux/if_arp.h>
55#include <linux/netfilter_ipv4.h>
56#include <linux/netfilter_bridge.h>
57#include <linux/if_bridge.h>
58#include <net/arp.h>
59#include <net/netfilter/nf_conntrack.h>
60#include <net/netfilter/nf_conntrack_acct.h>
61#include <net/netfilter/nf_conntrack_helper.h>
62#include <net/netfilter/nf_conntrack_l4proto.h>
63#include <net/netfilter/nf_conntrack_l3proto.h>
64#include <net/netfilter/nf_conntrack_zones.h>
65#include <net/netfilter/nf_conntrack_core.h>
66#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
67#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
Gareth Williams141d2382014-11-25 11:35:19 -080068#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +000069#include <linux/../../net/8021q/vlan.h>
70#include <linux/if_vlan.h>
Gareth Williams141d2382014-11-25 11:35:19 -080071#endif
Murat Sezgina683edd2015-01-20 10:48:30 -080072#ifdef ECM_INTERFACE_PPP_ENABLE
73#include <linux/if_pppox.h>
ratheesh kannotha32fdd12015-09-09 08:02:58 +053074#ifdef ECM_INTERFACE_L2TPV2_ENABLE
75#include <linux/l2tp.h>
76#include <linux/../../net/l2tp/l2tp_core.h>
77#endif
Murat Sezgina683edd2015-01-20 10:48:30 -080078#endif
Ben Menchaca84f36632014-02-28 20:57:38 +000079
80/*
81 * Debug output levels
82 * 0 = OFF
83 * 1 = ASSERTS / ERRORS
84 * 2 = 1 + WARN
85 * 3 = 2 + INFO
86 * 4 = 3 + TRACE
87 */
88#define DEBUG_LEVEL ECM_INTERFACE_DEBUG_LEVEL
89
Shyam Sunder6358b862015-05-04 15:06:24 +053090#ifdef ECM_MULTICAST_ENABLE
91#include <mc_ecm.h>
92#endif
93
Ben Menchaca84f36632014-02-28 20:57:38 +000094#include "ecm_types.h"
95#include "ecm_db_types.h"
Gareth Williamsd5618a82015-05-20 11:13:32 +010096#include "ecm_state.h"
Ben Menchaca84f36632014-02-28 20:57:38 +000097#include "ecm_tracker.h"
98#include "ecm_classifier.h"
99#include "ecm_front_end_types.h"
100#include "ecm_tracker_datagram.h"
101#include "ecm_tracker_udp.h"
102#include "ecm_tracker_tcp.h"
103#include "ecm_db.h"
104#include "ecm_interface.h"
105
Gareth Williams8ac34292015-03-17 14:06:58 +0000106#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000107/*
Gareth Williamsadf425f2014-05-26 19:29:02 +0100108 * TODO: Remove once the Linux image and headers get propogated.
109 */
110struct net_device *ipv6_dev_find(struct net *net, struct in6_addr *addr, int strict);
Murat Sezgin49465a42014-11-24 15:37:48 -0800111#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +0100112
113/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000114 * Locking - concurrency control
115 */
Murat Sezgin908ecb32015-05-10 20:54:36 -0700116static DEFINE_SPINLOCK(ecm_interface_lock); /* Protect against SMP access between netfilter, events and private threaded function. */
Ben Menchaca84f36632014-02-28 20:57:38 +0000117
118/*
119 * Management thread control
120 */
121static bool ecm_interface_terminate_pending = false; /* True when the user has signalled we should quit */
Ben Menchaca84f36632014-02-28 20:57:38 +0000122
123/*
Murat Sezginb3731e82014-11-26 12:20:59 -0800124 * ecm_interface_get_and_hold_dev_master()
125 * Returns the master device of a net device if any.
126 */
127struct net_device *ecm_interface_get_and_hold_dev_master(struct net_device *dev)
128{
129 struct net_device *master;
130#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,6,0))
131 rcu_read_lock();
132 master = netdev_master_upper_dev_get_rcu(dev);
133 if (!master) {
134 rcu_read_unlock();
135 return NULL;
136 }
137 dev_hold(master);
138 rcu_read_unlock();
139#else
140 master = dev->master;
141 if (!master) {
142 return NULL;
143 }
144 dev_hold(master);
145#endif
146 return master;
147}
148EXPORT_SYMBOL(ecm_interface_get_and_hold_dev_master);
149
150/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100151 * ecm_interface_dev_find_by_local_addr_ipv4()
152 * Return a hold to the device for the given local IP address. Returns NULL on failure.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100153 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100154static struct net_device *ecm_interface_dev_find_by_local_addr_ipv4(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100155{
156 __be32 be_addr;
157 struct net_device *dev;
158
159 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, addr);
160 dev = ip_dev_find(&init_net, be_addr);
161 return dev;
162}
163
Gareth Williams8ac34292015-03-17 14:06:58 +0000164#ifdef ECM_IPV6_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +0100165/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100166 * ecm_interface_dev_find_by_local_addr_ipv6()
167 * Return a hold to the device for the given local IP address. Returns NULL on failure.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100168 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100169static struct net_device *ecm_interface_dev_find_by_local_addr_ipv6(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100170{
171 struct in6_addr addr6;
172 struct net_device *dev;
173
174 ECM_IP_ADDR_TO_NIN6_ADDR(addr6, addr);
175 dev = (struct net_device *)ipv6_dev_find(&init_net, &addr6, 1);
176 return dev;
177}
Murat Sezgin49465a42014-11-24 15:37:48 -0800178#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +0100179
180/*
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100181 * ecm_interface_dev_find_by_local_addr()
182 * Return the device on which the local address resides.
Gareth Williamsadf425f2014-05-26 19:29:02 +0100183 *
184 * Returns a hold to the device or NULL on failure.
185 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100186struct net_device *ecm_interface_dev_find_by_local_addr(ip_addr_t addr)
Gareth Williamsadf425f2014-05-26 19:29:02 +0100187{
188 char __attribute__((unused)) addr_str[40];
189
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100190 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
Gareth Williamsadf425f2014-05-26 19:29:02 +0100191 DEBUG_TRACE("Locate dev for: %s\n", addr_str);
192
193 if (ECM_IP_ADDR_IS_V4(addr)) {
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100194 return ecm_interface_dev_find_by_local_addr_ipv4(addr);
Gareth Williamsadf425f2014-05-26 19:29:02 +0100195 }
196
Gareth Williams8ac34292015-03-17 14:06:58 +0000197#ifdef ECM_IPV6_ENABLE
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100198 return ecm_interface_dev_find_by_local_addr_ipv6(addr);
Murat Sezgin49465a42014-11-24 15:37:48 -0800199#else
200 return NULL;
201#endif
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100202}
203EXPORT_SYMBOL(ecm_interface_dev_find_by_local_addr);
204
205/*
206 * ecm_interface_dev_find_by_addr()
207 * Return the net device on which the given IP address resides. Returns NULL on faiure.
208 *
209 * NOTE: The device may be the device upon which has a default gateway to reach the address.
210 * from_local_addr is true when the device was found by a local address search.
211 */
212struct net_device *ecm_interface_dev_find_by_addr(ip_addr_t addr, bool *from_local_addr)
213{
214 char __attribute__((unused)) addr_str[40];
215 struct ecm_interface_route ecm_rt;
216 struct net_device *dev;
217 struct dst_entry *dst;
218
219 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
220
221 /*
222 * Is the address a local IP?
223 */
224 DEBUG_TRACE("find net device for address: %s\n", addr_str);
225 dev = ecm_interface_dev_find_by_local_addr(addr);
226 if (dev) {
227 *from_local_addr = true;
228 DEBUG_TRACE("addr: %s is local: %p (%s)\n", addr_str, dev, dev->name);
229 return dev;
230 }
231
232 DEBUG_TRACE("addr: %s is not local\n", addr_str);
233
234 /*
235 * Try a route to the address instead
236 * NOTE: This will locate a route entry in the route destination *cache*.
237 */
238 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
239 DEBUG_WARN("addr: %s - no dev locatable\n", addr_str);
240 return NULL;
241 }
242
243 *from_local_addr = false;
244 dst = ecm_rt.dst;
245 dev = dst->dev;
246 dev_hold(dev);
247 ecm_interface_route_release(&ecm_rt);
248 DEBUG_TRACE("dest_addr: %s uses dev: %p(%s)\n", addr_str, dev, dev->name);
249 return dev;
Gareth Williamsadf425f2014-05-26 19:29:02 +0100250}
251EXPORT_SYMBOL(ecm_interface_dev_find_by_addr);
252
Gareth Williams8ac34292015-03-17 14:06:58 +0000253#ifdef ECM_IPV6_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +0100254/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000255 * ecm_interface_mac_addr_get_ipv6()
256 * Return mac for an IPv6 address
257 *
258 * GGG TODO Need to make sure this also works for local IP addresses too.
259 */
260static bool ecm_interface_mac_addr_get_ipv6(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
261{
262 struct in6_addr daddr;
263 struct ecm_interface_route ecm_rt;
264 struct neighbour *neigh;
265 struct rt6_info *rt;
266 struct dst_entry *dst;
267
268 /*
269 * Get the MAC address that corresponds to IP address given.
270 * We look up the rt6_info entries and, from its neighbour structure, obtain the hardware address.
271 * This means we will also work if the neighbours are routers too.
272 */
273 ECM_IP_ADDR_TO_NIN6_ADDR(daddr, addr);
274 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
Kiran Kumar C. S. K7d178222014-06-27 18:47:29 +0530275 *on_link = false;
Ben Menchaca84f36632014-02-28 20:57:38 +0000276 return false;
277 }
278 DEBUG_ASSERT(!ecm_rt.v4_route, "Did not locate a v6 route!\n");
279
280 /*
281 * Is this destination on link or off-link via a gateway?
282 */
283 rt = ecm_rt.rt.rtv6;
284 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)) {
285 *on_link = false;
286 ECM_NIN6_ADDR_TO_IP_ADDR(gw_addr, rt->rt6i_gateway)
287 } else {
288 *on_link = true;
289 }
290
291 rcu_read_lock();
292 dst = ecm_rt.dst;
Murat Sezgine9b84582015-01-27 17:34:14 -0800293#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000294 neigh = dst_get_neighbour_noref(dst);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700295 if (neigh) {
296 neigh_hold(neigh);
Murat Sezgine9b84582015-01-27 17:34:14 -0800297 }
298#else
299 neigh = dst_neigh_lookup(dst, &daddr);
300#endif
301 if (!neigh) {
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700302 neigh = neigh_lookup(&nd_tbl, &daddr, dst->dev);
303 }
Murat Sezgine9b84582015-01-27 17:34:14 -0800304
Ben Menchaca84f36632014-02-28 20:57:38 +0000305 if (!neigh) {
306 rcu_read_unlock();
307 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700308 DEBUG_WARN("No neigh reference\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000309 return false;
310 }
311 if (!(neigh->nud_state & NUD_VALID)) {
312 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700313 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000314 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700315 DEBUG_WARN("NUD invalid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000316 return false;
317 }
318 if (!neigh->dev) {
319 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700320 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000321 ecm_interface_route_release(&ecm_rt);
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700322 DEBUG_WARN("Neigh dev invalid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000323 return false;
324 }
325
326 /*
327 * If neigh->dev is a loopback then addr is a local address in which case we take the MAC from given device
328 */
329 if (neigh->dev->flags & IFF_LOOPBACK) {
330 // GGG TODO Create an equivalent logic to that for ipv4, maybe need to create an ip6_dev_find()?
331 DEBUG_TRACE("local address " ECM_IP_ADDR_OCTAL_FMT " (found loopback)\n", ECM_IP_ADDR_TO_OCTAL(addr));
332 memset(mac_addr, 0, 6);
333 } else {
334 memcpy(mac_addr, neigh->ha, 6);
335 }
336 rcu_read_unlock();
Murat Sezgindcbcdb52014-05-15 16:06:13 -0700337 neigh_release(neigh);
Ben Menchaca84f36632014-02-28 20:57:38 +0000338 ecm_interface_route_release(&ecm_rt);
339
340 DEBUG_TRACE(ECM_IP_ADDR_OCTAL_FMT " maps to %pM\n", ECM_IP_ADDR_TO_OCTAL(addr), mac_addr);
341 return true;
342}
Murat Sezgin49465a42014-11-24 15:37:48 -0800343#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000344
345/*
346 * ecm_interface_mac_addr_get_ipv4()
347 * Return mac for an IPv4 address
348 */
349static bool ecm_interface_mac_addr_get_ipv4(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
350{
351 struct neighbour *neigh;
352 struct ecm_interface_route ecm_rt;
353 struct rtable *rt;
354 struct dst_entry *dst;
355 __be32 ipv4_addr;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530356
Ben Menchaca84f36632014-02-28 20:57:38 +0000357 /*
358 * Get the MAC address that corresponds to IP address given.
359 * We look up the rtable entries and, from its neighbour structure, obtain the hardware address.
360 * This means we will also work if the neighbours are routers too.
361 * We also locate the MAC if the address is a local host address.
362 */
363 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
364 if (!ecm_interface_find_route_by_addr(addr, &ecm_rt)) {
Kiran Kumar C. S. K7d178222014-06-27 18:47:29 +0530365 *on_link = false;
Ben Menchaca84f36632014-02-28 20:57:38 +0000366 return false;
367 }
368 DEBUG_ASSERT(ecm_rt.v4_route, "Did not locate a v4 route!\n");
Murat Sezginb3731e82014-11-26 12:20:59 -0800369 DEBUG_TRACE("Found route\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000370
371 /*
372 * Is this destination on link or off-link via a gateway?
373 */
374 rt = ecm_rt.rt.rtv4;
Murat Sezginb3731e82014-11-26 12:20:59 -0800375#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000376 if ((rt->rt_dst != rt->rt_gateway) || (rt->rt_flags & RTF_GATEWAY)) {
Murat Sezginb3731e82014-11-26 12:20:59 -0800377#else
378 if (rt->rt_uses_gateway || (rt->rt_flags & RTF_GATEWAY)) {
379#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000380 *on_link = false;
381 ECM_NIN4_ADDR_TO_IP_ADDR(gw_addr, rt->rt_gateway)
382 } else {
383 *on_link = true;
384 }
385
386 /*
387 * Get the neighbour entry for the address
388 */
389 rcu_read_lock();
390 dst = ecm_rt.dst;
Murat Sezginb3731e82014-11-26 12:20:59 -0800391#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
Ben Menchaca84f36632014-02-28 20:57:38 +0000392 neigh = dst_get_neighbour_noref(dst);
393 if (neigh) {
394 neigh_hold(neigh);
Murat Sezginb3731e82014-11-26 12:20:59 -0800395 }
396#else
397 neigh = dst_neigh_lookup(dst, &ipv4_addr);
398#endif
399 if (!neigh) {
Ben Menchaca84f36632014-02-28 20:57:38 +0000400 neigh = neigh_lookup(&arp_tbl, &ipv4_addr, dst->dev);
401 }
402 if (!neigh) {
403 rcu_read_unlock();
404 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800405 DEBUG_WARN("no neigh\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000406 return false;
407 }
408 if (!(neigh->nud_state & NUD_VALID)) {
409 rcu_read_unlock();
410 neigh_release(neigh);
411 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800412 DEBUG_WARN("neigh nud state is not valid\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000413 return false;
414 }
415 if (!neigh->dev) {
416 rcu_read_unlock();
417 neigh_release(neigh);
418 ecm_interface_route_release(&ecm_rt);
Murat Sezginb3731e82014-11-26 12:20:59 -0800419 DEBUG_WARN("neigh has no device\n");
Ben Menchaca84f36632014-02-28 20:57:38 +0000420 return false;
421 }
422
423 /*
424 * If the device is loopback this will be because the address is a local address
425 * In this case locate the device that has this local address and get its mac.
426 */
427 if (neigh->dev->type == ARPHRD_LOOPBACK) {
428 struct net_device *dev;
429
430 DEBUG_TRACE("%pI4 finds loopback device, dev: %p (%s)\n", &ipv4_addr, neigh->dev, neigh->dev->name);
431 rcu_read_unlock();
432 neigh_release(neigh);
433 ecm_interface_route_release(&ecm_rt);
434
435 /*
436 * Lookup the device that has this IP address assigned
437 */
438 dev = ip_dev_find(&init_net, ipv4_addr);
439 if (!dev) {
440 DEBUG_WARN("Unable to locate dev for: %pI4\n", &ipv4_addr);
441 return false;
442 }
443 memcpy(mac_addr, dev->dev_addr, (size_t)dev->addr_len);
444 DEBUG_TRACE("is local addr: %pI4, mac: %pM, dev ifindex: %d, dev: %p (%s), dev_type: %d\n",
445 &ipv4_addr, mac_addr, dev->ifindex, dev, dev->name, dev->type);
446 dev_put(dev);
447 return true;
448 }
449
450 if (!(neigh->dev->flags & IFF_NOARP)) {
451 memcpy(mac_addr, neigh->ha, (size_t)neigh->dev->addr_len);
452 } else {
453 DEBUG_TRACE("non-arp device: %p (%s, type: %d) to reach %pI4\n", neigh->dev, neigh->dev->name, neigh->dev->type, &ipv4_addr);
454 memset(mac_addr, 0, 6);
455 }
456 DEBUG_TRACE("addr: %pI4, mac: %pM, iif: %d, neigh dev ifindex: %d, dev: %p (%s), dev_type: %d\n",
457 &ipv4_addr, mac_addr, rt->rt_iif, neigh->dev->ifindex, neigh->dev, neigh->dev->name, neigh->dev->type);
458
459 rcu_read_unlock();
460 neigh_release(neigh);
461 ecm_interface_route_release(&ecm_rt);
462 return true;
463}
464
465/*
466 * ecm_interface_mac_addr_get()
467 * Return the mac address for the given IP address. Returns false on failure.
468 *
469 * dev is the device on which the addr was sent/received. If addr is a local address then mac shall be the given dev mac.
470 *
471 * GGG TODO Make this function work for IPv6!!!!!!!!!!!!!!
472 */
473bool ecm_interface_mac_addr_get(ip_addr_t addr, uint8_t *mac_addr, bool *on_link, ip_addr_t gw_addr)
474{
475 if (ECM_IP_ADDR_IS_V4(addr)) {
476 return ecm_interface_mac_addr_get_ipv4(addr, mac_addr, on_link, gw_addr);
477 }
478
Gareth Williams8ac34292015-03-17 14:06:58 +0000479#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000480 return ecm_interface_mac_addr_get_ipv6(addr, mac_addr, on_link, gw_addr);
Murat Sezgin49465a42014-11-24 15:37:48 -0800481#else
482 return false;
483#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000484}
485EXPORT_SYMBOL(ecm_interface_mac_addr_get);
486
Shyam Sunder6358b862015-05-04 15:06:24 +0530487#ifdef ECM_MULTICAST_ENABLE
488/*
489 * ecm_interface_multicast_check_for_br_dev()
490 * Find a bridge dev is present or not in an
491 * array of Ifindexs
492 */
493bool ecm_interface_multicast_check_for_br_dev(uint32_t dest_if[], uint8_t max_if)
494{
495 struct net_device *br_dev;
496 int i;
497
498 for (i = 0; i < max_if; i++) {
499 br_dev = dev_get_by_index(&init_net, dest_if[i]);
500 if (!br_dev) {
501 DEBUG_ASSERT(NULL, "expected only valid netdev here\n");
502 continue;
503 }
504
505 if (ecm_front_end_is_bridge_device(br_dev)) {
506 dev_put(br_dev);
507 return true;
508 }
509 dev_put(br_dev);
510 }
511 return false;
512}
513EXPORT_SYMBOL(ecm_interface_multicast_check_for_br_dev);
514#endif
515
Ben Menchaca84f36632014-02-28 20:57:38 +0000516/*
517 * ecm_interface_addr_find_route_by_addr_ipv4()
518 * Return the route for the given IP address. Returns NULL on failure.
519 */
520static bool ecm_interface_find_route_by_addr_ipv4(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
521{
522 __be32 be_addr;
523
524 /*
525 * Get a route to the given IP address, this will allow us to also find the interface
526 * it is using to communicate with that IP address.
527 */
528 ECM_IP_ADDR_TO_NIN4_ADDR(be_addr, addr);
529 ecm_rt->rt.rtv4 = ip_route_output(&init_net, be_addr, 0, 0, 0);
530 if (IS_ERR(ecm_rt->rt.rtv4)) {
531 DEBUG_TRACE("No output route to: %pI4n\n", &be_addr);
532 return false;
533 }
534 DEBUG_TRACE("Output route to: %pI4n is: %p\n", &be_addr, ecm_rt->rt.rtv4);
535 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv4;
536 ecm_rt->v4_route = true;
537 return true;
538}
539
Gareth Williams8ac34292015-03-17 14:06:58 +0000540#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000541/*
542 * ecm_interface_addr_find_route_by_addr_ipv6()
543 * Return the route for the given IP address. Returns NULL on failure.
544 */
545static bool ecm_interface_find_route_by_addr_ipv6(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
546{
547 struct in6_addr naddr;
548
549 ECM_IP_ADDR_TO_NIN6_ADDR(naddr, addr);
550
551 /*
552 * Get a route to the given IP address, this will allow us to also find the interface
553 * it is using to communicate with that IP address.
554 */
555 ecm_rt->rt.rtv6 = rt6_lookup(&init_net, &naddr, NULL, 0, 0);
556 if (!ecm_rt->rt.rtv6) {
557 DEBUG_TRACE("No output route to: " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
558 return NULL;
559 }
560 DEBUG_TRACE("Output route to: " ECM_IP_ADDR_OCTAL_FMT " is: %p\n", ECM_IP_ADDR_TO_OCTAL(addr), ecm_rt->rt.rtv6);
561 ecm_rt->dst = (struct dst_entry *)ecm_rt->rt.rtv6;
562 ecm_rt->v4_route = false;
563 return true;
564}
Murat Sezgin49465a42014-11-24 15:37:48 -0800565#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000566
567/*
568 * ecm_interface_addr_find_route_by_addr()
569 * Return the route (in the given parameter) for the given IP address. Returns false on failure.
570 *
571 * Route is the device on which the addr is reachable, which may be loopback for local addresses.
572 *
573 * Returns true if the route was able to be located. The route must be released using ecm_interface_route_release().
574 */
575bool ecm_interface_find_route_by_addr(ip_addr_t addr, struct ecm_interface_route *ecm_rt)
576{
577 char __attribute__((unused)) addr_str[40];
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530578
Gareth Williams46f4b5f2014-06-01 23:35:23 +0100579 DEBUG_ECM_IP_ADDR_TO_STRING(addr_str, addr);
Ben Menchaca84f36632014-02-28 20:57:38 +0000580 DEBUG_TRACE("Locate route to: %s\n", addr_str);
581
582 if (ECM_IP_ADDR_IS_V4(addr)) {
583 return ecm_interface_find_route_by_addr_ipv4(addr, ecm_rt);
584 }
585
Gareth Williams8ac34292015-03-17 14:06:58 +0000586#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000587 return ecm_interface_find_route_by_addr_ipv6(addr, ecm_rt);
Murat Sezgin49465a42014-11-24 15:37:48 -0800588#else
589 return false;
590#endif
Ben Menchaca84f36632014-02-28 20:57:38 +0000591}
592EXPORT_SYMBOL(ecm_interface_find_route_by_addr);
593
594/*
595 * ecm_interface_route_release()
596 * Release an ecm route
597 */
598void ecm_interface_route_release(struct ecm_interface_route *rt)
599{
600 dst_release(rt->dst);
601}
602EXPORT_SYMBOL(ecm_interface_route_release);
603
Murat Sezgin188b4a32015-06-03 10:58:59 -0700604#ifdef ECM_IPV6_ENABLE
605/*
606 * ecm_interface_send_neighbour_solicitation()
607 * Issue an IPv6 Neighbour soliciation request.
608 */
609void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t addr)
610{
611 struct in6_addr dst_addr, src_addr;
612 struct in6_addr mc_dst_addr;
613 struct rt6_info *rt6i;
614 struct neighbour *neigh;
615 ip_addr_t ecm_mc_dst_addr, ecm_src_addr;
616 struct net *netf = dev_net(dev);
617 int ret;
618
619 char __attribute__((unused)) dst_addr_str[ECM_IP_ADDR_STRING_BUFFER_SIZE];
620 char __attribute__((unused)) mc_dst_addr_str[ECM_IP_ADDR_STRING_BUFFER_SIZE];
621 char __attribute__((unused)) src_addr_str[ECM_IP_ADDR_STRING_BUFFER_SIZE];
622
623 /*
624 * Find source and destination addresses in Linux format. We need
625 * mcast destination address as well.
626 */
627 ECM_IP_ADDR_TO_NIN6_ADDR(dst_addr, addr);
628 addrconf_addr_solict_mult(&dst_addr, &mc_dst_addr);
629 ret = ipv6_dev_get_saddr(netf, dev, &dst_addr, 0, &src_addr);
630
631 /*
632 * IP address in string format for debug
633 */
634 ecm_ip_addr_to_string(dst_addr_str, addr);
635 ECM_NIN6_ADDR_TO_IP_ADDR(ecm_mc_dst_addr, mc_dst_addr);
636 ecm_ip_addr_to_string(mc_dst_addr_str, ecm_mc_dst_addr);
637 ECM_NIN6_ADDR_TO_IP_ADDR(ecm_src_addr, src_addr);
638 ecm_ip_addr_to_string(src_addr_str, ecm_src_addr);
639
640 /*
641 * Find the route entry
642 */
643 rt6i = rt6_lookup(netf, &dst_addr, NULL, 0, 0);
644 if (!rt6i) {
645 DEBUG_TRACE("IPv6 Route lookup failure for destination IPv6 address %s\n", dst_addr_str);
646 return;
647 }
648
649 /*
650 * Find the neighbor entry
651 */
652#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0))
653 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, &dst_addr);
654#else
655 neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr);
656#endif
657 if (neigh == NULL) {
658 DEBUG_TRACE("Neighbour lookup failure for destination IPv6 address %s\n", dst_addr_str);
659 dst_release(&rt6i->dst);
660 return;
661 }
662
663 /*
664 * Issue a Neighbour soliciation request
665 */
666 DEBUG_TRACE("Issue Neighbour solicitation request\n");
667 ndisc_send_ns(dev, neigh, &dst_addr, &mc_dst_addr, &src_addr);
668 neigh_release(neigh);
669 dst_release(&rt6i->dst);
670}
671EXPORT_SYMBOL(ecm_interface_send_neighbour_solicitation);
672#endif
673
674/*
675 * ecm_interface_send_arp_request()
676 * Issue and ARP request.
677 */
678void ecm_interface_send_arp_request(struct net_device *dest_dev, ip_addr_t dest_addr, bool on_link, ip_addr_t gw_addr)
679{
680 /*
681 * Possible ARP does not know the address yet
682 */
683 __be32 ipv4_addr;
684 __be32 src_ip;
685
686 /*
687 * Issue an ARP request for it, select the src_ip from which to issue the request.
688 */
689 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, dest_addr);
690 src_ip = inet_select_addr(dest_dev, ipv4_addr, RT_SCOPE_LINK);
691 if (!src_ip) {
692 DEBUG_TRACE("Failed to lookup IP for %pI4\n", &ipv4_addr);
693 return;
694 }
695
696 /*
697 * If we have a GW for this address, then we have to send ARP request to the GW
698 */
699 if (!on_link && !ECM_IP_ADDR_IS_NULL(gw_addr)) {
700 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, gw_addr);
701 }
702
703 DEBUG_TRACE("Send ARP for %pI4 using src_ip as %pI4\n", &ipv4_addr, &src_ip);
704 arp_send(ARPOP_REQUEST, ETH_P_ARP, ipv4_addr, dest_dev, src_ip, NULL, NULL, NULL);
705
706 return;
707}
708EXPORT_SYMBOL(ecm_interface_send_arp_request);
709
Xiaoping Fanc7735462015-08-09 18:57:26 -0700710/*
711 * ecm_interface_ipv4_neigh_get()
712 * Returns neighbour reference for a given IP address which must be released when you are done with it.
713 *
714 * Returns NULL on fail.
715 */
716struct neighbour *ecm_interface_ipv4_neigh_get(ip_addr_t addr)
717{
718 struct neighbour *neigh;
719 struct rtable *rt;
720 struct dst_entry *dst;
721 __be32 ipv4_addr;
722
723 ECM_IP_ADDR_TO_NIN4_ADDR(ipv4_addr, addr);
724 rt = ip_route_output(&init_net, ipv4_addr, 0, 0, 0);
725 if (IS_ERR(rt)) {
726 return NULL;
727 }
728 dst = (struct dst_entry *)rt;
729 neigh = dst_neigh_lookup(dst, &ipv4_addr);
730 ip_rt_put(rt);
731 return neigh;
732}
733
734#ifdef ECM_IPV6_ENABLE
735/*
736 * ecm_interface_ipv6_neigh_get()
737 * Returns neighbour reference for a given IP address which must be released when you are done with it.
738 *
739 * Returns NULL on fail.
740 */
741struct neighbour *ecm_interface_ipv6_neigh_get(ip_addr_t addr)
742{
743 struct neighbour *neigh;
744 struct rt6_info *rt;
745 struct dst_entry *dst;
746 struct in6_addr ipv6_addr;
747
748 ECM_IP_ADDR_TO_NIN6_ADDR(ipv6_addr, addr);
749 rt = rt6_lookup(&init_net, &ipv6_addr, NULL, 0, 0);
750 if (!rt) {
751 return NULL;
752 }
753 dst = (struct dst_entry *)rt;
754 neigh = dst_neigh_lookup(dst, &ipv6_addr);
755 dst_release(dst);
756 return neigh;
757}
758#endif
759
Xiaoping Fan80e406b2015-01-29 16:15:31 -0800760#ifdef ECM_INTERFACE_PPP_ENABLE
ratheesh kannotha32fdd12015-09-09 08:02:58 +0530761#ifdef ECM_INTERFACE_L2TPV2_ENABLE
762/*
763 * ecm_interface_skip_l2tpv3_pptp()
764 * skip pptp tunnel encapsulated traffic
765 *
766 * ECM does not handle PPTP and l2tpv3,
767 * this function detects packets of that type so they can be skipped over to improve their throughput.
768 */
769bool ecm_interface_skip_l2tpv3_pptp(struct sk_buff *skb, const struct net_device *out)
770{
771 struct ppp_channel *ppp_chan[1];
772 int px_proto;
773 struct net_device *in;
774 bool ret = true;
775 struct sock *sk = NULL;
776 struct l2tp_session *session = NULL;
777 struct l2tp_tunnel *tunnel = NULL;
778 struct ppp_channel *pch = NULL;
779
780 /*
781 * skip first pass of l2tpv3/pptp tunnel encapsulated traffic
782 */
783 if (out->type == ARPHRD_PPP) {
784 if (ppp_hold_channels((struct net_device *)out, ppp_chan, 1) != 1) {
785 return true;
786 }
787
788 px_proto = ppp_channel_get_protocol(ppp_chan[0]);
789
790 /*
791 * Skip packets for PPPoPPTP channel
792 */
793 if (px_proto == PX_PROTO_PPTP) {
794 ppp_release_channels(ppp_chan, 1);
795 return true;
796 }
797
798 /*
799 * Check for PPPoL2TP channel
800 */
801 if (px_proto == PX_PROTO_OL2TP) {
802 pch = ppp_chan[0];
803 sk = pch->private;
804 sock_hold(sk);
805
806 /*
807 * Get L2TP session for this PPP channel
808 */
809 session = (struct l2tp_session *)(sk->sk_user_data);
810 if ((session == NULL) || (session->magic != L2TP_SESSION_MAGIC)) {
811 sock_put(sk);
812 ppp_release_channels(ppp_chan, 1);
813 return true;
814 }
815
816 tunnel = session->tunnel;
817
818 /*
819 * Check L2TP tunnel version
820 */
821 if (tunnel->version == 2) {
822 ret = false;
823 } else {
824 ret = true;
825 }
826
827 sock_put(sk);
828 ppp_release_channels(ppp_chan, 1);
829 return ret;
830 }
831
832 ppp_release_channels(ppp_chan, 1);
833 return false;
834 }
835
836 in = dev_get_by_index(&init_net, skb->skb_iif);
837 if (in && in->type == ARPHRD_PPP) {
838 /*
839 * Skip L2TPv3 IP encapsulated packets
840 */
841 if ((skb->sk) && (skb->sk->sk_protocol == IPPROTO_L2TP)) {
842 dev_put(in);
843 return true;
844 }
845
846 /*
847 * Chack for L2TP UDP encapsulated packets
848 */
849 if ((skb->sk) && (skb->sk->sk_protocol == IPPROTO_UDP)
850 && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
851 /*
852 * Get the L2TP tunnel socket this packet is associated with
853 */
854 sk = skb->sk;
855 tunnel = l2tp_sock_to_tunnel(sk);
856 if (tunnel == NULL) {
857 dev_put(in);
858 return false;
859 }
860
861 if (tunnel->version == 2) {
862 ret = false;
863 } else {
864 ret = true;
865 }
866
867 dev_put(in);
868 sock_put(sk);
869 return ret;
870 }
871
872 /*
873 * Packet is not associated with a L2TP tunnel socket.
874 * Check 'in' netdevice for type of PPPoX channel.
875 */
876 if (ppp_hold_channels((struct net_device *)in, ppp_chan, 1) != 1) {
877 dev_put(in);
878 return true;
879 }
880
881 dev_put(in);
882 px_proto = ppp_channel_get_protocol(ppp_chan[0]);
883
884 /*
885 * Skip packets for PPPoPPTP channel
886 */
887 if (px_proto == PX_PROTO_PPTP) {
888 ppp_release_channels(ppp_chan, 1);
889 return true;
890 }
891
892 /*
893 * Check for PPPoL2TP channel
894 */
895 if (px_proto == PX_PROTO_OL2TP) {
896 pch = ppp_chan[0];
897 sk = pch->private;
898 sock_hold(sk);
899
900 /*
901 * Get L2TP session for this PPP channel
902 */
903 session = (struct l2tp_session *)(sk->sk_user_data);
904 if ((session == NULL) || (session->magic != L2TP_SESSION_MAGIC)) {
905 sock_put(sk);
906 ppp_release_channels(ppp_chan, 1);
907 return true;
908 }
909
910 tunnel = session->tunnel;
911
912 /*
913 * Check L2TP tunnel version
914 */
915 if (tunnel->version == 2) {
916 ret = false;
917 } else {
918 ret = true;
919 }
920
921 sock_put(sk);
922 ppp_release_channels(ppp_chan, 1);
923 return ret;
924 }
925
926 ppp_release_channels(ppp_chan, 1);
927 return false;
928 }
929
930 if (in) {
931 dev_put(in);
932 }
933
934 return false;
935}
936#endif
937
Xiaoping Fan80e406b2015-01-29 16:15:31 -0800938/*
939 * ecm_interface_skip_l2tp_pptp()
940 * skip l2tp/pptp tunnel encapsulated traffic
941 *
942 * ECM does not handle L2TP or PPTP encapsulated packets,
943 * this function detects packets of that type so they can be skipped over to improve their throughput.
944 */
945bool ecm_interface_skip_l2tp_pptp(struct sk_buff *skb, const struct net_device *out)
946{
947 struct ppp_channel *ppp_chan[1];
948 int px_proto;
949
950 /*
951 * skip first pass of l2tp/pptp tunnel encapsulated traffic
952 */
953 if (out->type == ARPHRD_PPP) {
954 if (ppp_hold_channels((struct net_device *)out, ppp_chan, 1) == 1) {
955 px_proto = ppp_channel_get_protocol(ppp_chan[0]);
956 ppp_release_channels(ppp_chan, 1);
957 return ((px_proto == PX_PROTO_OL2TP) || (px_proto == PX_PROTO_PPTP));
958 }
959 }
960
961 /*
962 * skip second pass of l2tp tunnel encapsulated traffic
963 */
964 if (!skb->sk) {
965 return false;
966 }
967
968 if (skb->sk->sk_protocol != IPPROTO_UDP) {
969 return false;
970 }
971
972 if (unlikely(udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
973 return true;
974 }
975
976 return false;
977}
978#endif
979
Gareth Williams141d2382014-11-25 11:35:19 -0800980#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +0000981/*
Ben Menchaca84f36632014-02-28 20:57:38 +0000982 * ecm_interface_vlan_interface_establish()
983 * Returns a reference to a iface of the VLAN type, possibly creating one if necessary.
984 * Returns NULL on failure or a reference to interface.
985 */
986static 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 -0700987 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +0000988{
989 struct ecm_db_iface_instance *nii;
990 struct ecm_db_iface_instance *ii;
991
Murat Sezgin91c5d712015-06-12 15:16:22 -0700992 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",
993 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 +0000994
995 /*
996 * Locate the iface
997 */
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +0530998 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 +0000999 if (ii) {
1000 DEBUG_TRACE("%p: iface established\n", ii);
1001 return ii;
1002 }
1003
1004 /*
1005 * No iface - create one
1006 */
1007 nii = ecm_db_iface_alloc();
1008 if (!nii) {
1009 DEBUG_WARN("Failed to establish iface\n");
1010 return NULL;
1011 }
1012
1013 /*
1014 * Add iface into the database, atomically to avoid races creating the same thing
1015 */
1016 spin_lock_bh(&ecm_interface_lock);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301017 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 +00001018 if (ii) {
1019 spin_unlock_bh(&ecm_interface_lock);
1020 ecm_db_iface_deref(nii);
1021 return ii;
1022 }
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301023 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 -07001024 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001025 spin_unlock_bh(&ecm_interface_lock);
1026
1027 DEBUG_TRACE("%p: vlan iface established\n", nii);
1028 return nii;
1029}
Gareth Williams141d2382014-11-25 11:35:19 -08001030#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001031
1032/*
1033 * ecm_interface_bridge_interface_establish()
1034 * Returns a reference to a iface of the BRIDGE type, possibly creating one if necessary.
1035 * Returns NULL on failure or a reference to interface.
1036 */
1037static 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 -07001038 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001039{
1040 struct ecm_db_iface_instance *nii;
1041 struct ecm_db_iface_instance *ii;
1042
Murat Sezgin91c5d712015-06-12 15:16:22 -07001043 DEBUG_INFO("Establish BRIDGE iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1044 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001045
1046 /*
1047 * Locate the iface
1048 */
1049 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1050 if (ii) {
1051 DEBUG_TRACE("%p: iface established\n", ii);
1052 return ii;
1053 }
1054
1055 /*
1056 * No iface - create one
1057 */
1058 nii = ecm_db_iface_alloc();
1059 if (!nii) {
1060 DEBUG_WARN("Failed to establish iface\n");
1061 return NULL;
1062 }
1063
1064 /*
1065 * Add iface into the database, atomically to avoid races creating the same thing
1066 */
1067 spin_lock_bh(&ecm_interface_lock);
1068 ii = ecm_db_iface_find_and_ref_bridge(type_info->address);
1069 if (ii) {
1070 spin_unlock_bh(&ecm_interface_lock);
1071 ecm_db_iface_deref(nii);
1072 return ii;
1073 }
1074 ecm_db_iface_add_bridge(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001075 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001076 spin_unlock_bh(&ecm_interface_lock);
1077
1078 DEBUG_TRACE("%p: bridge iface established\n", nii);
1079 return nii;
1080}
1081
Murat Sezgin910c9662015-03-11 16:15:06 -07001082#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001083/*
1084 * ecm_interface_lag_interface_establish()
1085 * Returns a reference to a iface of the LAG type, possibly creating one if necessary.
1086 * Returns NULL on failure or a reference to interface.
1087 */
1088static 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 -07001089 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001090{
1091 struct ecm_db_iface_instance *nii;
1092 struct ecm_db_iface_instance *ii;
1093
Murat Sezgin91c5d712015-06-12 15:16:22 -07001094 DEBUG_INFO("Establish LAG iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1095 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001096
1097 /*
1098 * Locate the iface
1099 */
1100 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1101 if (ii) {
1102 DEBUG_TRACE("%p: iface established\n", ii);
1103 return ii;
1104 }
1105
1106 /*
1107 * No iface - create one
1108 */
1109 nii = ecm_db_iface_alloc();
1110 if (!nii) {
1111 DEBUG_WARN("Failed to establish iface\n");
1112 return NULL;
1113 }
1114
1115 /*
1116 * Add iface into the database, atomically to avoid races creating the same thing
1117 */
1118 spin_lock_bh(&ecm_interface_lock);
1119 ii = ecm_db_iface_find_and_ref_lag(type_info->address);
1120 if (ii) {
1121 spin_unlock_bh(&ecm_interface_lock);
1122 ecm_db_iface_deref(nii);
1123 return ii;
1124 }
1125 ecm_db_iface_add_lag(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001126 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001127 spin_unlock_bh(&ecm_interface_lock);
1128
1129 DEBUG_TRACE("%p: lag iface established\n", nii);
1130 return nii;
1131}
Murat Sezgin910c9662015-03-11 16:15:06 -07001132#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001133
1134/*
1135 * ecm_interface_ethernet_interface_establish()
1136 * Returns a reference to a iface of the ETHERNET type, possibly creating one if necessary.
1137 * Returns NULL on failure or a reference to interface.
1138 */
1139static 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 -07001140 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001141{
1142 struct ecm_db_iface_instance *nii;
1143 struct ecm_db_iface_instance *ii;
1144
Murat Sezgin91c5d712015-06-12 15:16:22 -07001145 DEBUG_INFO("Establish ETHERNET iface: %s with address: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1146 dev_name, type_info->address, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001147
1148 /*
1149 * Locate the iface
1150 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301151 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
1152
Ben Menchaca84f36632014-02-28 20:57:38 +00001153 if (ii) {
1154 DEBUG_TRACE("%p: iface established\n", ii);
1155 return ii;
1156 }
1157
1158 /*
1159 * No iface - create one
1160 */
1161 nii = ecm_db_iface_alloc();
1162 if (!nii) {
1163 DEBUG_WARN("Failed to establish iface\n");
1164 return NULL;
1165 }
1166
1167 /*
1168 * Add iface into the database, atomically to avoid races creating the same thing
1169 */
1170 spin_lock_bh(&ecm_interface_lock);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05301171 ii = ecm_db_iface_ifidx_find_and_ref_ethernet(type_info->address, dev_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001172 if (ii) {
1173 spin_unlock_bh(&ecm_interface_lock);
1174 ecm_db_iface_deref(nii);
1175 return ii;
1176 }
1177 ecm_db_iface_add_ethernet(nii, type_info->address, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001178 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001179 spin_unlock_bh(&ecm_interface_lock);
1180
1181 DEBUG_TRACE("%p: ethernet iface established\n", nii);
1182 return nii;
1183}
1184
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301185#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001186/*
1187 * ecm_interface_pppoe_interface_establish()
1188 * Returns a reference to a iface of the PPPoE type, possibly creating one if necessary.
1189 * Returns NULL on failure or a reference to interface.
1190 */
1191static 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 -07001192 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001193{
1194 struct ecm_db_iface_instance *nii;
1195 struct ecm_db_iface_instance *ii;
1196
Murat Sezgin91c5d712015-06-12 15:16:22 -07001197 DEBUG_INFO("Establish PPPoE iface: %s with session id: %u, remote mac: %pM, MTU: %d, if num: %d, accel engine if id: %d\n",
1198 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 +00001199
1200 /*
1201 * Locate the iface
1202 */
1203 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1204 if (ii) {
1205 DEBUG_TRACE("%p: iface established\n", ii);
1206 return ii;
1207 }
1208
1209 /*
1210 * No iface - create one
1211 */
1212 nii = ecm_db_iface_alloc();
1213 if (!nii) {
1214 DEBUG_WARN("Failed to establish iface\n");
1215 return NULL;
1216 }
1217
1218 /*
1219 * Add iface into the database, atomically to avoid races creating the same thing
1220 */
1221 spin_lock_bh(&ecm_interface_lock);
1222 ii = ecm_db_iface_find_and_ref_pppoe(type_info->pppoe_session_id, type_info->remote_mac);
1223 if (ii) {
1224 spin_unlock_bh(&ecm_interface_lock);
1225 ecm_db_iface_deref(nii);
1226 return ii;
1227 }
1228 ecm_db_iface_add_pppoe(nii, type_info->pppoe_session_id, type_info->remote_mac, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001229 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001230 spin_unlock_bh(&ecm_interface_lock);
1231
1232 DEBUG_TRACE("%p: pppoe iface established\n", nii);
1233 return nii;
1234}
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001235#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001236
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301237#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1238/*
1239 * ecm_interface_pppol2tpv2_interface_establish()
1240 * Returns a reference to a iface of the PPPoL2TPV2 type, possibly creating one if necessary.
1241 * Returns NULL on failure or a reference to interface.
1242 */
1243static struct ecm_db_iface_instance *ecm_interface_pppol2tpv2_interface_establish(struct ecm_db_interface_info_pppol2tpv2 *type_info,
1244 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
1245{
1246 struct ecm_db_iface_instance *nii;
1247 struct ecm_db_iface_instance *ii;
1248
1249 DEBUG_INFO("Establish PPPol2tp iface: %s with tunnel id=%u session id %u\n", dev_name, type_info->l2tp.tunnel.tunnel_id,
1250 type_info->l2tp.session.session_id);
1251 /*
1252 * Locate the iface
1253 */
1254 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1255 if (ii) {
1256 DEBUG_TRACE("%p: iface established\n", ii);
ratheesh kannothed721852015-09-28 12:39:52 +05301257 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301258 return ii;
1259 }
1260
1261 /*
1262 * No iface - create one
1263 */
1264 nii = ecm_db_iface_alloc();
1265 if (!nii) {
1266 DEBUG_WARN("Failed to establish iface\n");
1267 return NULL;
1268 }
1269
1270 /*
1271 * Add iface into the database, atomically to avoid races creating the same thing
1272 */
1273 spin_lock_bh(&ecm_interface_lock);
1274 ii = ecm_db_iface_find_and_ref_pppol2tpv2(type_info->l2tp.tunnel.tunnel_id, type_info->l2tp.session.session_id);
1275 if (ii) {
1276 spin_unlock_bh(&ecm_interface_lock);
1277 ecm_db_iface_deref(nii);
ratheesh kannothed721852015-09-28 12:39:52 +05301278 ecm_db_iface_update_ae_interface_identifier(ii, ae_interface_num);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301279 return ii;
1280 }
1281
1282 ecm_db_iface_add_pppol2tpv2(nii, type_info, dev_name, mtu, dev_interface_num, ae_interface_num, NULL, nii);
1283 spin_unlock_bh(&ecm_interface_lock);
1284
1285 DEBUG_TRACE("%p: pppol2tpv2 iface established\n", nii);
1286 return nii;
1287}
1288
1289#endif
1290
Ben Menchaca84f36632014-02-28 20:57:38 +00001291/*
1292 * ecm_interface_unknown_interface_establish()
1293 * Returns a reference to a iface of the UNKNOWN type, possibly creating one if necessary.
1294 * Returns NULL on failure or a reference to interface.
1295 */
1296static 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 -07001297 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001298{
1299 struct ecm_db_iface_instance *nii;
1300 struct ecm_db_iface_instance *ii;
1301
Murat Sezgin91c5d712015-06-12 15:16:22 -07001302 DEBUG_INFO("Establish UNKNOWN iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1303 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001304
1305 /*
1306 * Locate the iface
1307 */
1308 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1309 if (ii) {
1310 DEBUG_TRACE("%p: iface established\n", ii);
1311 return ii;
1312 }
1313
1314 /*
1315 * No iface - create one
1316 */
1317 nii = ecm_db_iface_alloc();
1318 if (!nii) {
1319 DEBUG_WARN("Failed to establish iface\n");
1320 return NULL;
1321 }
1322
1323 /*
1324 * Add iface into the database, atomically to avoid races creating the same thing
1325 */
1326 spin_lock_bh(&ecm_interface_lock);
1327 ii = ecm_db_iface_find_and_ref_unknown(type_info->os_specific_ident);
1328 if (ii) {
1329 spin_unlock_bh(&ecm_interface_lock);
1330 ecm_db_iface_deref(nii);
1331 return ii;
1332 }
1333 ecm_db_iface_add_unknown(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001334 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001335 spin_unlock_bh(&ecm_interface_lock);
1336
1337 DEBUG_TRACE("%p: unknown iface established\n", nii);
1338 return nii;
1339}
1340
1341/*
1342 * ecm_interface_loopback_interface_establish()
1343 * Returns a reference to a iface of the LOOPBACK type, possibly creating one if necessary.
1344 * Returns NULL on failure or a reference to interface.
1345 */
1346static 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 -07001347 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001348{
1349 struct ecm_db_iface_instance *nii;
1350 struct ecm_db_iface_instance *ii;
1351
Murat Sezgin91c5d712015-06-12 15:16:22 -07001352 DEBUG_INFO("Establish LOOPBACK iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1353 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001354
1355 /*
1356 * Locate the iface
1357 */
1358 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1359 if (ii) {
1360 DEBUG_TRACE("%p: iface established\n", ii);
1361 return ii;
1362 }
1363
1364 /*
1365 * No iface - create one
1366 */
1367 nii = ecm_db_iface_alloc();
1368 if (!nii) {
1369 DEBUG_WARN("Failed to establish iface\n");
1370 return NULL;
1371 }
1372
1373 /*
1374 * Add iface into the database, atomically to avoid races creating the same thing
1375 */
1376 spin_lock_bh(&ecm_interface_lock);
1377 ii = ecm_db_iface_find_and_ref_loopback(type_info->os_specific_ident);
1378 if (ii) {
1379 spin_unlock_bh(&ecm_interface_lock);
1380 ecm_db_iface_deref(nii);
1381 return ii;
1382 }
1383 ecm_db_iface_add_loopback(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001384 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001385 spin_unlock_bh(&ecm_interface_lock);
1386
1387 DEBUG_TRACE("%p: loopback iface established\n", nii);
1388 return nii;
1389}
1390
Murat Sezgin69a27532015-03-12 14:09:40 -07001391#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001392/*
1393 * ecm_interface_ipsec_tunnel_interface_establish()
1394 * Returns a reference to a iface of the IPSEC_TUNNEL type, possibly creating one if necessary.
1395 * Returns NULL on failure or a reference to interface.
1396 *
1397 * NOTE: GGG TODO THIS NEEDS TO TAKE A PROPER APPROACH TO IPSEC TUNNELS USING ENDPOINT ADDRESSING AS THE TYPE INFO KEYS
1398 */
1399static 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 -07001400 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001401{
1402 struct ecm_db_iface_instance *nii;
1403 struct ecm_db_iface_instance *ii;
1404
Murat Sezgin91c5d712015-06-12 15:16:22 -07001405 DEBUG_INFO("Establish IPSEC_TUNNEL iface: %s with os_specific_ident: %u, MTU: %d, if num: %d, accel engine if id: %d\n",
1406 dev_name, type_info->os_specific_ident, mtu, dev_interface_num, ae_interface_num);
Ben Menchaca84f36632014-02-28 20:57:38 +00001407
1408 /*
1409 * Locate the iface
1410 */
1411 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1412 if (ii) {
1413 DEBUG_TRACE("%p: iface established\n", ii);
1414 return ii;
1415 }
1416
1417 /*
1418 * No iface - create one
1419 */
1420 nii = ecm_db_iface_alloc();
1421 if (!nii) {
1422 DEBUG_WARN("Failed to establish iface\n");
1423 return NULL;
1424 }
1425
1426 /*
1427 * Add iface into the database, atomically to avoid races creating the same thing
1428 */
1429 spin_lock_bh(&ecm_interface_lock);
1430 ii = ecm_db_iface_find_and_ref_ipsec_tunnel(type_info->os_specific_ident);
1431 if (ii) {
1432 spin_unlock_bh(&ecm_interface_lock);
1433 ecm_db_iface_deref(nii);
1434 return ii;
1435 }
1436 ecm_db_iface_add_ipsec_tunnel(nii, type_info->os_specific_ident, dev_name,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001437 mtu, dev_interface_num, ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001438 spin_unlock_bh(&ecm_interface_lock);
1439
1440 DEBUG_TRACE("%p: ipsec_tunnel iface established\n", nii);
1441 return nii;
1442}
Murat Sezgin69a27532015-03-12 14:09:40 -07001443#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001444
Murat Sezginb3731e82014-11-26 12:20:59 -08001445#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07001446#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00001447/*
1448 * ecm_interface_sit_interface_establish()
1449 * Returns a reference to a iface of the SIT type, possibly creating one if necessary.
1450 * Returns NULL on failure or a reference to interface.
1451 */
1452static 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 -07001453 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001454{
1455 struct ecm_db_iface_instance *nii;
1456 struct ecm_db_iface_instance *ii;
1457
Murat Sezgin91c5d712015-06-12 15:16:22 -07001458 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",
1459 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 +00001460
1461 /*
1462 * Locate the iface
1463 */
1464 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr);
1465 if (ii) {
1466 DEBUG_TRACE("%p: iface established\n", ii);
1467 return ii;
1468 }
1469
1470 /*
1471 * No iface - create one
1472 */
1473 nii = ecm_db_iface_alloc();
1474 if (!nii) {
1475 DEBUG_WARN("Failed to establish iface\n");
1476 return NULL;
1477 }
1478
1479 /*
1480 * Add iface into the database, atomically to avoid races creating the same thing
1481 */
1482 spin_lock_bh(&ecm_interface_lock);
1483 ii = ecm_db_iface_find_and_ref_sit(type_info->saddr, type_info->daddr);
1484 if (ii) {
1485 spin_unlock_bh(&ecm_interface_lock);
1486 ecm_db_iface_deref(nii);
1487 return ii;
1488 }
1489 ecm_db_iface_add_sit(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001490 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001491 spin_unlock_bh(&ecm_interface_lock);
1492
1493 DEBUG_TRACE("%p: sit iface established\n", nii);
1494 return nii;
1495}
Murat Sezgincc6eedf2014-05-09 23:59:19 -07001496#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08001497#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001498
Murat Sezginc1402562015-03-12 12:32:20 -07001499#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001500#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001501/*
1502 * ecm_interface_tunipip6_interface_establish()
1503 * Returns a reference to a iface of the TUNIPIP6 type, possibly creating one if necessary.
1504 * Returns NULL on failure or a reference to interface.
1505 */
1506static 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 -07001507 char *dev_name, int32_t dev_interface_num, int32_t ae_interface_num, int32_t mtu)
Ben Menchaca84f36632014-02-28 20:57:38 +00001508{
1509 struct ecm_db_iface_instance *nii;
1510 struct ecm_db_iface_instance *ii;
1511
Murat Sezgin91c5d712015-06-12 15:16:22 -07001512 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",
1513 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 +00001514
1515 /*
1516 * Locate the iface
1517 */
1518 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1519 if (ii) {
1520 DEBUG_TRACE("%p: iface established\n", ii);
1521 return ii;
1522 }
1523
1524 /*
1525 * No iface - create one
1526 */
1527 nii = ecm_db_iface_alloc();
1528 if (!nii) {
1529 DEBUG_WARN("Failed to establish iface\n");
1530 return NULL;
1531 }
1532
1533 /*
1534 * Add iface into the database, atomically to avoid races creating the same thing
1535 */
1536 spin_lock_bh(&ecm_interface_lock);
1537 ii = ecm_db_iface_find_and_ref_tunipip6(type_info->saddr, type_info->daddr);
1538 if (ii) {
1539 spin_unlock_bh(&ecm_interface_lock);
1540 ecm_db_iface_deref(nii);
1541 return ii;
1542 }
1543 ecm_db_iface_add_tunipip6(nii, type_info, dev_name, mtu, dev_interface_num,
Murat Sezgin91c5d712015-06-12 15:16:22 -07001544 ae_interface_num, NULL, nii);
Ben Menchaca84f36632014-02-28 20:57:38 +00001545 spin_unlock_bh(&ecm_interface_lock);
1546
1547 DEBUG_TRACE("%p: tunipip6 iface established\n", nii);
1548 return nii;
1549}
Murat Sezginc1402562015-03-12 12:32:20 -07001550#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001551#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001552
1553/*
1554 * ecm_interface_establish_and_ref()
1555 * Establish an interface instance for the given interface detail.
1556 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001557struct ecm_db_iface_instance *ecm_interface_establish_and_ref(struct ecm_front_end_connection_instance *feci,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301558 struct net_device *dev, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00001559{
1560 int32_t dev_interface_num;
1561 char *dev_name;
1562 int32_t dev_type;
1563 int32_t dev_mtu;
Murat Sezgin91c5d712015-06-12 15:16:22 -07001564 int32_t ae_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00001565 struct ecm_db_iface_instance *ii;
1566 union {
1567 struct ecm_db_interface_info_ethernet ethernet; /* type == ECM_DB_IFACE_TYPE_ETHERNET */
Gareth Williams141d2382014-11-25 11:35:19 -08001568#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001569 struct ecm_db_interface_info_vlan vlan; /* type == ECM_DB_IFACE_TYPE_VLAN */
Gareth Williams141d2382014-11-25 11:35:19 -08001570#endif
Murat Sezgin910c9662015-03-11 16:15:06 -07001571#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001572 struct ecm_db_interface_info_lag lag; /* type == ECM_DB_IFACE_TYPE_LAG */
Murat Sezgin910c9662015-03-11 16:15:06 -07001573#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001574 struct ecm_db_interface_info_bridge bridge; /* type == ECM_DB_IFACE_TYPE_BRIDGE */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301575#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001576 struct ecm_db_interface_info_pppoe pppoe; /* type == ECM_DB_IFACE_TYPE_PPPOE */
Murat Sezginaad635c2015-03-06 16:11:41 -08001577#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301578#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1579 struct ecm_db_interface_info_pppol2tpv2 pppol2tpv2; /* type == ECM_DB_IFACE_TYPE_PPPOL2TPV2 */
1580#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001581 struct ecm_db_interface_info_unknown unknown; /* type == ECM_DB_IFACE_TYPE_UNKNOWN */
1582 struct ecm_db_interface_info_loopback loopback; /* type == ECM_DB_IFACE_TYPE_LOOPBACK */
Murat Sezgin69a27532015-03-12 14:09:40 -07001583#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001584 struct ecm_db_interface_info_ipsec_tunnel ipsec_tunnel; /* type == ECM_DB_IFACE_TYPE_IPSEC_TUNNEL */
Murat Sezgin69a27532015-03-12 14:09:40 -07001585#endif
Murat Sezginbde55f92015-03-11 16:44:11 -07001586#ifdef ECM_INTERFACE_SIT_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001587 struct ecm_db_interface_info_sit sit; /* type == ECM_DB_IFACE_TYPE_SIT */
Murat Sezginbde55f92015-03-11 16:44:11 -07001588#endif
Murat Sezginc1402562015-03-12 12:32:20 -07001589#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001590#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001591 struct ecm_db_interface_info_tunipip6 tunipip6; /* type == ECM_DB_IFACE_TYPE_TUNIPIP6 */
Murat Sezginc1402562015-03-12 12:32:20 -07001592#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001593#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001594 } type_info;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001595
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08001596#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001597 int channel_count;
1598 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00001599 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301600#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001601 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001602#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301603#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001604
1605 /*
1606 * Get basic information about the given device
1607 */
1608 dev_interface_num = dev->ifindex;
1609 dev_name = dev->name;
1610 dev_type = dev->type;
1611 dev_mtu = dev->mtu;
1612
1613 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07001614 * Does the accel engine recognise this interface?
Ben Menchaca84f36632014-02-28 20:57:38 +00001615 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001616 ae_interface_num = feci->ae_interface_number_by_dev_get(dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00001617
Murat Sezgin91c5d712015-06-12 15:16:22 -07001618 DEBUG_TRACE("Establish interface instance for device: %p is type: %d, name: %s, ifindex: %d, ae_if: %d, mtu: %d\n",
1619 dev, dev_type, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
Ben Menchaca84f36632014-02-28 20:57:38 +00001620
1621 /*
1622 * Extract from the device more type-specific information
1623 */
1624 if (dev_type == ARPHRD_ETHER) {
Shyam Sunder39e25672015-09-03 14:28:09 +05301625
Ben Menchaca84f36632014-02-28 20:57:38 +00001626 /*
1627 * Ethernet - but what sub type?
1628 */
1629
Gareth Williams141d2382014-11-25 11:35:19 -08001630#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001631 /*
1632 * VLAN?
1633 */
1634 if (is_vlan_dev(dev)) {
1635 /*
1636 * VLAN master
1637 * GGG No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
1638 */
1639 memcpy(type_info.vlan.address, dev->dev_addr, 6);
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301640 type_info.vlan.vlan_tag = vlan_dev_vlan_id(dev);
Murat Sezginb2676062015-06-12 17:05:31 -07001641 type_info.vlan.vlan_tpid = ETH_P_8021Q;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301642 DEBUG_TRACE("Net device: %p is VLAN, mac: %pM, vlan_id: %x vlan_tpid: %x\n",
1643 dev, type_info.vlan.address, type_info.vlan.vlan_tag, type_info.vlan.vlan_tpid);
Ben Menchaca84f36632014-02-28 20:57:38 +00001644
1645 /*
1646 * Establish this type of interface
1647 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001648 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 +05301649 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00001650 }
Gareth Williams141d2382014-11-25 11:35:19 -08001651#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001652
1653 /*
1654 * BRIDGE?
1655 */
1656 if (ecm_front_end_is_bridge_device(dev)) {
1657 /*
1658 * Bridge
1659 */
1660 memcpy(type_info.bridge.address, dev->dev_addr, 6);
1661
1662 DEBUG_TRACE("Net device: %p is BRIDGE, mac: %pM\n",
1663 dev, type_info.bridge.address);
1664
1665 /*
1666 * Establish this type of interface
1667 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001668 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 +05301669 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00001670 }
1671
Murat Sezgin910c9662015-03-11 16:15:06 -07001672#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001673 /*
1674 * LAG?
1675 */
1676 if (ecm_front_end_is_lag_master(dev)) {
1677 /*
1678 * Link aggregation
1679 */
1680 memcpy(type_info.lag.address, dev->dev_addr, 6);
1681
1682 DEBUG_TRACE("Net device: %p is LAG, mac: %pM\n",
1683 dev, type_info.lag.address);
1684
1685 /*
1686 * Establish this type of interface
1687 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001688 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 +05301689 goto identifier_update;
Ben Menchaca84f36632014-02-28 20:57:38 +00001690 }
Murat Sezgin910c9662015-03-11 16:15:06 -07001691#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001692
1693 /*
1694 * ETHERNET!
1695 * Just plain ethernet it seems
1696 */
1697 memcpy(type_info.ethernet.address, dev->dev_addr, 6);
1698 DEBUG_TRACE("Net device: %p is ETHERNET, mac: %pM\n",
1699 dev, type_info.ethernet.address);
1700
1701 /*
1702 * Establish this type of interface
1703 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001704 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 +05301705
1706identifier_update:
1707 if (ii) {
1708 /*
1709 * An interface identifier/ifindex can be change after network restart. Below
1710 * functtion will check interface_identifier present in 'ii' with new dev_interface_num.
1711 * If differ then update new ifindex and update the interface identifier hash table.
1712 */
1713 ecm_db_iface_identifier_hash_table_entry_check_and_update(ii, dev_interface_num);
1714 }
1715
Ben Menchaca84f36632014-02-28 20:57:38 +00001716 return ii;
1717 }
1718
1719 /*
1720 * LOOPBACK?
1721 */
1722 if (dev_type == ARPHRD_LOOPBACK) {
1723 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dev, dev_type);
1724 type_info.loopback.os_specific_ident = dev_interface_num;
Murat Sezgin91c5d712015-06-12 15:16:22 -07001725 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 +00001726 return ii;
1727 }
1728
Murat Sezgin69a27532015-03-12 14:09:40 -07001729#ifdef ECM_INTERFACE_IPSEC_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001730 /*
1731 * IPSEC?
1732 */
1733 if (dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
1734 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dev, dev_type);
1735 type_info.ipsec_tunnel.os_specific_ident = dev_interface_num;
Ankit Dhanuka6d5014a2014-06-22 17:21:44 +05301736
Ben Menchaca84f36632014-02-28 20:57:38 +00001737 // GGG TODO Flesh this out with tunnel endpoint addressing detail
Murat Sezgin91c5d712015-06-12 15:16:22 -07001738 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 +00001739 return ii;
1740 }
Murat Sezgin69a27532015-03-12 14:09:40 -07001741#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001742
Murat Sezginb3731e82014-11-26 12:20:59 -08001743#ifdef ECM_INTERFACE_SIT_ENABLE
Murat Sezginbde55f92015-03-11 16:44:11 -07001744#ifdef CONFIG_IPV6_SIT_6RD
Ben Menchaca84f36632014-02-28 20:57:38 +00001745 /*
1746 * SIT (6-in-4)?
1747 */
1748 if (dev_type == ARPHRD_SIT) {
1749 struct ip_tunnel *tunnel;
1750 struct ip_tunnel_6rd_parm *ip6rd;
1751 const struct iphdr *tiph;
1752
1753 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dev, dev_type);
1754
1755 tunnel = (struct ip_tunnel*)netdev_priv(dev);
1756 ip6rd = &tunnel->ip6rd;
1757
1758 /*
1759 * Get the Tunnel device IP header info
1760 */
1761 tiph = &tunnel->parms.iph ;
1762
1763 type_info.sit.prefixlen = ip6rd->prefixlen;
1764 type_info.sit.relay_prefix = ip6rd->relay_prefix;
1765 type_info.sit.relay_prefixlen = ip6rd->relay_prefixlen;
1766 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.saddr, tiph->saddr);
1767 ECM_NIN4_ADDR_TO_IP_ADDR(type_info.sit.daddr, tiph->daddr);
1768 type_info.sit.prefix[0] = ntohl(ip6rd->prefix.s6_addr32[0]);
1769 type_info.sit.prefix[1] = ntohl(ip6rd->prefix.s6_addr32[1]);
1770 type_info.sit.prefix[2] = ntohl(ip6rd->prefix.s6_addr32[2]);
1771 type_info.sit.prefix[3] = ntohl(ip6rd->prefix.s6_addr32[3]);
1772 type_info.sit.ttl = tiph->ttl;
1773 type_info.sit.tos = tiph->tos;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05301774
Murat Sezgin91c5d712015-06-12 15:16:22 -07001775 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 +00001776 return ii;
1777 }
Murat Sezgincc6eedf2014-05-09 23:59:19 -07001778#endif
Murat Sezginb3731e82014-11-26 12:20:59 -08001779#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00001780
Murat Sezginc1402562015-03-12 12:32:20 -07001781#ifdef ECM_INTERFACE_TUNIPIP6_ENABLE
Gareth Williams8ac34292015-03-17 14:06:58 +00001782#ifdef ECM_IPV6_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00001783 /*
1784 * IPIP6 Tunnel?
1785 */
1786 if (dev_type == ARPHRD_TUNNEL6) {
1787 struct ip6_tnl *tunnel;
1788 struct flowi6 *fl6;
1789
1790 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dev, dev_type);
1791
1792 /*
1793 * Get the tunnel device flow information (discover the output path of the tunnel)
1794 */
1795 tunnel = (struct ip6_tnl *)netdev_priv(dev);
1796 fl6 = &tunnel->fl.u.ip6;
1797
1798 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.saddr, fl6->saddr);
1799 ECM_NIN6_ADDR_TO_IP_ADDR(type_info.tunipip6.daddr, fl6->daddr);
1800 type_info.tunipip6.hop_limit = tunnel->parms.hop_limit;
1801 type_info.tunipip6.flags = ntohl(tunnel->parms.flags);
1802 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 +05301803
Murat Sezgin91c5d712015-06-12 15:16:22 -07001804 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 +00001805 return ii;
1806 }
Murat Sezginc1402562015-03-12 12:32:20 -07001807#endif
Gareth Williams8ac34292015-03-17 14:06:58 +00001808#endif
1809
Ben Menchaca84f36632014-02-28 20:57:38 +00001810 /*
1811 * If this is NOT PPP then it is unknown to the ecm
1812 */
1813 if (dev_type != ARPHRD_PPP) {
1814 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dev, dev_type);
1815 type_info.unknown.os_specific_ident = dev_interface_num;
1816
1817 /*
1818 * Establish this type of interface
1819 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001820 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 +00001821 return ii;
1822 }
1823
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08001824#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01001825 /*
1826 * PPP support is NOT provided for.
1827 * Interface is therefore unknown
1828 */
1829 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dev, dev_type);
1830 type_info.unknown.os_specific_ident = dev_interface_num;
1831
1832 /*
1833 * Establish this type of interface
1834 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001835 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 +01001836 return ii;
1837#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301838
1839#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1840 /*
1841 * ppp_xmit lock is held by linux kernel for l2tp packet in transmit
1842 * direction. we need to check for l2tp packet and avoid calls to
1843 * ppp_is_multilink() and ppp_hold_channels() which acquire same lock
1844 */
1845 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP)
1846 && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
ratheesh kannothed721852015-09-28 12:39:52 +05301847 if (skb->skb_iif == dev->ifindex) {
1848 struct sock *sk = NULL;
1849 struct inet_sock *inet = NULL;
1850 struct l2tp_session *session = NULL;
1851 struct l2tp_tunnel *tunnel = NULL;
1852 int hash;
1853 struct hlist_node *walk = NULL;
1854 bool session_found = false;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301855
ratheesh kannothed721852015-09-28 12:39:52 +05301856 /*
1857 * PPPoL2TPV2 channel
1858 */
1859 DEBUG_TRACE("%p: PPP channel is PPPoL2TPV2 (%s)\n", dev, dev->name);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301860
ratheesh kannothed721852015-09-28 12:39:52 +05301861 /*
1862 * Get the L2TP tunnel socket this packet is associated with
1863 */
1864 sk = skb->sk;
1865 tunnel = l2tp_sock_to_tunnel(sk);
1866 if (tunnel == NULL) {
1867 return NULL;
1868 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301869
ratheesh kannothed721852015-09-28 12:39:52 +05301870 /*
1871 * Check L2TPv2 tunnel version
1872 */
1873 if (tunnel->version != 2) {
1874 sock_put(sk);
1875 return NULL;
1876 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301877
ratheesh kannothed721852015-09-28 12:39:52 +05301878 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = tunnel->tunnel_id;
1879 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = tunnel->peer_tunnel_id;
1880
1881 /*
1882 * Find the L2TP session this packet is associated with
1883 */
1884 rcu_read_lock_bh();
1885 for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
1886 hlist_for_each_entry_rcu(session, walk,
1887 &tunnel->session_hlist[hash], hlist) {
1888 if (!strcmp(session->ifname, dev_name)) {
1889 type_info.pppol2tpv2.l2tp.session.session_id = session->session_id;
1890 type_info.pppol2tpv2.l2tp.session.peer_session_id = session->peer_session_id;
1891 session_found = true;
1892 break;
1893 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301894 }
1895 }
ratheesh kannothed721852015-09-28 12:39:52 +05301896 rcu_read_unlock_bh();
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301897
ratheesh kannothed721852015-09-28 12:39:52 +05301898 if (!session_found) {
1899 sock_put(sk);
1900 return NULL;
1901 }
1902
1903 inet = inet_sk(sk);
1904
1905 type_info.pppol2tpv2.udp.sport = ntohs(inet->inet_sport);
1906 type_info.pppol2tpv2.udp.dport = ntohs(inet->inet_sport);
1907 type_info.pppol2tpv2.ip.saddr = ntohl(inet->inet_saddr);
1908 type_info.pppol2tpv2.ip.daddr = ntohl(inet->inet_daddr);
1909
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301910 sock_put(sk);
ratheesh kannothed721852015-09-28 12:39:52 +05301911
1912 DEBUG_TRACE("%p: found PPPo2L2TP session\n", dev);
1913
1914 /*
1915 * Establish this type of interface
1916 */
1917 ii = ecm_interface_pppol2tpv2_interface_establish(&type_info.pppol2tpv2, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
1918 return ii;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301919 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301920 }
1921#endif
1922
Ben Menchaca84f36632014-02-28 20:57:38 +00001923 /*
1924 * PPP - but what is the channel type?
1925 * First: If this is multi-link then we do not support it
1926 */
1927 if (ppp_is_multilink(dev) > 0) {
1928 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dev);
1929 type_info.unknown.os_specific_ident = dev_interface_num;
1930
1931 /*
1932 * Establish this type of interface
1933 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001934 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 +00001935 return ii;
1936 }
1937
1938 DEBUG_TRACE("Net device: %p is PPP\n", dev);
1939
1940 /*
1941 * Get the PPP channel and then enquire what kind of channel it is
1942 * NOTE: Not multilink so only one channel to get.
1943 */
1944 channel_count = ppp_hold_channels(dev, ppp_chan, 1);
1945 if (channel_count != 1) {
Gareth Williams6f96a4b2014-05-29 19:41:21 +01001946 DEBUG_TRACE("Net device: %p PPP has %d channels - ECM cannot handle this (interface becomes Unknown type)\n",
1947 dev, channel_count);
Ben Menchaca84f36632014-02-28 20:57:38 +00001948 type_info.unknown.os_specific_ident = dev_interface_num;
1949
1950 /*
1951 * Establish this type of interface
1952 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07001953 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 +00001954 return ii;
1955 }
1956
1957 /*
1958 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01001959 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00001960 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01001961 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301962
1963#ifdef ECM_INTERFACE_L2TPV2_ENABLE
1964 if (channel_protocol == PX_PROTO_OL2TP) {
1965 struct ppp_channel *pch = ppp_chan[0];
1966 struct sock *sk = NULL;
1967 struct sock *tunsk = NULL;
1968 struct l2tp_session *session = NULL;
1969 struct l2tp_tunnel *tunnel = NULL;
1970 struct inet_sock *inet = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00001971
1972 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05301973 * PPPoL2TPV2 channel
1974 */
1975 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2 %s\n", dev, dev->name);
1976
1977 sk = pch->private;
1978 sock_hold(sk);
1979
1980 /*
1981 * Get L2TP session
1982 */
1983 session = (struct l2tp_session *)(sk->sk_user_data);
1984 if ((session == NULL) || (session->magic != L2TP_SESSION_MAGIC)) {
1985 sock_put(sk);
1986 ppp_release_channels(ppp_chan, 1);
1987 return NULL;
1988 }
1989
1990 l2tp_session_inc_refcount(session);
1991 sock_put(sk);
1992
1993 /*
1994 * Get L2TPv2 tunnel
1995 */
1996 tunnel = session->tunnel;
1997 if (tunnel->version != 2) {
1998 l2tp_session_dec_refcount(session);
1999 ppp_release_channels(ppp_chan, 1);
2000 return NULL;
2001 }
2002
2003 tunsk = tunnel->sock;
2004 sock_hold(tunsk);
2005 inet = inet_sk(tunsk);
2006
2007 type_info.pppol2tpv2.l2tp.tunnel.tunnel_id = tunnel->tunnel_id;
2008 type_info.pppol2tpv2.l2tp.tunnel.peer_tunnel_id = tunnel->peer_tunnel_id;
2009 type_info.pppol2tpv2.l2tp.session.session_id = session->session_id;
2010 type_info.pppol2tpv2.l2tp.session.peer_session_id = session->peer_session_id;
2011 type_info.pppol2tpv2.udp.sport = ntohs(inet->inet_sport);
2012 type_info.pppol2tpv2.udp.dport = ntohs(inet->inet_sport);
2013 type_info.pppol2tpv2.ip.saddr = ntohl(inet->inet_saddr);
2014 type_info.pppol2tpv2.ip.daddr = ntohl(inet->inet_daddr);
2015
2016 l2tp_session_dec_refcount(session);
2017 sock_put(tunsk);
2018
2019 /*
2020 * Release the channel. Note that next_dev is still (correctly) held.
Ben Menchaca84f36632014-02-28 20:57:38 +00002021 */
2022 ppp_release_channels(ppp_chan, 1);
2023
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302024 DEBUG_TRACE("Net device: %p PPPo2L2TP session: %d,n", dev, type_info.pppol2tpv2.l2tp.session.peer_session_id);
2025
Ben Menchaca84f36632014-02-28 20:57:38 +00002026 /*
2027 * Establish this type of interface
2028 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302029 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 +00002030 return ii;
2031 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302032#endif
2033#ifdef ECM_INTERFACE_PPPOE_ENABLE
2034 if (channel_protocol == PX_PROTO_OE) {
2035
2036 /*
2037 * PPPoE channel
2038 */
2039 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dev);
2040
2041 /*
2042 * Get PPPoE session information and the underlying device it is using.
2043 */
2044 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2045 type_info.pppoe.pppoe_session_id = (uint16_t)ntohs((uint16_t)addressing.pa.sid);
2046 memcpy(type_info.pppoe.remote_mac, addressing.pa.remote, ETH_ALEN);
2047 dev_put(addressing.dev);
2048
2049 /*
2050 * Release the channel. Note that next_dev is still (correctly) held.
2051 */
2052 ppp_release_channels(ppp_chan, 1);
2053
2054 DEBUG_TRACE("Net device: %p PPPoE session: %x, remote mac: %pM\n",
2055 dev, type_info.pppoe.pppoe_session_id, type_info.pppoe.remote_mac);
2056
2057 /*
2058 * Establish this type of interface
2059 */
2060 ii = ecm_interface_pppoe_interface_establish(&type_info.pppoe, dev_name, dev_interface_num, ae_interface_num, dev_mtu);
2061 return ii;
2062 }
2063#endif
2064 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n", dev, channel_protocol);
2065 type_info.unknown.os_specific_ident = dev_interface_num;
Ben Menchaca84f36632014-02-28 20:57:38 +00002066
2067 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302068 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00002069 */
2070 ppp_release_channels(ppp_chan, 1);
2071
Ben Menchaca84f36632014-02-28 20:57:38 +00002072 /*
2073 * Establish this type of interface
2074 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302075 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 +00002076 return ii;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302077
Gareth Williamsc5b9d712014-05-09 20:40:07 +01002078#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00002079}
2080EXPORT_SYMBOL(ecm_interface_establish_and_ref);
2081
Shyam Sunder6358b862015-05-04 15:06:24 +05302082#ifdef ECM_MULTICAST_ENABLE
2083/*
2084 * ecm_interface_multicast_heirarchy_construct_single()
2085 * Create and return an interface heirarchy for a single interface for a multicast connection
2086 *
2087 * src_addr IP source address
2088 * dest_addr IP Destination address/Group Address
2089 * interface Pointer to a single multicast interface heirarchy
2090 * given_dest_dev Netdev pointer for destination interface
2091 * br_slave_dev Netdev pointer to a bridge slave device. It could be NULL in case of pure
2092 * routed flow without any bridge interface in destination dev list.
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302093 * skb sk_buff
Shyam Sunder6358b862015-05-04 15:06:24 +05302094 */
Shyam Sunder81836832015-07-09 19:18:25 +05302095static uint32_t ecm_interface_multicast_heirarchy_construct_single(struct ecm_front_end_connection_instance *feci, ip_addr_t src_addr,
2096 ip_addr_t dest_addr, struct ecm_db_iface_instance *interface,
2097 struct net_device *given_dest_dev, struct net_device *br_slave_dev,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302098 uint8_t *src_node_addr, bool is_routed, __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302099{
2100 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2101 struct ecm_db_iface_instance **ifaces;
2102 struct ecm_db_iface_instance *ii_temp;
2103 struct net_device *dest_dev;
2104 int32_t current_interface_index;
2105 int32_t interfaces_cnt = 0;
2106 int32_t dest_dev_type;
2107
2108 dest_dev = given_dest_dev;
2109 dev_hold(dest_dev);
2110 dest_dev_type = dest_dev->type;
2111 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
2112
2113 while (current_interface_index > 0) {
2114 struct ecm_db_iface_instance *ii;
2115 struct net_device *next_dev;
2116
2117 /*
2118 * Get the ecm db interface instance for the device at hand
2119 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302120 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Shyam Sunder6358b862015-05-04 15:06:24 +05302121 interfaces_cnt++;
2122
2123 /*
2124 * If the interface could not be established then we abort
2125 */
2126 if (!ii) {
2127 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev->name);
2128 dev_put(dest_dev);
2129
2130 /*
2131 * Release the interfaces heirarchy we constructed to this point.
2132 */
2133 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2134 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2135 return ECM_DB_IFACE_HEIRARCHY_MAX;
2136 }
2137
2138 /*
2139 * Record the interface instance into the *ifaces
2140 */
2141 current_interface_index--;
2142 ii_temp = ecm_db_multicast_if_instance_get_at_index(interface, current_interface_index);
2143 ifaces = (struct ecm_db_iface_instance **)ii_temp;
2144 *ifaces = ii;
2145
2146 /*
2147 * Now we have to figure out what the next device will be (in the transmission path)
2148 */
2149 do {
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302150#ifdef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302151 int channel_count;
2152 struct ppp_channel *ppp_chan[1];
2153 int channel_protocol;
2154 struct pppoe_opt addressing;
2155#endif
2156 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev->name);
2157 next_dev = NULL;
2158
2159 if (dest_dev_type == ARPHRD_ETHER) {
2160 /*
2161 * Ethernet - but what sub type?
2162 */
2163
2164 /*
2165 * VLAN?
2166 */
2167 if (is_vlan_dev(dest_dev)) {
2168 /*
2169 * VLAN master
2170 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
2171 */
2172 next_dev = vlan_dev_real_dev(dest_dev);
2173 dev_hold(next_dev);
2174 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
2175 dest_dev, next_dev, next_dev->name);
2176 break;
2177 }
2178
2179 /*
2180 * BRIDGE?
2181 */
2182 if (ecm_front_end_is_bridge_device(dest_dev)) {
2183 if (!ecm_front_end_is_bridge_port(br_slave_dev)) {
2184 DEBUG_ASSERT(NULL, "%p: expected only bridge slave here\n", interface);
2185
2186 /*
2187 * Release the interfaces heirarchy we constructed to this point.
2188 */
2189 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2190 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2191 dev_put(dest_dev);
2192 return ECM_DB_IFACE_HEIRARCHY_MAX;
2193 }
2194
2195 next_dev = br_slave_dev;
2196 if (!next_dev) {
2197 DEBUG_WARN("Unable to obtain output port \n");
2198
2199 /*
2200 * Release the interfaces heirarchy we constructed to this point.
2201 */
2202 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2203 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2204 dev_put(dest_dev);
2205 return ECM_DB_IFACE_HEIRARCHY_MAX;
2206 }
2207 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2208 dev_hold(next_dev);
2209 break;
2210 }
2211
Shyam Sunder81836832015-07-09 19:18:25 +05302212#ifdef ECM_INTERFACE_BOND_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302213 /*
2214 * LAG?
2215 */
2216 if (ecm_front_end_is_lag_master(dest_dev)) {
2217 /*
2218 * Link aggregation
2219 * Figure out which slave device of the link aggregation will be used to reach the destination.
2220 */
2221 uint32_t src_addr_32 = 0;
2222 uint32_t dest_addr_32 = 0;
2223 uint8_t src_mac_addr[ETH_ALEN];
2224 uint8_t dest_mac_addr[ETH_ALEN];
2225
2226 memset(src_mac_addr, 0, ETH_ALEN);
2227 memset(dest_mac_addr, 0, ETH_ALEN);
2228
Shyam Sunder81836832015-07-09 19:18:25 +05302229 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2230 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
2231 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
2232 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302233
Shyam Sunder81836832015-07-09 19:18:25 +05302234 if (!is_routed) {
2235 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
Shyam Sunder6358b862015-05-04 15:06:24 +05302236 } else {
Shyam Sunder81836832015-07-09 19:18:25 +05302237 struct net_device *dest_dev_master;
2238
2239 /*
2240 * Use appropriate source MAC address for routed packets
2241 */
2242 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
2243 if (dest_dev_master) {
2244 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
2245 dev_put(dest_dev_master);
2246 } else {
2247 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
2248 }
Shyam Sunder6358b862015-05-04 15:06:24 +05302249 }
2250
2251 /*
2252 * Create Destination MAC address using IP multicast destination address
2253 */
2254 ecm_translate_multicast_mac(dest_addr, dest_mac_addr);
2255
Shyam Sunder81836832015-07-09 19:18:25 +05302256 if (ECM_IP_ADDR_IS_V4(src_addr)) {
2257 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
2258 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302259 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Shyam Sunder81836832015-07-09 19:18:25 +05302260 } else {
2261 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
2262 src_addr, dest_addr,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302263 htons((uint16_t)ETH_P_IPV6), dest_dev, NULL);
Shyam Sunder81836832015-07-09 19:18:25 +05302264 }
2265
Shyam Sunder6358b862015-05-04 15:06:24 +05302266 if (!(next_dev && netif_carrier_ok(next_dev))) {
2267 DEBUG_WARN("Unable to obtain LAG output slave device\n");
2268 dev_put(dest_dev);
2269
2270 /*
2271 * Release the interfaces heirarchy we constructed to this point.
2272 */
2273 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2274 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2275 return ECM_DB_IFACE_HEIRARCHY_MAX;
2276 }
2277
2278 dev_hold(next_dev);
2279 DEBUG_TRACE("Net device: %p is LAG, slave dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
2280 break;
2281 }
2282#endif
2283
2284 /*
2285 * ETHERNET!
2286 * Just plain ethernet it seems.
2287 */
2288 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
2289 break;
2290 }
2291
2292 /*
2293 * LOOPBACK?
2294 */
2295 if (dest_dev_type == ARPHRD_LOOPBACK) {
2296 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
2297 break;
2298 }
2299
2300 /*
2301 * IPSEC?
2302 */
2303 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
2304 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
2305 /*
2306 * TODO Figure out the next device the tunnel is using...
2307 */
2308 break;
2309 }
2310
2311 /*
2312 * SIT (6-in-4)?
2313 */
2314 if (dest_dev_type == ARPHRD_SIT) {
2315 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
2316 /*
2317 * TODO Figure out the next device the tunnel is using...
2318 */
2319 break;
2320 }
2321
2322 /*
2323 * IPIP6 Tunnel?
2324 */
2325 if (dest_dev_type == ARPHRD_TUNNEL6) {
2326 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
2327 /*
2328 * TODO Figure out the next device the tunnel is using...
2329 */
2330 break;
2331 }
2332
2333 /*
2334 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
2335 */
2336 if (dest_dev_type != ARPHRD_PPP) {
2337 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
2338 break;
2339 }
2340
Kiran Kumar C.S.Kd43bc3f2015-08-04 16:51:03 +05302341#ifndef ECM_INTERFACE_PPP_ENABLE
Shyam Sunder6358b862015-05-04 15:06:24 +05302342 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
2343#else
2344 /*
2345 * PPP - but what is the channel type?
2346 * First: If this is multi-link then we do not support it
2347 */
2348 if (ppp_is_multilink(dest_dev) > 0) {
2349 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
2350 break;
2351 }
2352
2353 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
2354
2355 /*
2356 * Get the PPP channel and then enquire what kind of channel it is
2357 * NOTE: Not multilink so only one channel to get.
2358 */
2359 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
2360 if (channel_count != 1) {
2361 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
2362 dest_dev, channel_count);
2363 break;
2364 }
2365
2366 /*
2367 * Get channel protocol type
2368 * NOTE: Not all PPP channels support channel specific methods.
2369 */
2370 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
2371 if (channel_protocol != PX_PROTO_OE) {
2372 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
2373 dest_dev, channel_protocol);
2374
2375 /*
2376 * Release the channel
2377 */
2378 ppp_release_channels(ppp_chan, 1);
2379
2380 break;
2381 }
2382
2383 /*
2384 * PPPoE channel
2385 */
2386 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
2387
2388 /*
2389 * Get PPPoE session information and the underlying device it is using.
2390 */
2391 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
2392
2393 /*
2394 * Copy the dev hold into this, we will release the hold later
2395 */
2396 next_dev = addressing.dev;
2397
Shyam Sunder6358b862015-05-04 15:06:24 +05302398 /*
2399 * Release the channel. Note that next_dev is still (correctly) held.
2400 */
2401 ppp_release_channels(ppp_chan, 1);
2402#endif
2403 } while (false);
2404
2405 /*
2406 * No longer need dest_dev as it may become next_dev
2407 */
2408 dev_put(dest_dev);
2409
2410 /*
2411 * Check out the next_dev, if any
2412 */
2413 if (!next_dev) {
2414 int32_t i __attribute__((unused));
2415 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
2416#if DEBUG_LEVEL > 1
2417 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2418 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
2419 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n", \
2420 i, to_list_single[i], ecm_db_connection_iface_type_get(to_list_single[i]), \
2421 ecm_db_interface_type_to_string(ecm_db_connection_iface_type_get(to_list_single[i])));
2422 }
2423#endif
2424 return current_interface_index;
2425 }
2426
2427 /*
2428 * dest_dev becomes next_dev
2429 */
2430 dest_dev = next_dev;
2431 dest_dev_type = dest_dev->type;
2432 }
2433
2434 dev_put(dest_dev);
2435
2436 ecm_db_multicast_copy_if_heirarchy(to_list_single, interface);
2437 ecm_db_connection_interfaces_deref(to_list_single, current_interface_index);
2438 return ECM_DB_IFACE_HEIRARCHY_MAX;
2439}
2440
2441/*
2442 * ecm_interface_multicast_heirarchy_construct_routed()
2443 * Create destination interface heirarchy for a routed multicast connectiona
2444 *
2445 * interfaces Pointer to the 2-D array of multicast interface heirarchies
2446 * in_dev Pointer to the source netdev
2447 * packet_src_addr Source IP of the multicast flow
2448 * packet_dest_addr Group(dest) IP of the multicast flow
2449 * max_dst Maximum number of netdev joined the multicast group
2450 * dst_if_index_base An array of if index joined the multicast group
2451 * interface_first_base An array of the index of the first interface in the list
2452 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002453int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_connection_instance *feci,
2454 struct ecm_db_iface_instance *interfaces,
2455 struct net_device *in_dev,
2456 ip_addr_t packet_src_addr,
2457 ip_addr_t packet_dest_addr, uint8_t max_if,
2458 uint32_t *dst_if_index_base,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302459 uint32_t *interface_first_base,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302460 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302461{
2462 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2463 struct ecm_db_iface_instance *ifaces;
2464 struct net_device *dest_dev = NULL;
2465 struct net_device *br_dev_src = NULL;
2466 uint32_t *dst_if_index;
2467 uint32_t *interface_first;
2468 uint32_t br_if;
2469 uint32_t valid_if;
Shyam Sunder41637872015-06-11 21:19:05 +05302470 int32_t if_num;
Shyam Sunder6358b862015-05-04 15:06:24 +05302471 int32_t dest_dev_type;
2472 int if_index;
2473 int ii_cnt;
2474 int total_ii_count = 0;
2475 bool src_dev_is_bridge = false;
2476
2477 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",
2478 ECM_IP_ADDR_TO_DOT(packet_dest_addr), ECM_IP_ADDR_TO_DOT(packet_src_addr), max_if);
2479
2480 /*
2481 * Check if the source net_dev is a bridge slave.
2482 */
2483 if (in_dev) {
2484 if (ecm_front_end_is_bridge_port(in_dev)) {
2485 src_dev_is_bridge = true;
2486 br_dev_src = in_dev->master;
2487
2488 /*
2489 * The source net_dev found as bridge slave. In case of routed interface
2490 * heirarchy MFC is not aware of any other bridge slave has joined the same
2491 * multicast group as a destination interface. Therfore we assume there
2492 * are bridge slaves present in multicast destination interface list
2493 * and increase the max_if by one.
2494 */
2495 max_if++;
2496 }
2497 }
2498
2499 ii_cnt = 0;
2500 br_if = if_num = 0;
2501
2502 /*
2503 * This loop is for creating the destination interface hierarchy list.
2504 * We take the destination interface array we got from MFC (in form of ifindex array)
2505 * as input for this.
2506 */
2507 for (if_index = 0, valid_if = 0; if_index < max_if; if_index++) {
2508 dst_if_index = ecm_db_multicast_if_first_get_at_index(dst_if_index_base, if_index);
2509
2510 if (*dst_if_index == ECM_INTERFACE_LOOPBACK_DEV_INDEX) {
2511 continue;
2512 }
2513
2514 dest_dev = dev_get_by_index(&init_net, *dst_if_index);
2515 if (!dest_dev) {
2516 if (!src_dev_is_bridge) {
2517 int i;
2518
2519 /*
2520 * If already constructed any interface heirarchies before hitting
2521 * this error condition then Deref all interface heirarchies.
2522 */
2523 if (valid_if > 0) {
2524 for (i = 0; i < valid_if; i++) {
2525 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2526 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2527 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2528 }
2529 }
2530
2531 /*
2532 * If valid netdev not found, Return 0
2533 */
2534 return 0;
2535 }
2536 dest_dev = br_dev_src;
2537 dev_hold(dest_dev);
2538 }
2539
2540 dest_dev_type = dest_dev->type;
2541
2542 if (ecm_front_end_is_bridge_device(dest_dev)) {
2543 struct net_device *mc_br_slave_dev = NULL;
2544 uint32_t mc_max_dst = ECM_DB_MULTICAST_IF_MAX;
2545 uint32_t mc_dst_if_index[ECM_DB_MULTICAST_IF_MAX];
2546
2547 if (ECM_IP_ADDR_IS_V4(packet_src_addr)) {
2548 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);
2549 } else {
2550 struct in6_addr origin6;
2551 struct in6_addr group6;
2552 ECM_IP_ADDR_TO_NIN6_ADDR(origin6, packet_src_addr);
2553 ECM_IP_ADDR_TO_NIN6_ADDR(group6, packet_dest_addr);
2554 if_num = mc_bridge_ipv6_get_if(dest_dev, &origin6, &group6, mc_max_dst, mc_dst_if_index);
2555 }
2556
Shyam Sunder81836832015-07-09 19:18:25 +05302557 if ((if_num < 0) || (if_num > ECM_DB_MULTICAST_IF_MAX)) {
2558 int i;
2559 DEBUG_WARN("MCS is not ready\n");
2560
2561 /*
2562 * If already constructed any interface heirarchies before hitting
2563 * this error condition then Deref all interface heirarchies.
2564 */
2565 if (valid_if > 0) {
2566 for (i = 0; i < valid_if; i++) {
2567 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2568 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2569 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2570 }
2571 }
2572
Shyam Sunder41637872015-06-11 21:19:05 +05302573 dev_put(dest_dev);
2574 return 0;
2575 }
2576
Shyam Sunder6358b862015-05-04 15:06:24 +05302577 for (br_if = 0; br_if < if_num; br_if++) {
2578 mc_br_slave_dev = dev_get_by_index(&init_net, mc_dst_if_index[br_if]);
2579 if (!mc_br_slave_dev) {
2580 continue;
2581 }
2582
2583 if ((valid_if + br_if) > ECM_DB_MULTICAST_IF_MAX) {
2584 int i;
2585
2586 /*
2587 * If already constructed any interface heirarchies before hitting
2588 * this error condition then Deref all interface heirarchies.
2589 */
2590 for (i = 0; i < (valid_if + br_if); i++) {
2591 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2592 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2593 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2594 }
2595
2596 dev_put(dest_dev);
2597 dev_put(mc_br_slave_dev);
2598 return 0;
2599 }
2600
2601 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if + br_if);
2602 /*
2603 * Construct a single interface heirarchy of a multicast dev.
2604 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302605 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 +05302606 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
2607
2608 /*
2609 * If already constructed any interface heirarchies before hitting
2610 * this error condition then Deref all interface heirarchies.
2611 */
2612 if ((valid_if + br_if) > 0) {
2613 int i;
2614 for (i = 0; i < (valid_if + br_if); i++) {
2615 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2616 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2617 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2618 }
2619 }
2620
2621 dev_put(dest_dev);
2622 dev_put(mc_br_slave_dev);
2623 return 0;
2624 }
2625
2626 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, (valid_if + br_if));
2627 *interface_first = ii_cnt;
2628 total_ii_count += ii_cnt;
2629 dev_put(mc_br_slave_dev);
2630 }
2631
2632 valid_if += br_if;
2633
2634 } else {
2635
2636 DEBUG_ASSERT(valid_if < ECM_DB_MULTICAST_IF_MAX, "Bad array index size %d\n", valid_if);
2637 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
2638 /*
2639 * Construct a single interface heirarchy of a multicast dev.
2640 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302641 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 +05302642 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
2643
2644 /*
2645 * If already constructed any interface heirarchies before hitting
2646 * this error condition then Deref all interface heirarchies.
2647 */
2648 if (valid_if > 0) {
2649 int i;
2650 for (i = 0; i < valid_if; i++) {
2651 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2652 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2653 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2654 }
2655 }
2656
2657 dev_put(dest_dev);
2658 return 0;
2659 }
2660
2661 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
2662 *interface_first = ii_cnt;
2663 total_ii_count += ii_cnt;
2664 valid_if++;
2665 }
2666
2667 dev_put(dest_dev);
2668 }
2669 return total_ii_count;
2670}
2671EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed);
2672
2673/*
2674 * ecm_interface_multicast_heirarchy_construct_bridged()
2675 * This function called when the Hyfi bridge snooper has IGMP/IMLD updates, this function
2676 * creates destination interface heirarchy for a bridged multicast connection.
2677 *
2678 * interfaces Pointer to the 2-D array of multicast interface heirarchies
2679 * dest_dev Pointer to the destination dev, here dest_dev is always a bridge type
2680 * packet_src_addr Source IP of the multicast flow
2681 * packet_dest_addr Group(dest) IP of the multicast flow
2682 * mc_max_dst Maximum number of bridge slaves joined the multicast group
2683 * mc_dst_if_index_base An array of if index joined the multicast group
2684 * interface_first_base An array of the index of the first interface in the list
2685 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002686int32_t ecm_interface_multicast_heirarchy_construct_bridged(struct ecm_front_end_connection_instance *feci,
Shyam Sunder81836832015-07-09 19:18:25 +05302687 struct ecm_db_iface_instance *interfaces, struct net_device *dest_dev,
2688 ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, uint8_t mc_max_dst,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302689 int *mc_dst_if_index_base, uint32_t *interface_first_base, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302690 __be16 *layer4hdr, struct sk_buff *skb)
Shyam Sunder6358b862015-05-04 15:06:24 +05302691{
2692 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
2693 struct ecm_db_iface_instance *ifaces;
2694 struct net_device *mc_br_slave_dev = NULL;
2695 uint32_t *interface_first;
2696 int *mc_dst_if_index;
2697 int valid_if;
2698 int ii_cnt = 0;
2699 int br_if;
2700 int total_ii_cnt = 0;
2701
2702 /*
2703 * Go through the newly joined interface index one by one and
2704 * create an interface heirarchy for each valid interface.
2705 */
2706 for (br_if = 0, valid_if = 0; br_if < mc_max_dst; br_if++) {
2707 mc_dst_if_index = (int *)ecm_db_multicast_if_num_get_at_index(mc_dst_if_index_base, br_if);
2708 mc_br_slave_dev = dev_get_by_index(&init_net, *mc_dst_if_index);
2709 if (!mc_br_slave_dev) {
2710
2711 /*
2712 * If already constructed any interface heirarchies before hitting
2713 * this error condition then Deref all interface heirarchies.
2714 */
2715 if (valid_if > 0) {
2716 int i;
2717 for (i = 0; i < valid_if; i++) {
2718 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2719 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2720 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2721 }
2722 }
2723
2724 /*
2725 * If valid netdev not found, Return 0
2726 */
2727 return 0;
2728 }
2729
2730 if (valid_if > ECM_DB_MULTICAST_IF_MAX) {
2731 int i;
2732
2733 /*
2734 * If already constructed any interface heirarchies before hitting
2735 * this error condition then Deref all interface heirarchies.
2736 */
2737 for (i = 0; i < valid_if; i++) {
2738 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2739 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2740 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2741 }
2742
2743 dev_put(mc_br_slave_dev);
2744 return 0;
2745 }
2746
2747 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if);
2748
2749 /*
2750 * Construct a single interface heirarchy of a multicast dev.
2751 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302752 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 +05302753 if (ii_cnt == ECM_DB_IFACE_HEIRARCHY_MAX) {
2754
2755 /*
2756 * If already constructed any interface heirarchies before hitting
2757 * this error condition then Deref all interface heirarchies.
2758 */
2759 if (valid_if > 0) {
2760 int i;
2761 for (i = 0; i < valid_if; i++) {
2762 ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
2763 ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
2764 ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
2765 }
2766 }
2767
2768 dev_put(mc_br_slave_dev);
2769 return 0;
2770 }
2771
2772 interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
2773 *interface_first = ii_cnt;
2774 total_ii_cnt += ii_cnt;
2775 valid_if++;
2776 dev_put(mc_br_slave_dev);
2777 }
2778
2779 return ii_cnt;
2780}
2781EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_bridged);
2782#endif
2783
Ben Menchaca84f36632014-02-28 20:57:38 +00002784/*
2785 * ecm_interface_heirarchy_construct()
2786 * Construct an interface heirarchy.
2787 *
2788 * Using the given addressing, locate the interface heirarchy used to emit packets to that destination.
2789 * This is the heirarchy of interfaces a packet would transit to emit from the device.
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002790 *
2791 * We will use the given src/dest devices when is_routed is false.
2792 * When is_routed is true we will try routing tables first, failing back to any given.
2793 *
Ben Menchaca84f36632014-02-28 20:57:38 +00002794 * For example, with this network arrangement:
2795 *
2796 * PPPoE--VLAN--BRIDGE--BRIDGE_PORT(LAG_MASTER)--LAG_SLAVE_0--10.22.33.11
2797 *
Gareth Williams43fc0852014-05-26 19:10:00 +01002798 * 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 +00002799 * LAG_SLAVE_0 @ [ECM_DB_IFACE_HEIRARCHY_MAX - 5]
2800 * LAG_MASTER @ [ECM_DB_IFACE_HEIRARCHY_MAX - 4]
2801 * BRIDGE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 3]
2802 * VLAN @ [ECM_DB_IFACE_HEIRARCHY_MAX - 2]
2803 * PPPOE @ [ECM_DB_IFACE_HEIRARCHY_MAX - 1]
2804 * The value returned is (ECM_DB_IFACE_HEIRARCHY_MAX - 5)
2805 *
2806 * IMPORTANT: This function will return any known interfaces in the database, when interfaces do not exist in the database
2807 * they will be created and added automatically to the database.
Ben Menchaca84f36632014-02-28 20:57:38 +00002808 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07002809int32_t ecm_interface_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
2810 struct ecm_db_iface_instance *interfaces[],
Murat Sezgin188b4a32015-06-03 10:58:59 -07002811 ip_addr_t packet_src_addr,
2812 ip_addr_t packet_dest_addr,
2813 int ip_version, int packet_protocol,
2814 struct net_device *given_dest_dev,
2815 bool is_routed, struct net_device *given_src_dev,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05302816 uint8_t *dest_node_addr, uint8_t *src_node_addr,
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302817 __be16 *layer4hdr, struct sk_buff *skb)
Ben Menchaca84f36632014-02-28 20:57:38 +00002818{
Ben Menchaca84f36632014-02-28 20:57:38 +00002819 int protocol;
2820 ip_addr_t src_addr;
2821 ip_addr_t dest_addr;
Ben Menchaca84f36632014-02-28 20:57:38 +00002822 struct net_device *dest_dev;
Ben Menchaca84f36632014-02-28 20:57:38 +00002823 char *dest_dev_name;
Ben Menchaca84f36632014-02-28 20:57:38 +00002824 int32_t dest_dev_type;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002825 struct net_device *src_dev;
2826 char *src_dev_name;
2827 int32_t src_dev_type;
Ben Menchaca84f36632014-02-28 20:57:38 +00002828 int32_t current_interface_index;
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002829 bool from_local_addr;
Murat Sezgin7ef29962015-08-14 10:53:24 -07002830 bool next_dest_addr_valid;
2831 bool next_dest_node_addr_valid;
2832 ip_addr_t next_dest_addr;
2833 uint8_t next_dest_node_addr[ETH_ALEN] = {0};
Ben Menchaca84f36632014-02-28 20:57:38 +00002834
2835 /*
2836 * Get a big endian of the IPv4 address we have been given as our starting point.
2837 */
2838 protocol = packet_protocol;
2839 ECM_IP_ADDR_COPY(src_addr, packet_src_addr);
2840 ECM_IP_ADDR_COPY(dest_addr, packet_dest_addr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07002841
2842 if (ip_version == 4) {
2843 DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_DOT_FMT " to dest_addr: " ECM_IP_ADDR_DOT_FMT ", protocol: %d\n",
2844 ECM_IP_ADDR_TO_DOT(src_addr), ECM_IP_ADDR_TO_DOT(dest_addr), protocol);
2845#ifdef ECM_IPV6_ENABLE
2846 } else if (ip_version == 6) {
2847 DEBUG_TRACE("Construct interface heirarchy for from src_addr: " ECM_IP_ADDR_OCTAL_FMT " to dest_addr: " ECM_IP_ADDR_OCTAL_FMT ", protocol: %d\n",
2848 ECM_IP_ADDR_TO_OCTAL(src_addr), ECM_IP_ADDR_TO_OCTAL(dest_addr), protocol);
2849#endif
2850 } else {
2851 DEBUG_WARN("Wrong IP protocol: %d\n", ip_version);
2852 return ECM_DB_IFACE_HEIRARCHY_MAX;
2853 }
Ben Menchaca84f36632014-02-28 20:57:38 +00002854
2855 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002856 * Get device to reach the given destination address.
2857 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_dest_dev.
2858 * 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 +00002859 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002860 from_local_addr = false;
2861 if (is_routed) {
2862 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
2863 if (!dest_dev && given_dest_dev) {
2864 /*
2865 * Fall back to any given
2866 */
2867 dest_dev = given_dest_dev;
2868 dev_hold(dest_dev);
Gareth Williams43fc0852014-05-26 19:10:00 +01002869 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002870 } else if (given_dest_dev) {
2871 dest_dev = given_dest_dev;
2872 dev_hold(dest_dev);
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05302873 } else {
2874 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002875 * Fall back to routed look up
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05302876 */
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002877 dest_dev = ecm_interface_dev_find_by_addr(dest_addr, &from_local_addr);
Gareth Williams43fc0852014-05-26 19:10:00 +01002878 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05302879
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002880 /*
2881 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
2882 * then this connection is a tunnel endpoint made to this device.
2883 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
2884 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
2885 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
2886 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
2887 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07002888 if (dest_dev && from_local_addr) {
2889 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
2890 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
2891 dev_put(dest_dev);
2892 dest_dev = given_dest_dev;
2893 if (dest_dev) {
2894 dev_hold(dest_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05302895 if (ip_version == 4) {
2896 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);
2897 } else {
2898 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);
2899 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07002900 }
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05302901 }
Gareth Williams43fc0852014-05-26 19:10:00 +01002902 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05302903
2904#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2905 /*
2906 * if the address is a local address and indev=l2tp.
2907 */
2908 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
2909 dev_put(dest_dev);
2910 dest_dev = given_dest_dev;
2911 if (dest_dev) {
2912 dev_hold(dest_dev);
2913 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);
2914 }
2915 }
2916#endif
2917
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002918 if (!dest_dev) {
2919 DEBUG_WARN("dest_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(dest_addr));
2920 return ECM_DB_IFACE_HEIRARCHY_MAX;
2921 }
Ben Menchaca84f36632014-02-28 20:57:38 +00002922 dest_dev_name = dest_dev->name;
2923 dest_dev_type = dest_dev->type;
2924
2925 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002926 * Get device to reach the given source address.
2927 * If the heirarchy is for a routed connection we must try route lookup first, falling back to any given_src_dev.
2928 * If the heirarchy is NOT for a routed connection we try the given_src_dev first, followed by routed lookup.
2929 */
2930 from_local_addr = false;
2931 if (is_routed) {
2932 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
2933 if (!src_dev && given_src_dev) {
2934 /*
2935 * Fall back to any given
2936 */
2937 src_dev = given_src_dev;
2938 dev_hold(src_dev);
2939 }
2940 } else if (given_src_dev) {
2941 src_dev = given_src_dev;
2942 dev_hold(src_dev);
2943 } else {
2944 /*
2945 * Fall back to routed look up
2946 */
2947 src_dev = ecm_interface_dev_find_by_addr(src_addr, &from_local_addr);
2948 }
2949
2950 /*
2951 * GGG ALERT: If the address is a local address and protocol is an IP tunnel
2952 * then this connection is a tunnel endpoint made to this device.
2953 * In which case we circumvent all proper procedure and just hack the devices to make stuff work.
2954 * GGG TODO THIS MUST BE FIXED - WE MUST USE THE INTERFACE HIERARCHY FOR ITS INTENDED PURPOSE TO
2955 * PARSE THE DEVICES AND WORK OUT THE PROPER INTERFACES INVOLVED.
2956 * E.G. IF WE TRIED TO RUN A TUNNEL OVER A VLAN OR QINQ THIS WILL BREAK AS WE DON'T DISCOVER THAT HIERARCHY
2957 */
Murat Sezgin188b4a32015-06-03 10:58:59 -07002958 if (src_dev && from_local_addr) {
2959 if (((ip_version == 4) && (protocol == IPPROTO_IPV6)) ||
2960 ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
2961 dev_put(src_dev);
2962 src_dev = given_src_dev;
2963 if (src_dev) {
2964 dev_hold(src_dev);
Tushar Mathurbac03242015-09-15 18:41:59 +05302965 if (ip_version == 4) {
2966 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);
2967 } else {
2968 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);
2969 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07002970 }
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002971 }
2972 }
Murat Sezgin188b4a32015-06-03 10:58:59 -07002973
ratheesh kannothed721852015-09-28 12:39:52 +05302974#ifdef ECM_INTERFACE_L2TPV2_ENABLE
2975 /*
2976 * if the address is a local address and indev=l2tp.
2977 */
2978 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
2979 if (dest_dev != given_src_dev) {
2980 dev_put(src_dev);
2981 src_dev = given_src_dev;
2982 if (src_dev) {
2983 dev_hold(src_dev);
2984 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);
2985 }
2986 }
2987 }
2988#endif
2989
Gareth Williams46f4b5f2014-06-01 23:35:23 +01002990 if (!src_dev) {
2991 DEBUG_WARN("src_addr: " ECM_IP_ADDR_OCTAL_FMT " - cannot locate device\n", ECM_IP_ADDR_TO_OCTAL(src_addr));
2992 dev_put(dest_dev);
2993 return ECM_DB_IFACE_HEIRARCHY_MAX;
2994 }
2995 src_dev_name = src_dev->name;
2996 src_dev_type = src_dev->type;
2997
2998 /*
2999 * Check if source and dest dev are same.
3000 * For the forwarded flows which involve tunnels this will happen when called from input hook.
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05303001 */
3002 if (src_dev == dest_dev) {
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003003 DEBUG_TRACE("Protocol is :%d source dev and dest dev are same\n", protocol);
Murat Sezgin188b4a32015-06-03 10:58:59 -07003004 if (((ip_version == 4) && ((protocol == IPPROTO_IPV6) || (protocol == IPPROTO_ESP)))
3005 || ((ip_version == 6) && (protocol == IPPROTO_IPIP))) {
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05303006 /*
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003007 * This happens from the input hook
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05303008 * We do not want to create a connection entry for this
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003009 * GGG TODO YES WE DO.
3010 * GGG TODO THIS CONCERNS ME AS THIS SHOULD BE CAUGHT MUCH
3011 * EARLIER IN THE FRONT END IF POSSIBLE TO AVOID PERFORMANCE PENALTIES.
3012 * WE HAVE DONE A TREMENDOUS AMOUT OF WORK TO GET TO THIS POINT.
3013 * WE WILL ABORT HERE AND THIS WILL BE REPEATED FOR EVERY PACKET.
3014 * IN KEEPING WITH THE ECM DESIGN IT IS BETTER TO CREATE A CONNECTION AND RECORD IN THE HIERARCHY
3015 * ENOUGH INFORMATION TO ENSURE THAT ACCELERATION IS NOT BROKEN / DOES NOT OCCUR AT ALL.
3016 * THAT WAY WE DO A HEAVYWEIGHT ESTABLISHING OF A CONNECTION ONCE AND NEVER AGAIN...
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05303017 */
3018 dev_put(src_dev);
3019 dev_put(dest_dev);
3020 return ECM_DB_IFACE_HEIRARCHY_MAX;
3021 }
3022 }
3023
Murat Sezgin7ef29962015-08-14 10:53:24 -07003024 next_dest_addr_valid = true;
3025 next_dest_node_addr_valid = false;
3026 ECM_IP_ADDR_COPY(next_dest_addr, dest_addr);
3027
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05303028 /*
Ben Menchaca84f36632014-02-28 20:57:38 +00003029 * Iterate until we are done or get to the max number of interfaces we can record.
3030 * NOTE: current_interface_index tracks the position of the first interface position in interfaces[]
3031 * because we add from the end first_interface grows downwards.
3032 */
3033 current_interface_index = ECM_DB_IFACE_HEIRARCHY_MAX;
3034 while (current_interface_index > 0) {
3035 struct ecm_db_iface_instance *ii;
3036 struct net_device *next_dev;
3037
3038 /*
3039 * Get the ecm db interface instance for the device at hand
3040 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303041 ii = ecm_interface_establish_and_ref(feci, dest_dev, skb);
Ben Menchaca84f36632014-02-28 20:57:38 +00003042
3043 /*
3044 * If the interface could not be established then we abort
3045 */
3046 if (!ii) {
3047 DEBUG_WARN("Failed to establish interface: %p, name: %s\n", dest_dev, dest_dev_name);
3048 dev_put(src_dev);
3049 dev_put(dest_dev);
3050
3051 /*
3052 * Release the interfaces heirarchy we constructed to this point.
3053 */
3054 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3055 return ECM_DB_IFACE_HEIRARCHY_MAX;
3056 }
3057
3058 /*
3059 * Record the interface instance into the interfaces[]
3060 */
3061 current_interface_index--;
3062 interfaces[current_interface_index] = ii;
3063
3064 /*
3065 * Now we have to figure out what the next device will be (in the transmission path) the skb
3066 * will use to emit to the destination address.
3067 */
3068 do {
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08003069#ifdef ECM_INTERFACE_PPP_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00003070 int channel_count;
3071 struct ppp_channel *ppp_chan[1];
Ben Menchaca84f36632014-02-28 20:57:38 +00003072 int channel_protocol;
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303073#ifdef ECM_INTERFACE_PPPOE_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00003074 struct pppoe_opt addressing;
Gareth Williamsc5b9d712014-05-09 20:40:07 +01003075#endif
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303076#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00003077
3078 DEBUG_TRACE("Net device: %p is type: %d, name: %s\n", dest_dev, dest_dev_type, dest_dev_name);
3079 next_dev = NULL;
3080
3081 if (dest_dev_type == ARPHRD_ETHER) {
3082 /*
3083 * Ethernet - but what sub type?
3084 */
3085
Gareth Williams141d2382014-11-25 11:35:19 -08003086#ifdef ECM_INTERFACE_VLAN_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00003087 /*
3088 * VLAN?
3089 */
3090 if (is_vlan_dev(dest_dev)) {
3091 /*
3092 * VLAN master
3093 * No locking needed here, ASSUMPTION is that real_dev is held for as long as we have dev.
3094 */
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05303095 next_dev = vlan_dev_real_dev(dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00003096 dev_hold(next_dev);
3097 DEBUG_TRACE("Net device: %p is VLAN, slave dev: %p (%s)\n",
3098 dest_dev, next_dev, next_dev->name);
3099 break;
3100 }
Gareth Williams141d2382014-11-25 11:35:19 -08003101#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00003102
3103 /*
3104 * BRIDGE?
3105 */
3106 if (ecm_front_end_is_bridge_device(dest_dev)) {
3107 /*
3108 * Bridge
3109 * Figure out which port device the skb will go to using the dest_addr.
3110 */
3111 bool on_link;
Murat Sezginebf8a642014-06-06 12:51:43 -07003112 ip_addr_t gw_addr = ECM_IP_ADDR_NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00003113 uint8_t mac_addr[ETH_ALEN];
Murat Sezgin7ef29962015-08-14 10:53:24 -07003114
3115 if (next_dest_node_addr_valid) {
3116 memcpy(mac_addr, next_dest_node_addr, ETH_ALEN);
3117 } else if (!next_dest_addr_valid) {
Ben Menchaca84f36632014-02-28 20:57:38 +00003118 dev_put(src_dev);
3119 dev_put(dest_dev);
3120
3121 /*
3122 * Release the interfaces heirarchy we constructed to this point.
3123 */
3124 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3125 return ECM_DB_IFACE_HEIRARCHY_MAX;
Murat Sezgin7ef29962015-08-14 10:53:24 -07003126 } else {
3127 if (!ecm_interface_mac_addr_get(next_dest_addr, mac_addr, &on_link, gw_addr)) {
3128 if (ip_version == 4) {
3129 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n",
3130 ECM_IP_ADDR_TO_DOT(dest_addr));
3131 ecm_interface_send_arp_request(dest_dev, dest_addr, on_link, gw_addr);
3132 }
3133#ifdef ECM_IPV6_ENABLE
3134 if (ip_version == 6) {
3135 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n",
3136 ECM_IP_ADDR_TO_OCTAL(dest_addr));
3137 ecm_interface_send_neighbour_solicitation(dest_dev, dest_addr);
3138 }
3139#endif
3140 dev_put(src_dev);
3141 dev_put(dest_dev);
3142
3143 /*
3144 * Release the interfaces heirarchy we constructed to this point.
3145 */
3146 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3147 return ECM_DB_IFACE_HEIRARCHY_MAX;
3148 }
Ben Menchaca84f36632014-02-28 20:57:38 +00003149 }
3150 next_dev = br_port_dev_get(dest_dev, mac_addr);
3151 if (!next_dev) {
3152 DEBUG_WARN("Unable to obtain output port for: %pM\n", mac_addr);
3153 dev_put(src_dev);
3154 dev_put(dest_dev);
3155
3156 /*
3157 * Release the interfaces heirarchy we constructed to this point.
3158 */
3159 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3160 return ECM_DB_IFACE_HEIRARCHY_MAX;
3161 }
3162 DEBUG_TRACE("Net device: %p is BRIDGE, next_dev: %p (%s)\n", dest_dev, next_dev, next_dev->name);
3163 break;
3164 }
Gareth Williams8ac34292015-03-17 14:06:58 +00003165
Murat Sezginb3731e82014-11-26 12:20:59 -08003166#ifdef ECM_INTERFACE_BOND_ENABLE
Ben Menchaca84f36632014-02-28 20:57:38 +00003167 /*
3168 * LAG?
3169 */
3170 if (ecm_front_end_is_lag_master(dest_dev)) {
3171 /*
3172 * Link aggregation
Murat Sezginb3731e82014-11-26 12:20:59 -08003173 * Figure out whiich slave device of the link aggregation will be used to reach the destination.
Ben Menchaca84f36632014-02-28 20:57:38 +00003174 */
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303175 bool dest_on_link = false;
3176 ip_addr_t dest_gw_addr = ECM_IP_ADDR_NULL;
3177 uint32_t src_addr_32 = 0;
3178 uint32_t dest_addr_32 = 0;
Ben Menchaca84f36632014-02-28 20:57:38 +00003179 uint8_t src_mac_addr[ETH_ALEN];
3180 uint8_t dest_mac_addr[ETH_ALEN];
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303181 struct net_device *master_dev = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00003182
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303183 memset(src_mac_addr, 0, ETH_ALEN);
3184 memset(dest_mac_addr, 0, ETH_ALEN);
Ben Menchaca84f36632014-02-28 20:57:38 +00003185
Gareth Williams341df382015-07-20 16:44:17 +01003186 if (ip_version == 4) {
3187 ECM_IP_ADDR_TO_NIN4_ADDR(src_addr_32, src_addr);
3188 ECM_IP_ADDR_TO_NIN4_ADDR(dest_addr_32, dest_addr);
3189 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303190
3191 if (!is_routed) {
3192 memcpy(src_mac_addr, src_node_addr, ETH_ALEN);
3193 memcpy(dest_mac_addr, dest_node_addr, ETH_ALEN);
3194 } else {
Murat Sezginb3731e82014-11-26 12:20:59 -08003195 struct net_device *dest_dev_master;
3196
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303197 /*
3198 * Use appropriate source MAC address for routed packets
3199 */
Murat Sezginb3731e82014-11-26 12:20:59 -08003200 dest_dev_master = ecm_interface_get_and_hold_dev_master(dest_dev);
3201 if (dest_dev_master) {
3202 memcpy(src_mac_addr, dest_dev_master->dev_addr, ETH_ALEN);
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303203 } else {
3204 memcpy(src_mac_addr, dest_dev->dev_addr, ETH_ALEN);
3205 }
3206
3207 /*
3208 * Determine destination MAC address for this routed packet
3209 */
Tushar Mathur78b5f432015-09-18 20:13:31 +05303210 if (next_dest_node_addr_valid) {
3211 memcpy(dest_mac_addr, next_dest_node_addr, ETH_ALEN);
3212 } else if (!next_dest_addr_valid) {
3213 dev_put(src_dev);
3214 dev_put(dest_dev);
Murat Sezginb3731e82014-11-26 12:20:59 -08003215 if (dest_dev_master) {
3216 dev_put(dest_dev_master);
3217 }
3218
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303219 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3220 return ECM_DB_IFACE_HEIRARCHY_MAX;
Tushar Mathur78b5f432015-09-18 20:13:31 +05303221 } else {
3222 if (!ecm_interface_mac_addr_get(dest_addr, dest_mac_addr,
3223 &dest_on_link, dest_gw_addr)) {
3224
3225 /*
3226 * Find proper interfce from which to issue ARP
3227 * or neighbour solicitation packet.
3228 */
3229 if (dest_dev_master) {
3230 master_dev = dest_dev_master;
3231 } else {
3232 master_dev = dest_dev;
3233 }
3234
3235 dev_hold(master_dev);
3236
3237 if (dest_dev_master) {
3238 dev_put(dest_dev_master);
3239 }
3240
3241 if (ip_version == 4) {
3242 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_DOT_FMT "\n", ECM_IP_ADDR_TO_DOT(dest_addr));
3243 ecm_interface_send_arp_request(dest_dev, dest_addr, dest_on_link, dest_gw_addr);
3244 }
3245#ifdef ECM_IPV6_ENABLE
3246 if (ip_version == 6) {
3247 DEBUG_WARN("Unable to obtain MAC address for " ECM_IP_ADDR_OCTAL_FMT "\n",ECM_IP_ADDR_TO_OCTAL(dest_addr));
3248 ecm_interface_send_neighbour_solicitation(master_dev, dest_addr);
3249 }
3250#endif
3251 dev_put(src_dev);
3252 dev_put(dest_dev);
3253 dev_put(master_dev);
3254 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3255 return ECM_DB_IFACE_HEIRARCHY_MAX;
3256 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303257 }
Murat Sezginb3731e82014-11-26 12:20:59 -08003258
3259 if (dest_dev_master) {
3260 dev_put(dest_dev_master);
3261 }
Tushar Mathur4ab0bf92014-06-10 20:37:07 +05303262 }
3263
Murat Sezgin188b4a32015-06-03 10:58:59 -07003264 if (ip_version == 4) {
3265 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3266 &src_addr_32, &dest_addr_32,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05303267 htons((uint16_t)ETH_P_IP), dest_dev, layer4hdr);
Murat Sezgin188b4a32015-06-03 10:58:59 -07003268 } else if (ip_version == 6) {
3269 next_dev = bond_get_tx_dev(NULL, src_mac_addr, dest_mac_addr,
3270 src_addr, dest_addr,
Suman Ghoshfb8e7702015-08-20 15:27:57 +05303271 htons((uint16_t)ETH_P_IPV6), dest_dev, NULL);
Murat Sezgin188b4a32015-06-03 10:58:59 -07003272 }
3273
Tushar Mathur933907c2014-06-24 17:06:14 +05303274 if (next_dev && netif_carrier_ok(next_dev)) {
Ben Menchaca84f36632014-02-28 20:57:38 +00003275 dev_hold(next_dev);
3276 } else {
3277 DEBUG_WARN("Unable to obtain LAG output slave device\n");
3278 dev_put(src_dev);
3279 dev_put(dest_dev);
3280
3281 /*
3282 * Release the interfaces heirarchy we constructed to this point.
3283 */
3284 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3285 return ECM_DB_IFACE_HEIRARCHY_MAX;
3286 }
3287
3288 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 +00003289 break;
3290 }
Murat Sezginb3731e82014-11-26 12:20:59 -08003291#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00003292
3293 /*
3294 * ETHERNET!
3295 * Just plain ethernet it seems.
3296 */
3297 DEBUG_TRACE("Net device: %p is ETHERNET\n", dest_dev);
3298 break;
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05303299 }
Ben Menchaca84f36632014-02-28 20:57:38 +00003300
3301 /*
3302 * LOOPBACK?
3303 */
3304 if (dest_dev_type == ARPHRD_LOOPBACK) {
3305 DEBUG_TRACE("Net device: %p is LOOPBACK type: %d\n", dest_dev, dest_dev_type);
3306 break;
3307 }
3308
3309 /*
3310 * IPSEC?
3311 */
3312 if (dest_dev_type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE) {
3313 DEBUG_TRACE("Net device: %p is IPSec tunnel type: %d\n", dest_dev, dest_dev_type);
3314 // GGG TODO Figure out the next device the tunnel is using...
3315 break;
3316 }
3317
3318 /*
3319 * SIT (6-in-4)?
3320 */
3321 if (dest_dev_type == ARPHRD_SIT) {
3322 DEBUG_TRACE("Net device: %p is SIT (6-in-4) type: %d\n", dest_dev, dest_dev_type);
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003323 // GGG TODO Figure out the next device the tunnel is using...
Ben Menchaca84f36632014-02-28 20:57:38 +00003324 break;
3325 }
3326
3327 /*
3328 * IPIP6 Tunnel?
3329 */
3330 if (dest_dev_type == ARPHRD_TUNNEL6) {
3331 DEBUG_TRACE("Net device: %p is TUNIPIP6 type: %d\n", dest_dev, dest_dev_type);
Gareth Williams46f4b5f2014-06-01 23:35:23 +01003332 // GGG TODO Figure out the next device the tunnel is using...
Ben Menchaca84f36632014-02-28 20:57:38 +00003333 break;
3334 }
3335
3336 /*
3337 * If this is NOT PPP then it is unknown to the ecm and we cannot figure out it's next device.
3338 */
3339 if (dest_dev_type != ARPHRD_PPP) {
3340 DEBUG_TRACE("Net device: %p is UNKNOWN type: %d\n", dest_dev, dest_dev_type);
3341 break;
3342 }
3343
Gareth Williamsdbb2bfd2014-11-20 16:42:09 -08003344#ifndef ECM_INTERFACE_PPP_ENABLE
Gareth Williamsc5b9d712014-05-09 20:40:07 +01003345 DEBUG_TRACE("Net device: %p is UNKNOWN (PPP Unsupported) type: %d\n", dest_dev, dest_dev_type);
3346#else
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303347 DEBUG_TRACE("Net device: %p is PPP\n", dest_dev);
3348
3349#ifdef ECM_INTERFACE_L2TPV2_ENABLE
3350 if (skb && skb->sk && (skb->sk->sk_protocol == IPPROTO_UDP) && (udp_sk(skb->sk)->encap_type == UDP_ENCAP_L2TPINUDP)) {
ratheesh kannothed721852015-09-28 12:39:52 +05303351 if (skb->skb_iif == dest_dev->ifindex) {
3352 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
3353 break;
3354 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303355 }
3356#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00003357 /*
3358 * PPP - but what is the channel type?
3359 * First: If this is multi-link then we do not support it
3360 */
3361 if (ppp_is_multilink(dest_dev) > 0) {
3362 DEBUG_TRACE("Net device: %p is MULTILINK PPP - Unknown to the ECM\n", dest_dev);
3363 break;
3364 }
3365
Ben Menchaca84f36632014-02-28 20:57:38 +00003366 /*
3367 * Get the PPP channel and then enquire what kind of channel it is
3368 * NOTE: Not multilink so only one channel to get.
3369 */
3370 channel_count = ppp_hold_channels(dest_dev, ppp_chan, 1);
3371 if (channel_count != 1) {
3372 DEBUG_TRACE("Net device: %p PPP has %d channels - Unknown to the ECM\n",
3373 dest_dev, channel_count);
3374 break;
3375 }
3376
3377 /*
3378 * Get channel protocol type
Gareth Williams6f96a4b2014-05-29 19:41:21 +01003379 * NOTE: Not all PPP channels support channel specific methods.
Ben Menchaca84f36632014-02-28 20:57:38 +00003380 */
Gareth Williams6f96a4b2014-05-29 19:41:21 +01003381 channel_protocol = ppp_channel_get_protocol(ppp_chan[0]);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303382
3383#ifdef ECM_INTERFACE_L2TPV2_ENABLE
3384 if (channel_protocol == PX_PROTO_OL2TP) {
Radha krishna Simha Jiguruf7dc34c2014-05-12 18:59:07 +05303385
Ben Menchaca84f36632014-02-28 20:57:38 +00003386 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303387 * PPPoL2TPV2 channel
Ben Menchaca84f36632014-02-28 20:57:38 +00003388 */
3389 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303390 DEBUG_TRACE("Net device: %p PPP channel is PPPoL2TPV2\n", dest_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00003391
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303392 /*
3393 * Release the channel. Note that next_dev not held.
3394 */
Ben Menchaca84f36632014-02-28 20:57:38 +00003395 break;
3396 }
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303397#endif
3398#ifdef ECM_INTERFACE_PPPOE_ENABLE
3399 if (channel_protocol == PX_PROTO_OE) {
3400 /*
3401 * PPPoE channel
3402 */
3403 DEBUG_TRACE("Net device: %p PPP channel is PPPoE\n", dest_dev);
3404
3405 /*
3406 * Get PPPoE session information and the underlying device it is using.
3407 */
3408 pppoe_channel_addressing_get(ppp_chan[0], &addressing);
3409
3410 /*
3411 * Copy the dev hold into this, we will release the hold later
3412 */
3413 next_dev = addressing.dev;
3414 next_dest_addr_valid = false;
3415 next_dest_node_addr_valid = true;
3416 memcpy(next_dest_node_addr, addressing.pa.remote, ETH_ALEN);
3417
3418 /*
3419 * Release the channel. Note that next_dev is still (correctly) held.
3420 */
3421 ppp_release_channels(ppp_chan, 1);
3422 break;
3423 }
3424#endif
3425
3426 DEBUG_TRACE("Net device: %p PPP channel protocol: %d - Unknown to the ECM\n",
3427 dest_dev, channel_protocol);
Ben Menchaca84f36632014-02-28 20:57:38 +00003428
3429 /*
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303430 * Release the channel
Ben Menchaca84f36632014-02-28 20:57:38 +00003431 */
3432 ppp_release_channels(ppp_chan, 1);
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303433
Gareth Williamsc5b9d712014-05-09 20:40:07 +01003434#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00003435 } while (false);
3436
3437 /*
Gareth Williamsa11d4352014-05-14 18:25:49 +01003438 * No longer need dest_dev as it may become next_dev
Ben Menchaca84f36632014-02-28 20:57:38 +00003439 */
Ben Menchaca84f36632014-02-28 20:57:38 +00003440 dev_put(dest_dev);
3441
3442 /*
3443 * Check out the next_dev, if any
3444 */
3445 if (!next_dev) {
3446 int32_t i __attribute__((unused));
3447 DEBUG_INFO("Completed interface heirarchy construct with first interface @: %d\n", current_interface_index);
3448#if DEBUG_LEVEL > 1
3449 for (i = current_interface_index; i < ECM_DB_IFACE_HEIRARCHY_MAX; ++i) {
3450 DEBUG_TRACE("\tInterface @ %d: %p, type: %d, name: %s\n",
3451 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 +05303452
Ben Menchaca84f36632014-02-28 20:57:38 +00003453 }
3454#endif
Gareth Williamsa11d4352014-05-14 18:25:49 +01003455
3456 /*
3457 * Release src_dev now
3458 */
3459 dev_put(src_dev);
Ben Menchaca84f36632014-02-28 20:57:38 +00003460 return current_interface_index;
3461 }
3462
Gareth Williamsa11d4352014-05-14 18:25:49 +01003463 /*
3464 * dest_dev becomes next_dev
3465 */
Ben Menchaca84f36632014-02-28 20:57:38 +00003466 dest_dev = next_dev;
3467 dest_dev_name = dest_dev->name;
3468 dest_dev_type = dest_dev->type;
3469 }
3470
3471 DEBUG_WARN("Too many interfaces: %d\n", current_interface_index);
3472 DEBUG_ASSERT(current_interface_index == 0, "Bad logic handling current_interface_index: %d\n", current_interface_index);
3473 dev_put(src_dev);
3474 dev_put(dest_dev);
3475
3476 /*
3477 * Release the interfaces heirarchy we constructed to this point.
3478 */
3479 ecm_db_connection_interfaces_deref(interfaces, current_interface_index);
3480 return ECM_DB_IFACE_HEIRARCHY_MAX;
3481}
3482EXPORT_SYMBOL(ecm_interface_heirarchy_construct);
3483
3484/*
Gareth Williamsadf425f2014-05-26 19:29:02 +01003485 * ecm_interface_list_stats_update()
3486 * Given an interface list, walk the interfaces and update the stats for certain types.
3487 */
3488static 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 +05303489 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 +01003490{
3491 int list_index;
3492
3493 for (list_index = iface_list_first; (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) {
3494 struct ecm_db_iface_instance *ii;
3495 ecm_db_iface_type_t ii_type;
3496 char *ii_name;
3497 struct net_device *dev;
3498
3499 ii = iface_list[list_index];
3500 ii_type = ecm_db_connection_iface_type_get(ii);
3501 ii_name = ecm_db_interface_type_to_string(ii_type);
3502 DEBUG_TRACE("list_index: %d, ii: %p, type: %d (%s)\n", list_index, ii, ii_type, ii_name);
3503
3504 /*
3505 * Locate real device in system
3506 */
3507 dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii));
3508 if (!dev) {
3509 DEBUG_WARN("Could not locate interface\n");
3510 continue;
3511 }
3512 DEBUG_TRACE("found dev: %p (%s)\n", dev, dev->name);
3513
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05303514 if (likely(!is_mcast_flow)) {
3515 /*
3516 * Refresh the bridge forward table entry if the port is a bridge port
3517 * Note: A bridge port can be of different interface type, e.g VLAN, ethernet.
3518 * This check, therefore, should be performed for all interface types.
3519 */
3520 if (is_valid_ether_addr(mac_addr) && ecm_front_end_is_bridge_port(dev) && rx_packets) {
3521 DEBUG_TRACE("Update bridge fdb entry for mac: %pM\n", mac_addr);
3522 br_refresh_fdb_entry(dev, mac_addr);
3523 }
Selin Dag1af781a2014-06-10 10:37:54 -07003524 }
3525
Gareth Williamsadf425f2014-05-26 19:29:02 +01003526 switch (ii_type) {
3527 struct rtnl_link_stats64 stats;
3528
Gareth Williams141d2382014-11-25 11:35:19 -08003529#ifdef ECM_INTERFACE_VLAN_ENABLE
Gareth Williamsadf425f2014-05-26 19:29:02 +01003530 case ECM_DB_IFACE_TYPE_VLAN:
Radha krishna Simha Jigurue9d46fd2014-06-03 22:17:19 +05303531 DEBUG_INFO("VLAN\n");
Gareth Williamsadf425f2014-05-26 19:29:02 +01003532 stats.rx_packets = rx_packets;
3533 stats.rx_bytes = rx_bytes;
3534 stats.tx_packets = tx_packets;
3535 stats.tx_bytes = tx_bytes;
3536 __vlan_dev_update_accel_stats(dev, &stats);
3537 break;
Gareth Williams141d2382014-11-25 11:35:19 -08003538#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01003539 case ECM_DB_IFACE_TYPE_BRIDGE:
3540 DEBUG_INFO("BRIDGE\n");
3541 stats.rx_packets = rx_packets;
3542 stats.rx_bytes = rx_bytes;
3543 stats.tx_packets = tx_packets;
3544 stats.tx_bytes = tx_bytes;
3545 br_dev_update_stats(dev, &stats);
Gareth Williamsadf425f2014-05-26 19:29:02 +01003546 break;
Murat Sezgina683edd2015-01-20 10:48:30 -08003547
ratheesh kannotha32fdd12015-09-09 08:02:58 +05303548#ifdef ECM_INTERFACE_PPPOE_ENABLE
Murat Sezgina683edd2015-01-20 10:48:30 -08003549 case ECM_DB_IFACE_TYPE_PPPOE:
3550 DEBUG_INFO("PPPOE\n");
ratheesh kannothb1b753a2015-09-28 11:17:35 +05303551 ppp_update_stats(dev, rx_packets, rx_bytes, tx_packets, tx_bytes, 0, 0, 0, 0);
Murat Sezgina683edd2015-01-20 10:48:30 -08003552 break;
3553#endif
Gareth Williamsadf425f2014-05-26 19:29:02 +01003554 default:
3555 /*
3556 * TODO: Extend it accordingly
3557 */
3558 break;
3559 }
3560
3561 dev_put(dev);
3562 }
3563}
3564
3565/*
3566 * ecm_interface_stats_update()
3567 * Using the interface lists for the given connection, update the interface statistics for each.
3568 *
3569 * 'from' here is wrt the connection 'from' side. Likewise with 'to'.
3570 * TX is wrt what the interface has transmitted. RX is what the interface has received.
3571 */
3572void ecm_interface_stats_update(struct ecm_db_connection_instance *ci,
3573 uint32_t from_tx_packets, uint32_t from_tx_bytes, uint32_t from_rx_packets, uint32_t from_rx_bytes,
3574 uint32_t to_tx_packets, uint32_t to_tx_bytes, uint32_t to_rx_packets, uint32_t to_rx_bytes)
3575{
3576 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
3577 struct ecm_db_iface_instance *to_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
3578 int from_ifaces_first;
3579 int to_ifaces_first;
3580 uint8_t mac_addr[ETH_ALEN];
3581
3582 /*
3583 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
3584 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
3585 * from_rx_packets / bytes: the amount received by the 'from' interface
3586 */
3587 DEBUG_INFO("%p: Update from interface stats\n", ci);
3588 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
3589 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05303590 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 +01003591 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
3592
3593 /*
3594 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
3595 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
3596 * to_rx_packets / bytes: the amount received by the 'to' interface
3597 */
3598 DEBUG_INFO("%p: Update to interface stats\n", ci);
3599 to_ifaces_first = ecm_db_connection_to_interfaces_get_and_ref(ci, to_ifaces);
3600 ecm_db_connection_to_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05303601 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 +01003602 ecm_db_connection_interfaces_deref(to_ifaces, to_ifaces_first);
3603}
3604EXPORT_SYMBOL(ecm_interface_stats_update);
3605
Shyam Sunder6358b862015-05-04 15:06:24 +05303606#ifdef ECM_MULTICAST_ENABLE
3607/*
Shyam Sunder6358b862015-05-04 15:06:24 +05303608 * ecm_interface_multicast_stats_update()
3609 * Using the interface lists for the given connection, update the interface statistics for each.
3610 *
3611 * 'from interface' here is the connection 'from' side. Likewise with 'to interface'.
3612 * TX is wrt what the interface has transmitted. RX is what the interface has received.
3613 */
3614void ecm_interface_multicast_stats_update(struct ecm_db_connection_instance *ci, uint32_t from_tx_packets, uint32_t from_tx_bytes,
3615 uint32_t from_rx_packets, uint32_t from_rx_bytes, uint32_t to_tx_packets, uint32_t to_tx_bytes,
3616 uint32_t to_rx_packets, uint32_t to_rx_bytes)
3617{
3618 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05303619 struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
Shyam Sunder6358b862015-05-04 15:06:24 +05303620 struct ecm_db_iface_instance *to_ifaces;
3621 struct ecm_db_iface_instance *ii_temp;
3622 int from_ifaces_first;
3623 int *to_ifaces_first;
3624 int if_index;
3625 int ret;
3626 uint8_t mac_addr[ETH_ALEN];
3627
3628 /*
3629 * Iterate the 'from' side interfaces and update statistics and state for the real HLOS interfaces
3630 * from_tx_packets / bytes: the amount transmitted by the 'from' interface
3631 * from_rx_packets / bytes: the amount received by the 'from' interface
3632 */
3633 DEBUG_INFO("%p: Update from interface stats\n", ci);
3634 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(ci, from_ifaces);
3635 ecm_db_connection_from_node_address_get(ci, mac_addr);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05303636 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 +05303637 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
3638
3639 /*
3640 * Iterate the 'to' side interfaces and update statistics and state for the real HLOS interfaces
3641 * to_tx_packets / bytes: the amount transmitted by the 'to' interface
3642 * to_rx_packets / bytes: the amount received by the 'to' interface
3643 */
3644 DEBUG_INFO("%p: Update to interface stats\n", ci);
3645
3646 /*
3647 * This function allocates the memory for temporary destination interface heirarchies.
3648 * This memory needs to be free at the end.
3649 */
3650 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &to_ifaces, &to_ifaces_first);
3651 if (ret == 0) {
3652 DEBUG_WARN("%p: Get and ref to all multicast detination interface heirarchies failed\n", ci);
3653 return;
3654 }
3655
3656 for (if_index = 0; if_index < ECM_DB_MULTICAST_IF_MAX; if_index++) {
3657 if (to_ifaces_first[if_index] < ECM_DB_IFACE_HEIRARCHY_MAX) {
3658 ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, if_index);
Shyam Sunderbf40d0e2015-06-23 15:56:37 +05303659 ecm_db_multicast_copy_if_heirarchy(to_list_single, ii_temp);
3660 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 +05303661 }
3662 }
3663
3664 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
3665}
3666EXPORT_SYMBOL(ecm_interface_multicast_stats_update);
3667#endif
3668
Gareth Williamsadf425f2014-05-26 19:29:02 +01003669/*
Ben Menchaca84f36632014-02-28 20:57:38 +00003670 * ecm_interface_regenerate_connections()
3671 * Cause regeneration of all connections that are using the specified interface.
3672 */
3673static void ecm_interface_regenerate_connections(struct ecm_db_iface_instance *ii)
3674{
Gareth Williamsb5903892015-03-20 15:13:07 +00003675#ifdef ECM_DB_XREF_ENABLE
Gareth Williamsa4390962015-08-26 12:51:31 +01003676 struct ecm_db_connection_instance *ci_from;
3677 struct ecm_db_connection_instance *ci_to;
3678 struct ecm_db_connection_instance *ci_from_nat;
3679 struct ecm_db_connection_instance *ci_to_nat;
3680 struct ecm_db_connection_instance *ci_mcast __attribute__ ((unused));
Gareth Williamsb5903892015-03-20 15:13:07 +00003681#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00003682
3683 DEBUG_TRACE("Regenerate connections using interface: %p\n", ii);
3684
Gareth Williamsb5903892015-03-20 15:13:07 +00003685#ifndef ECM_DB_XREF_ENABLE
3686 /*
3687 * An interface has changed, re-generate the connections to ensure all state is updated.
3688 */
Tushar Mathurd38cacd2015-07-28 12:19:10 +05303689 ecm_db_regeneration_needed();
Gareth Williamsb5903892015-03-20 15:13:07 +00003690#else
Ben Menchaca84f36632014-02-28 20:57:38 +00003691 /*
Gareth Williamsa4390962015-08-26 12:51:31 +01003692 * If the interface has NO connections then we re-generate all.
3693 */
3694 ci_from = ecm_db_iface_connections_from_get_and_ref_first(ii);
3695 ci_to = ecm_db_iface_connections_to_get_and_ref_first(ii);
3696 ci_from_nat = ecm_db_iface_connections_nat_from_get_and_ref_first(ii);
3697 ci_to_nat = ecm_db_iface_connections_nat_to_get_and_ref_first(ii);
3698 if (!ci_from && !ci_to && !ci_from_nat && !ci_to_nat) {
3699 ecm_db_regeneration_needed();
3700 DEBUG_TRACE("%p: Regenerate (ALL) COMPLETE\n", ii);
3701 return;
3702 }
3703
3704 /*
3705 * Re-generate all connections associated with this interface
Ben Menchaca84f36632014-02-28 20:57:38 +00003706 */
3707 DEBUG_TRACE("%p: Regenerate 'from' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01003708 while (ci_from) {
Ben Menchaca84f36632014-02-28 20:57:38 +00003709 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01003710 cin = ecm_db_connection_iface_from_get_and_ref_next(ci_from);
Ben Menchaca84f36632014-02-28 20:57:38 +00003711
Gareth Williamsa4390962015-08-26 12:51:31 +01003712 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07003713 ecm_db_connection_regenerate(ci_from);
Gareth Williamsa4390962015-08-26 12:51:31 +01003714 ecm_db_connection_deref(ci_from);
3715 ci_from = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00003716 }
3717
3718 DEBUG_TRACE("%p: Regenerate 'to' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01003719 while (ci_to) {
Ben Menchaca84f36632014-02-28 20:57:38 +00003720 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01003721 cin = ecm_db_connection_iface_to_get_and_ref_next(ci_to);
Ben Menchaca84f36632014-02-28 20:57:38 +00003722
Gareth Williamsa4390962015-08-26 12:51:31 +01003723 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07003724 ecm_db_connection_regenerate(ci_to);
Gareth Williamsa4390962015-08-26 12:51:31 +01003725 ecm_db_connection_deref(ci_to);
3726 ci_to = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00003727 }
3728
Gareth Williamsa4390962015-08-26 12:51:31 +01003729 /*
3730 * GGG TODO These deprecated lists _nat_ lists will eventually be removed
3731 */
Ben Menchaca84f36632014-02-28 20:57:38 +00003732 DEBUG_TRACE("%p: Regenerate 'from_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01003733 while (ci_from_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00003734 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01003735 cin = ecm_db_connection_iface_nat_from_get_and_ref_next(ci_from_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00003736
Gareth Williamsa4390962015-08-26 12:51:31 +01003737 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_from_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07003738 ecm_db_connection_regenerate(ci_from_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01003739 ecm_db_connection_deref(ci_from_nat);
3740 ci_from_nat = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00003741 }
3742
3743 DEBUG_TRACE("%p: Regenerate 'to_nat' connections\n", ii);
Gareth Williamsa4390962015-08-26 12:51:31 +01003744 while (ci_to_nat) {
Ben Menchaca84f36632014-02-28 20:57:38 +00003745 struct ecm_db_connection_instance *cin;
Gareth Williamsa4390962015-08-26 12:51:31 +01003746 cin = ecm_db_connection_iface_nat_to_get_and_ref_next(ci_to_nat);
Ben Menchaca84f36632014-02-28 20:57:38 +00003747
Gareth Williamsa4390962015-08-26 12:51:31 +01003748 DEBUG_TRACE("%p: Regenerate: %p", ii, ci_to_nat);
Xiaoping Faned6d37e2015-09-17 14:13:47 -07003749 ecm_db_connection_regenerate(ci_to_nat);
Gareth Williamsa4390962015-08-26 12:51:31 +01003750 ecm_db_connection_deref(ci_to_nat);
3751 ci_to_nat = cin;
3752 }
3753
3754#ifdef ECM_MULTICAST_ENABLE
3755 /*
3756 * Multicasts would not have recorded in the lists above.
3757 * Our only way to re-gen those is to iterate all multicasts.
3758 * GGG TODO This will be optimised in a future release.
3759 */
3760 ci_mcast = ecm_db_connections_get_and_ref_first();
3761 while (ci_mcast) {
3762 struct ecm_db_connection_instance *cin;
3763
3764 /*
3765 * Multicast and NOT flagged for re-gen?
3766 */
3767 if (ecm_db_multicast_connection_to_interfaces_set_check(ci_mcast)
3768 && ecm_db_connection_regeneration_required_peek(ci_mcast)) {
Xiaoping Faned6d37e2015-09-17 14:13:47 -07003769 ecm_db_connection_regenerate(ci_mcast);
Gareth Williamsa4390962015-08-26 12:51:31 +01003770 }
3771
3772 cin = ecm_db_connection_get_and_ref_next(ci_mcast);
3773 ecm_db_connection_deref(ci_mcast);
3774 ci_mcast = cin;
Ben Menchaca84f36632014-02-28 20:57:38 +00003775 }
Gareth Williamsb5903892015-03-20 15:13:07 +00003776#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00003777
Gareth Williamsa4390962015-08-26 12:51:31 +01003778#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00003779 DEBUG_TRACE("%p: Regenerate COMPLETE\n", ii);
3780}
3781
3782/*
3783 * ecm_interface_dev_regenerate_connections()
3784 * Cause regeneration of all connections that are using the specified interface.
3785 */
Tushar Mathurcccbf282015-01-13 01:22:44 +05303786void ecm_interface_dev_regenerate_connections(struct net_device *dev)
Ben Menchaca84f36632014-02-28 20:57:38 +00003787{
3788 struct ecm_db_iface_instance *ii;
3789
3790 DEBUG_INFO("Regenerate connections for: %p (%s)\n", dev, dev->name);
3791
3792 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07003793 * If the interface is known to us then we will get it returned by this
3794 * function and process it accordingly.
Ben Menchaca84f36632014-02-28 20:57:38 +00003795 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003796 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00003797 if (!ii) {
3798 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
3799 return;
3800 }
3801 ecm_interface_regenerate_connections(ii);
3802 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
3803 ecm_db_iface_deref(ii);
3804}
3805
3806/*
3807 * ecm_interface_mtu_change()
3808 * MTU of interface has changed
3809 */
3810static void ecm_interface_mtu_change(struct net_device *dev)
3811{
3812 int mtu;
3813 struct ecm_db_iface_instance *ii;
3814
3815 mtu = dev->mtu;
3816 DEBUG_INFO("%p (%s): MTU Change to: %d\n", dev, dev->name, mtu);
3817
3818 /*
Murat Sezgin91c5d712015-06-12 15:16:22 -07003819 * Find the interface for the given device.
Ben Menchaca84f36632014-02-28 20:57:38 +00003820 */
Murat Sezgin91c5d712015-06-12 15:16:22 -07003821 ii = ecm_db_iface_find_and_ref_by_interface_identifier(dev->ifindex);
Ben Menchaca84f36632014-02-28 20:57:38 +00003822 if (!ii) {
3823 DEBUG_WARN("%p: No interface instance could be established for this dev\n", dev);
3824 return;
3825 }
3826
3827 /*
3828 * Change the mtu
3829 */
3830 ecm_db_iface_mtu_reset(ii, mtu);
3831 DEBUG_TRACE("%p (%s): MTU Changed to: %d\n", dev, dev->name, mtu);
Tushar Mathurad534d62015-06-10 18:37:52 +05303832 if (netif_is_bond_slave(dev)) {
3833 struct net_device *master = NULL;
3834 master = ecm_interface_get_and_hold_dev_master(dev);
3835 DEBUG_ASSERT(master, "Expected a master\n");
3836 ecm_interface_dev_regenerate_connections(master);
3837 dev_put(master);
3838 } else {
3839 ecm_interface_regenerate_connections(ii);
3840 }
3841
Ben Menchaca84f36632014-02-28 20:57:38 +00003842 DEBUG_TRACE("%p: Regenerate for %p: COMPLETE\n", dev, ii);
3843 ecm_db_iface_deref(ii);
3844}
3845
3846/*
3847 * ecm_interface_netdev_notifier_callback()
3848 * Netdevice notifier callback to inform us of change of state of a netdevice
3849 */
3850static int ecm_interface_netdev_notifier_callback(struct notifier_block *this, unsigned long event, void *ptr)
3851{
Stephen Wang69379c32015-02-04 18:37:13 -08003852#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 0))
Ben Menchaca84f36632014-02-28 20:57:38 +00003853 struct net_device *dev __attribute__ ((unused)) = (struct net_device *)ptr;
Stephen Wang69379c32015-02-04 18:37:13 -08003854#else
3855 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
3856#endif
Tushar Mathurad534d62015-06-10 18:37:52 +05303857 struct net_device *master = NULL;
Ben Menchaca84f36632014-02-28 20:57:38 +00003858
3859 DEBUG_INFO("Net device notifier for: %p, name: %s, event: %lx\n", dev, dev->name, event);
3860
3861 switch (event) {
3862 case NETDEV_DOWN:
3863 DEBUG_INFO("Net device: %p, DOWN\n", dev);
Tushar Mathurad534d62015-06-10 18:37:52 +05303864 if (netif_is_bond_slave(dev)) {
3865 master = ecm_interface_get_and_hold_dev_master(dev);
3866 DEBUG_ASSERT(master, "Expected a master\n");
3867 ecm_interface_dev_regenerate_connections(master);
3868 dev_put(master);
3869 } else {
3870 ecm_interface_dev_regenerate_connections(dev);
3871 }
Ben Menchaca84f36632014-02-28 20:57:38 +00003872 break;
3873
3874 case NETDEV_CHANGE:
3875 DEBUG_INFO("Net device: %p, CHANGE\n", dev);
3876 if (!netif_carrier_ok(dev)) {
3877 DEBUG_INFO("Net device: %p, CARRIER BAD\n", dev);
Tushar Mathur933907c2014-06-24 17:06:14 +05303878 if (netif_is_bond_slave(dev)) {
Murat Sezginb3731e82014-11-26 12:20:59 -08003879 master = ecm_interface_get_and_hold_dev_master(dev);
3880 DEBUG_ASSERT(master, "Expected a master\n");
3881 ecm_interface_dev_regenerate_connections(master);
3882 dev_put(master);
Tushar Mathur933907c2014-06-24 17:06:14 +05303883 } else {
3884 ecm_interface_dev_regenerate_connections(dev);
3885 }
Ben Menchaca84f36632014-02-28 20:57:38 +00003886 }
3887 break;
3888
3889 case NETDEV_CHANGEMTU:
3890 DEBUG_INFO("Net device: %p, MTU CHANGE\n", dev);
3891 ecm_interface_mtu_change(dev);
3892 break;
3893
3894 default:
3895 DEBUG_TRACE("Net device: %p, UNHANDLED: %lx\n", dev, event);
3896 break;
3897 }
3898
3899 return NOTIFY_DONE;
3900}
3901
3902/*
3903 * struct notifier_block ecm_interface_netdev_notifier
3904 * Registration for net device changes of state.
3905 */
3906static struct notifier_block ecm_interface_netdev_notifier __read_mostly = {
3907 .notifier_call = ecm_interface_netdev_notifier_callback,
3908};
Murat Sezgin8c345822015-05-27 15:35:38 -07003909#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
Ben Menchaca84f36632014-02-28 20:57:38 +00003910/*
ratheesh kannoth37e35b02015-03-26 11:25:02 +05303911 * ecm_interfae_node_br_fdb_notify_event()
3912 * This is a call back for "bridge fdb update event/ageing timer expire
3913 * event".
3914 */
3915static int ecm_interface_node_br_fdb_notify_event(struct notifier_block *nb,
3916 unsigned long val,
3917 void *data)
3918{
3919 uint8_t *mac = (uint8_t *)data;
3920 struct ecm_db_node_instance *node = NULL;
3921
3922 if(unlikely(!mac)) {
3923 DEBUG_WARN("mac address passed to ecm_interface_node_br_fdb_notify_event is null \n");
3924 return NOTIFY_DONE;
3925 }
3926
3927 /*
3928 * find node instance corresponding to mac address
3929 */
3930 node = ecm_db_node_find_and_ref(mac);
3931
3932 if(unlikely(!node)) {
3933 DEBUG_WARN("node address is null \n");
3934 return NOTIFY_DONE;
3935 }
3936
3937 ecm_db_traverse_node_from_connection_list_and_decelerate(node);
3938 ecm_db_traverse_node_to_connection_list_and_decelerate(node);
3939 ecm_db_traverse_node_from_nat_connection_list_and_decelerate(node);
3940 ecm_db_traverse_node_to_nat_connection_list_and_decelerate(node);
3941
3942 ecm_db_node_deref(node);
3943
3944 return NOTIFY_DONE;
3945}
3946
3947static struct notifier_block ecm_interface_node_br_fdb_update_nb = {
3948 .notifier_call = ecm_interface_node_br_fdb_notify_event,
3949};
Murat Sezgin8c345822015-05-27 15:35:38 -07003950#endif
Shyam Sunder6358b862015-05-04 15:06:24 +05303951
3952#ifdef ECM_MULTICAST_ENABLE
3953/*
3954 * ecm_interface_multicast_find_outdated_iface_instances()
3955 *
3956 * Called in the case of Routing/Bridging Multicast update events.
3957 *
3958 * This function takes a list of ifindex for the connection which was received
3959 * from MFC or bridge snooper, compares it against the existing list of interfaces
3960 * in the DB connection, and extracts the list of those interfaces that have left
3961 * the multicast group.
3962 *
3963 * ci A DB connection instance.
3964 * mc_updates Part of return Information. The function will mark the index of those
3965 * interfaces in the DB connection 'to_mcast_interfaces' array that have
3966 * left the group, in the mc_updates->if_leave_idx array. The caller uses this
3967 * information to delete those outdated interface heirarchies from the
3968 * connection.
3969 * is_bridged True if the function called due to bridge multicast snooper update event.
3970 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
3971 * by the update from MFC or Bridge snooper.
3972 * max_to_dev Size of the array 'dst_dev'
3973 *
3974 * Return true if outdated interfaces found
3975 */
3976static bool ecm_interface_multicast_find_outdated_iface_instances(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
3977 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
3978{
3979 struct ecm_db_iface_instance *mc_ifaces;
3980 struct ecm_db_iface_instance *ii_temp;
3981 struct ecm_db_iface_instance *ii_single;
3982 struct ecm_db_iface_instance **ifaces;
3983 struct ecm_db_iface_instance *to_iface;
3984 int32_t *to_iface_first;
3985 int32_t *mc_ifaces_first;
3986 uint32_t *dst_if_index;
3987 ecm_db_iface_type_t ii_type;
3988 int32_t heirarchy_index;
3989 int32_t if_index;
3990 int32_t if_cnt = 0;
3991 int found = 0;
3992 int ii;
3993 int ret;
3994 int32_t ifaces_identifier;
3995
3996 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
3997 if (ret == 0) {
3998 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
3999 return false;
4000 }
4001
4002 /*
4003 * Loop through the current interface list in the DB
4004 * connection 'to_mcast_interfaces' array
4005 */
4006 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX; heirarchy_index++) {
4007 found = 0;
4008 to_iface_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
4009
4010 /*
4011 * Invalid interface entry, skip
4012 */
4013 if (*to_iface_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
4014 continue;
4015 }
4016
4017 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
4018 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ECM_DB_IFACE_HEIRARCHY_MAX - 1);
4019 ifaces = (struct ecm_db_iface_instance **)ii_single;
4020 to_iface = *ifaces;
4021 ii_type = ecm_db_connection_iface_type_get(to_iface);
4022
4023 /*
4024 * If the update was received from bridge snooper, do not consider entries in the
4025 * interface list that are not part of a bridge.
4026 */
4027 if (is_br_snooper && (ii_type != ECM_DB_IFACE_TYPE_BRIDGE)) {
4028 continue;
4029 }
4030
4031 /*
4032 * If the update was received from MFC, do not consider entries in the
4033 * interface list that are part of a bridge. The bridge entries will be
4034 * taken care by the Bridge Snooper Callback
4035 */
4036 if (ii_type == ECM_DB_IFACE_TYPE_BRIDGE) {
4037 if (!is_br_snooper && !(flags & ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG)) {
4038 continue;
4039 }
4040 }
4041
4042 /*
4043 * Try to find a match in the newly received interface list, for any of
4044 * the interface instance in the heirarchy. If found, it means that this
4045 * interface has not left the group. If not found, it means that this
4046 * interface has left the group.
4047 */
4048 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_iface_first; ii--) {
4049 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
4050 ifaces = (struct ecm_db_iface_instance **)ii_single;
4051 to_iface = *ifaces;
4052
4053 ii_type = ecm_db_connection_iface_type_get(to_iface);
4054 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_iface);
4055 for (if_index = 0; if_index < max_to_dev; if_index++) {
4056 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
4057 if (*dst_if_index == ifaces_identifier) {
4058 found = 1;
4059 break;
4060 }
4061 }
4062 if (found) {
4063 break;
4064 }
4065 }
4066
4067 /*
4068 * We did not find a match for the interface in the present list. So mark
4069 * if as one that has left the group.
4070 */
4071 if (!found) {
4072 if_cnt++;
4073 mc_updates->if_leave_idx[heirarchy_index] = 1;
4074 }
4075 }
4076
4077 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
4078 mc_updates->if_leave_cnt = if_cnt;
4079 return (if_cnt > 0);
4080}
4081
4082/*
4083 * ecm_interface_multicast_find_new_iface_instances()
4084 *
4085 * Called in the case of Routing/Bridging Multicast update events.
4086 *
4087 * This function takes a list of ifindex for the connection which was received
4088 * from MFC or bridge snooper, compares it against the existing list of interfaces
4089 * in the DB connection, and extracts the list of the new joinees for the multicast
4090 * group.
4091 *
4092 * ci A DB connection instance.
4093 * mc_updates Part of return Information. The function will mark the index of those
4094 * interfaces in the 'dst_dev' array that have joined the group, in the
4095 * mc_updates->if_join_idx array. The caller uses this information to add the new
4096 * interface heirarchies into the connection.
4097 * dst_dev Holds the netdevice ifindex number of the new list of interfaces as reported
4098 * by the update from MFC or Bridge snooper.
4099 * max_to_dev Size of the array 'dst_dev'
4100 *
4101 * Return true if new joinees found
4102 */
4103static bool ecm_interface_multicast_find_new_iface_instances(struct ecm_db_connection_instance *ci,
4104 struct ecm_multicast_if_update *mc_updates, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
4105{
4106 struct ecm_db_iface_instance *mc_ifaces;
4107 struct ecm_db_iface_instance *ii_temp;
4108 struct ecm_db_iface_instance *ii_single;
4109 struct ecm_db_iface_instance **ifaces;
4110 int32_t *mc_ifaces_first;
4111 int32_t *to_list_first;
4112 int32_t heirarchy_index;
4113 int32_t if_index;
4114 int32_t if_cnt = 0;
4115 int found = 0;
4116 int ii;
4117 int ret;
4118 uint32_t *dst_if_index;
4119 int32_t ifaces_identifier;
4120 struct ecm_db_iface_instance *to_list;
4121
4122 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(ci, &mc_ifaces, &mc_ifaces_first);
4123 if (ret == 0) {
4124 DEBUG_WARN("%p: multicast interfaces ref fail!\n", ci);
4125 return false;
4126 }
4127
4128 /*
4129 * Loop through the new interface list 'dst_dev'
4130 */
4131 for (if_index = 0; if_index < max_to_dev; if_index++) {
4132 found = 0;
4133 dst_if_index = ecm_db_multicast_if_num_get_at_index(mc_dst_if_index, if_index);
4134 if (*dst_if_index == 0) {
4135 continue;
4136 }
4137
4138 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
4139 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
4140
4141 /*
4142 * Invalid interface entry, skip
4143 */
4144 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
4145 continue;
4146 }
4147
4148 ii_temp = ecm_db_multicast_if_heirarchy_get(mc_ifaces, heirarchy_index);
4149
4150 /*
4151 * Try to find a match for this ifindex (dst_dev[if_index]), in any of the
4152 * interface instance in the heirarchy. If not found, it means that this
4153 * ifindex has joined the group. If found, it means that this ifindex was
4154 * already part of the list of destination interfaces.
4155 */
4156 for (ii = ECM_DB_IFACE_HEIRARCHY_MAX - 1; ii >= *to_list_first; ii--) {
4157 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, ii);
4158 ifaces = (struct ecm_db_iface_instance **)ii_single;
4159 to_list = *ifaces;
4160 ifaces_identifier = ecm_db_iface_interface_identifier_get(to_list);
4161 if (*dst_if_index == ifaces_identifier) {
4162 found = 1;
4163 break;
4164 }
4165 }
4166
4167 if (found) {
4168 break;
4169 }
4170 }
4171
4172 /*
4173 * We did not find a match for the interface in the present list. So mark
4174 * it as one that has joined the group.
4175 */
4176 if (!found) {
4177
4178 /*
4179 * Store the if index of the new joinee
4180 */
4181 mc_updates->join_dev[if_cnt] = *dst_if_index;
4182
4183 /*
4184 * Identify a new vacant slot in the 'to_mcast_interfaces' to place
4185 * the new interface
4186 */
4187 for (heirarchy_index = 0; heirarchy_index < ECM_DB_MULTICAST_IF_MAX ; heirarchy_index++) {
4188 to_list_first = ecm_db_multicast_if_first_get_at_index(mc_ifaces_first, heirarchy_index);
4189 if (*to_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
4190 mc_updates->if_join_idx[heirarchy_index] = 1;
4191 break;
4192 }
4193 }
4194
4195 if_cnt++;
4196 }
4197 }
4198
4199 ecm_db_multicast_connection_to_interfaces_deref_all(mc_ifaces, mc_ifaces_first);
4200 mc_updates->if_join_cnt = if_cnt;
4201
4202 return (if_cnt > 0);
4203}
4204
4205/*
4206 * ecm_interface_multicast_find_updates_to_iface_list()
4207 * Process IGMP/MLD updates either from MFC or bridge snooper. Identity the interfaces
4208 * that have left the group and new interfaces that have joined the group.
4209 *
4210 * The function returns true if there was any update necessary to the current destination
4211 * interface list
4212 */
4213bool ecm_interface_multicast_find_updates_to_iface_list(struct ecm_db_connection_instance *ci, struct ecm_multicast_if_update *mc_updates,
4214 uint32_t flags, bool is_br_snooper, uint32_t *mc_dst_if_index, uint32_t max_to_dev)
4215{
4216 bool join;
4217 bool leave;
4218 /*
4219 * Find destination interfaces that have left the group
4220 */
4221 leave = ecm_interface_multicast_find_outdated_iface_instances(ci, mc_updates, flags, is_br_snooper, mc_dst_if_index, max_to_dev);
4222 /*
4223 * Find new destination interfaces that have joined the group
4224 */
4225 join = ecm_interface_multicast_find_new_iface_instances(ci, mc_updates, mc_dst_if_index, max_to_dev);
4226
4227 return (leave || join);
4228}
4229EXPORT_SYMBOL(ecm_interface_multicast_find_updates_to_iface_list);
4230#endif
4231
Murat Sezgin1f381852014-11-20 09:51:07 -08004232/*
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004233 * ecm_interface_init()
Ben Menchaca84f36632014-02-28 20:57:38 +00004234 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004235int ecm_interface_init(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00004236{
4237 int result;
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004238 DEBUG_INFO("ECM Interface init\n");
Ben Menchaca84f36632014-02-28 20:57:38 +00004239
Ben Menchaca84f36632014-02-28 20:57:38 +00004240 result = register_netdevice_notifier(&ecm_interface_netdev_notifier);
4241 if (result != 0) {
4242 DEBUG_ERROR("Failed to register netdevice notifier %d\n", result);
Murat Sezgin908ecb32015-05-10 20:54:36 -07004243 return result;
Ben Menchaca84f36632014-02-28 20:57:38 +00004244 }
Murat Sezgin8c345822015-05-27 15:35:38 -07004245#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05304246 /*
4247 * register for bridge fdb database modificationevents
4248 */
ratheesh kannotha32fdd12015-09-09 08:02:58 +05304249 br_fdb_update_register_notify(&ecm_interface_node_br_fdb_update_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07004250#endif
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004251 return 0;
Ben Menchaca84f36632014-02-28 20:57:38 +00004252}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004253EXPORT_SYMBOL(ecm_interface_init);
Ben Menchaca84f36632014-02-28 20:57:38 +00004254
4255/*
4256 * ecm_interface_exit()
4257 */
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004258void ecm_interface_exit(void)
Ben Menchaca84f36632014-02-28 20:57:38 +00004259{
4260 DEBUG_INFO("ECM Interface exit\n");
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004261
4262 spin_lock_bh(&ecm_interface_lock);
4263 ecm_interface_terminate_pending = true;
4264 spin_unlock_bh(&ecm_interface_lock);
4265
4266 unregister_netdevice_notifier(&ecm_interface_netdev_notifier);
Murat Sezgin8c345822015-05-27 15:35:38 -07004267#if defined(ECM_DB_XREF_ENABLE) && defined(ECM_BAND_STEERING_ENABLE)
ratheesh kannoth37e35b02015-03-26 11:25:02 +05304268 /*
4269 * unregister for bridge fdb update events
4270 */
4271 br_fdb_update_unregister_notify(&ecm_interface_node_br_fdb_update_nb);
Murat Sezgin8c345822015-05-27 15:35:38 -07004272#endif
Ben Menchaca84f36632014-02-28 20:57:38 +00004273}
Nicolas Costaf46c33b2014-05-15 10:02:00 -05004274EXPORT_SYMBOL(ecm_interface_exit);