Merge "[qca-nss-ecm] Improve NSS / HyFi integration"
diff --git a/Makefile b/Makefile
index a0e5d4a..f017c40 100755
--- a/Makefile
+++ b/Makefile
@@ -109,13 +109,10 @@
# Define ECM_MULTICAST_ENABLE=y in order to enable support for ECM Multicast
# #############################################################################
ifeq ($(ECM_FRONT_END_NSS_ENABLE), y)
-ifneq ($(findstring 3.4, $(KERNELVERSION)),)
-ECM_MULTICAST_ENABLE=y
-endif
-endif
ecm-$(ECM_MULTICAST_ENABLE) += frontends/nss/ecm_nss_multicast_ipv4.o
ecm-$(ECM_MULTICAST_ENABLE) += frontends/nss/ecm_nss_multicast_ipv6.o
ccflags-$(ECM_MULTICAST_ENABLE) += -DECM_MULTICAST_ENABLE
+endif
# #############################################################################
# Define ECM_INTERFACE_VLAN_ENABLE=y in order to enable support for VLAN
diff --git a/ecm_interface.c b/ecm_interface.c
index 9ff2b9e..c94bb6b 100644
--- a/ecm_interface.c
+++ b/ecm_interface.c
@@ -2381,7 +2381,8 @@
if (in_dev && !mfc_update) {
if (ecm_front_end_is_bridge_port(in_dev)) {
src_dev_is_bridge = true;
- br_dev_src = in_dev->master;
+ br_dev_src = ecm_interface_get_and_hold_dev_master(in_dev);
+ DEBUG_ASSERT(br_dev_src, "Expected a master\n");
/*
* The source net_dev found as bridge slave. In case of routed interface
@@ -2431,8 +2432,9 @@
*/
return 0;
}
+
dest_dev = br_dev_src;
- dev_hold(dest_dev);
+
}
dest_dev_type = dest_dev->type;
diff --git a/frontends/nss/ecm_nss_multicast_ipv4.c b/frontends/nss/ecm_nss_multicast_ipv4.c
index 1b87bb1..20ab413 100644
--- a/frontends/nss/ecm_nss_multicast_ipv4.c
+++ b/frontends/nss/ecm_nss_multicast_ipv4.c
@@ -2166,6 +2166,7 @@
int dest_port;
int src_port_nat = 0;
struct net_device *in_dev_nat = NULL;
+ struct net_device *out_dev_master = NULL;
struct ecm_db_multicast_tuple_instance *tuple_instance;
struct ecm_db_connection_instance *ci;
ip_addr_t match_addr;
@@ -2268,14 +2269,18 @@
is_routed = true;
br_dev_found_in_mfc = ecm_interface_multicast_check_for_br_dev(dst_dev, if_cnt);
} else {
+ out_dev_master = ecm_interface_get_and_hold_dev_master(out_dev);
+ DEBUG_ASSERT(out_dev_master, "Expected a master\n");
+
+
/*
* Packet flow is pure bridge. Try to query the snooper for the destination
* interface list
*/
- if_cnt = mc_bridge_ipv4_get_if(out_dev->master, ip_src, ip_grp, ECM_DB_MULTICAST_IF_MAX, dst_dev);
+ if_cnt = mc_bridge_ipv4_get_if(out_dev_master, ip_src, ip_grp, ECM_DB_MULTICAST_IF_MAX, dst_dev);
if (if_cnt <= 0) {
DEBUG_WARN("Not found a valid MCS if count %d\n", if_cnt);
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2287,7 +2292,7 @@
if_cnt = ecm_interface_multicast_check_for_src_ifindex(dst_dev, if_cnt, in_dev->ifindex);
if (if_cnt <= 0) {
DEBUG_WARN("Not found a valid MCS if count %d\n", if_cnt);
- return NF_ACCEPT;
+ goto done;
}
}
}
@@ -2298,7 +2303,7 @@
if (!is_routed) {
if (iph->ttl < 2) {
DEBUG_TRACE("%p: Ignoring, Multicast IPv4 Header has TTL one\n", skb);
- return NF_ACCEPT;
+ goto done;
}
}
@@ -2315,7 +2320,7 @@
*/
in_dev_nat = ecm_interface_dev_find_by_addr(ip_src_addr_nat, &from_local_addr);
if (!in_dev_nat) {
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2335,7 +2340,7 @@
* list for a NAT flow, which should not happen.
*/
if (!nat_if_found) {
- return NF_ACCEPT;
+ goto done;
}
}
@@ -2385,7 +2390,7 @@
/*
* As we are terminating we just allow the packet to pass - it's no longer our concern
*/
- return NF_ACCEPT;
+ goto done;
}
spin_unlock_bh(&ecm_nss_ipv4_lock);
@@ -2395,7 +2400,7 @@
nci = ecm_db_connection_alloc();
if (!nci) {
DEBUG_WARN("Failed to allocate connection\n");
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2405,7 +2410,7 @@
if (!feci) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to allocate front end\n");
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2415,7 +2420,7 @@
if (!tuple_instance) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to allocate tuple instance\n");
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2434,7 +2439,7 @@
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
- return NF_ACCEPT;
+ goto done;
}
ecm_db_connection_from_interfaces_reset(nci, from_list, from_list_first);
@@ -2446,7 +2451,7 @@
feci->deref(feci);
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
- return NF_ACCEPT;
+ goto done;
}
DEBUG_TRACE("%p: Create source mapping\n", nci);
@@ -2457,7 +2462,7 @@
feci->deref(feci);
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
- return NF_ACCEPT;
+ goto done;
}
to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
@@ -2468,7 +2473,7 @@
feci->deref(feci);
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
- return NF_ACCEPT;
+ goto done;
}
to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
@@ -2481,7 +2486,7 @@
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
kfree(to_list);
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2494,7 +2499,7 @@
}
interface_idx_cnt = ecm_nss_multicast_connection_to_interface_heirarchy_construct(feci, to_list, ip_src_addr, ip_dest_addr, in_dev,
- out_dev->master, if_cnt, dst_dev, to_list_first,
+ out_dev_master, if_cnt, dst_dev, to_list_first,
src_node_addr, is_routed, layer4hdr, skb);
if (interface_idx_cnt == 0) {
ecm_db_node_deref(src_ni);
@@ -2505,7 +2510,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("%p: Failed to obtain mutlicast 'to' heirarchy list\n", nci);
- return NF_ACCEPT;
+ goto done;
}
ret = ecm_db_multicast_connection_to_interfaces_reset(nci, to_list, to_list_first);
if (ret < 0) {
@@ -2524,7 +2529,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("%p: Failed to obtain mutlicast 'to' heirarchy list\n", nci);
- return NF_ACCEPT;
+ goto done;
}
DEBUG_TRACE("%p: Create destination node\n", nci);
@@ -2550,7 +2555,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to establish destination node\n");
- return NF_ACCEPT;
+ goto done;
}
DEBUG_TRACE("%p: Create source mapping\n", nci);
@@ -2572,7 +2577,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to establish dst mapping\n");
- return NF_ACCEPT;
+ goto done;
}
DEBUG_TRACE("%p: Create the 'from NAT' interface heirarchy list\n", nci);
@@ -2595,7 +2600,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to obtain 'from NAT' heirarchy list\n");
- return NF_ACCEPT;
+ goto done;
}
ecm_db_connection_from_nat_interfaces_reset(nci, from_nat_list, from_nat_list_first);
@@ -2619,7 +2624,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to obtain 'from NAT' node\n");
- return NF_ACCEPT;
+ goto done;
}
DEBUG_TRACE("%p: Create from NAT mapping\n", nci);
@@ -2644,7 +2649,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to establish from nat mapping\n");
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2671,7 +2676,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to allocate default classifier\n");
- return NF_ACCEPT;
+ goto done;
}
ecm_db_connection_classifier_assign(nci, (struct ecm_classifier_instance *)dci);
@@ -2704,7 +2709,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to allocate classifiers assignments\n");
- return NF_ACCEPT;
+ goto done;
}
}
@@ -2799,14 +2804,14 @@
to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
if (!to_list) {
ecm_db_connection_deref(ci);
- return NF_ACCEPT;
+ goto done;
}
to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
if (!to_list_first) {
ecm_db_connection_deref(ci);
kfree(to_list);
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2819,7 +2824,7 @@
feci = ecm_db_connection_front_end_get_and_ref(ci);
interface_idx_cnt = ecm_nss_multicast_connection_to_interface_heirarchy_construct(feci, to_list, ip_src_addr, ip_dest_addr, in_dev,
- out_dev->master, if_cnt, dst_dev, to_list_first,
+ out_dev_master, if_cnt, dst_dev, to_list_first,
src_node_addr, is_routed, (__be16 *)&udp_hdr, skb);
feci->deref(feci);
if (interface_idx_cnt == 0) {
@@ -2827,7 +2832,7 @@
ecm_db_connection_deref(ci);
kfree(to_list);
kfree(to_list_first);
- return NF_ACCEPT;
+ goto done;
}
ret = ecm_db_multicast_connection_to_interfaces_reset(ci, to_list, to_list_first);
@@ -2850,7 +2855,7 @@
*/
if (ret < 0) {
ecm_db_connection_deref(ci);
- return NF_ACCEPT;
+ goto done;
}
}
}
@@ -2860,7 +2865,7 @@
*/
if (!ecm_db_connection_defunct_timer_touch(ci)) {
ecm_db_connection_deref(ci);
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -3013,7 +3018,7 @@
DEBUG_TRACE("%p: drop: %p\n", ci, skb);
ecm_db_connection_data_totals_update_dropped(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1);
ecm_db_connection_deref(ci);
- return NF_ACCEPT;
+ goto done;
}
ecm_db_multicast_connection_data_totals_update(ci, false, skb->len, 1);
@@ -3025,11 +3030,13 @@
feci = ecm_db_connection_front_end_get_and_ref(ci);
ecm_nss_multicast_ipv4_connection_accelerate(feci, &prevalent_pr);
feci->deref(feci);
- } else {
- goto done;
}
-done:
ecm_db_connection_deref(ci);
+
+done:
+ if (out_dev_master) {
+ dev_put(out_dev_master);
+ }
return NF_ACCEPT;
}
diff --git a/frontends/nss/ecm_nss_multicast_ipv6.c b/frontends/nss/ecm_nss_multicast_ipv6.c
index a40d0a1..42ddefd 100644
--- a/frontends/nss/ecm_nss_multicast_ipv6.c
+++ b/frontends/nss/ecm_nss_multicast_ipv6.c
@@ -2125,6 +2125,7 @@
bool br_dev_found_in_mfc = false;
int protocol = (int)orig_tuple->dst.protonum;
__be16 *layer4hdr = NULL;
+ struct net_device *out_dev_master = NULL;
if (protocol != IPPROTO_UDP) {
DEBUG_WARN("Invalid Protocol %d in skb %p\n", protocol, skb);
@@ -2207,15 +2208,17 @@
is_routed = true;
br_dev_found_in_mfc = ecm_interface_multicast_check_for_br_dev(mc_dest_if, mc_if_cnt);
} else {
+ out_dev_master = ecm_interface_get_and_hold_dev_master(out_dev);
+ DEBUG_ASSERT(out_dev_master, "Expected a master\n");
/*
* Packet flow is pure bridge. Try to query the snooper for the destination
* interface list
*/
- mc_if_cnt = mc_bridge_ipv6_get_if(out_dev->master, &origin6, &group6, ECM_DB_MULTICAST_IF_MAX, mc_dest_if);
+ mc_if_cnt = mc_bridge_ipv6_get_if(out_dev_master, &origin6, &group6, ECM_DB_MULTICAST_IF_MAX, mc_dest_if);
if (mc_if_cnt <= 0) {
DEBUG_WARN("Not found a valid MCS if count %d\n", mc_if_cnt);
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2227,7 +2230,7 @@
mc_if_cnt = ecm_interface_multicast_check_for_src_ifindex(mc_dest_if, mc_if_cnt, in_dev->ifindex);
if (mc_if_cnt <= 0) {
DEBUG_WARN("Not found a valid MCS if count %d\n", mc_if_cnt);
- return NF_ACCEPT;
+ goto done;
}
}
}
@@ -2238,7 +2241,7 @@
if (!is_routed) {
if (iph->ttl < 2) {
DEBUG_TRACE("%p: Ignoring, Multicast IPv6 Header has Hop Limit one\n", skb);
- return NF_ACCEPT;
+ goto done;
}
}
@@ -2288,7 +2291,7 @@
/*
* As we are terminating we just allow the packet to pass - it's no longer our concern
*/
- return NF_ACCEPT;
+ goto done;
}
spin_unlock_bh(&ecm_nss_ipv6_lock);
@@ -2298,7 +2301,7 @@
nci = ecm_db_connection_alloc();
if (!nci) {
DEBUG_WARN("Failed to allocate connection\n");
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2308,7 +2311,7 @@
if (!feci) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to allocate front end\n");
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2318,7 +2321,7 @@
if (!tuple_instance) {
ecm_db_connection_deref(nci);
DEBUG_WARN("Failed to allocate tuple instance\n");
- return NF_ACCEPT;
+ goto done;
}
/*
* Create Destination MAC address using IP multicast destination address
@@ -2338,7 +2341,7 @@
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
DEBUG_WARN("Failed to obtain 'from' heirarchy list\n");
- return NF_ACCEPT;
+ goto done;
}
ecm_db_connection_from_interfaces_reset(nci, from_list, from_list_first);
@@ -2350,7 +2353,7 @@
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
DEBUG_WARN("Failed to establish source node\n");
- return NF_ACCEPT;
+ goto done;
}
DEBUG_TRACE("%p: Create source mapping\n", nci);
@@ -2361,7 +2364,7 @@
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
DEBUG_WARN("Failed to establish src mapping\n");
- return NF_ACCEPT;
+ goto done;
}
DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci);
@@ -2373,7 +2376,7 @@
feci->deref(feci);
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
- return NF_ACCEPT;
+ goto done;
}
to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
@@ -2385,7 +2388,7 @@
ecm_db_connection_deref(nci);
ecm_db_multicast_tuple_instance_deref(tuple_instance);
kfree(to_list);
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2397,7 +2400,7 @@
*to_first = ECM_DB_IFACE_HEIRARCHY_MAX;
}
- interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev->master, ip_src_addr,
+ interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev_master, ip_src_addr,
ip_dest_addr, mc_if_cnt, mc_dest_if, to_list_first, src_node_addr, is_routed, skb);
if (interface_idx_cnt == 0) {
DEBUG_WARN("Failed to obtain 'to' heirarchy list\n");
@@ -2407,7 +2410,7 @@
ecm_db_connection_deref(nci);
kfree(to_list);
kfree(to_list_first);
- return NF_ACCEPT;
+ goto done;
}
ret = ecm_db_multicast_connection_to_interfaces_reset(nci, to_list, to_list_first);
@@ -2427,7 +2430,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to obtain 'to' heirarchy list\n");
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2458,7 +2461,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to establish dest node\n");
- return NF_ACCEPT;
+ goto done;
}
DEBUG_TRACE("%p: Create dest mapping\n", nci);
@@ -2479,7 +2482,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to establish dest mapping\n");
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2503,7 +2506,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to allocate default classifier\n");
- return NF_ACCEPT;
+ goto done;
}
ecm_db_connection_classifier_assign(nci, (struct ecm_classifier_instance *)dci);
@@ -2533,7 +2536,7 @@
kfree(to_list);
kfree(to_list_first);
DEBUG_WARN("Failed to allocate classifiers assignments\n");
- return NF_ACCEPT;
+ goto done;
}
}
@@ -2634,14 +2637,14 @@
to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN);
if (!to_list) {
ecm_db_connection_deref(ci);
- return NF_ACCEPT;
+ goto done;
}
to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN);
if (!to_list_first) {
ecm_db_connection_deref(ci);
kfree(to_list);
- return NF_ACCEPT;
+ goto done;
}
for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) {
@@ -2650,7 +2653,7 @@
}
feci = ecm_db_connection_front_end_get_and_ref(ci);
- interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev->master,\
+ interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev_master,\
ip_src_addr, ip_dest_addr, mc_if_cnt,\
mc_dest_if, to_list_first, src_node_addr,
is_routed, skb);
@@ -2660,7 +2663,7 @@
ecm_db_connection_deref(ci);
kfree(to_list);
kfree(to_list_first);
- return NF_ACCEPT;
+ goto done;
}
ret = ecm_db_multicast_connection_to_interfaces_reset(ci, to_list, to_list_first);
@@ -2684,7 +2687,7 @@
*/
if (ret < 0) {
ecm_db_connection_deref(ci);
- return NF_ACCEPT;
+ goto done;
}
}
}
@@ -2694,7 +2697,7 @@
*/
if (!ecm_db_connection_defunct_timer_touch(ci)) {
ecm_db_connection_deref(ci);
- return NF_ACCEPT;
+ goto done;
}
/*
@@ -2847,7 +2850,7 @@
DEBUG_TRACE("%p: drop: %p\n", ci, skb);
ecm_db_connection_data_totals_update_dropped(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1);
ecm_db_connection_deref(ci);
- return NF_ACCEPT;
+ goto done;
}
ecm_db_connection_data_totals_update(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1);
@@ -2867,11 +2870,13 @@
feci = ecm_db_connection_front_end_get_and_ref(ci);
ecm_nss_multicast_ipv6_connection_accelerate(feci, &prevalent_pr);
feci->deref(feci);
- } else {
- goto done;
}
-done:
ecm_db_connection_deref(ci);
+
+done:
+ if (out_dev_master) {
+ dev_put(out_dev_master);
+ }
return NF_ACCEPT;
}