1/*
2 **************************************************************************
3 * Copyright (c) 2014-2015 The Linux Foundation.  All rights reserved.
4 * 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
17#include <linux/version.h>
18#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>
24#include <linux/debugfs.h>
25#include <linux/kthread.h>
26#include <linux/pkt_sched.h>
27#include <linux/string.h>
28#include <net/ip6_route.h>
29#include <net/ip6_fib.h>
30#include <net/addrconf.h>
31#include <net/ipv6.h>
32#include <net/tcp.h>
33#include <asm/unaligned.h>
34#include <asm/uaccess.h>	/* for put_user */
35#include <net/ipv6.h>
36#include <linux/inet.h>
37#include <linux/in6.h>
38#include <linux/udp.h>
39#include <linux/tcp.h>
40#include <linux/ppp_defs.h>
41#include <linux/mroute6.h>
42#include <linux/vmalloc.h>
43
44#include <linux/inetdevice.h>
45#include <linux/if_arp.h>
46#include <linux/netfilter_ipv6.h>
47#include <linux/netfilter_bridge.h>
48#include <linux/if_bridge.h>
49#include <net/arp.h>
50#include <net/netfilter/nf_conntrack.h>
51#include <net/netfilter/nf_conntrack_acct.h>
52#include <net/netfilter/nf_conntrack_helper.h>
53#include <net/netfilter/nf_conntrack_l4proto.h>
54#include <net/netfilter/nf_conntrack_l3proto.h>
55#include <net/netfilter/nf_conntrack_zones.h>
56#include <net/netfilter/nf_conntrack_core.h>
57#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
58#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
59#ifdef ECM_INTERFACE_VLAN_ENABLE
60#include <linux/../../net/8021q/vlan.h>
61#include <linux/if_vlan.h>
62#endif
63
64/*
65 * Debug output levels
66 * 0 = OFF
67 * 1 = ASSERTS / ERRORS
68 * 2 = 1 + WARN
69 * 3 = 2 + INFO
70 * 4 = 3 + TRACE
71 */
72#define DEBUG_LEVEL ECM_NSS_MULTICAST_IPV6_DEBUG_LEVEL
73
74#include <nss_api_if.h>
75#include <mc_ecm.h>
76
77#include "ecm_types.h"
78#include "ecm_db_types.h"
79#include "ecm_state.h"
80#include "ecm_tracker.h"
81#include "ecm_classifier.h"
82#include "ecm_front_end_types.h"
83#include "ecm_tracker_datagram.h"
84#include "ecm_tracker_udp.h"
85#include "ecm_tracker_tcp.h"
86#include "ecm_db.h"
87#include "ecm_classifier_default.h"
88#include "ecm_interface.h"
89#include "ecm_nss_ipv6.h"
90#include "ecm_nss_multicast_ipv6.h"
91#include "ecm_nss_common.h"
92
93/*
94 * Magic numbers
95 */
96#define ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC 0xED13
97
98/*
99 * struct ecm_nss_ipv6_multicast_connection_instance
100 *	A connection specific front end instance for MULTICAST connections
101 */
102struct ecm_nss_multicast_ipv6_connection_instance {
103	struct ecm_front_end_connection_instance base;		/* Base class */
104#if (DEBUG_LEVEL > 0)
105	uint16_t magic;
106#endif
107};
108
109static int ecm_nss_multicast_ipv6_accelerated_count = 0;
110						/* Number of IPv6 multicast connections currently offloaded */
111
112/*
113 * ecm_nss_multicast_ipv6_interface_heirarchy_construct()
114 *   Create destination multicast interface heirachy for Route/Bridge connection flow
115 */
116static int ecm_nss_multicast_ipv6_interface_heirarchy_construct(struct ecm_front_end_connection_instance *feci,
117								struct ecm_db_iface_instance *interfaces, struct net_device *in_dev,
118								struct net_device *brdev, ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, uint8_t max_if,
119								uint32_t *dst_dev, int32_t *to_interface_first, uint8_t *src_node_addr, bool is_routed)
120{
121	int32_t iface_instance_cnt;
122
123	if (is_routed) {
124		iface_instance_cnt = ecm_interface_multicast_heirarchy_construct_routed(feci, interfaces, in_dev, packet_src_addr, packet_dest_addr, max_if, dst_dev, to_interface_first, NULL);
125	} else {
126		iface_instance_cnt = ecm_interface_multicast_heirarchy_construct_bridged(feci, interfaces, brdev,
127											 packet_src_addr, packet_dest_addr, max_if,
128											 dst_dev, to_interface_first, src_node_addr, NULL);
129	}
130	return iface_instance_cnt;
131}
132
133/*
134 * ecm_nss_multicast_ipv6_connection_update_callback()
135 * 	Callback for handling Ack/Nack for update accelerate rules.
136 */
137static void ecm_nss_multicast_ipv6_connection_update_callback(void *app_data, struct nss_ipv6_msg *nim)
138{
139	struct nss_ipv6_mc_rule_create_msg *nircm = &nim->msg.mc_rule_create;
140	uint32_t serial = (uint32_t)app_data;
141	struct ecm_db_connection_instance *ci;
142	struct ecm_front_end_connection_instance *feci;
143	struct ecm_nss_multicast_ipv6_connection_instance *nmci;
144	//ip_addr_t flow_ip;
145	//ip_addr_t return_ip;
146
147	/*TODO: If the response is NACK then decelerate the flow and flushes all rules */
148	DEBUG_TRACE("%p: update callback, response received from FW : %u\n", nim, nim->cm.response);
149
150	/*
151	 * Is this a response to a create message?
152	 */
153	if (nim->cm.type != NSS_IPV6_TX_CREATE_MC_RULE_MSG) {
154		DEBUG_ERROR("%p: multicast update callback with improper type: %d, serial: %u\n", nim, nim->cm.type, serial);
155		return;
156	}
157
158	/*
159	 * Is this a response to a update rule message?
160	 */
161	if ( !(nircm->rule_flags & NSS_IPV6_MC_RULE_CREATE_FLAG_MC_UPDATE)) {
162		DEBUG_ERROR("%p: multicast update callback with improper type: %d, serial: %u\n", nim, nim->cm.type, serial);
163		return;
164	}
165
166	/*
167	 * Look up ecm connection so that we can update the status.
168	 */
169	ci = ecm_db_connection_serial_find_and_ref(serial);
170	if (!ci) {
171		DEBUG_TRACE("%p: multicast update callback, connection not found, serial: %u\n", nim, serial);
172		return;
173	}
174
175	/*
176	 * Release ref held for this ack/nack response.
177	 * NOTE: It's okay to do this here, ci won't go away, because the ci is held as
178	 * a result of the ecm_db_connection_serial_find_and_ref()
179	 */
180	ecm_db_connection_deref(ci);
181
182	/*
183	 * Get the front end instance
184	 */
185	feci = ecm_db_connection_front_end_get_and_ref(ci);
186	nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
187	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
188
189	/*
190	 * Dump some useful trace information.
191	 */
192	DEBUG_TRACE("%p: Update accelerate response for connection: %p, serial: %u\n", nmci, feci->ci, serial);
193	DEBUG_TRACE("%p: valid_flags: %x\n", nmci, nircm->valid_flags);
194	//DEBUG_TRACE("%p: flow_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(flow_ip), nircm->tuple.flow_ident);
195	//DEBUG_TRACE("%p: return_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(return_ip), nircm->tuple.return_ident);
196	DEBUG_TRACE("%p: protocol: %d\n", nmci, nircm->tuple.protocol);
197
198	/*
199	 * Release the connection.
200	 */
201	feci->deref(feci);
202	ecm_db_connection_deref(ci);
203	return;
204}
205
206/*
207 * ecm_nss_multicast_ipv6_connection_create_callback()
208 * 	callback for handling create ack/nack calls for multicast create commands.
209 */
210static void ecm_nss_multicast_ipv6_connection_create_callback(void *app_data, struct nss_ipv6_msg *nim)
211{
212	struct nss_ipv6_mc_rule_create_msg *__attribute__((unused))nircm = &nim->msg.mc_rule_create;
213	uint32_t serial = (uint32_t)app_data;
214	struct ecm_db_connection_instance *ci;
215	struct ecm_front_end_connection_instance *feci;
216	struct ecm_nss_multicast_ipv6_connection_instance *nmci;
217	ip_addr_t flow_ip;
218	ip_addr_t return_ip;
219
220	/*
221	 * Is this a response to a create message?
222	 */
223	if (nim->cm.type != NSS_IPV6_TX_CREATE_MC_RULE_MSG) {
224		DEBUG_ERROR("%p: udp create callback with improper type: %d, serial: %u\n", nim, nim->cm.type, serial);
225		return;
226	}
227
228	/*
229	 * Look up ecm connection so that we can update the status.
230	 */
231	ci = ecm_db_connection_serial_find_and_ref(serial);
232	if (!ci) {
233		DEBUG_TRACE("%p: create callback, connection not found, serial: %u\n", nim, serial);
234		return;
235	}
236
237	/*
238	 * Release ref held for this ack/nack response.
239	 * NOTE: It's okay to do this here, ci won't go away, because the ci is held as
240	 * a result of the ecm_db_connection_serial_find_and_ref()
241	 */
242	ecm_db_connection_deref(ci);
243
244	/*
245	 * Get the front end instance
246	 */
247	feci = ecm_db_connection_front_end_get_and_ref(ci);
248	nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
249	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
250
251	ECM_NSS_IPV6_ADDR_TO_IP_ADDR(flow_ip, nircm->tuple.flow_ip);
252	ECM_NSS_IPV6_ADDR_TO_IP_ADDR(return_ip, nircm->tuple.return_ip);
253
254	/*
255	 * Dump some useful trace information.
256	 */
257	DEBUG_TRACE("%p: accelerate response for connection: %p, serial: %u\n", nmci, feci->ci, serial);
258	DEBUG_TRACE("%p: rule_flags: %x, valid_flags: %x\n", nmci, nircm->rule_flags, nircm->valid_flags);
259	DEBUG_TRACE("%p: flow_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(flow_ip), nircm->tuple.flow_ident);
260	DEBUG_TRACE("%p: return_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(return_ip), nircm->tuple.return_ident);
261	DEBUG_TRACE("%p: protocol: %d\n", nmci, nircm->tuple.protocol);
262
263	/*
264	 * Handle the creation result code.
265	 */
266	DEBUG_TRACE("%p: response: %d\n", nmci, nim->cm.response);
267	if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
268		/*
269		 * Creation command failed (specific reason ignored).
270		 */
271		DEBUG_TRACE("%p: accel nack: %d\n", nmci, nim->cm.error);
272		spin_lock_bh(&feci->lock);
273		DEBUG_ASSERT(feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING, "%p: Unexpected mode: %d\n", ci, feci->accel_mode);
274		feci->stats.ae_nack++;
275		feci->stats.ae_nack_total++;
276		if (nmci->base.stats.ae_nack >= nmci->base.stats.ae_nack_limit) {
277			/*
278			 * Too many NSS rejections
279			 */
280			feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_ACCEL_ENGINE;
281		} else {
282			/*
283			 * Revert to decelerated
284			 */
285			feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL;
286		}
287
288		/*
289		 * Clear any decelerate pending flag since we aren't accelerated anyway we can just clear this whether it is set or not
290		 */
291		nmci->base.stats.decelerate_pending = false;
292
293		/*
294		 * If connection is now defunct then set mode to ensure no further accel attempts occur
295		 */
296		if (feci->is_defunct) {
297			feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DEFUNCT;
298		}
299		spin_unlock_bh(&feci->lock);
300
301		/*
302		 * Release the connection.
303		 */
304		feci->deref(feci);
305		ecm_db_connection_deref(ci);
306		return;
307	}
308
309	spin_lock_bh(&feci->lock);
310	DEBUG_ASSERT(feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING, "%p: Unexpected mode: %d\n", ci, feci->accel_mode);
311
312	/*
313	 * If a flush occured before we got the ACK then our acceleration was effectively cancelled on us
314	 * GGG TODO This is a workaround for a NSS message OOO quirk, this should eventually be removed.
315	 */
316	if (nmci->base.stats.flush_happened) {
317		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL;
318		nmci->base.stats.flush_happened = false;
319
320		/*
321		 * We are decelerated, clear any pending flag as that is meaningless now.
322		 */
323		nmci->base.stats.decelerate_pending = false;
324
325		/*
326		 * Increement the no-action counter.  Our connectin was decelerated on us with no action occurring.
327		 */
328		nmci->base.stats.no_action_seen++;
329		spin_unlock_bh(&feci->lock);
330
331		/*
332		 * Release the connection.
333		 */
334		feci->deref(feci);
335		ecm_db_connection_deref(ci);
336		return;
337	}
338
339	/*
340	 * We got an ACK - we are accelerated.
341	 */
342	feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_ACCEL;
343
344	/*
345	 * Create succeeded, declare that we are accelerated.
346	 */
347	spin_lock_bh(&ecm_nss_ipv6_lock);
348	ecm_nss_multicast_ipv6_accelerated_count++;	/* Protocol specific counter */
349	ecm_nss_ipv6_accelerated_count++;		/* General running counter */
350	spin_unlock_bh(&ecm_nss_ipv6_lock);
351
352	/*
353	 * Clear any nack count
354	 */
355	nmci->base.stats.ae_nack = 0;
356
357	/*
358	 * Decelerate may have been attempted while we were accel pending.
359	 * If decelerate is pending then we need to begin deceleration :-(
360	 */
361	if (!nmci->base.stats.decelerate_pending) {
362
363		/*
364		 * Increement the no-action counter, this is reset if offload action is seen
365		 */
366		nmci->base.stats.no_action_seen++;
367
368		spin_unlock_bh(&feci->lock);
369
370		/*
371		 * Release the connection.
372		 */
373		feci->deref(feci);
374		ecm_db_connection_deref(ci);
375		return;
376	}
377
378	DEBUG_INFO("%p: Decelerate was pending\n", ci);
379	nmci->base.stats.decelerate_pending = false;
380	spin_unlock_bh(&feci->lock);
381
382	feci->decelerate(feci);
383
384	/*
385	 * Release the connection.
386	 */
387	feci->deref(feci);
388	ecm_db_connection_deref(ci);
389}
390
391/*
392 * ecm_nss_multicast_ipv6_connection_update_accelerate()
393 * 	Push destination interface list updates for a multicast connection
394 * 	to NSS
395 *
396 * 	This function receives a list of interfaces that have either left or joined the connection,
397 * 	and sends a 'multicast update' command to NSS to inform about these interface state changes.
398 */
399static int ecm_nss_multicast_ipv6_connection_update_accelerate(struct ecm_front_end_connection_instance *feci,
400							       struct ecm_multicast_if_update *rp)
401{
402	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
403	uint16_t regen_occurrances;
404	struct ecm_db_iface_instance *to_ifaces;
405	struct ecm_db_iface_instance *ii_temp;
406	struct ecm_db_iface_instance *ii_single;
407	struct ecm_db_iface_instance **ifaces;
408	struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
409	struct ecm_db_iface_instance *from_nss_iface;
410	int32_t *to_ifaces_first;
411	int32_t *to_ii_first;
412	struct nss_ipv6_msg *nim;
413	struct nss_ipv6_mc_rule_create_msg *create;
414	ip_addr_t addr;
415	ecm_db_iface_type_t from_iface_type = ECM_DB_IFACE_TYPE_COUNT;
416	ecm_db_iface_type_t to_iface_type = ECM_DB_IFACE_TYPE_COUNT;
417	int32_t ret, vif;
418	int32_t valid_vif_idx = 0;
419	int32_t from_ifaces_first;
420	int32_t to_nss_iface_id = 0;
421	int32_t from_nss_iface_id = 0;
422	uint8_t to_nss_iface_address[ETH_ALEN];
423	nss_tx_status_t nss_tx_status;
424	int32_t list_index;
425	int32_t to_mtu = 0;
426	int32_t interface_type_counts[ECM_DB_IFACE_TYPE_COUNT];
427	bool rule_invalid;
428	uint8_t dest_mac[ETH_ALEN];
429	int from_iface_identifier = 0;
430	int to_iface_bridge_identifier = 0;
431
432	DEBUG_INFO("%p: UPDATE Accel conn: %p\n", nmci, feci->ci);
433
434	/*
435	 * Get the re-generation occurrance counter of the connection.
436	 * We compare it again at the end - to ensure that the rule construction has seen no generation
437	 * changes during rule creation.
438	 */
439	regen_occurrances = ecm_db_connection_regeneration_occurrances_get(feci->ci);
440
441	nim = (struct nss_ipv6_msg *)vzalloc(sizeof(struct nss_ipv6_msg));
442	if (!nim) {
443		return -1;
444	}
445
446	nss_ipv6_msg_init(nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_CREATE_MC_RULE_MSG,
447			sizeof(struct nss_ipv6_mc_rule_create_msg),
448			ecm_nss_multicast_ipv6_connection_update_callback,
449			(void *)ecm_db_connection_serial_get(feci->ci));
450
451	create = &nim->msg.mc_rule_create;
452
453	/*
454	 * Construct an accel command.
455	 */
456	ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(feci->ci, &to_ifaces, &to_ifaces_first);
457	if (ret == 0) {
458		DEBUG_WARN("%p: Accel attempt failed - no interfaces in to_interfaces list!\n", nmci);
459		vfree(nim);
460		return -1;
461	}
462
463	from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(feci->ci, from_ifaces);
464	if (from_ifaces_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
465		DEBUG_WARN("%p: Accel attempt failed - no interfaces in from_interfaces list!\n", nmci);
466		ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
467		vfree(nim);
468		return -1;
469	}
470
471	create->ingress_vlan_tag[0] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED;
472	create->ingress_vlan_tag[1] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED;
473
474	/*
475	 * Set the source NSS interface identifier
476	 */
477	from_nss_iface = from_ifaces[from_ifaces_first];
478	from_nss_iface_id = ecm_db_iface_ae_interface_identifier_get(from_nss_iface);
479	if (from_nss_iface_id < 0) {
480                DEBUG_TRACE("%p: from_nss_iface_id: %d\n", nmci, from_nss_iface_id);
481		ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
482		ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
483		vfree(nim);
484		return -1;
485        }
486
487	create->src_interface_num = from_nss_iface_id;
488	from_nss_iface = from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX - 1];
489	from_iface_type = ecm_db_connection_iface_type_get(from_nss_iface);
490	from_iface_identifier = ecm_db_iface_interface_identifier_get(from_nss_iface);
491	ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
492
493	/*
494	 * Now examine the TO / DEST heirarchy list to construct the destination interface
495	 * information
496	 */
497	DEBUG_TRACE("%p: Examine to/dest heirarchy list\n", nmci);
498	rule_invalid = false;
499
500	/*
501	 * Loop through the list of interface updates
502	 */
503	for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
504#ifdef ECM_INTERFACE_VLAN_ENABLE
505		create->if_rule[vif].egress_vlan_tag[0] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED;
506		create->if_rule[vif].egress_vlan_tag[1] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED;
507#endif
508		/*
509		 * If there is no state change for an interface at this index,
510		 * then ignore
511		 */
512		if (!(rp->if_join_idx[vif] || rp->if_leave_idx[vif])) {
513			continue;
514		}
515
516		ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, vif);
517
518		/*
519		 * We have an update for this interface. Construct the interface information
520		 */
521		to_nss_iface_id = -1;
522		to_iface_type = ECM_DB_IFACE_TYPE_COUNT;
523		memset(interface_type_counts, 0, sizeof(interface_type_counts));
524		to_ii_first = ecm_db_multicast_if_first_get_at_index(to_ifaces_first, vif);
525
526		for (list_index = *to_ii_first; !rule_invalid && (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) {
527			struct ecm_db_iface_instance *ii;
528			ecm_db_iface_type_t ii_type;
529			char *ii_name;
530
531			ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, list_index);
532			ifaces = (struct ecm_db_iface_instance **)ii_single;
533			ii = *ifaces;
534			ii_type = ecm_db_connection_iface_type_get(ii);
535			ii_name = ecm_db_interface_type_to_string(ii_type);
536			DEBUG_TRACE("%p: list_index: %d, ii: %p, type: %d (%s)\n", nmci, list_index, ii, ii_type, ii_name);
537
538			/*
539			 * Extract information from this interface type if it is applicable to the rule.
540			 * Conflicting information may cause accel to be unsupported.
541			 */
542			switch (ii_type) {
543#ifdef ECM_INTERFACE_PPP_ENABLE
544				struct ecm_db_interface_info_pppoe pppoe_info;
545#endif
546#ifdef ECM_INTERFACE_VLAN_ENABLE
547				struct ecm_db_interface_info_vlan vlan_info;
548#endif
549
550			case ECM_DB_IFACE_TYPE_BRIDGE:
551				DEBUG_TRACE("%p: Bridge\n", nmci);
552				if (interface_type_counts[ii_type] != 0) {
553					/*
554					 * Cannot cascade bridges
555					 */
556					rule_invalid = true;
557					DEBUG_TRACE("%p: Bridge - ignore additional\n", nmci);
558					break;
559				}
560
561				ecm_db_iface_bridge_address_get(ii, to_nss_iface_address);
562				to_iface_type = ECM_DB_IFACE_TYPE_BRIDGE;
563				to_iface_bridge_identifier = ecm_db_iface_interface_identifier_get(ii);
564				DEBUG_TRACE("%p: Bridge - mac: %pM\n", nmci, to_nss_iface_address);
565				break;
566			case ECM_DB_IFACE_TYPE_ETHERNET:
567				 DEBUG_TRACE("%p: Ethernet\n", nmci);
568				if (interface_type_counts[ii_type] != 0) {
569
570					/*
571					 * Ignore additional mac addresses, these are usually as a result of address propagation
572					 * from bridges down to ports etc. */
573
574					DEBUG_TRACE("%p: Ethernet - ignore additional\n", nmci);
575					break;
576				}
577
578				/*
579				 * Can only handle one MAC, the first outermost mac.
580				 */
581				ecm_db_iface_ethernet_address_get(ii, to_nss_iface_address);
582				to_mtu = (uint32_t)ecm_db_connection_to_iface_mtu_get(feci->ci);
583				to_nss_iface_id = ecm_db_iface_ae_interface_identifier_get(ii);
584				if (to_nss_iface_id < 0) {
585					DEBUG_TRACE("%p: to_nss_iface_id: %d\n", nmci, to_nss_iface_id);
586					ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
587					vfree(nim);
588					return -1;
589			        }
590
591				DEBUG_TRACE("%p: Ethernet - mac: %pM\n", nmci, to_nss_iface_address);
592				break;
593			case ECM_DB_IFACE_TYPE_PPPOE:
594#ifdef ECM_INTERFACE_PPP_ENABLE
595				/*
596				 * More than one PPPoE in the list is not valid!
597				 */
598				if (interface_type_counts[ii_type] != 0) {
599					DEBUG_TRACE("%p: PPPoE - additional unsupported\n", nmci);
600					rule_invalid = true;
601					break;
602				}
603
604				/*
605				 * Copy pppoe session info to the creation structure.
606				 */
607				ecm_db_iface_pppoe_session_info_get(ii, &pppoe_info);
608				create->if_rule[valid_vif_idx].pppoe_session_id = pppoe_info.pppoe_session_id;
609				memcpy(create->if_rule[valid_vif_idx].pppoe_remote_mac, pppoe_info.remote_mac, ETH_ALEN);
610
611				DEBUG_TRACE("%p: PPPoE - session: %x, mac: %pM\n", nmci, create->if_rule[valid_vif_idx].pppoe_session_id, create->if_rule[valid_vif_idx].pppoe_remote_mac);
612#else
613				DEBUG_TRACE("%p: PPPoE - unsupported\n", nmci);
614				rule_invalid = true;
615#endif
616				break;
617			case ECM_DB_IFACE_TYPE_VLAN:
618#ifdef ECM_INTERFACE_VLAN_ENABLE
619				DEBUG_TRACE("%p: VLAN\n", nmci);
620				if (interface_type_counts[ii_type] > 1) {
621
622					/*
623					 * Can only support two vlans
624					 */
625					rule_invalid = true;
626					DEBUG_TRACE("%p: VLAN - additional unsupported\n", nmci);
627					break;
628				}
629				ecm_db_iface_vlan_info_get(ii, &vlan_info);
630				create->if_rule[valid_vif_idx].egress_vlan_tag[interface_type_counts[ii_type]] = ((vlan_info.vlan_tpid << 16) | vlan_info.vlan_tag);
631
632				/*
633				 * If we have not yet got an ethernet mac then take this one (very unlikely as mac should have been propagated to the slave (outer) device
634				 */
635				if (interface_type_counts[ECM_DB_IFACE_TYPE_ETHERNET] == 0) {
636					memcpy(to_nss_iface_address, vlan_info.address, ETH_ALEN);
637					interface_type_counts[ECM_DB_IFACE_TYPE_ETHERNET]++;
638					DEBUG_TRACE("%p: VLAN use mac: %pM\n", nmci, to_nss_iface_address);
639				}
640				create->if_rule[valid_vif_idx].valid_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_VLAN_VALID;
641				DEBUG_TRACE("%p: vlan tag: %x\n", nmci, create->if_rule[valid_vif_idx].egress_vlan_tag[interface_type_counts[ii_type]]);
642#else
643				rule_invalid = true;
644				DEBUG_TRACE("%p: VLAN - unsupported\n", nmci);
645#endif
646				break;
647			default:
648				DEBUG_TRACE("%p: Ignoring: %d (%s)\n", nmci, ii_type, ii_name);
649			}
650
651			/*
652			 * Seen an interface of this type
653			 */
654			interface_type_counts[ii_type]++;
655		}
656
657		if (rule_invalid) {
658			DEBUG_WARN("%p: to/dest Rule invalid\n", nmci);
659			ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
660			vfree(nim);
661			return -1;
662		}
663
664		/*
665		 * Is this a valid interface?
666		 */
667		if (to_nss_iface_id != -1) {
668			bool is_bridge;
669			create->if_rule[valid_vif_idx].if_num = to_nss_iface_id;
670			create->if_rule[valid_vif_idx].if_mtu = to_mtu;
671			if (rp->if_join_idx[vif]) {
672
673				/*
674				 * The interface has joined the group
675				 */
676				create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_JOIN;
677			} else if (rp->if_leave_idx[vif]) {
678
679				/*
680				 * The interface has left the group
681				 */
682				create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_LEAVE;
683			}
684
685			is_bridge = !ecm_db_connection_is_routed_get(feci->ci);
686
687			/*
688			 * Do not set the ROUTED flag for pure bridged interfaces
689			 */
690			if (((from_iface_type == ECM_DB_IFACE_TYPE_BRIDGE &&
691				to_iface_type == ECM_DB_IFACE_TYPE_BRIDGE) || is_bridge) &&
692				(to_iface_bridge_identifier == from_iface_identifier)) {
693				uint8_t from_nss_iface_address[ETH_ALEN];
694				ecm_db_connection_from_node_address_get(feci->ci, (uint8_t *)from_nss_iface_address);
695				memcpy(create->if_rule[valid_vif_idx].if_mac, from_nss_iface_address, ETH_ALEN);
696				create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_BRIDGE_FLOW;
697			} else {
698				memcpy(create->if_rule[valid_vif_idx].if_mac, to_nss_iface_address, ETH_ALEN);
699				create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_ROUTED_FLOW;
700			}
701
702			valid_vif_idx++;
703		}
704	}
705
706	/*
707	 * Set number of interface updates in the update rule
708	 */
709	create->if_count = valid_vif_idx;
710
711	/*
712	 * Set the UPDATE flag
713	 */
714	create->rule_flags |= NSS_IPV6_MC_RULE_CREATE_FLAG_MC_UPDATE;
715
716	/*
717	 * Set protocol
718	 */
719	create->tuple.protocol = IPPROTO_UDP;
720
721	/*
722	 * The src_ip is where the connection established from
723	 */
724	ecm_db_connection_from_address_get(feci->ci, addr);
725	ECM_IP_ADDR_TO_NSS_IPV6_ADDR(create->tuple.flow_ip, addr);
726
727
728	/*
729	 * The destination address is what the destination IP is translated to as it is forwarded to the next interface.
730	 * For egress this would yield the normal wan host and for ingress this would correctly NAT back to the LAN host
731	 */
732	ecm_db_connection_to_address_get(feci->ci, addr);
733	ECM_IP_ADDR_TO_NSS_IPV6_ADDR(create->tuple.return_ip, addr);
734
735	/*
736	 * Same approach as above for port information
737	 */
738	create->tuple.flow_ident = ecm_db_connection_from_port_get(feci->ci);
739	create->tuple.return_ident = ecm_db_connection_to_port_get(feci->ci);
740
741	/*
742	 * Destination Node(MAC) address. This address will be same for all to side intefaces
743	 */
744	ecm_db_connection_to_node_address_get(feci->ci, dest_mac);
745	memcpy(create->dest_mac, dest_mac, ETH_ALEN);
746
747	ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
748
749	for (vif = 0; vif < valid_vif_idx ; vif++) {
750		DEBUG_TRACE("ACCEL UPDATE %p: UDP Accelerate connection %p\n"
751				"Rule flag: %x\n"
752				"Vif: %d\n"
753				"Protocol: %d\n"
754				"from_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n"
755				"to_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n"
756				"to_mtu: %u\n"
757				"to_mac: %pM\n"
758				"dest_iface_num: %u\n"
759				"out_vlan[0] %x\n"
760				"out_vlan[1] %x\n",
761				nmci,
762				feci->ci,
763				create->if_rule[vif].rule_flags,
764				vif,
765				create->tuple.protocol,
766				ECM_IP_ADDR_TO_OCTAL(create->tuple.flow_ip), create->tuple.flow_ident,
767				ECM_IP_ADDR_TO_OCTAL(create->tuple.return_ip), create->tuple.return_ident,
768				create->if_rule[vif].if_mtu,
769				create->if_rule[vif].if_mac,
770				create->if_rule[vif].if_num,
771				create->if_rule[vif].egress_vlan_tag[0],
772				create->if_rule[vif].egress_vlan_tag[1]);
773
774	}
775
776	/*
777	 * Now that the rule has been constructed we re-compare the generation occurrance counter.
778	 * If there has been a change then we abort because the rule may have been created using
779	 * unstable data - especially if another thread has begun regeneration of the connection state.
780	 * NOTE: This does not prevent a regen from being flagged immediately after this line of code either,
781	 * or while the acceleration rule is in flight to the nss.
782	 * This is only to check for consistency of rule state - not that the state is stale.
783	 */
784	if (regen_occurrances != ecm_db_connection_regeneration_occurrances_get(feci->ci)) {
785		DEBUG_INFO("%p: connection:%p regen occurred - aborting accel rule.\n", feci, feci->ci);
786		vfree(nim);
787		return -1;
788	}
789
790	/*
791	 * Ref the connection before issuing an NSS rule
792	 * This ensures that when the NSS responds to the command - which may even be immediately -
793	 * the callback function can trust the correct ref was taken for its purpose.
794	 * NOTE: remember that this will also implicitly hold the feci.
795	 */
796	ecm_db_connection_ref(feci->ci);
797
798	/*
799	 * We are about to issue the command, record the time of transmission
800	 */
801	spin_lock_bh(&feci->lock);
802	feci->stats.cmd_time_begun = jiffies;
803	spin_unlock_bh(&feci->lock);
804
805	/*
806	 * Call the rule create function
807	 */
808	nss_tx_status = nss_ipv6_tx(ecm_nss_ipv6_nss_ipv6_mgr, nim);
809	if (nss_tx_status == NSS_TX_SUCCESS) {
810		spin_lock_bh(&feci->lock);
811		nmci->base.stats.driver_fail = 0;		/* Reset */
812		spin_unlock_bh(&feci->lock);
813		vfree(nim);
814		return 0;
815	}
816
817	/*
818	 * Revert accel mode if necessary
819	 */
820	DEBUG_WARN("%p: ACCEL UPDATE attempt failed\n", nmci);
821
822	/*
823	 * Release that ref!
824	 */
825	ecm_db_connection_deref(feci->ci);
826
827	vfree(nim);
828
829	/*
830	 * TX failed
831	 */
832	spin_lock_bh(&feci->lock);
833	feci->stats.driver_fail_total++;
834	feci->stats.driver_fail++;
835	if (nmci->base.stats.driver_fail >= nmci->base.stats.driver_fail_limit) {
836		DEBUG_WARN("%p: Accel failed - driver fail limit\n", nmci);
837		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
838	}
839	spin_unlock_bh(&feci->lock);
840	return -1;
841}
842
843/*
844 * ecm_nss_multicast_ipv6_connection_accelerate()
845 * 	Accelerate a multicast UDP connection
846 */
847static void ecm_nss_multicast_ipv6_connection_accelerate(struct ecm_front_end_connection_instance *feci,
848									struct ecm_classifier_process_response *pr)
849{
850	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
851	uint16_t regen_occurrances;
852	struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX];
853	struct ecm_db_iface_instance *from_nss_iface;
854	int32_t from_ifaces_first;
855	struct ecm_db_iface_instance *to_ifaces;
856	struct ecm_db_iface_instance *ii_temp;
857	struct ecm_db_iface_instance *ii_single;
858	struct ecm_db_iface_instance **ifaces;
859	struct nss_ipv6_msg *nim;
860	ecm_db_iface_type_t from_iface_type = ECM_DB_IFACE_TYPE_COUNT;
861	ecm_db_iface_type_t to_iface_type = ECM_DB_IFACE_TYPE_COUNT;
862	int32_t *to_ifaces_first;
863	int32_t *to_ii_first;
864	int32_t from_nss_iface_id;
865	int32_t to_nss_iface_id;
866	uint8_t to_nss_iface_address[ETH_ALEN];
867	ip_addr_t addr;
868	struct nss_ipv6_mc_rule_create_msg *create;
869	struct ecm_classifier_instance *assignments[ECM_CLASSIFIER_TYPES];
870	int aci_index;
871	int32_t vif, ret;
872	int assignment_count;
873	int from_iface_identifier = 0;
874	int to_iface_bridge_identifier = 0;
875	nss_tx_status_t nss_tx_status;
876	int32_t list_index;
877	int32_t valid_vif_idx = 0;
878	int32_t interface_type_counts[ECM_DB_IFACE_TYPE_COUNT];
879	uint8_t dest_mac[ETH_ALEN];
880	bool rule_invalid;
881	ecm_front_end_acceleration_mode_t result_mode;
882
883	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
884
885	/*
886	 * Get the re-generation occurrance counter of the connection.
887	 * We compare it again at the end - to ensure that the rule construction has seen no generation
888	 * changes during rule creation.
889	 */
890	regen_occurrances = ecm_db_connection_regeneration_occurrances_get(feci->ci);
891
892	/*
893	 * Can this connection be accelerated at all?
894	 */
895	if (!ecm_nss_ipv6_accel_pending_set(feci)) {
896		DEBUG_TRACE("%p: Acceleration denied: %p\n", feci, feci->ci);
897		return;
898	}
899
900	/*
901	 * Construct an accel command.
902	 * Initialise Multicast create structure.
903	 * NOTE: We leverage the app_data void pointer to be our 32 bit connection serial number.
904	 * When we get it back we re-cast it to a uint32 and do a faster connection lookup.
905	 */
906	nim = (struct nss_ipv6_msg *)kzalloc(sizeof(struct nss_ipv6_msg), GFP_ATOMIC | __GFP_NOWARN);
907	if (!nim) {
908		return;
909	}
910
911	nss_ipv6_msg_init(nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_CREATE_MC_RULE_MSG,
912			sizeof(struct nss_ipv6_mc_rule_create_msg),
913			 ecm_nss_multicast_ipv6_connection_create_callback,
914			(void *)ecm_db_connection_serial_get(feci->ci));
915
916	create = &nim->msg.mc_rule_create;
917
918	/*
919	 * Populate the multicast creation structure
920	 */
921	from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(feci->ci, from_ifaces);
922	if (from_ifaces_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
923		DEBUG_WARN("%p: Accel attempt failed - no interfaces in from_interfaces list!\n", nmci);
924		kfree(nim);
925		return;
926	}
927
928	create->ingress_vlan_tag[0] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED;
929	create->ingress_vlan_tag[1] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED;
930	from_nss_iface = from_ifaces[from_ifaces_first];
931	from_nss_iface_id = ecm_db_iface_ae_interface_identifier_get(from_nss_iface);
932
933	if (from_nss_iface_id < 0) {
934		DEBUG_TRACE("%p: from_nss_iface_id: %d\n", nmci, from_nss_iface_id);
935		ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
936		kfree(nim);
937		return;
938	}
939
940	memset(interface_type_counts, 0, sizeof(interface_type_counts));
941	rule_invalid = false;
942	for (list_index = from_ifaces_first; list_index < ECM_DB_IFACE_HEIRARCHY_MAX; list_index++) {
943		struct ecm_db_iface_instance *ii;
944		ecm_db_iface_type_t ii_type;
945		char *ii_name;
946
947		ii = from_ifaces[list_index];
948		ii_type = ecm_db_connection_iface_type_get(ii);
949		ii_name = ecm_db_interface_type_to_string(ii_type);
950		DEBUG_TRACE("%p: list_index: %d, ii: %p, type: %d (%s)\n", nmci, list_index, ii, ii_type, ii_name);
951
952		/*
953		 * Extract information from this interface type if it is applicable to the rule.
954		 * Conflicting information may cause accel to be unsupported.
955		 */
956		switch (ii_type) {
957#ifdef ECM_INTERFACE_VLAN_ENABLE
958			struct ecm_db_interface_info_vlan vlan_info;
959#endif
960		case ECM_DB_IFACE_TYPE_BRIDGE:
961			DEBUG_TRACE("%p: Bridge\n", nmci);
962			from_iface_type = ECM_DB_IFACE_TYPE_BRIDGE;
963			from_iface_identifier = ecm_db_iface_interface_identifier_get(ii);
964			break;
965		case ECM_DB_IFACE_TYPE_VLAN:
966#ifdef ECM_INTERFACE_VLAN_ENABLE
967			DEBUG_TRACE("%p: VLAN\n", nmci);
968			if (interface_type_counts[ii_type] > 1) {
969
970				/*
971				 * Can only support two vlans
972				 */
973				rule_invalid = true;
974				DEBUG_TRACE("%p: VLAN - additional unsupported\n", nmci);
975				break;
976			}
977			ecm_db_iface_vlan_info_get(ii, &vlan_info);
978			create->ingress_vlan_tag[interface_type_counts[ii_type]] = ((vlan_info.vlan_tpid << 16) | vlan_info.vlan_tag);
979			create->valid_flags |= NSS_IPV6_MC_RULE_CREATE_FLAG_INGRESS_VLAN_VALID;
980			DEBUG_TRACE("%p: vlan tag: %x\n", nmci, create->ingress_vlan_tag[interface_type_counts[ii_type]]);
981#else
982			rule_invalid = true;
983			DEBUG_TRACE("%p: VLAN - unsupported\n", nmci);
984#endif
985			break;
986		default:
987			DEBUG_TRACE("%p: Ignoring: %d (%s)\n", nmci, ii_type, ii_name);
988		}
989		interface_type_counts[ii_type]++;
990	}
991
992	ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first);
993
994	ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(feci->ci, &to_ifaces, &to_ifaces_first);
995	if (!ret) {
996		DEBUG_WARN("%p: Accel attempt failed - no multicast interfaces in to_interfaces list!\n", nmci);
997		kfree(nim);
998		return;
999	}
1000
1001
1002	/*
1003	 * Now examine the TO / DEST heirarchy list to construct the destination part of the rule
1004	 */
1005	DEBUG_TRACE("%p: Examine to/dest heirarchy list\n", nmci);
1006	rule_invalid = false;
1007	for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
1008		int32_t to_mtu = 0;
1009		to_nss_iface_id = -1;
1010		to_iface_type = ECM_DB_IFACE_TYPE_COUNT;
1011
1012#ifdef ECM_INTERFACE_VLAN_ENABLE
1013		create->if_rule[vif].egress_vlan_tag[0] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED;
1014		create->if_rule[vif].egress_vlan_tag[1] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED;
1015#endif
1016
1017		ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, vif);
1018		to_ii_first = ecm_db_multicast_if_first_get_at_index(to_ifaces_first, vif);
1019		memset(interface_type_counts, 0, sizeof(interface_type_counts));
1020
1021		for (list_index = *to_ii_first; !rule_invalid && (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) {
1022			struct ecm_db_iface_instance *ii;
1023			ecm_db_iface_type_t ii_type;
1024			char *ii_name;
1025
1026			ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, list_index);
1027			ifaces = (struct ecm_db_iface_instance **)ii_single;
1028			ii = *ifaces;
1029			ii_type = ecm_db_connection_iface_type_get(ii);
1030			ii_name = ecm_db_interface_type_to_string(ii_type);
1031
1032			DEBUG_TRACE("%p: list_index: %d, ii: %p, type: %d (%s)\n", nmci, list_index, ii, ii_type, ii_name);
1033
1034			/*
1035			 * Extract information from this interface type if it is applicable to the rule.
1036			 * Conflicting information may cause accel to be unsupported.
1037			 */
1038			switch (ii_type) {
1039#ifdef ECM_INTERFACE_PPP_ENABLE
1040				struct ecm_db_interface_info_pppoe pppoe_info;
1041#endif
1042#ifdef ECM_INTERFACE_VLAN_ENABLE
1043				struct ecm_db_interface_info_vlan vlan_info;
1044				struct net_device *vlan_out_dev = NULL;
1045				uint32_t vlan_prio = 0;
1046#endif
1047			case ECM_DB_IFACE_TYPE_BRIDGE:
1048
1049				/*
1050				 * TODO: Find and set the bridge/route flag for this interface
1051				 */
1052				DEBUG_TRACE("%p: Bridge\n", nmci);
1053				if (interface_type_counts[ii_type] != 0) {
1054
1055					/*
1056					 * Cannot cascade bridges
1057					 */
1058					rule_invalid = true;
1059					DEBUG_TRACE("%p: Bridge - ignore additional\n", nmci);
1060					break;
1061				}
1062				ecm_db_iface_bridge_address_get(ii, to_nss_iface_address);
1063				to_iface_type = ECM_DB_IFACE_TYPE_BRIDGE;
1064				to_iface_bridge_identifier = ecm_db_iface_interface_identifier_get(ii);
1065				DEBUG_TRACE("%p: Bridge - mac: %pM\n", nmci, to_nss_iface_address);
1066				break;
1067			case ECM_DB_IFACE_TYPE_ETHERNET:
1068				DEBUG_TRACE("%p: Ethernet\n", nmci);
1069				if (interface_type_counts[ii_type] != 0) {
1070
1071					/*
1072					 * Ignore additional mac addresses, these are usually as a result of address propagation
1073					 * from bridges down to ports etc.
1074					 */
1075					DEBUG_TRACE("%p: Ethernet - ignore additional\n", nmci);
1076					break;
1077				}
1078
1079				/*
1080				 * Can only handle one MAC, the first outermost mac.
1081				 */
1082				ecm_db_iface_ethernet_address_get(ii, to_nss_iface_address);
1083				to_mtu = (uint32_t)ecm_db_connection_to_iface_mtu_get(feci->ci);
1084				to_nss_iface_id = ecm_db_iface_ae_interface_identifier_get(ii);
1085				if (to_nss_iface_id < 0) {
1086					DEBUG_TRACE("%p: to_nss_iface_id: %d\n", nmci, to_nss_iface_id);
1087					ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
1088					kfree(nim);
1089					return;
1090			        }
1091
1092				DEBUG_TRACE("%p: Ethernet - mac: %pM\n", nmci, to_nss_iface_address);
1093				break;
1094			case ECM_DB_IFACE_TYPE_PPPOE:
1095#ifdef ECM_INTERFACE_PPP_ENABLE
1096				/*
1097				 * More than one PPPoE in the list is not valid!
1098				 */
1099				if (interface_type_counts[ii_type] != 0) {
1100					DEBUG_TRACE("%p: PPPoE - additional unsupported\n", nmci);
1101					rule_invalid = true;
1102					break;
1103				}
1104
1105				/*
1106				 * Copy pppoe session info to the creation structure.
1107				 */
1108				ecm_db_iface_pppoe_session_info_get(ii, &pppoe_info);
1109				create->if_rule[valid_vif_idx].pppoe_session_id = pppoe_info.pppoe_session_id;
1110				memcpy(create->if_rule[valid_vif_idx].pppoe_remote_mac, pppoe_info.remote_mac, ETH_ALEN);
1111				create->if_rule[valid_vif_idx].valid_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_PPPOE_VALID;
1112				DEBUG_TRACE("%p: PPPoE - session: %x, mac: %pM\n", nmci, create->if_rule[valid_vif_idx].pppoe_session_id, create->if_rule[valid_vif_idx].pppoe_remote_mac);
1113#else
1114				DEBUG_TRACE("%p: PPPoE - unsupported\n", nmci);
1115				rule_invalid = true;
1116#endif
1117				break;
1118			case ECM_DB_IFACE_TYPE_VLAN:
1119#ifdef ECM_INTERFACE_VLAN_ENABLE
1120				DEBUG_TRACE("%p: VLAN\n", nmci);
1121				if (interface_type_counts[ii_type] > 1) {
1122					/*
1123					 * Can only support two vlans
1124					 */
1125					rule_invalid = true;
1126					DEBUG_TRACE("%p: VLAN - additional unsupported\n", nmci);
1127					break;
1128				}
1129
1130				ecm_db_iface_vlan_info_get(ii, &vlan_info);
1131				create->if_rule[valid_vif_idx].egress_vlan_tag[interface_type_counts[ii_type]] = ((vlan_info.vlan_tpid << 16) | vlan_info.vlan_tag);
1132
1133				vlan_out_dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii));
1134				if (vlan_out_dev) {
1135					vlan_prio = vlan_dev_get_egress_prio(vlan_out_dev, pr->flow_qos_tag);
1136					create->if_rule[valid_vif_idx].egress_vlan_tag[interface_type_counts[ii_type]] |= vlan_prio;
1137					dev_put(vlan_out_dev);
1138					vlan_out_dev = NULL;
1139				}
1140
1141				/*
1142				 * If we have not yet got an ethernet mac then take this one (very unlikely as mac should have been propagated to the slave (outer) device
1143				 */
1144				if (interface_type_counts[ECM_DB_IFACE_TYPE_ETHERNET] == 0) {
1145					memcpy(to_nss_iface_address, vlan_info.address, ETH_ALEN);
1146					interface_type_counts[ECM_DB_IFACE_TYPE_ETHERNET]++;
1147					DEBUG_TRACE("%p: VLAN use mac: %pM\n", nmci, to_nss_iface_address);
1148				}
1149				create->if_rule[valid_vif_idx].valid_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_VLAN_VALID;
1150				DEBUG_TRACE("%p: vlan tag: %x\n", nmci, create->if_rule[vif].egress_vlan_tag[interface_type_counts[ii_type]]);
1151#else
1152				rule_invalid = true;
1153				DEBUG_TRACE("%p: VLAN - unsupported\n", nmci);
1154#endif
1155				break;
1156			default:
1157				DEBUG_TRACE("%p: Ignoring: %d (%s)\n", nmci, ii_type, ii_name);
1158			}
1159
1160			/*
1161			 * Seen an interface of this type
1162			 */
1163			interface_type_counts[ii_type]++;
1164		}
1165
1166		if (rule_invalid) {
1167			DEBUG_WARN("%p: to/dest Rule invalid\n", nmci);
1168			ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
1169			kfree(nim);
1170			return;
1171		}
1172
1173		/*
1174		 * Populate the interface details for a valid interface in the multicast destination
1175		 * interface list.
1176		 */
1177		if (to_nss_iface_id != -1) {
1178			bool is_bridge;
1179			create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_JOIN;
1180			create->if_rule[valid_vif_idx].if_num = to_nss_iface_id;
1181			create->if_rule[valid_vif_idx].if_mtu = to_mtu;
1182
1183			is_bridge = !ecm_db_connection_is_routed_get(feci->ci);
1184
1185			/*
1186			 * Identify if the destination interface blongs to pure bridge or routed flow.
1187			 */
1188			if (((from_iface_type == ECM_DB_IFACE_TYPE_BRIDGE &&
1189				to_iface_type == ECM_DB_IFACE_TYPE_BRIDGE) || is_bridge) &&
1190				(from_iface_identifier == to_iface_bridge_identifier)) {
1191				uint8_t from_nss_iface_address[ETH_ALEN];
1192				ecm_db_connection_from_node_address_get(feci->ci, (uint8_t *)from_nss_iface_address);
1193				memcpy(create->if_rule[valid_vif_idx].if_mac, from_nss_iface_address, ETH_ALEN);
1194				create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_BRIDGE_FLOW;
1195			} else {
1196				memcpy(create->if_rule[valid_vif_idx].if_mac, to_nss_iface_address, ETH_ALEN);
1197				create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_ROUTED_FLOW;
1198			}
1199
1200			valid_vif_idx++;
1201		}
1202	}
1203
1204	create->if_count = valid_vif_idx;
1205	create->src_interface_num = from_nss_iface_id;
1206
1207	/*
1208	 * Set up the flow qos tags
1209	 */
1210	create->qos_tag = (uint32_t)pr->flow_qos_tag;
1211
1212	/*
1213	 * DSCP information?
1214	 */
1215	if (pr->process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DSCP) {
1216			create->egress_dscp = pr->flow_dscp;
1217			create->valid_flags |= NSS_IPV6_MC_RULE_CREATE_FLAG_DSCP_MARKING_VALID;
1218	}
1219
1220	ecm_db_connection_to_node_address_get(feci->ci, dest_mac);
1221	memcpy(create->dest_mac, dest_mac, ETH_ALEN);
1222
1223	/*
1224	 * Set protocol
1225	 */
1226	create->tuple.protocol = IPPROTO_UDP;
1227
1228	/*
1229	 * The src_ip is where the connection established from
1230	 */
1231	ecm_db_connection_from_address_get(feci->ci, addr);
1232	ECM_IP_ADDR_TO_NSS_IPV6_ADDR(create->tuple.flow_ip, addr);
1233
1234
1235	/*
1236	 * The destination address is what the destination IP is translated to as it is forwarded to the next interface.
1237	 * For egress this would yield the normal wan host and for ingress this would correctly NAT back to the LAN host
1238	 */
1239	ecm_db_connection_to_address_get(feci->ci, addr);
1240	ECM_IP_ADDR_TO_NSS_IPV6_ADDR(create->tuple.return_ip, addr);
1241
1242	/*
1243	 * Same approach as above for port information
1244	 */
1245	create->tuple.flow_ident = ecm_db_connection_from_port_get(feci->ci);
1246	create->tuple.return_ident = ecm_db_connection_to_port_get(feci->ci);
1247
1248	/*
1249	 * Sync our creation command from the assigned classifiers to get specific additional creation rules.
1250	 * NOTE: These are called in ascending order of priority and so the last classifier (highest) shall
1251	 * override any preceding classifiers.
1252	 * This also gives the classifiers a chance to see that acceleration is being attempted.
1253	 */
1254	assignment_count = ecm_db_connection_classifier_assignments_get_and_ref(feci->ci, assignments);
1255	for (aci_index = 0; aci_index < assignment_count; ++aci_index) {
1256		struct ecm_classifier_instance *aci;
1257		struct ecm_classifier_rule_create ecrc;
1258		/*
1259		 * NOTE: The current classifiers do not sync anything to the underlying accel engines.
1260		 * In the future, if any of the classifiers wants to pass any parameter, these parameters
1261		 * should be received via this object and copied to the accel engine's create object (nircm).
1262		*/
1263		aci = assignments[aci_index];
1264		DEBUG_TRACE("%p: sync from: %p, type: %d\n", nmci, aci, aci->type_get(aci));
1265		aci->sync_from_v6(aci, &ecrc);
1266	}
1267	ecm_db_connection_assignments_release(assignment_count, assignments);
1268
1269	/*
1270	 * Release the interface lists
1271	 */
1272	ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first);
1273
1274	for (vif = 0; vif < valid_vif_idx ; vif++){
1275		DEBUG_TRACE("%p: UDP Accelerate connection %p\n"
1276			"Vif: %d\n"
1277			"Protocol: %d\n"
1278			"to_mtu: %u\n"
1279			"from_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n"
1280			"to_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n"
1281			"to_mac: %pM\n"
1282			"dest_iface_num: %u\n"
1283			"in_vlan[0] %x\n"
1284			"in_vlan[1] %x\n"
1285			"out_vlan[0] %x\n"
1286			"out_vlan[1] %x\n",
1287			nmci,
1288			feci->ci,
1289			vif,
1290			create->tuple.protocol,
1291			create->if_rule[vif].if_mtu,
1292			ECM_IP_ADDR_TO_OCTAL(create->tuple.flow_ip), create->tuple.flow_ident,
1293			ECM_IP_ADDR_TO_OCTAL(create->tuple.return_ip), create->tuple.return_ident,
1294			create->if_rule[vif].if_mac,
1295			create->if_rule[vif].if_num,
1296			create->ingress_vlan_tag[0],
1297			create->ingress_vlan_tag[1],
1298			create->if_rule[vif].egress_vlan_tag[0],
1299			create->if_rule[vif].egress_vlan_tag[1]);
1300	}
1301
1302	/*
1303	 * Now that the rule has been constructed we re-compare the generation occurrance counter.
1304	 * If there has been a change then we abort because the rule may have been created using
1305	 * unstable data - especially if another thread has begun regeneration of the connection state.
1306	 * NOTE: This does not prevent a regen from being flagged immediately after this line of code either,
1307	 * or while the acceleration rule is in flight to the nss.
1308	 * This is only to check for consistency of rule state - not that the state is stale.
1309	 * Remember that the connection is marked as "accel pending state" so if a regen is flagged immediately
1310	 * after this check passes, the connection will be decelerated and refreshed very quickly.
1311	 */
1312	if (regen_occurrances != ecm_db_connection_regeneration_occurrances_get(feci->ci)) {
1313		DEBUG_INFO("%p: connection:%p regen occurred - aborting accel rule.\n", feci, feci->ci);
1314		ecm_nss_ipv6_accel_pending_clear(feci, ECM_FRONT_END_ACCELERATION_MODE_DECEL);
1315		kfree(nim);
1316		return;
1317	}
1318
1319	/*
1320	 * Ref the connection before issuing an NSS rule
1321	 * This ensures that when the NSS responds to the command - which may even be immediately -
1322	 * the callback function can trust the correct ref was taken for its purpose.
1323	 * NOTE: remember that this will also implicitly hold the feci.
1324	 */
1325	ecm_db_connection_ref(feci->ci);
1326
1327	/*
1328	 * We are about to issue the command, record the time of transmission
1329	 */
1330	spin_lock_bh(&feci->lock);
1331	feci->stats.cmd_time_begun = jiffies;
1332	spin_unlock_bh(&feci->lock);
1333
1334	/*
1335	 * Call the rule create function
1336	 */
1337	nss_tx_status = nss_ipv6_tx(ecm_nss_ipv6_nss_ipv6_mgr, nim);
1338	if (nss_tx_status == NSS_TX_SUCCESS) {
1339
1340		/*
1341		 * Reset the driver_fail count - transmission was okay here.
1342		 */
1343		spin_lock_bh(&feci->lock);
1344		nmci->base.stats.driver_fail = 0;	/* Reset */
1345		spin_unlock_bh(&feci->lock);
1346		kfree(nim);
1347		return;
1348	}
1349
1350	/*
1351	 * Release that ref!
1352	 */
1353	ecm_db_connection_deref(feci->ci);
1354
1355	/*
1356	 * TX failed
1357	 */
1358	spin_lock_bh(&feci->lock);
1359	DEBUG_ASSERT(feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING, "%p: accel mode unexpected: %d\n", nmci, feci->accel_mode);
1360	feci->stats.driver_fail_total++;
1361	feci->stats.driver_fail++;
1362	if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
1363		DEBUG_WARN("%p: Accel failed - driver fail limit\n", nmci);
1364		result_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
1365	} else {
1366		result_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL;
1367	}
1368
1369	spin_lock_bh(&ecm_nss_ipv6_lock);
1370	_ecm_nss_ipv6_accel_pending_clear(feci, result_mode);
1371	spin_unlock_bh(&ecm_nss_ipv6_lock);
1372
1373	spin_unlock_bh(&feci->lock);
1374	kfree(nim);
1375	return;
1376}
1377
1378/*
1379 * ecm_nss_multicast_ipv6_connection_destroy_callback()
1380 *	Callback for handling destroy ack/nack calls.
1381 */
1382static void ecm_nss_multicast_ipv6_connection_destroy_callback(void *app_data, struct nss_ipv6_msg *nim)
1383{
1384	struct nss_ipv6_rule_destroy_msg *nirdm = &nim->msg.rule_destroy;
1385	uint32_t serial = (uint32_t)app_data;
1386	struct ecm_db_connection_instance *ci;
1387	struct ecm_front_end_connection_instance *feci;
1388	struct ecm_nss_multicast_ipv6_connection_instance *nmci;
1389	ip_addr_t flow_ip;
1390	ip_addr_t return_ip;
1391
1392	/*
1393	 * Is this a response to a destroy message?
1394	 */
1395	if (nim->cm.type != NSS_IPV6_TX_DESTROY_RULE_MSG) {
1396		DEBUG_ERROR("%p: multicast destroy callback with improper type: %d\n", nim, nim->cm.type);
1397		return;
1398	}
1399
1400	/*
1401	 * Look up ecm connection so that we can update the status.
1402	 */
1403	ci = ecm_db_connection_serial_find_and_ref(serial);
1404	if (!ci) {
1405		DEBUG_TRACE("%p: destroy callback, connection not found, serial: %u\n", nim, serial);
1406		return;
1407	}
1408
1409	/*
1410	 * Release ref held for this ack/nack response.
1411	 * NOTE: It's okay to do this here, ci won't go away, because the ci is held as
1412	 * a result of the ecm_db_connection_serial_find_and_ref()
1413	 */
1414	ecm_db_connection_deref(ci);
1415
1416	/*
1417	 * Get the front end instance
1418	 */
1419	feci = ecm_db_connection_front_end_get_and_ref(ci);
1420	nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1421	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1422
1423	ECM_NSS_IPV6_ADDR_TO_IP_ADDR(flow_ip, nirdm->tuple.flow_ip);
1424	ECM_NSS_IPV6_ADDR_TO_IP_ADDR(return_ip, nirdm->tuple.return_ip);
1425
1426	/*
1427	 * Record command duration
1428	 */
1429	ecm_nss_ipv6_decel_done_time_update(feci);
1430
1431	/*
1432	 * Dump some useful trace information.
1433	 */
1434	DEBUG_TRACE("%p: decelerate response for connection: %p\n", nmci, feci->ci);
1435	DEBUG_TRACE("%p: flow_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(flow_ip), nirdm->tuple.flow_ident);
1436	DEBUG_TRACE("%p: return_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(return_ip), nirdm->tuple.return_ident);
1437	DEBUG_TRACE("%p: protocol: %d\n", nmci, nirdm->tuple.protocol);
1438
1439	/*
1440	 * Drop decel pending counter
1441	 */
1442	spin_lock_bh(&ecm_nss_ipv6_lock);
1443	ecm_nss_ipv6_pending_decel_count--;
1444	DEBUG_ASSERT(ecm_nss_ipv6_pending_decel_count >= 0, "Bad decel pending counter\n");
1445	spin_unlock_bh(&ecm_nss_ipv6_lock);
1446
1447	spin_lock_bh(&feci->lock);
1448
1449	/*
1450	 * If decel is not still pending then it's possible that the NSS ended acceleration by some other reason e.g. flush
1451	 * In which case we cannot rely on the response we get here.
1452	 */
1453	if (feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_DECEL_PENDING) {
1454		spin_unlock_bh(&feci->lock);
1455
1456		/*
1457		 * Release the connections.
1458		 */
1459		feci->deref(feci);
1460		ecm_db_connection_deref(ci);
1461		return;
1462	}
1463
1464	DEBUG_TRACE("%p: response: %d\n", nmci, nim->cm.response);
1465	if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
1466		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DECEL;
1467	} else {
1468		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL;
1469	}
1470
1471	/*
1472	 * If connection became defunct then set mode so that no further accel/decel attempts occur.
1473	 */
1474	if (feci->is_defunct) {
1475		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DEFUNCT;
1476	}
1477
1478	spin_unlock_bh(&feci->lock);
1479
1480	/*
1481	 * Multicast acceleration ends
1482	 */
1483	spin_lock_bh(&ecm_nss_ipv6_lock);
1484	ecm_nss_multicast_ipv6_accelerated_count--;	/* Protocol specific counter */
1485	DEBUG_ASSERT(ecm_nss_multicast_ipv6_accelerated_count >= 0, "Bad udp accel counter\n");
1486	ecm_nss_ipv6_accelerated_count--;		/* General running counter */
1487	DEBUG_ASSERT(ecm_nss_ipv6_accelerated_count >= 0, "Bad accel counter\n");
1488	spin_unlock_bh(&ecm_nss_ipv6_lock);
1489
1490	/*
1491	 * Release the connections.
1492	 */
1493	feci->deref(feci);
1494	ecm_db_connection_deref(ci);
1495}
1496
1497/*
1498 * ecm_nss_multicast_ipv6_connection_decelerate()
1499 *	Decelerate a connection
1500 */
1501static void ecm_nss_multicast_ipv6_connection_decelerate(struct ecm_front_end_connection_instance *feci)
1502{
1503	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1504	struct nss_ipv6_msg nim;
1505	struct nss_ipv6_rule_destroy_msg *nirdm;
1506	ip_addr_t src_ip;
1507	ip_addr_t dest_ip;
1508	nss_tx_status_t nss_tx_status;
1509
1510	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1511
1512	/*
1513	 * If decelerate is in error or already pending then ignore
1514	 */
1515	spin_lock_bh(&feci->lock);
1516	if (feci->stats.decelerate_pending) {
1517		spin_unlock_bh(&feci->lock);
1518		return;
1519	}
1520
1521	/*
1522	 * If acceleration is pending then we cannot decelerate right now or we will race with it
1523	 * Set a decelerate pending flag that will be actioned when the acceleration command is complete.
1524	 */
1525	if (feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING) {
1526		feci->stats.decelerate_pending = true;
1527		spin_unlock_bh(&feci->lock);
1528		return;
1529	}
1530
1531	/*
1532	 * Can only decelerate if accelerated
1533	 * NOTE: This will also deny accel when the connection is in fail condition too.
1534	 */
1535	if (feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL) {
1536		spin_unlock_bh(&feci->lock);
1537		return;
1538	}
1539
1540	/*
1541	 * Initiate deceleration
1542	 */
1543	feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL_PENDING;
1544	spin_unlock_bh(&feci->lock);
1545
1546	/*
1547	 * Increment the decel pending counter
1548	 */
1549	spin_lock_bh(&ecm_nss_ipv6_lock);
1550	ecm_nss_ipv6_pending_decel_count++;
1551	spin_unlock_bh(&ecm_nss_ipv6_lock);
1552
1553	/*
1554	 * Prepare deceleration message
1555	 */
1556	nss_ipv6_msg_init(&nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_DESTROY_RULE_MSG,
1557			sizeof(struct nss_ipv6_rule_destroy_msg),
1558			ecm_nss_multicast_ipv6_connection_destroy_callback,
1559			(void *)ecm_db_connection_serial_get(feci->ci));
1560
1561	nirdm = &nim.msg.rule_destroy;
1562	nirdm->tuple.protocol = (int32_t)ecm_db_connection_protocol_get(feci->ci);
1563
1564	/*
1565	 * Get addressing information
1566	 */
1567	ecm_db_connection_from_address_get(feci->ci, src_ip);
1568	ECM_IP_ADDR_TO_NSS_IPV6_ADDR(nirdm->tuple.flow_ip, src_ip);
1569	ecm_db_connection_to_address_get(feci->ci, dest_ip);
1570	ECM_IP_ADDR_TO_NSS_IPV6_ADDR(nirdm->tuple.return_ip, dest_ip);
1571	nirdm->tuple.flow_ident = ecm_db_connection_from_port_get(feci->ci);
1572	nirdm->tuple.return_ident = ecm_db_connection_to_port_get(feci->ci);
1573
1574	DEBUG_INFO("%p: Mcast Connection %p decelerate\n"
1575			"src_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n"
1576			"dest_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n",
1577			nmci, feci->ci,
1578			ECM_IP_ADDR_TO_OCTAL(src_ip), nirdm->tuple.flow_ident,
1579			ECM_IP_ADDR_TO_OCTAL(dest_ip), nirdm->tuple.return_ident);
1580
1581
1582	/*
1583	 * Right place to free the multicast destination interfaces list.
1584	 */
1585	ecm_db_multicast_connection_to_interfaces_clear(feci->ci);
1586
1587	/*
1588	 * Take a ref to the feci->ci so that it will persist until we get a response from the NSS.
1589	 * NOTE: This will implicitly hold the feci too.
1590	 */
1591	ecm_db_connection_ref(feci->ci);
1592
1593	/*
1594	 * We are about to issue the command, record the time of transmission
1595	 */
1596	spin_lock_bh(&feci->lock);
1597	feci->stats.cmd_time_begun = jiffies;
1598	spin_unlock_bh(&feci->lock);
1599
1600	/*
1601	 * Destroy the NSS connection cache entry.
1602	 */
1603	nss_tx_status = nss_ipv6_tx(ecm_nss_ipv6_nss_ipv6_mgr, &nim);
1604	if (nss_tx_status == NSS_TX_SUCCESS) {
1605		/*
1606		 * Reset the driver_fail count - transmission was okay here.
1607		 */
1608		spin_lock_bh(&feci->lock);
1609		feci->stats.driver_fail = 0;
1610		spin_unlock_bh(&feci->lock);
1611		return;
1612	}
1613
1614	/*
1615	 * Release the ref take, NSS driver did not accept our command.
1616	 */
1617	ecm_db_connection_deref(feci->ci);
1618
1619	/*
1620	 * TX failed
1621	 */
1622	spin_lock_bh(&feci->lock);
1623	feci->stats.driver_fail_total++;
1624	feci->stats.driver_fail++;
1625	if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
1626		DEBUG_WARN("%p: Decel failed - driver fail limit\n", nmci);
1627		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
1628	}
1629	spin_unlock_bh(&feci->lock);
1630
1631	/*
1632	 * Could not send the request, decrement the decel pending counter
1633	 */
1634	spin_lock_bh(&ecm_nss_ipv6_lock);
1635	ecm_nss_ipv6_pending_decel_count--;
1636	DEBUG_ASSERT(ecm_nss_ipv6_pending_decel_count >= 0, "Bad decel pending counter\n");
1637	spin_unlock_bh(&ecm_nss_ipv6_lock);
1638
1639}
1640
1641/*
1642 * ecm_nss_multicast_ipv6_connection_defunct_callback()
1643 *	Callback to be called when a Mcast connection has become defunct.
1644 */
1645static void ecm_nss_multicast_ipv6_connection_defunct_callback(void *arg)
1646{
1647	struct ecm_front_end_connection_instance *feci = (struct ecm_front_end_connection_instance *)arg;
1648	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1649
1650	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1651
1652	spin_lock_bh(&feci->lock);
1653
1654	/*
1655	 * If connection has already become defunct, do nothing.
1656	 */
1657	if (feci->is_defunct) {
1658		spin_unlock_bh(&feci->lock);
1659		return;
1660	}
1661	feci->is_defunct = true;
1662
1663	/*
1664	 * If the connection is already in one of the fail modes, do nothing, keep the current accel_mode.
1665	 */
1666	if (ECM_FRONT_END_ACCELERATION_FAILED(feci->accel_mode)) {
1667		spin_unlock_bh(&feci->lock);
1668		return;
1669	}
1670
1671	/*
1672	 * If the connection is decel then ensure it will not attempt accel while defunct.
1673	 */
1674	if (feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_DECEL) {
1675		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DEFUNCT;
1676		spin_unlock_bh(&feci->lock);
1677		return;
1678	}
1679
1680	/*
1681	 * If the connection is decel pending then decel operation is in progress anyway.
1682	 */
1683	if (feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_DECEL_PENDING) {
1684		spin_unlock_bh(&feci->lock);
1685		return;
1686	}
1687
1688	/*
1689	 * If none of the cases matched above, this means the connection is in one of the
1690	 * accel modes (accel or accel_pending) so we force a deceleration.
1691	 * NOTE: If the mode is accel pending then the decel will be actioned when that is completed.
1692	 */
1693	spin_unlock_bh(&feci->lock);
1694	ecm_nss_multicast_ipv6_connection_decelerate(feci);
1695}
1696
1697/*
1698 * ecm_nss_multicast_ipv6_connection_accel_state_get()
1699 *	Get acceleration state
1700 */
1701static ecm_front_end_acceleration_mode_t ecm_nss_multicast_ipv6_connection_accel_state_get(struct ecm_front_end_connection_instance *feci)
1702{
1703	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1704	ecm_front_end_acceleration_mode_t state;
1705
1706	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1707	spin_lock_bh(&feci->lock);
1708	state = feci->accel_mode;
1709	spin_unlock_bh(&feci->lock);
1710	return state;
1711}
1712
1713/*
1714 * ecm_nss_multicast_ipv6_connection_action_seen()
1715 *	Acceleration action / activity has been seen for this connection.
1716 *
1717 * NOTE: Call the action_seen() method when the NSS has demonstrated that it has offloaded some data for a connection.
1718 */
1719static void ecm_nss_multicast_ipv6_connection_action_seen(struct ecm_front_end_connection_instance *feci)
1720{
1721	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1722
1723	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1724	DEBUG_INFO("%p: Action seen\n", nmci);
1725	spin_lock_bh(&feci->lock);
1726	feci->stats.no_action_seen = 0;
1727	spin_unlock_bh(&feci->lock);
1728}
1729
1730/*
1731 * ecm_nss_multicast_ipv6_connection_accel_ceased()
1732 *	NSS has indicated that acceleration has stopped.
1733 *
1734 * NOTE: This is called in response to an NSS self-initiated termination of acceleration.
1735 * This must NOT be called because the ECM terminated the acceleration.
1736 */
1737static void ecm_nss_multicast_ipv6_connection_accel_ceased(struct ecm_front_end_connection_instance *feci)
1738{
1739	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1740
1741	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1742	DEBUG_INFO("%p: accel ceased\n", nmci);
1743
1744	spin_lock_bh(&feci->lock);
1745
1746	/*
1747	 * If we are in accel-pending state then the NSS has issued a flush out-of-order
1748	 * with the ACK/NACK we are actually waiting for.
1749	 * To work around this we record a "flush has already happened" and will action it when we finally get that ACK/NACK.
1750	 * GGG TODO This should eventually be removed when the NSS honours messaging sequence.
1751	 */
1752	if (feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING) {
1753		feci->stats.flush_happened = true;
1754		feci->stats.flush_happened_total++;
1755		spin_unlock_bh(&feci->lock);
1756		return;
1757	}
1758
1759	/*
1760	 * If connection is no longer accelerated by the time we get here just ignore the command
1761	 */
1762	if (feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL) {
1763		spin_unlock_bh(&feci->lock);
1764		return;
1765	}
1766
1767	/*
1768	 * If the no_action_seen counter was not reset then acceleration ended without any offload action
1769	 */
1770	if (feci->stats.no_action_seen) {
1771		feci->stats.no_action_seen_total++;
1772	}
1773
1774	/*
1775	 * If the no_action_seen indicates successive cessations of acceleration without any offload action occuring
1776	 * then we fail out this connection
1777	 */
1778	if (feci->stats.no_action_seen >= feci->stats.no_action_seen_limit) {
1779		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_NO_ACTION;
1780	} else {
1781		feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL;
1782	}
1783	spin_unlock_bh(&feci->lock);
1784
1785	/*
1786	 * Mcast acceleration ends
1787	 */
1788	spin_lock_bh(&ecm_nss_ipv6_lock);
1789	ecm_nss_multicast_ipv6_accelerated_count--;	/* Protocol specific counter */
1790	DEBUG_ASSERT(ecm_nss_multicast_ipv6_accelerated_count >= 0, "Bad Mcast accel counter\n");
1791	ecm_nss_ipv6_accelerated_count--;		/* General running counter */
1792	DEBUG_ASSERT(ecm_nss_ipv6_accelerated_count >= 0, "Bad accel counter\n");
1793	spin_unlock_bh(&ecm_nss_ipv6_lock);
1794}
1795
1796/*
1797 * ecm_nss_multicast_ipv6_connection_ref()
1798 *	Ref a connection front end instance
1799 */
1800static void ecm_nss_multicast_ipv6_connection_ref(struct ecm_front_end_connection_instance *feci)
1801{
1802	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1803
1804	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1805	spin_lock_bh(&feci->lock);
1806	feci->refs++;
1807	DEBUG_TRACE("%p: nmci ref %d\n", nmci, feci->refs);
1808	DEBUG_ASSERT(feci->refs > 0, "%p: ref wrap\n", nmci);
1809	spin_unlock_bh(&feci->lock);
1810}
1811
1812/*
1813 * ecm_nss_multicast_ipv6_connection_deref()
1814 *	Deref a connection front end instance
1815 */
1816static int ecm_nss_multicast_ipv6_connection_deref(struct ecm_front_end_connection_instance *feci)
1817{
1818	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1819
1820	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1821
1822	spin_lock_bh(&feci->lock);
1823	feci->refs--;
1824	DEBUG_ASSERT(feci->refs >= 0, "%p: ref wrap\n", nmci);
1825
1826	if (feci->refs > 0) {
1827		int refs = feci->refs;
1828		spin_unlock_bh(&feci->lock);
1829		DEBUG_TRACE("%p: nmci deref %d\n", nmci, refs);
1830		return refs;
1831	}
1832	spin_unlock_bh(&feci->lock);
1833
1834	/*
1835	 * We can now destroy the instance
1836	 */
1837	DEBUG_TRACE("%p: nmci final\n", nmci);
1838	DEBUG_CLEAR_MAGIC(nmci);
1839	kfree(nmci);
1840
1841	return 0;
1842}
1843
1844/*
1845 * ecm_nss_multicast_ipv6_connection_regenerate()
1846 *	Re-generate a connection.
1847 *
1848 * Re-generating a connection involves re-evaluating the interface lists in case interface heirarchies have changed.
1849 * It also involves the possible triggering of classifier re-evaluation but only if all currently assigned
1850 * classifiers permit this operation.
1851 */
1852static void ecm_nss_multicast_ipv6_connection_regenerate(struct ecm_db_connection_instance *ci, ecm_tracker_sender_type_t sender,
1853							struct net_device *out_dev, struct net_device *in_dev)
1854{
1855	int i;
1856	bool reclassify_allowed;
1857	struct ecm_db_iface_instance *from_list[ECM_DB_IFACE_HEIRARCHY_MAX];
1858	int32_t from_list_first;
1859	ip_addr_t ip_src_addr;
1860	ip_addr_t ip_dest_addr;
1861	int protocol;
1862	bool is_routed;
1863	uint8_t src_node_addr[ETH_ALEN];
1864	uint8_t dest_node_addr[ETH_ALEN];
1865	int assignment_count;
1866	struct ecm_classifier_instance *assignments[ECM_CLASSIFIER_TYPES];
1867	struct ecm_front_end_connection_instance *feci;
1868
1869	/*
1870	 * Update the interface lists - these may have changed, e.g. LAG path change etc.
1871	 * NOTE: We never have to change the usual mapping->host->node_iface arrangements for each side of the connection (to/from sides)
1872	 * This is because if these interfaces change then the connection is dead anyway.
1873	 * But a LAG slave might change the heirarchy the connection is using but the LAG master is still sane.
1874	 * If any of the new interface heirarchies cannot be created then simply set empty-lists as this will deny
1875	 * acceleration and ensure that a bad rule cannot be created.
1876	 * IMPORTANT: The 'sender' defines who has sent the packet that triggered this re-generation
1877	 */
1878	protocol = ecm_db_connection_protocol_get(ci);
1879	is_routed = ecm_db_connection_is_routed_get(ci);
1880
1881	ecm_db_connection_from_address_get(ci, ip_src_addr);
1882	ecm_db_connection_to_address_get(ci, ip_dest_addr);
1883	ecm_db_connection_from_node_address_get(ci, src_node_addr);
1884	ecm_db_connection_to_node_address_get(ci, dest_node_addr);
1885
1886	feci = ecm_db_connection_front_end_get_and_ref(ci);
1887
1888	DEBUG_TRACE("%p: Update the 'from' interface heirarchy list\n", ci);
1889	from_list_first = ecm_interface_heirarchy_construct(feci, from_list, ip_dest_addr, ip_src_addr, 4, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr, NULL);
1890	if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
1891		goto ecm_multicast_ipv6_retry_regen;
1892	}
1893
1894	ecm_db_connection_from_interfaces_reset(ci, from_list, from_list_first);
1895	ecm_db_connection_interfaces_deref(from_list, from_list_first);
1896
1897	feci->deref(feci);
1898
1899	/*
1900	 * Get list of assigned classifiers to reclassify.
1901	 * Remember: This also includes our default classifier too.
1902	 */
1903	assignment_count = ecm_db_connection_classifier_assignments_get_and_ref(ci, assignments);
1904
1905	/*
1906	 * All of the assigned classifiers must permit reclassification.
1907	 */
1908	reclassify_allowed = true;
1909	for (i = 0; i < assignment_count; ++i) {
1910		DEBUG_TRACE("%p: Calling to reclassify: %p, type: %d\n", ci, assignments[i], assignments[i]->type_get(assignments[i]));
1911		if (!assignments[i]->reclassify_allowed(assignments[i])) {
1912			DEBUG_TRACE("%p: reclassify denied: %p, by type: %d\n", ci, assignments[i], assignments[i]->type_get(assignments[i]));
1913			reclassify_allowed = false;
1914			break;
1915		}
1916	}
1917
1918	/*
1919	 * Re-generation of state is successful.
1920	 */
1921	ecm_db_conection_regeneration_completed(ci);
1922
1923	/*
1924	 * Now we action any classifier re-classify
1925	 */
1926	if (!reclassify_allowed) {
1927		/*
1928		 * Regeneration came to a successful conclusion even though reclassification was denied
1929		 */
1930		DEBUG_WARN("%p: re-classify denied\n", ci);
1931
1932		/*
1933		 * Release the assignments
1934		 */
1935		ecm_db_connection_assignments_release(assignment_count, assignments);
1936		return;
1937	}
1938
1939	/*
1940	 * Reclassify
1941	 */
1942	DEBUG_INFO("%p: reclassify\n", ci);
1943	if (!ecm_nss_ipv6_reclassify(ci, assignment_count, assignments)) {
1944		/*
1945		 * We could not set up the classifiers to reclassify, it is safer to fail out and try again next time
1946		 */
1947		DEBUG_WARN("%p: Regeneration: reclassify failed\n", ci);
1948		ecm_db_connection_assignments_release(assignment_count, assignments);
1949		return;
1950	}
1951	DEBUG_INFO("%p: reclassify success\n", ci);
1952
1953	/*
1954	 * Release the assignments
1955	 */
1956	ecm_db_connection_assignments_release(assignment_count, assignments);
1957	return;
1958
1959ecm_multicast_ipv6_retry_regen:
1960	feci->deref(feci);
1961	ecm_db_conection_regeneration_failed(ci);
1962	return;
1963}
1964
1965#ifdef ECM_STATE_OUTPUT_ENABLE
1966/*
1967 * ecm_nss_multicast_ipv6_connection_state_get()
1968 *	Return state of this multicast front end instance
1969 */
1970static int ecm_nss_multicast_ipv6_connection_state_get(struct ecm_front_end_connection_instance *feci, struct ecm_state_file_instance *sfi)
1971{
1972	int result;
1973	bool can_accel;
1974	ecm_front_end_acceleration_mode_t accel_mode;
1975	struct ecm_front_end_connection_mode_stats stats;
1976	struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci;
1977
1978	DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci);
1979
1980	spin_lock_bh(&feci->lock);
1981	can_accel = feci->can_accel;
1982	accel_mode = feci->accel_mode;
1983	memcpy(&stats, &feci->stats, sizeof(struct ecm_front_end_connection_mode_stats));
1984	spin_unlock_bh(&feci->lock);
1985
1986	if ((result = ecm_state_prefix_add(sfi, "front_end_v6.multicast"))) {
1987		return result;
1988	}
1989
1990	if ((result = ecm_state_write(sfi, "can_accel", "%d", can_accel))) {
1991		return result;
1992	}
1993	if ((result = ecm_state_write(sfi, "accel_mode", "%d", accel_mode))) {
1994		return result;
1995	}
1996	if ((result = ecm_state_write(sfi, "decelerate_pending", "%d", stats.decelerate_pending))) {
1997		return result;
1998	}
1999	if ((result = ecm_state_write(sfi, "flush_happened_total", "%d", stats.flush_happened_total))) {
2000		return result;
2001	}
2002	if ((result = ecm_state_write(sfi, "no_action_seen_total", "%d", stats.no_action_seen_total))) {
2003		return result;
2004	}
2005	if ((result = ecm_state_write(sfi, "no_action_seen", "%d", stats.no_action_seen))) {
2006		return result;
2007	}
2008	if ((result = ecm_state_write(sfi, "no_action_seen_limit", "%d", stats.no_action_seen_limit))) {
2009		return result;
2010	}
2011	if ((result = ecm_state_write(sfi, "driver_fail_total", "%d", stats.driver_fail_total))) {
2012		return result;
2013	}
2014	if ((result = ecm_state_write(sfi, "driver_fail", "%d", stats.driver_fail))) {
2015		return result;
2016	}
2017	if ((result = ecm_state_write(sfi, "driver_fail_limit", "%d", stats.driver_fail_limit))) {
2018		return result;
2019	}
2020	if ((result = ecm_state_write(sfi, "ae_nack_total", "%d", stats.ae_nack_total))) {
2021		return result;
2022	}
2023	if ((result = ecm_state_write(sfi, "ae_nack", "%d", stats.ae_nack))) {
2024		return result;
2025	}
2026	if ((result = ecm_state_write(sfi, "ae_nack_limit", "%d", stats.ae_nack_limit))) {
2027		return result;
2028	}
2029
2030 	return ecm_state_prefix_remove(sfi);
2031}
2032#endif
2033
2034/*
2035 * ecm_nss_multicast_ipv6_connection_instance_alloc()
2036 *	Create a front end instance specific for Mcast connection
2037 */
2038static struct ecm_nss_multicast_ipv6_connection_instance *ecm_nss_multicast_ipv6_connection_instance_alloc(
2039								struct ecm_db_connection_instance *ci,
2040								bool can_accel)
2041{
2042	struct ecm_nss_multicast_ipv6_connection_instance *nmci;
2043	struct ecm_front_end_connection_instance *feci;
2044
2045	nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)kzalloc(sizeof(struct ecm_nss_multicast_ipv6_connection_instance), GFP_ATOMIC | __GFP_NOWARN);
2046	if (!nmci) {
2047		DEBUG_WARN("Mcast Front end alloc failed\n");
2048		return NULL;
2049	}
2050
2051	/*
2052	 * Refs is 1 for the creator of the connection
2053	 */
2054	feci = (struct ecm_front_end_connection_instance *)nmci;
2055	feci->refs = 1;
2056	DEBUG_SET_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC);
2057	spin_lock_init(&feci->lock);
2058
2059	feci->can_accel = can_accel;
2060	feci->accel_mode = (can_accel) ? ECM_FRONT_END_ACCELERATION_MODE_DECEL : ECM_FRONT_END_ACCELERATION_MODE_FAIL_DENIED;
2061	spin_lock_bh(&ecm_nss_ipv6_lock);
2062	feci->stats.no_action_seen_limit = ecm_nss_ipv6_no_action_limit_default;
2063	feci->stats.driver_fail_limit = ecm_nss_ipv6_driver_fail_limit_default;
2064	feci->stats.ae_nack_limit = ecm_nss_ipv6_nack_limit_default;
2065	spin_unlock_bh(&ecm_nss_ipv6_lock);
2066
2067	/*
2068	 * Copy reference to connection - no need to ref ci as ci maintains a ref to this instance instead (this instance persists for as long as ci does)
2069	 */
2070	feci->ci = ci;
2071
2072	/*
2073	 * Populate the methods and callbacks
2074	 */
2075	feci->ref = ecm_nss_multicast_ipv6_connection_ref;
2076	feci->deref = ecm_nss_multicast_ipv6_connection_deref;
2077	feci->decelerate = ecm_nss_multicast_ipv6_connection_decelerate;
2078	feci->accel_state_get = ecm_nss_multicast_ipv6_connection_accel_state_get;
2079	feci->action_seen = ecm_nss_multicast_ipv6_connection_action_seen;
2080	feci->accel_ceased = ecm_nss_multicast_ipv6_connection_accel_ceased;
2081#ifdef ECM_STATE_OUTPUT_ENABLE
2082	feci->state_get = ecm_nss_multicast_ipv6_connection_state_get;
2083#endif
2084	feci->ae_interface_number_by_dev_get = ecm_nss_common_get_interface_number_by_dev;
2085
2086	return nmci;
2087}
2088
2089/*
2090 * ecm_nss_multicast_ipv6_connection_process()
2091 *	Process a UDP Multicast packet
2092 */
2093unsigned int ecm_nss_multicast_ipv6_connection_process(struct net_device *out_dev,
2094							struct net_device *in_dev,
2095							uint8_t *src_node_addr,
2096							uint8_t *dest_node_addr,
2097							bool can_accel, bool is_routed, struct sk_buff *skb,
2098							struct ecm_tracker_ip_header *iph,
2099							struct nf_conn *ct, ecm_tracker_sender_type_t sender,
2100							struct nf_conntrack_tuple *orig_tuple, struct nf_conntrack_tuple *reply_tuple)
2101{
2102	struct udphdr *udp_hdr;
2103	struct udphdr udp_hdr_buff;
2104	struct in6_addr origin6;
2105	struct in6_addr group6;
2106	struct ecm_db_multicast_tuple_instance *tuple_instance;
2107	int src_port;
2108	int dest_port;
2109	struct ecm_db_connection_instance *ci;
2110	ecm_db_direction_t ecm_dir = ECM_DB_DIRECTION_NON_NAT;
2111	ip_addr_t match_addr;
2112	struct ecm_classifier_instance *assignments[ECM_CLASSIFIER_TYPES];
2113	int aci_index;
2114	int32_t mc_if_cnt;
2115	int assignment_count;
2116	ecm_db_timer_group_t ci_orig_timer_group;
2117	struct ecm_classifier_process_response prevalent_pr;
2118	ip_addr_t ip_src_addr;
2119	ip_addr_t ip_dest_addr;
2120	uint32_t mc_dest_if[ECM_DB_MULTICAST_IF_MAX];
2121	bool br_dev_found_in_mfc = false;
2122	int protocol = (int)orig_tuple->dst.protonum;
2123
2124	if (protocol != IPPROTO_UDP) {
2125		DEBUG_WARN("Invalid Protocol %d in skb %p\n", protocol, skb);
2126		return NF_ACCEPT;
2127	}
2128
2129	/*
2130	 * Extract UDP header to obtain port information
2131	 */
2132	udp_hdr = ecm_tracker_udp_check_header_and_read(skb, iph, &udp_hdr_buff);
2133	if (unlikely(!udp_hdr)) {
2134		DEBUG_WARN("Invalid UDP header in skb %p\n", skb);
2135		return NF_ACCEPT;
2136	}
2137
2138	/*
2139	 * Return if source dev is any tunnel type
2140	 */
2141	if (in_dev->type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE ||
2142	    in_dev->type == ARPHRD_SIT ||
2143	    in_dev->type == ARPHRD_TUNNEL6) {
2144		DEBUG_TRACE("Net device: %p is TUNNEL type: %d\n", in_dev, in_dev->type);
2145		return NF_ACCEPT;
2146	}
2147
2148	/*
2149	 * Now extract information, if we have conntrack then use that (which would already be in the tuples)
2150	 */
2151	if (unlikely(!ct)) {
2152		orig_tuple->src.u.udp.port = udp_hdr->source;
2153		orig_tuple->dst.u.udp.port = udp_hdr->dest;
2154		reply_tuple->src.u.udp.port = udp_hdr->dest;
2155		reply_tuple->dst.u.udp.port = udp_hdr->source;
2156	}
2157
2158	/*
2159	 * Extract transport port information
2160	 * Refer to the ecm_nss_ipv6_process() for information on how we extract this information.
2161	 */
2162	src_port = ntohs(orig_tuple->src.u.udp.port);
2163	dest_port = ntohs(orig_tuple->dst.u.udp.port);
2164
2165	ECM_NIN6_ADDR_TO_IP_ADDR(ip_src_addr, orig_tuple->src.u3.in6);
2166	ECM_NIN6_ADDR_TO_IP_ADDR(ip_dest_addr, orig_tuple->dst.u3.in6);
2167
2168	/*
2169	 * Query MFC/Bridge Snooper to access the destination interface list.
2170	 */
2171	ECM_IP_ADDR_TO_NIN6_ADDR(origin6, ip_src_addr);
2172	ECM_IP_ADDR_TO_NIN6_ADDR(group6, ip_dest_addr);
2173
2174	memset(mc_dest_if, 0, sizeof(mc_dest_if));
2175
2176	mc_if_cnt =  ip6mr_find_mfc_entry(&init_net, &origin6, &group6, ECM_DB_MULTICAST_IF_MAX, mc_dest_if);
2177
2178	if (is_routed) {
2179		/*
2180		 * This is a routed flow, hence look for a valid MFC rule
2181		 */
2182		if (mc_if_cnt <= 0){
2183			DEBUG_WARN("Not found a valid vif count %d\n", mc_if_cnt);
2184			return NF_ACCEPT;
2185		}
2186
2187		/*
2188		 * Check for the presence of a bridge device in the destination
2189		 * interface list given to us by MFC
2190		 */
2191
2192		br_dev_found_in_mfc = ecm_interface_multicast_check_for_br_dev(mc_dest_if, mc_if_cnt);
2193	} else {
2194		if (mc_if_cnt > 0) {
2195
2196			/*
2197			 *  In case of Bridge + Route there is chance that Bridge post routing hook called first and
2198			 *  is_route flag is false. To make sure this is a routed flow, query the MFC and if MFC if_cnt
2199			 *  is not Zero than this is a routed flow.
2200			 */
2201			is_routed = true;
2202			br_dev_found_in_mfc = ecm_interface_multicast_check_for_br_dev(mc_dest_if, mc_if_cnt);
2203		} else {
2204
2205			/*
2206			 * Packet flow is pure bridge. Try to query the snooper for the destination
2207			 * interface list
2208			 */
2209			mc_if_cnt = mc_bridge_ipv6_get_if(out_dev->master, &origin6, &group6, ECM_DB_MULTICAST_IF_MAX, mc_dest_if);
2210			if (mc_if_cnt <= 0) {
2211				DEBUG_WARN("Not found a valid MCS if count %d\n", mc_if_cnt);
2212				return NF_ACCEPT;
2213			}
2214		}
2215	}
2216
2217	/*
2218	 * In pure bridge flow, do not process further if Hop Limit is less than two.
2219	 */
2220	if (!is_routed) {
2221		if (iph->ttl < 2) {
2222			DEBUG_TRACE("%p: Ignoring, Multicast IPv6 Header has Hop Limit one\n", skb);
2223			return NF_ACCEPT;
2224		}
2225	}
2226
2227	DEBUG_TRACE("UDP src: " ECM_IP_ADDR_OCTAL_FMT ":%d, dest: " ECM_IP_ADDR_OCTAL_FMT ":%d\n",
2228			ECM_IP_ADDR_TO_OCTAL(ip_src_addr), src_port, ECM_IP_ADDR_TO_OCTAL(ip_dest_addr), dest_port);
2229
2230	/*
2231	 * Look up a connection
2232	 */
2233	ci = ecm_db_connection_find_and_ref(ip_src_addr, ip_dest_addr, IPPROTO_UDP, src_port, dest_port);
2234
2235	/*
2236	 * If there is no existing connection then create a new one.
2237	 */
2238	if (unlikely(!ci)) {
2239		struct ecm_db_mapping_instance *src_mi;
2240		struct ecm_db_mapping_instance *dest_mi;
2241		struct ecm_db_node_instance *src_ni;
2242		struct ecm_db_node_instance *dest_ni;
2243		struct ecm_classifier_default_instance *dci;
2244		struct ecm_front_end_connection_instance *feci;
2245		struct ecm_db_connection_instance *nci;
2246		struct ecm_db_iface_instance *from_list[ECM_DB_IFACE_HEIRARCHY_MAX];
2247		struct ecm_db_iface_instance *to_list;
2248		struct ecm_db_iface_instance *to_list_single;
2249		struct ecm_db_iface_instance *to_list_temp[ECM_DB_IFACE_HEIRARCHY_MAX];
2250		ecm_classifier_type_t classifier_type;
2251		int32_t *to_list_first;
2252		int32_t *to_first;
2253		int32_t from_list_first;
2254		int32_t interface_idx_cnt = 0;
2255		int vif;
2256		int ret;
2257		char dest_mac_addr[6];
2258
2259		DEBUG_TRACE("New UDP connection from " ECM_IP_ADDR_OCTAL_FMT ":%u to " ECM_IP_ADDR_OCTAL_FMT ":%u\n",
2260				ECM_IP_ADDR_TO_OCTAL(ip_src_addr), src_port, ECM_IP_ADDR_TO_OCTAL(ip_dest_addr), dest_port);
2261
2262		/*
2263		 * Before we attempt to create the connection are we being terminated?
2264		 */
2265		spin_lock_bh(&ecm_nss_ipv6_lock);
2266		if (ecm_nss_ipv6_terminate_pending) {
2267			spin_unlock_bh(&ecm_nss_ipv6_lock);
2268			DEBUG_WARN("Terminating\n");
2269
2270			/*
2271			 * As we are terminating we just allow the packet to pass - it's no longer our concern
2272			 */
2273			return NF_ACCEPT;
2274		}
2275		spin_unlock_bh(&ecm_nss_ipv6_lock);
2276
2277		/*
2278		 * Now allocate the new connection
2279		 */
2280		nci = ecm_db_connection_alloc();
2281		if (!nci) {
2282			DEBUG_WARN("Failed to allocate connection\n");
2283			return NF_ACCEPT;
2284		}
2285
2286		/*
2287		 * Connection must have a front end instance associated with it
2288		 */
2289		feci = (struct ecm_front_end_connection_instance *)ecm_nss_multicast_ipv6_connection_instance_alloc(nci, can_accel);
2290		if (!feci) {
2291			ecm_db_connection_deref(nci);
2292			DEBUG_WARN("Failed to allocate front end\n");
2293			return NF_ACCEPT;
2294		}
2295
2296		/*
2297		 * Create a tuple instance
2298		 */
2299		tuple_instance = ecm_db_multicast_tuple_instance_alloc(ip_src_addr, ip_dest_addr, src_port, dest_port);
2300		if (!tuple_instance) {
2301			ecm_db_connection_deref(nci);
2302			DEBUG_WARN("Failed to allocate tuple instance\n");
2303			return NF_ACCEPT;
2304		}
2305		/*
2306		 * Create Destination MAC address using IP multicast destination address
2307		 */
2308		ecm_translate_multicast_mac(ip_dest_addr, dest_mac_addr);
2309
2310		/*
2311		 * Get the src and destination mappings
2312		 * For this we also need the interface lists which we also set upon the new connection while we are at it.
2313		 * GGG TODO rework terms of "src/dest" - these need to be named consistently as from/to as per database terms.
2314		 * GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway.
2315		 */
2316		DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci);
2317		from_list_first = ecm_interface_heirarchy_construct(feci, from_list, ip_dest_addr, ip_src_addr, 6, IPPROTO_UDP, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr, NULL);
2318		if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) {
2319			feci->deref(feci);
2320			ecm_db_connection_deref(nci);
2321			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2322			DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
2323			return NF_ACCEPT;
2324		}
2325		ecm_db_connection_from_interfaces_reset(nci, from_list, from_list_first);
2326
2327		DEBUG_TRACE("%p: Create source node\n", nci);
2328		src_ni = ecm_nss_ipv6_node_establish_and_ref(feci, in_dev, ip_src_addr, from_list, from_list_first, src_node_addr);
2329		ecm_db_connection_interfaces_deref(from_list, from_list_first);
2330		if (!src_ni) {
2331			feci->deref(feci);
2332			ecm_db_connection_deref(nci);
2333			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2334			DEBUG_WARN("Failed to establish source node\n");
2335			return NF_ACCEPT;
2336		}
2337
2338		DEBUG_TRACE("%p: Create source mapping\n", nci);
2339		src_mi = ecm_nss_ipv6_mapping_establish_and_ref(ip_src_addr, src_port);
2340		if (!src_mi) {
2341			ecm_db_node_deref(src_ni);
2342			feci->deref(feci);
2343			ecm_db_connection_deref(nci);
2344			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2345			DEBUG_WARN("Failed to establish src mapping\n");
2346			return NF_ACCEPT;
2347		}
2348
2349		DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci);
2350
2351		to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
2352		if (!to_list) {
2353			ecm_db_mapping_deref(src_mi);
2354			ecm_db_node_deref(src_ni);
2355			feci->deref(feci);
2356			ecm_db_connection_deref(nci);
2357			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2358			return NF_ACCEPT;
2359		}
2360
2361		to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
2362		if (!to_list_first) {
2363			kfree(to_list);
2364			ecm_db_mapping_deref(src_mi);
2365			ecm_db_node_deref(src_ni);
2366			feci->deref(feci);
2367			ecm_db_connection_deref(nci);
2368			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2369			kfree(to_list);
2370			return NF_ACCEPT;
2371		}
2372
2373		/*
2374		 * Create the multicast 'to' interface heirarchy
2375		 */
2376		DEBUG_TRACE("%p: Create the multicast  'to' interface heirarchy list\n", nci);
2377		for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
2378			to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif);
2379			*to_first = ECM_DB_IFACE_HEIRARCHY_MAX;
2380		}
2381
2382		interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev->master, ip_src_addr,
2383										      ip_dest_addr, mc_if_cnt, mc_dest_if, to_list_first, src_node_addr,  is_routed);
2384		if (interface_idx_cnt == 0) {
2385			DEBUG_WARN("Failed to obtain 'to' heirarchy list\n");
2386			ecm_db_mapping_deref(src_mi);
2387			ecm_db_node_deref(src_ni);
2388			feci->deref(feci);
2389			ecm_db_connection_deref(nci);
2390			kfree(to_list);
2391			kfree(to_list_first);
2392			return NF_ACCEPT;
2393		}
2394
2395		ret = ecm_db_multicast_connection_to_interfaces_reset(nci, to_list, to_list_first);
2396		if (ret < 0) {
2397			for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
2398				to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif);
2399				ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
2400				to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif);
2401				ecm_db_connection_interfaces_deref(to_list_temp, *to_first);
2402			}
2403
2404			feci->deref(feci);
2405			ecm_db_mapping_deref(src_mi);
2406			ecm_db_node_deref(src_ni);
2407			ecm_db_connection_deref(nci);
2408			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2409			kfree(to_list);
2410			kfree(to_list_first);
2411			DEBUG_WARN("Failed to obtain 'to' heirarchy list\n");
2412			return NF_ACCEPT;
2413		}
2414
2415		/*
2416		 * De-ref the destination interface list
2417		 */
2418		for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
2419			to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif);
2420			ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
2421			to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif);
2422			ecm_db_connection_interfaces_deref(to_list_temp, *to_first);
2423		}
2424
2425		DEBUG_TRACE("%p: Create dest node\n", nci);
2426		ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list);
2427		dest_ni = ecm_nss_ipv6_node_establish_and_ref(feci, out_dev, ip_dest_addr, to_list_temp, *to_list_first, dest_mac_addr);
2428		if (!dest_ni) {
2429			for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
2430				to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif);
2431				ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
2432				to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif);
2433				ecm_db_connection_interfaces_deref(to_list_temp, *to_first);
2434			}
2435			ecm_db_mapping_deref(src_mi);
2436			ecm_db_node_deref(src_ni);
2437			feci->deref(feci);
2438			ecm_db_connection_deref(nci);
2439			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2440			kfree(to_list);
2441			kfree(to_list_first);
2442			DEBUG_WARN("Failed to establish dest node\n");
2443			return NF_ACCEPT;
2444		}
2445
2446		DEBUG_TRACE("%p: Create dest mapping\n", nci);
2447		dest_mi = ecm_nss_ipv6_mapping_establish_and_ref(ip_dest_addr, dest_port);
2448		if (!dest_mi) {
2449			for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
2450				to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif);
2451				ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
2452				to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif);
2453				ecm_db_connection_interfaces_deref(to_list_temp, *to_first);
2454			}
2455			ecm_db_node_deref(dest_ni);
2456			ecm_db_mapping_deref(src_mi);
2457			ecm_db_node_deref(src_ni);
2458			feci->deref(feci);
2459			ecm_db_connection_deref(nci);
2460			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2461			kfree(to_list);
2462			kfree(to_list_first);
2463			DEBUG_WARN("Failed to establish dest mapping\n");
2464			return NF_ACCEPT;
2465		}
2466
2467		/*
2468		 * Every connection also needs a default classifier
2469		 */
2470		dci = ecm_classifier_default_instance_alloc(nci, IPPROTO_UDP, ecm_dir, src_port, dest_port);
2471		if (!dci) {
2472			for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
2473				to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif);
2474				ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
2475				to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif);
2476				ecm_db_connection_interfaces_deref(to_list_temp, *to_first);
2477			}
2478			ecm_db_mapping_deref(dest_mi);
2479			ecm_db_node_deref(dest_ni);
2480			ecm_db_mapping_deref(src_mi);
2481			ecm_db_node_deref(src_ni);
2482			feci->deref(feci);
2483			ecm_db_connection_deref(nci);
2484			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2485			kfree(to_list);
2486			kfree(to_list_first);
2487			DEBUG_WARN("Failed to allocate default classifier\n");
2488			return NF_ACCEPT;
2489		}
2490		ecm_db_connection_classifier_assign(nci, (struct ecm_classifier_instance *)dci);
2491
2492		/*
2493		 * Every connection starts with a full complement of classifiers assigned.
2494		 * NOTE: Default classifier is a special case considered previously
2495		 */
2496		for (classifier_type = ECM_CLASSIFIER_TYPE_DEFAULT + 1; classifier_type < ECM_CLASSIFIER_TYPES; ++classifier_type) {
2497			struct ecm_classifier_instance *aci = ecm_nss_ipv6_assign_classifier(nci, classifier_type);
2498			if (aci) {
2499				aci->deref(aci);
2500			} else {
2501				dci->base.deref((struct ecm_classifier_instance *)dci);
2502				for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
2503					to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif);
2504					ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
2505					to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif);
2506					ecm_db_connection_interfaces_deref(to_list_temp, *to_first);
2507				}
2508				ecm_db_mapping_deref(dest_mi);
2509				ecm_db_node_deref(dest_ni);
2510				ecm_db_mapping_deref(src_mi);
2511				ecm_db_node_deref(src_ni);
2512				feci->deref(feci);
2513				ecm_db_connection_deref(nci);
2514				ecm_db_multicast_tuple_instance_deref(tuple_instance);
2515				kfree(to_list);
2516				kfree(to_list_first);
2517				DEBUG_WARN("Failed to allocate classifiers assignments\n");
2518				return NF_ACCEPT;
2519			}
2520		}
2521
2522		/*
2523		 * Now add the connection into the database.
2524		 * NOTE: In an SMP situation such as ours there is a possibility that more than one packet for the same
2525		 * connection is being processed simultaneously.
2526		 * We *could* end up creating more than one connection instance for the same actual connection.
2527		 * To guard against this we now perform a mutex'd lookup of the connection + add once more - another cpu may have created it before us.
2528		 */
2529		spin_lock_bh(&ecm_nss_ipv6_lock);
2530		ci = ecm_db_connection_find_and_ref(ip_src_addr, ip_dest_addr, IPPROTO_UDP, src_port, dest_port);
2531		if (ci) {
2532			/*
2533			 * Another cpu created the same connection before us - use the one we just found
2534			 */
2535			spin_unlock_bh(&ecm_nss_ipv6_lock);
2536			for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) {
2537				to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif);
2538				ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
2539				to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif);
2540				ecm_db_connection_interfaces_deref(to_list_temp, *to_first);
2541			}
2542
2543			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2544			ecm_db_connection_deref(nci);
2545		} else {
2546			struct ecm_tracker_instance *ti;
2547			ecm_db_timer_group_t tg;
2548			ecm_tracker_sender_state_t src_state;
2549			ecm_tracker_sender_state_t dest_state;
2550			ecm_tracker_connection_state_t state;
2551
2552			/*
2553			 * Ask tracker for timer group to set the connection to initially.
2554			 */
2555			ti = dci->tracker_get_and_ref(dci);
2556			ti->state_get(ti, &src_state, &dest_state, &state, &tg);
2557			ti->deref(ti);
2558
2559			/*
2560			 * Add the new connection we created into the database
2561			 * NOTE: assign to a short timer group for now - it is the assigned classifiers responsibility to do this
2562			 */
2563			ecm_db_connection_add(nci, feci, src_mi, dest_mi, src_mi, dest_mi,
2564					src_ni, dest_ni, src_ni, dest_ni,
2565					6, IPPROTO_UDP, ecm_dir,
2566					NULL /* final callback */,
2567					ecm_nss_multicast_ipv6_connection_defunct_callback,
2568					tg, is_routed, nci);
2569
2570			/*
2571			 * Add the tuple instance and attach it with connection instance
2572			 */
2573			ecm_db_multicast_tuple_instance_add(tuple_instance, nci);
2574			if (br_dev_found_in_mfc) {
2575				ecm_db_multicast_tuple_instance_flags_set(tuple_instance, ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG);
2576			}
2577
2578			spin_unlock_bh(&ecm_nss_ipv6_lock);
2579			ecm_db_multicast_tuple_instance_deref(tuple_instance);
2580			ci = nci;
2581			DEBUG_INFO("%p: New UDP connection created\n", ci);
2582		}
2583
2584		/*
2585		 * No longer need referenecs to the objects we created
2586		 */
2587		dci->base.deref((struct ecm_classifier_instance *)dci);
2588		ecm_db_mapping_deref(dest_mi);
2589		ecm_db_node_deref(dest_ni);
2590		ecm_db_mapping_deref(src_mi);
2591		ecm_db_node_deref(src_ni);
2592		feci->deref(feci);
2593		kfree(to_list);
2594		kfree(to_list_first);
2595
2596	} else {
2597		bool is_dest_interface_list_empty;
2598
2599		/*
2600		 * At this pont the feci->accel_mode is ECM_FRONT_END_ACCELERATION_MODE_DEACCEL because the
2601		 * MC connection has expired and we had received a callback from MFC which had freed the
2602		 * multicast destination interface heirarchy. In this case, we reconstruct the multicast
2603		 * destination interface heirarchy and re-accelerate the connection.
2604		 */
2605		is_dest_interface_list_empty = ecm_db_multicast_connection_to_interfaces_set_check(ci);
2606		if (!is_dest_interface_list_empty) {
2607			struct ecm_db_iface_instance *to_list;
2608			struct ecm_db_iface_instance *to_list_temp[ECM_DB_IFACE_HEIRARCHY_MAX];
2609			struct ecm_db_iface_instance *to_list_single;
2610			int32_t *to_list_first;
2611			int32_t *to_first;
2612			int32_t i, interface_idx_cnt;
2613			int ret;
2614			struct ecm_front_end_connection_instance *feci;
2615
2616			to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
2617			if (!to_list) {
2618				ecm_db_connection_deref(ci);
2619				return NF_ACCEPT;
2620			}
2621
2622			to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
2623			if (!to_list_first) {
2624				ecm_db_connection_deref(ci);
2625				kfree(to_list);
2626				return NF_ACCEPT;
2627			}
2628
2629			for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) {
2630				to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, i);
2631				*to_first = ECM_DB_IFACE_HEIRARCHY_MAX;
2632			}
2633
2634			feci = ecm_db_connection_front_end_get_and_ref(ci);
2635			interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev->master,\
2636												   ip_src_addr, ip_dest_addr, mc_if_cnt,\
2637												   mc_dest_if, to_list_first, src_node_addr, is_routed);
2638			feci->deref(feci);
2639			if (interface_idx_cnt == 0) {
2640				DEBUG_WARN("Failed to reconstruct 'to mc' heirarchy list\n");
2641				ecm_db_connection_deref(ci);
2642				kfree(to_list);
2643				kfree(to_list_first);
2644				return NF_ACCEPT;
2645			}
2646
2647			ret = ecm_db_multicast_connection_to_interfaces_reset(ci, to_list, to_list_first);
2648
2649			/*
2650			 * De-ref the destination interface list
2651			 */
2652			for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) {
2653				to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, i);
2654				ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
2655				to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, i);
2656				ecm_db_connection_interfaces_deref(to_list_temp, *to_first);
2657			}
2658
2659			kfree(to_list);
2660			kfree(to_list_first);
2661
2662			/*
2663			 * If ret is less than zero than connection reset could not find memory for
2664			 * to_mcast_interfaces. Deref the CI and retrun.
2665			 */
2666			if (ret < 0) {
2667				ecm_db_connection_deref(ci);
2668				return NF_ACCEPT;
2669			}
2670		}
2671	}
2672
2673	/*
2674	 * Keep connection alive as we have seen activity
2675	 */
2676	if (!ecm_db_connection_defunct_timer_touch(ci)) {
2677		ecm_db_connection_deref(ci);
2678		return NF_ACCEPT;
2679	}
2680
2681	/*
2682	 * Identify which side of the connection is sending
2683	 */
2684	ecm_db_connection_from_address_get(ci, match_addr);
2685	if (ECM_IP_ADDR_MATCH(ip_src_addr, match_addr)) {
2686		sender = ECM_TRACKER_SENDER_TYPE_SRC;
2687	} else {
2688		sender = ECM_TRACKER_SENDER_TYPE_DEST;
2689	}
2690
2691	/*
2692	 * Do we need to action generation change?
2693	 */
2694	if (unlikely(ecm_db_connection_regeneration_required_check(ci))) {
2695		ecm_nss_multicast_ipv6_connection_regenerate(ci, sender, out_dev, in_dev);
2696	}
2697
2698	/*
2699	 * Iterate the assignments and call to process!
2700	 * Policy implemented:
2701	 * 1. Classifiers that say they are not relevant are unassigned and not actioned further.
2702	 * 2. Any drop command from any classifier is honoured.
2703	 * 3. All classifiers must action acceleration for accel to be honoured, any classifiers not sure of their relevance will stop acceleration.
2704	 * 4. Only the highest priority classifier, that actions it, will have its qos tag honoured.
2705	 * 5. Only the highest priority classifier, that actions it, will have its timer group honoured.
2706	 */
2707	DEBUG_TRACE("%p: process begin, skb: %p\n", ci, skb);
2708	prevalent_pr.drop = false;
2709	prevalent_pr.flow_qos_tag = skb->priority;
2710	prevalent_pr.return_qos_tag = skb->priority;
2711	prevalent_pr.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_ACCEL;
2712	prevalent_pr.timer_group = ci_orig_timer_group = ecm_db_connection_timer_group_get(ci);
2713	prevalent_pr.process_actions = 0;
2714	assignment_count = ecm_db_connection_classifier_assignments_get_and_ref(ci, assignments);
2715	for (aci_index = 0; aci_index < assignment_count; ++aci_index) {
2716		struct ecm_classifier_process_response aci_pr;
2717		struct ecm_classifier_instance *aci;
2718
2719		aci = assignments[aci_index];
2720		DEBUG_TRACE("%p: process: %p, type: %d\n", ci, aci, aci->type_get(aci));
2721		aci->process(aci, sender, iph, skb, &aci_pr);
2722		DEBUG_TRACE("%p: aci_pr: process actions: %x, became relevant: %u, relevance: %d, drop: %d, "
2723				"flow_qos_tag: %u, return_qos_tag: %u, accel_mode: %x, timer_group: %d\n",
2724				ci, aci_pr.process_actions, aci_pr.became_relevant, aci_pr.relevance, aci_pr.drop,
2725				aci_pr.flow_qos_tag, aci_pr.return_qos_tag, aci_pr.accel_mode, aci_pr.timer_group);
2726
2727		if (aci_pr.relevance == ECM_CLASSIFIER_RELEVANCE_NO) {
2728			ecm_classifier_type_t aci_type;
2729
2730			/*
2731			 * This classifier can be unassigned - PROVIDED it is not the default classifier
2732			 */
2733			aci_type = aci->type_get(aci);
2734			if (aci_type == ECM_CLASSIFIER_TYPE_DEFAULT) {
2735				continue;
2736			}
2737
2738			DEBUG_INFO("%p: Classifier not relevant, unassign: %d", ci, aci_type);
2739			ecm_db_connection_classifier_unassign(ci, aci);
2740			continue;
2741		}
2742
2743		/*
2744		 * Yes or Maybe relevant.
2745		 */
2746		if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DROP) {
2747			/*
2748			 * Drop command from any classifier is actioned.
2749			 */
2750			DEBUG_TRACE("%p: wants drop: %p, type: %d, skb: %p\n", ci, aci, aci->type_get(aci), skb);
2751			prevalent_pr.drop |= aci_pr.drop;
2752		}
2753
2754		/*
2755		 * Accel mode permission
2756		 */
2757		if (aci_pr.relevance == ECM_CLASSIFIER_RELEVANCE_MAYBE) {
2758			/*
2759			 * Classifier not sure of its relevance - cannot accel yet
2760			 */
2761			DEBUG_TRACE("%p: accel denied by maybe: %p, type: %d\n", ci, aci, aci->type_get(aci));
2762			prevalent_pr.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO;
2763		} else {
2764			if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_ACCEL_MODE) {
2765				if (aci_pr.accel_mode == ECM_CLASSIFIER_ACCELERATION_MODE_NO) {
2766					DEBUG_TRACE("%p: accel denied: %p, type: %d\n", ci, aci, aci->type_get(aci));
2767					prevalent_pr.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO;
2768				}
2769				/* else yes or don't care about accel */
2770			}
2771		}
2772
2773		/*
2774		 * Timer group (the last classifier i.e. the highest priority one) will 'win'
2775		 */
2776		if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_TIMER_GROUP) {
2777			DEBUG_TRACE("%p: timer group: %p, type: %d, group: %d\n", ci, aci, aci->type_get(aci), aci_pr.timer_group);
2778			prevalent_pr.timer_group = aci_pr.timer_group;
2779		}
2780
2781		/*
2782		 * Qos tag (the last classifier i.e. the highest priority one) will 'win'
2783		 */
2784		if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_QOS_TAG) {
2785			DEBUG_TRACE("%p: aci: %p, type: %d, flow qos tag: %u, return qos tag: %u\n",
2786					ci, aci, aci->type_get(aci), aci_pr.flow_qos_tag, aci_pr.return_qos_tag);
2787			prevalent_pr.flow_qos_tag = aci_pr.flow_qos_tag;
2788			prevalent_pr.return_qos_tag = aci_pr.return_qos_tag;
2789		}
2790
2791		/*
2792		 * If any classifier denied DSCP remarking then that overrides every classifier
2793		 */
2794		if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DSCP_DENY) {
2795			DEBUG_TRACE("%p: aci: %p, type: %d, DSCP remark denied\n",
2796					ci, aci, aci->type_get(aci));
2797			prevalent_pr.process_actions |= ECM_CLASSIFIER_PROCESS_ACTION_DSCP_DENY;
2798			prevalent_pr.process_actions &= ~ECM_CLASSIFIER_PROCESS_ACTION_DSCP;
2799		}
2800
2801		/*
2802		 * DSCP remark action, but only if it has not been denied by any classifier
2803		 */
2804		if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DSCP) {
2805			if (!(prevalent_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DSCP_DENY)) {
2806				DEBUG_TRACE("%p: aci: %p, type: %d, DSCP remark wanted, flow_dscp: %u, return dscp: %u\n",
2807						ci, aci, aci->type_get(aci), aci_pr.flow_dscp, aci_pr.return_dscp);
2808				prevalent_pr.process_actions |= ECM_CLASSIFIER_PROCESS_ACTION_DSCP;
2809				prevalent_pr.flow_dscp = aci_pr.flow_dscp;
2810				prevalent_pr.return_dscp = aci_pr.return_dscp;
2811			}
2812		}
2813	}
2814	ecm_db_connection_assignments_release(assignment_count, assignments);
2815
2816	/*
2817	 * Change timer group?
2818	 */
2819	if (ci_orig_timer_group != prevalent_pr.timer_group) {
2820		DEBUG_TRACE("%p: change timer group from: %d to: %d\n", ci, ci_orig_timer_group, prevalent_pr.timer_group);
2821		ecm_db_connection_defunct_timer_reset(ci, prevalent_pr.timer_group);
2822	}
2823
2824	/*
2825	 * Drop?
2826	 */
2827	if (prevalent_pr.drop) {
2828		DEBUG_TRACE("%p: drop: %p\n", ci, skb);
2829		ecm_db_connection_data_totals_update_dropped(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1);
2830		ecm_db_connection_deref(ci);
2831		return NF_ACCEPT;
2832	}
2833	ecm_db_connection_data_totals_update(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1);
2834
2835	/*
2836	 * Assign qos tag
2837	 * GGG TODO Should we use sender to identify whether to use flow or return qos tag?
2838	 */
2839	skb->priority = prevalent_pr.flow_qos_tag;
2840	DEBUG_TRACE("%p: skb priority: %u\n", ci, skb->priority);
2841
2842	/*
2843	 * Accelerate?
2844	 */
2845	if (prevalent_pr.accel_mode == ECM_CLASSIFIER_ACCELERATION_MODE_ACCEL) {
2846		struct ecm_front_end_connection_instance *feci;
2847		DEBUG_TRACE("%p: accel\n", ci);
2848		feci = ecm_db_connection_front_end_get_and_ref(ci);
2849		ecm_nss_multicast_ipv6_connection_accelerate(feci, &prevalent_pr);
2850		feci->deref(feci);
2851	} else {
2852		goto done;
2853	}
2854done:
2855	ecm_db_connection_deref(ci);
2856	return NF_ACCEPT;
2857}
2858
2859/*
2860 * ecm_nss_multicast_ipv6_br_update_event_callback()
2861 * 	Callback received from bridge multicast snooper module in the
2862 * 	following events:
2863 * 	a.) Updates to a muticast group due to IGMP JOIN/LEAVE.
2864 *
2865 * 	group: IP multicast group address
2866 * 	brdev: bridge netdevice
2867 *
2868 * This function does the following:
2869 * a.) Lookup the tuple_instance table to find any flows through the bridge for the group
2870 * b.) Query the MCS bridge using the source and group address, to receive a list
2871 *     of bridge slaves for the flow
2872 * c.) Process the updates by matching the received bridge slave list with existing
2873 *     destination interfaces heirarchy for the CI, and decide whether to delete an
2874 *     exiting interface heirarchy or add a new heirarchy.
2875 */
2876static void ecm_nss_multicast_ipv6_br_update_event_callback(struct net_device *brdev, struct in6_addr *group)
2877{
2878	struct ecm_db_multicast_tuple_instance *tuple_instance;
2879	struct ecm_db_multicast_tuple_instance *tuple_instance_next;
2880	struct ecm_db_connection_instance *ci;
2881	struct ecm_front_end_connection_instance *feci;
2882	struct ecm_db_iface_instance *to_list;
2883	struct ecm_db_iface_instance *to_list_single;
2884	struct ecm_db_iface_instance *to_list_temp[ECM_DB_IFACE_HEIRARCHY_MAX];
2885	struct ecm_multicast_if_update mc_sync;
2886	ip_addr_t dest_ip;
2887	ip_addr_t grp_ip;
2888	ip_addr_t src_ip;
2889	struct in6_addr group6;
2890	struct in6_addr origin6;
2891	uint8_t src_node_addr[ETH_ALEN];
2892	int32_t to_list_first[ECM_DB_MULTICAST_IF_MAX];
2893	int i, ret;
2894	uint32_t if_cnt, mc_flags = 0;
2895	bool mc_update;
2896	int32_t if_num;
2897	uint32_t mc_max_dst = ECM_DB_MULTICAST_IF_MAX;
2898	uint32_t mc_dst_dev[ECM_DB_MULTICAST_IF_MAX];
2899
2900
2901	memcpy(&group6, group, sizeof(struct in6_addr));
2902	ECM_NIN6_ADDR_TO_IP_ADDR(dest_ip, group6);
2903
2904	DEBUG_TRACE("IP dst: " ECM_IP_ADDR_OCTAL_FMT , ECM_IP_ADDR_TO_OCTAL(dest_ip));
2905
2906	/*
2907	 * Get the first entry for the group in the tuple_instance table
2908	 */
2909	tuple_instance = ecm_db_multicast_connection_get_and_ref_first(dest_ip);
2910	if (!tuple_instance) {
2911		DEBUG_TRACE("tuple info not found\n");
2912		return;
2913	}
2914
2915	while (tuple_instance) {
2916		/*
2917		 * We now have a 5-tuple which has been accelerated. Query the MCS bridge to receive a list
2918		 * of interfaces left or joined a group for a source.
2919		 */
2920		memset(mc_dst_dev, 0, sizeof(mc_dst_dev));
2921
2922		/*
2923		 * Get the group IP address stored in tuple_instance and match this with
2924		 * the group IP received from MCS update callback.
2925		 */
2926		ecm_db_multicast_tuple_instance_group_ip_get(tuple_instance, grp_ip);
2927		if (!ECM_IP_ADDR_MATCH(grp_ip, dest_ip)) {
2928			tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance);
2929			ecm_db_multicast_connection_deref(tuple_instance);
2930			tuple_instance = tuple_instance_next;
2931			continue;
2932		}
2933
2934		/*
2935		 * Get the source IP address for this entry for the group
2936		 */
2937		ecm_db_multicast_tuple_instance_source_ip_get(tuple_instance, src_ip);
2938		ECM_IP_ADDR_TO_NIN6_ADDR(origin6, src_ip);
2939
2940		/*
2941		 * Query bridge snooper for the destination list when given the group and source
2942		 * if, 	if_num < 0   mc_bridge_ipv6_get_if has encountered with some error, return immediately
2943		 * 	if_num = 0  All slaves has left the group. Deacel the flow.
2944		 * 	if_num > 0   An interface leave/Join the group. Process the leave/join interface request.
2945		 */
2946		if_num = mc_bridge_ipv6_get_if (brdev, &origin6, &group6, mc_max_dst, mc_dst_dev);
2947		if (if_num < 0) {
2948			DEBUG_TRACE("No valid bridge slaves for the group/source\n");
2949
2950			/*
2951			 * This may a valid case when all the interface has left a multicast group.
2952			 * In this case the MCS will return if_num 0, But we may have an oudated
2953			 * interface in multicast interface heirarchy list. At next step we have to
2954			 * check whether the DB instance is present or not.
2955			 */
2956			tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance);
2957			ecm_db_multicast_connection_deref(tuple_instance);
2958			tuple_instance = tuple_instance_next;
2959			continue;
2960		}
2961
2962		/*
2963		 * Get a DB connection instance for the 5-tuple
2964		 */
2965		ci = ecm_db_multicast_connection_get_from_tuple(tuple_instance);
2966
2967		/*
2968		 * All bridge slaves has left the group. If flow is pure bridge, Deacel the connection and return.
2969		 * If flow is routed, let MFC callback handle this.
2970		 */
2971		if (if_num == 0) {
2972			bool is_routed;
2973
2974			is_routed = ecm_db_connection_is_routed_get(ci);
2975
2976			/*
2977			 * If there are no routed interfaces, then decelerate. Else
2978			 * we let MFC update callback handle this
2979			 */
2980			if (!is_routed) {
2981				/*
2982				 * Decelerate the flow
2983				 */
2984				feci = ecm_db_connection_front_end_get_and_ref(ci);
2985				feci->decelerate(feci);
2986				feci->deref(feci);
2987
2988				/*
2989				 * Get next multicast connection instance
2990				 */
2991				tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance);
2992				ecm_db_multicast_connection_deref(tuple_instance);
2993				tuple_instance = tuple_instance_next;
2994				continue;
2995			}
2996
2997			ecm_db_multicast_connection_deref(tuple_instance);
2998			return;
2999		}
3000
3001		feci = ecm_db_connection_front_end_get_and_ref(ci);
3002
3003		DEBUG_TRACE("MCS-cb: src_ip = 0x%x, dest_ip = 0x%x, Num if = %d\n", src_ip[0], dest_ip[0], if_num);
3004
3005		memset(&mc_sync, 0, sizeof(mc_sync));
3006		spin_lock_bh(&ecm_nss_ipv6_lock);
3007
3008		/*
3009		 * Find out changes to the destination interfaces heirarchy
3010		 * of the connection. We try to find out the interfaces that
3011		 * have joined new, and the existing interfaces in the list
3012		 * that have left seperately.
3013		 */
3014		mc_update = ecm_interface_multicast_find_updates_to_iface_list(ci, &mc_sync, mc_flags, true, mc_dst_dev, if_num);
3015		if (!mc_update) {
3016
3017			/*
3018			 * No updates to this multicast flow. Move on to the next
3019			 * flow for the same group
3020			 */
3021			spin_unlock_bh(&ecm_nss_ipv6_lock);
3022			tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance);
3023			ecm_db_multicast_connection_deref(tuple_instance);
3024			tuple_instance = tuple_instance_next;
3025			continue;
3026		}
3027
3028		spin_unlock_bh(&ecm_nss_ipv6_lock);
3029		DEBUG_TRACE("BRIDGE UPDATE callback ===> leave_cnt %d, join_cnt %d\n", mc_sync.if_leave_cnt, mc_sync.if_join_cnt);
3030
3031		/*
3032		 * Do we have any new interfaces that have joined?
3033		 */
3034		if (mc_sync.if_join_cnt > 0) {
3035			to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
3036			if (!to_list) {
3037				feci->deref(feci);
3038				ecm_db_multicast_connection_deref(tuple_instance);
3039				return;
3040			}
3041
3042			/*
3043			 * Initialize the heirarchy's indices for the 'to_list'
3044			 * which will hold the interface heirarchies for the new joinees
3045			 */
3046			for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) {
3047				to_list_first[i] = ECM_DB_IFACE_HEIRARCHY_MAX;
3048			}
3049
3050			ecm_db_connection_from_node_address_get(ci, src_node_addr);
3051
3052			/*
3053			 * Create the interface heirarchy list for the new interfaces. We append this list later to
3054			 * the existing list of destination interfaces.
3055			 */
3056			if_cnt = ecm_interface_multicast_heirarchy_construct_bridged(feci, to_list, brdev, src_ip, dest_ip, mc_sync.if_join_cnt, mc_sync.join_dev, to_list_first, src_node_addr, NULL);
3057			if (if_cnt == 0) {
3058				DEBUG_WARN("Failed to obtain 'to_mcast_update' heirarchy list\n");
3059				feci->deref(feci);
3060				ecm_db_multicast_connection_deref(tuple_instance);
3061				kfree(to_list);
3062				break;
3063			}
3064
3065			/*
3066			 * Append the interface heirarchy array of the new joinees to the existing destination list
3067			 */
3068			ecm_db_multicast_connection_to_interfaces_update(ci, to_list, to_list_first, mc_sync.if_join_idx);
3069
3070			/*
3071			 * De-ref the updated destination interface list
3072			 */
3073			for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) {
3074				if (mc_sync.if_join_idx[i]) {
3075					to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, i);
3076					ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
3077					ecm_db_connection_interfaces_deref(to_list_temp, to_list_first[i]);
3078				}
3079			}
3080			kfree(to_list);
3081		}
3082
3083		/*
3084		 * Push the updates to NSS
3085		 */
3086		DEBUG_TRACE("%p: Update accel\n", ci);
3087		if ((feci->accel_mode <= ECM_FRONT_END_ACCELERATION_MODE_FAIL_DENIED) ||
3088				(feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL)) {
3089			DEBUG_TRACE("%p: Ignoring wrong mode accel for conn: %p\n", feci, feci->ci);
3090			feci->deref(feci);
3091			ecm_db_multicast_connection_deref(tuple_instance);
3092			return;
3093		}
3094
3095		ret = ecm_nss_multicast_ipv6_connection_update_accelerate(feci, &mc_sync);
3096		if (ret < 0) {
3097			feci->decelerate(feci);
3098			feci->deref(feci);
3099			ecm_db_multicast_connection_deref(tuple_instance);
3100			return;
3101		}
3102
3103		feci->deref(feci);
3104
3105		/*
3106		 * Release the interfaces that may have left the connection
3107		 */
3108		for (i = 0; i < ECM_DB_MULTICAST_IF_MAX && mc_sync.if_leave_cnt; i++) {
3109
3110			/*
3111			 * Is this entry marked? If yes, then the corresponding entry
3112			 * in the 'to_mcast_interfaces' array in the ci has left the
3113			 * connection
3114			 */
3115			if (mc_sync.if_leave_idx[i]) {
3116
3117				/*
3118				 * Release the interface heirarchy for this
3119				 * interface since it has left the group
3120				 */
3121				ecm_db_multicast_connection_to_interfaces_clear_at_index(ci, i);
3122				mc_sync.if_leave_cnt--;
3123			}
3124		}
3125
3126		tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance);
3127		ecm_db_multicast_connection_deref(tuple_instance);
3128		tuple_instance = tuple_instance_next;
3129	}
3130
3131	return;
3132}
3133
3134/*
3135 * ecm_nss_multicast_ipv6_mfc_update_event_callback()
3136 * 	Callback called by Linux kernel multicast routing module in the
3137 * 	following events:
3138 * 	a.) Updates to destination interface lists for a multicast route due to
3139 * 	    IGMP JOIN/LEAVE
3140 * 	b.) Multicast route delete event
3141 *
3142 * 	group: IP multicast group address
3143 *	origin: IP source for the multicast route
3144 *	to_dev_idx[]: Array of ifindex for destination interfaces for the route
3145 *	max_to_dev: size of the array
3146 *	op: UPDATE or DELETE event
3147 *
3148 * This function does the following:
3149 * a.) Lookup the tuple_instance table to find any accelerated flows for the group/source,
3150 *     and access their CI
3151 * b.) Process the updates by matching the received destination interface list with existing
3152 *     destination interfaces heirarchy for the CI, and decide whether to delete an
3153 *     exiting interface heirarchy or add a new heirarchy.
3154 */
3155static void ecm_nss_multicast_ipv6_mfc_update_event_callback(struct in6_addr *group, struct in6_addr *origin, uint32_t max_to_dev, uint32_t to_dev_idx[], uint8_t op)
3156{
3157	struct ecm_db_connection_instance *ci;
3158	struct ecm_db_multicast_tuple_instance *tuple_instance;
3159	struct ecm_multicast_if_update mc_sync;
3160	struct in6_addr origin6;
3161	struct in6_addr group6;
3162	int32_t vif_cnt;
3163	ip_addr_t src_ip;
3164	ip_addr_t dest_ip;
3165
3166	memcpy(&origin6, origin, sizeof(ip_addr_t));
3167	memcpy(&group6, group, sizeof(ip_addr_t));
3168
3169	ECM_NIN6_ADDR_TO_IP_ADDR(src_ip, origin6);
3170	ECM_NIN6_ADDR_TO_IP_ADDR(dest_ip, group6);
3171
3172	DEBUG_TRACE("IP Packet src: " ECM_IP_ADDR_OCTAL_FMT "dst: " ECM_IP_ADDR_OCTAL_FMT ,
3173			                                ECM_IP_ADDR_TO_OCTAL(src_ip),ECM_IP_ADDR_TO_OCTAL(dest_ip));
3174
3175	/*
3176	 * Access the 5-tuple information from the tuple_instance table, using the
3177	 * source and group addresses
3178	 */
3179	tuple_instance = ecm_db_multicast_connection_find_and_ref(src_ip, dest_ip);
3180	if (!tuple_instance) {
3181		DEBUG_TRACE("MFC_EVENT: Port info is not found\n");
3182		return;
3183	}
3184
3185	/*
3186	 * Get the DB connection instance using the tuple_instance
3187	 */
3188	ci = ecm_db_multicast_connection_get_from_tuple(tuple_instance);
3189
3190	DEBUG_TRACE("%p: Multicast conn\n", ci);
3191
3192	memset(&mc_sync, 0, sizeof(mc_sync));
3193
3194	switch (op) {
3195	case IP6MR_MFC_EVENT_UPDATE:
3196	{
3197		struct ecm_front_end_connection_instance *feci;
3198		struct ecm_db_iface_instance *to_list;
3199		struct ecm_db_iface_instance *to_list_single;
3200		struct ecm_db_iface_instance *to_list_temp[ECM_DB_IFACE_HEIRARCHY_MAX];
3201		uint32_t to_list_first[ECM_DB_MULTICAST_IF_MAX];
3202		uint32_t i, ret;
3203		uint32_t mc_flags = 0;
3204		bool br_present_in_dest_dev_list = false;
3205		bool mc_update = false;
3206
3207		/*
3208		 * Check if this multicast connection has a bridge
3209		 * device in multicast destination interface list.
3210		 */
3211		mc_flags = ecm_db_multicast_tuple_instance_flags_get(tuple_instance);
3212		if (br_present_in_dest_dev_list & ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG) {
3213			mc_flags |= ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG;
3214		}
3215
3216		spin_lock_bh(&ecm_nss_ipv6_lock);
3217
3218		/*
3219		 * Find out changes to the destination interfaces heirarchy
3220		 * of the connection. We try to find out the interfaces that
3221		 * have joined new, and the existing interfaces in the list
3222		 * that have left seperately.
3223		 */
3224		mc_update = ecm_interface_multicast_find_updates_to_iface_list(ci, &mc_sync, mc_flags, false, to_dev_idx, max_to_dev);
3225		if (!mc_update) {
3226			spin_unlock_bh(&ecm_nss_ipv6_lock);
3227			ecm_db_multicast_connection_deref(tuple_instance);
3228			return;
3229		}
3230
3231		br_present_in_dest_dev_list = ecm_interface_multicast_check_for_br_dev(mc_sync.join_dev, mc_sync.if_join_cnt);
3232		if (!br_present_in_dest_dev_list) {
3233			ecm_db_multicast_tuple_instance_flags_set(tuple_instance, ~ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG);
3234		}
3235
3236		spin_unlock_bh(&ecm_nss_ipv6_lock);
3237		DEBUG_TRACE("%p: MFC update callback ===> leave_cnt %d, join_cnt %d\n", ci, mc_sync.if_leave_cnt, mc_sync.if_join_cnt);
3238
3239		feci = ecm_db_connection_front_end_get_and_ref(ci);
3240
3241		/*
3242		 * Do we have any new interfaces that have joined?
3243		 */
3244		if (mc_sync.if_join_cnt > 0) {
3245			to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
3246			if (!to_list) {
3247				feci->deref(feci);
3248				ecm_db_multicast_connection_deref(tuple_instance);
3249				return;
3250			}
3251
3252			/*
3253			 * Initialize the heirarchy's indices for the 'to_list'
3254			 * which will hold the interface heirarchies for the new joinees
3255			 */
3256			for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) {
3257				to_list_first[i] = ECM_DB_IFACE_HEIRARCHY_MAX;
3258			}
3259
3260			/*
3261			 * Create the interface heirarchy list for the new interfaces. We append this list later to
3262			 * the existing list of destination interfaces.
3263			 */
3264			vif_cnt = ecm_interface_multicast_heirarchy_construct_routed(feci, to_list, NULL, src_ip, dest_ip, mc_sync.if_join_cnt, mc_sync.join_dev, to_list_first, NULL);
3265			if (vif_cnt == 0) {
3266				DEBUG_WARN("Failed to obtain 'to_mcast_update' heirarchy list\n");
3267				feci->deref(feci);
3268				ecm_db_multicast_connection_deref(tuple_instance);
3269				kfree(to_list);
3270				return;
3271			}
3272
3273			/*
3274			 * Append the interface heirarchy array of the new joinees to the existing destination list
3275			 */
3276			ecm_db_multicast_connection_to_interfaces_update(ci, to_list, to_list_first, mc_sync.if_join_idx);
3277
3278			/*
3279			 * De-ref the updated destination interface list
3280			 */
3281			for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) {
3282				if (mc_sync.if_join_idx[i]) {
3283					to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, i);
3284					ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single);
3285					ecm_db_connection_interfaces_deref(to_list_temp, to_list_first[i]);
3286				}
3287			}
3288			kfree(to_list);
3289		}
3290
3291		/*
3292		 * Push the updates to NSS
3293		 */
3294		DEBUG_TRACE("%p: Update accel\n", ci);
3295		if ((feci->accel_mode <= ECM_FRONT_END_ACCELERATION_MODE_FAIL_DENIED) ||
3296				(feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL)) {
3297			DEBUG_TRACE("%p: Ignoring wrong mode accel for conn: %p\n", feci, feci->ci);
3298			feci->deref(feci);
3299			ecm_db_multicast_connection_deref(tuple_instance);
3300			return;
3301		}
3302
3303		/*
3304		 * Update the new rules in FW. If returns error decelerate the connection
3305		 * and flush all ECM rules.
3306		 */
3307		ret = ecm_nss_multicast_ipv6_connection_update_accelerate(feci, &mc_sync);
3308		if (ret < 0) {
3309			feci->decelerate(feci);
3310			feci->deref(feci);
3311			ecm_db_multicast_connection_deref(tuple_instance);
3312			return;
3313		}
3314
3315		feci->deref(feci);
3316
3317		/*
3318		 * Release the interfaces that may have left the connection
3319		 */
3320		for (i = 0; i < ECM_DB_MULTICAST_IF_MAX && mc_sync.if_leave_cnt; i++) {
3321
3322			/*
3323			 * Is this entry marked? If yes, then the corresponding entry
3324			 * in the 'to_mcast_interfaces' array in the ci has left the
3325			 * connection
3326			 */
3327			if (mc_sync.if_leave_idx[i]) {
3328
3329				/*
3330				 * Release the interface heirarchy for this
3331				 * interface since it has left the group
3332				 */
3333				ecm_db_multicast_connection_to_interfaces_clear_at_index(ci, i);
3334				mc_sync.if_leave_cnt--;
3335			}
3336		}
3337
3338		ecm_db_multicast_connection_deref(tuple_instance);
3339		break;
3340	}
3341	case IP6MR_MFC_EVENT_DELETE:
3342	{
3343		struct ecm_front_end_connection_instance *feci;
3344
3345		/*
3346		 * MFC reports that the multicast connection has died.
3347		 * Now we can Decelerate connection and free the frontend instance
3348		 */
3349		DEBUG_TRACE("MFC callback ===> delete all entry\n");
3350
3351		/*
3352		 * Get the front end instance
3353		 */
3354		feci = ecm_db_connection_front_end_get_and_ref(ci);
3355		feci->decelerate(feci);
3356		feci->deref(feci);
3357		ecm_db_multicast_connection_deref(tuple_instance);
3358		break;
3359	}
3360	default:
3361		DEBUG_TRACE("Wrong op, shouldn't be here\n");
3362		break;
3363	}
3364
3365	return;
3366}
3367
3368/*
3369 * ecm_nss_multicast_ipv6_debugfs_init()
3370 */
3371bool ecm_nss_multicast_ipv6_debugfs_init(struct dentry *dentry)
3372{
3373	struct dentry *multicast_dentry;
3374
3375	multicast_dentry = debugfs_create_u32("multicast_accelerated_count", S_IRUGO, dentry,
3376						&ecm_nss_multicast_ipv6_accelerated_count);
3377	if (!multicast_dentry) {
3378		DEBUG_ERROR("Failed to create ecm nss ipv6 multicast_accelerated_count file in debugfs\n");
3379		return false;
3380	}
3381
3382	return true;
3383}
3384
3385/*
3386 * ecm_nss_multicast_ipv6_init()
3387 * 	Register the callbacks for MCS snooper and MFC update
3388 */
3389void ecm_nss_multicast_ipv6_init(void)
3390{
3391	/*
3392	 * Register multicast update callback to MCS snooper
3393	 */
3394	mc_bridge_ipv6_update_callback_register(ecm_nss_multicast_ipv6_br_update_event_callback);
3395
3396	/*
3397	 * Register multicast update callbacks to MFC
3398	 */
3399	ip6mr_register_mfc_event_offload_callback(ecm_nss_multicast_ipv6_mfc_update_event_callback);
3400}
3401
3402/*
3403 * ecm_nss_multicast_ipv6_exit()
3404 * 	De-register the callbacks for MCS snooper and MFC update
3405 */
3406void ecm_nss_multicast_ipv6_exit(void)
3407{
3408	/*
3409	 * De-register multicast update callbacks to
3410	 * MFC and MCS snooper
3411	 */
3412	ip6mr_unregister_mfc_event_offload_callback();
3413	mc_bridge_ipv6_update_callback_deregister();
3414}
3415