Initial commit

This commit is contained in:
domenico
2025-06-24 13:14:22 +02:00
commit 4002f145fc
9002 changed files with 1731834 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
--- a/Makefile
+++ b/Makefile
@@ -66,8 +66,7 @@ endif
# Define ECM_FRONT_END_SFE_ENABLE=y in order to select
# sfe as ECM's front end.
# #############################################################################
-ifeq ($(SoC),$(filter $(SoC),ipq806x ipq40xx))
-ECM_FRONT_END_SFE_ENABLE=y
+ifeq ($(ECM_FRONT_END_SFE_ENABLE), y)
ecm-$(ECM_FRONT_END_SFE_ENABLE) += frontends/sfe/ecm_sfe_ipv4.o
ecm-$(ECM_FRONT_END_SFE_ENABLE) += frontends/sfe/ecm_sfe_ported_ipv4.o
ccflags-$(ECM_FRONT_END_SFE_ENABLE) += -DECM_FRONT_END_SFE_ENABLE

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c
index 1ce4b61..29e70ba 100644
--- a/frontends/nss/ecm_nss_ipv4.c
+++ b/frontends/nss/ecm_nss_ipv4.c
@@ -2171,6 +2171,10 @@ sync_conntrack:
timeouts = nf_ct_timeout_lookup(ct);
+ /* Copy of udp_get_timeouts in kernel */
+ if (!timeouts)
+ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts;
+
spin_lock_bh(&ct->lock);
ct->timeout = jiffies + timeouts[UDP_CT_REPLIED];
spin_unlock_bh(&ct->lock);
diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c
index 2adc5ec..08253b6 100644
--- a/frontends/nss/ecm_nss_ipv6.c
+++ b/frontends/nss/ecm_nss_ipv6.c
@@ -1883,6 +1883,10 @@ sync_conntrack:
timeouts = nf_ct_timeout_lookup(ct);
+ /* Copy of udp_get_timeouts in kernel */
+ if (!timeouts)
+ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts;
+
spin_lock_bh(&ct->lock);
ct->timeout = jiffies + timeouts[UDP_CT_REPLIED];
spin_unlock_bh(&ct->lock);
diff --git a/frontends/sfe/ecm_sfe_ipv4.c b/frontends/sfe/ecm_sfe_ipv4.c
index 7cfe4fc..8f525ee 100644
--- a/frontends/sfe/ecm_sfe_ipv4.c
+++ b/frontends/sfe/ecm_sfe_ipv4.c
@@ -1608,6 +1608,10 @@ sync_conntrack:
timeouts = nf_ct_timeout_lookup(ct);
+ /* Copy of udp_get_timeouts in kernel */
+ if (!timeouts)
+ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts;
+
spin_lock_bh(&ct->lock);
ct->timeout = jiffies + timeouts[UDP_CT_REPLIED];
spin_unlock_bh(&ct->lock);
diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c
index dfde309..47c531a 100644
--- a/frontends/sfe/ecm_sfe_ipv6.c
+++ b/frontends/sfe/ecm_sfe_ipv6.c
@@ -1321,6 +1321,10 @@ sync_conntrack:
timeouts = nf_ct_timeout_lookup(ct);
+ /* Copy of udp_get_timeouts in kernel */
+ if (!timeouts)
+ timeouts = nf_udp_pernet(nf_ct_net(ct))->timeouts;
+
spin_lock_bh(&ct->lock);
ct->timeout = jiffies + timeouts[UDP_CT_REPLIED];
spin_unlock_bh(&ct->lock);

View File

@@ -0,0 +1,44 @@
The sync update work queue tasks is calling uninterruptible sleep function, which is
causing high CPU load. Changed to interruptible sleep function. The stats update
task should be interruptible.
--- a/frontends/nss/ecm_nss_ipv4.c
+++ b.frontends/nss/ecm_nss_ipv4.c
@@ -2411,7 +2411,7 @@ static void ecm_nss_ipv4_stats_sync_req_
}
spin_unlock_bh(&ecm_nss_ipv4_lock);
- usleep_range(ECM_NSS_IPV4_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV4_STATS_SYNC_UDELAY);
+ msleep_interruptible(ECM_NSS_IPV4_STATS_SYNC_UDELAY / 1000);
/*
* If index is 0, we are starting a new round, but if we still have time remain
@@ -2425,7 +2425,7 @@ static void ecm_nss_ipv4_stats_sync_req_
}
if (ecm_nss_ipv4_next_req_time > current_jiffies) {
- msleep(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies));
+ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies));
}
ecm_nss_ipv4_roll_check_jiffies = jiffies;
ecm_nss_ipv4_next_req_time = ecm_nss_ipv4_roll_check_jiffies + ECM_NSS_IPV4_STATS_SYNC_PERIOD;
--- a/frontends/nss/ecm_nss_ipv6.c
+++ b.frontends/nss/ecm_nss_ipv6.c
@@ -2128,7 +2128,7 @@ static void ecm_nss_ipv6_stats_sync_req_
}
spin_unlock_bh(&ecm_nss_ipv6_lock);
- usleep_range(ECM_NSS_IPV6_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV6_STATS_SYNC_UDELAY);
+ msleep_interruptible(ECM_NSS_IPV6_STATS_SYNC_UDELAY / 1000);
/*
* If index is 0, we are starting a new round, but if we still have time remain
@@ -2142,7 +2142,7 @@ static void ecm_nss_ipv6_stats_sync_req_
}
if (ecm_nss_ipv6_next_req_time > current_jiffies) {
- msleep(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies));
+ msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies));
}
ecm_nss_ipv6_roll_check_jiffies = jiffies;
ecm_nss_ipv6_next_req_time = ecm_nss_ipv6_roll_check_jiffies + ECM_NSS_IPV6_STATS_SYNC_PERIOD;

View File

@@ -0,0 +1,20 @@
--- a/ecm_conntrack_notifier.c
+++ b/ecm_conntrack_notifier.c
@@ -411,7 +411,7 @@ int ecm_conntrack_notifier_init(struct d
/*
* Eventing subsystem is available so we register a notifier hook to get fast notifications of expired connections
*/
- result = nf_conntrack_register_notifier(&init_net, &ecm_conntrack_notifier);
+ result = nf_conntrack_register_chain_notifier(&init_net, &ecm_conntrack_notifier);
if (result < 0) {
DEBUG_ERROR("Can't register nf notifier hook.\n");
debugfs_remove_recursive(ecm_conntrack_notifier_dentry);
@@ -430,7 +430,7 @@ void ecm_conntrack_notifier_exit(void)
{
DEBUG_INFO("ECM Conntrack Notifier exit\n");
#ifdef CONFIG_NF_CONNTRACK_EVENTS
- nf_conntrack_unregister_notifier(&init_net, &ecm_conntrack_notifier);
+ nf_conntrack_unregister_chain_notifier(&init_net, &ecm_conntrack_notifier);
#endif
/*
* Remove the debugfs files recursively.

View File

@@ -0,0 +1,236 @@
From 90cace88a342e77ee8ca1e961cf7b7a7930d4c89 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Mon, 9 Mar 2020 12:51:03 -0700
Subject: [qca-nss-ecm] Check TCP/UDP conntrack state earlier
Check the conntrack state before processing the flow
and adding it to the database. The unconfirmed
connections can be changed after the confirmation.
Changed the TCP tracker connection state matrix to set the
state of the connection as ESTABLISHED when any of the src or
dest side is set as ESTABLISHED. With this change ECM will not
handle the SYN and SYN-ACK packets of the TCP handshake. Only the
ACK and FIN flaged packets will be used during the creation and
closing the connection respectively.
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
Change-Id: I3e0a58d604df4c6a85478ca9c05f24d50cd8c894
---
ecm_classifier_default.c | 36 ++++++++----------------------------
ecm_tracker_tcp.c | 4 ++--
frontends/nss/ecm_nss_ported_ipv4.c | 17 +++++++++++++++++
frontends/nss/ecm_nss_ported_ipv6.c | 17 +++++++++++++++++
frontends/sfe/ecm_sfe_ported_ipv4.c | 17 +++++++++++++++++
frontends/sfe/ecm_sfe_ported_ipv6.c | 17 +++++++++++++++++
6 files changed, 78 insertions(+), 30 deletions(-)
diff --git a/ecm_classifier_default.c b/ecm_classifier_default.c
index 22c4bec..d04cdfa 100644
--- a/ecm_classifier_default.c
+++ b/ecm_classifier_default.c
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, 2020, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
@@ -285,12 +285,12 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci,
}
/*
- * Check the TCP connection state.
+ * Check the TCP connection state, when the ct is NULL.
+ * ct valid case was already checked in the ecm_nss{sfe}_ported_ipv4{6}_process functions.
* If we are not established then we deny acceleration.
- * Take lead from conntrack if exists.
*/
ct = nf_ct_get(skb, &ctinfo);
- if (ct == NULL) {
+ if (!ct) {
DEBUG_TRACE("%p: No Conntrack found for packet, using ECM tracker state\n", cdii);
if (unlikely(prevailing_state != ECM_TRACKER_CONNECTION_STATE_ESTABLISHED)) {
cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO;
@@ -298,29 +298,10 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci,
}
} else {
/*
- * Unconfirmed connection may be dropped by Linux at the final step,
- * So we don't allow acceleration for the unconfirmed connections.
- */
- if (!nf_ct_is_confirmed(ct)) {
- DEBUG_TRACE("%p: Unconfirmed connection\n", ct);
- cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO;
- goto return_response;
- }
-
- /*
- * Don't try to manage a non-established connection.
- */
- if (!test_bit(IPS_ASSURED_BIT, &ct->status)) {
- DEBUG_TRACE("%p: Non-established connection\n", ct);
- cdii->process_response.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO;
- goto return_response;
- }
-
- /*
- * If the connection is shutting down do not manage it.
- * state can not be SYN_SENT, SYN_RECV because connection is assured
- * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE.
- */
+ * If the connection is shutting down do not manage it.
+ * state can not be SYN_SENT, SYN_RECV because connection is assured
+ * Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE.
+ */
spin_lock_bh(&ct->lock);
if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) {
spin_unlock_bh(&ct->lock);
@@ -333,7 +314,6 @@ static void ecm_classifier_default_process(struct ecm_classifier_instance *aci,
return_response:
;
-
/*
* Return the process response
*/
diff --git a/ecm_tracker_tcp.c b/ecm_tracker_tcp.c
index f073c36..e5b327a 100644
--- a/ecm_tracker_tcp.c
+++ b/ecm_tracker_tcp.c
@@ -257,9 +257,9 @@ static DEFINE_SPINLOCK(ecm_tracker_tcp_lock); /* Global lock for the tracker gl
*/
static ecm_tracker_connection_state_t ecm_tracker_tcp_connection_state_matrix[ECM_TRACKER_SENDER_STATE_MAX][ECM_TRACKER_SENDER_STATE_MAX] =
{ /* Unknown Establishing Established Closing Closed Fault */
- /* Unknown */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT},
+ /* Unknown */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT},
/* Establishing */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT},
- /* Established */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT},
+ /* Established */ {ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_ESTABLISHING, ECM_TRACKER_CONNECTION_STATE_ESTABLISHED, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT},
/* Closing */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_FAULT},
/* Closed */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSING, ECM_TRACKER_CONNECTION_STATE_CLOSED, ECM_TRACKER_CONNECTION_STATE_FAULT},
/* Fault */ {ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT, ECM_TRACKER_CONNECTION_STATE_FAULT},
diff --git a/frontends/nss/ecm_nss_ported_ipv4.c b/frontends/nss/ecm_nss_ported_ipv4.c
index 1435ec0..34c056f 100644
--- a/frontends/nss/ecm_nss_ported_ipv4.c
+++ b/frontends/nss/ecm_nss_ported_ipv4.c
@@ -2002,8 +2002,25 @@ unsigned int ecm_nss_ported_ipv4_process(struct net_device *out_dev, struct net_
int protocol = (int)orig_tuple->dst.protonum;
__be16 *layer4hdr = NULL;
+ /*
+ * Unconfirmed connection may be dropped by Linux at the final step,
+ * So we don't allow acceleration for the unconfirmed connections.
+ */
+ if (likely(ct) && !nf_ct_is_confirmed(ct)) {
+ DEBUG_WARN("%p: Unconfirmed connection\n", ct);
+ return NF_ACCEPT;
+ }
+
if (protocol == IPPROTO_TCP) {
/*
+ * Don't try to manage a non-established connection.
+ */
+ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) {
+ DEBUG_WARN("%p: Non-established TCP connection\n", ct);
+ return NF_ACCEPT;
+ }
+
+ /*
* Extract TCP header to obtain port information
*/
tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff);
diff --git a/frontends/nss/ecm_nss_ported_ipv6.c b/frontends/nss/ecm_nss_ported_ipv6.c
index 4c154a6..bd6349b 100644
--- a/frontends/nss/ecm_nss_ported_ipv6.c
+++ b/frontends/nss/ecm_nss_ported_ipv6.c
@@ -1914,8 +1914,25 @@ unsigned int ecm_nss_ported_ipv6_process(struct net_device *out_dev,
int protocol = (int)orig_tuple->dst.protonum;
__be16 *layer4hdr = NULL;
+ /*
+ * Unconfirmed connection may be dropped by Linux at the final step,
+ * So we don't allow acceleration for the unconfirmed connections.
+ */
+ if (likely(ct) && !nf_ct_is_confirmed(ct)) {
+ DEBUG_WARN("%p: Unconfirmed connection\n", ct);
+ return NF_ACCEPT;
+ }
+
if (protocol == IPPROTO_TCP) {
/*
+ * Don't try to manage a non-established connection.
+ */
+ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) {
+ DEBUG_WARN("%p: Non-established TCP connection\n", ct);
+ return NF_ACCEPT;
+ }
+
+ /*
* Extract TCP header to obtain port information
*/
tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff);
diff --git a/frontends/sfe/ecm_sfe_ported_ipv4.c b/frontends/sfe/ecm_sfe_ported_ipv4.c
index e034cde..df1ce57 100644
--- a/frontends/sfe/ecm_sfe_ported_ipv4.c
+++ b/frontends/sfe/ecm_sfe_ported_ipv4.c
@@ -1805,8 +1805,25 @@ unsigned int ecm_sfe_ported_ipv4_process(struct net_device *out_dev, struct net_
int protocol = (int)orig_tuple->dst.protonum;
__be16 *layer4hdr = NULL;
+ /*
+ * Unconfirmed connection may be dropped by Linux at the final step,
+ * So we don't allow acceleration for the unconfirmed connections.
+ */
+ if (likely(ct) && !nf_ct_is_confirmed(ct)) {
+ DEBUG_WARN("%p: Unconfirmed connection\n", ct);
+ return NF_ACCEPT;
+ }
+
if (protocol == IPPROTO_TCP) {
/*
+ * Don't try to manage a non-established connection.
+ */
+ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) {
+ DEBUG_WARN("%p: Non-established TCP connection\n", ct);
+ return NF_ACCEPT;
+ }
+
+ /*
* Extract TCP header to obtain port information
*/
tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff);
diff --git a/frontends/sfe/ecm_sfe_ported_ipv6.c b/frontends/sfe/ecm_sfe_ported_ipv6.c
index 6ac05ad..657a1c7 100644
--- a/frontends/sfe/ecm_sfe_ported_ipv6.c
+++ b/frontends/sfe/ecm_sfe_ported_ipv6.c
@@ -1746,8 +1746,25 @@ unsigned int ecm_sfe_ported_ipv6_process(struct net_device *out_dev,
int protocol = (int)orig_tuple->dst.protonum;
__be16 *layer4hdr = NULL;
+ /*
+ * Unconfirmed connection may be dropped by Linux at the final step,
+ * So we don't allow acceleration for the unconfirmed connections.
+ */
+ if (likely(ct) && !nf_ct_is_confirmed(ct)) {
+ DEBUG_WARN("%p: Unconfirmed connection\n", ct);
+ return NF_ACCEPT;
+ }
+
if (protocol == IPPROTO_TCP) {
/*
+ * Don't try to manage a non-established connection.
+ */
+ if (likely(ct) && !test_bit(IPS_ASSURED_BIT, &ct->status)) {
+ DEBUG_WARN("%p: Non-established TCP connection\n", ct);
+ return NF_ACCEPT;
+ }
+
+ /*
* Extract TCP header to obtain port information
*/
tcp_hdr = ecm_tracker_tcp_check_header_and_read(skb, iph, &tcp_hdr_buff);
--
cgit v1.1

View File

@@ -0,0 +1,52 @@
From 9ad19ffdcfdf77baf3abd4fcc933fd3dc8e791a5 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Sat, 20 Jun 2020 09:41:01 -0700
Subject: [qca-nss-ecm] Fix NSS stats request roll over issue
Use the correct timer API to check the next request time
when jiffies wrap happens.
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
Change-Id: I18646d28df7e17daeff2986dfe4bd73866d47668
---
frontends/nss/ecm_nss_ipv4.c | 4 ++--
frontends/nss/ecm_nss_ipv6.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c
index 3eaf5d8..80e1aee 100644
--- a/frontends/nss/ecm_nss_ipv4.c
+++ b/frontends/nss/ecm_nss_ipv4.c
@@ -2421,10 +2421,10 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work)
current_jiffies = jiffies;
if (time_is_after_jiffies(ecm_nss_ipv4_roll_check_jiffies)) {
- ecm_nss_ipv4_next_req_time = 0;
+ ecm_nss_ipv4_next_req_time = jiffies + ECM_NSS_IPV4_STATS_SYNC_PERIOD;
}
- if (ecm_nss_ipv4_next_req_time > current_jiffies) {
+ if (time_after(ecm_nss_ipv4_next_req_time, current_jiffies)) {
msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv4_next_req_time - current_jiffies));
}
ecm_nss_ipv4_roll_check_jiffies = jiffies;
diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c
index 288dc55..483421e 100644
--- a/frontends/nss/ecm_nss_ipv6.c
+++ b/frontends/nss/ecm_nss_ipv6.c
@@ -2135,10 +2135,10 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work)
current_jiffies = jiffies;
if (time_is_after_jiffies(ecm_nss_ipv6_roll_check_jiffies)) {
- ecm_nss_ipv6_next_req_time = 0;
+ ecm_nss_ipv6_next_req_time = jiffies + ECM_NSS_IPV6_STATS_SYNC_PERIOD;
}
- if (ecm_nss_ipv6_next_req_time > current_jiffies) {
+ if (time_after(ecm_nss_ipv6_next_req_time, current_jiffies)) {
msleep_interruptible(jiffies_to_msecs(ecm_nss_ipv6_next_req_time - current_jiffies));
}
ecm_nss_ipv6_roll_check_jiffies = jiffies;
--
cgit v1.1

View File

@@ -0,0 +1,112 @@
From 4b41703a181b7187d9ff8cb744eb96d09997387c Mon Sep 17 00:00:00 2001
From: Suman Ghosh <sumaghos@codeaurora.org>
Date: Wed, 19 Feb 2020 15:09:19 +0530
Subject: [qca-nss-ecm] Fix for ref leak during multicast 'to' hierarchy
creation
Change-Id: I89df9dbe5ea054cf3b87d55ce68a751cb1d6c24f
Signed-off-by: Suman Ghosh <sumaghos@codeaurora.org>
---
ecm_interface.c | 34 ++++++++++++++++++++++++++++++----
1 file changed, 30 insertions(+), 4 deletions(-)
diff --git a/ecm_interface.c b/ecm_interface.c
index 4f7a886..2a0ca5b 100644
--- a/ecm_interface.c
+++ b/ecm_interface.c
@@ -3885,13 +3885,13 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
dest_dev = dev_get_by_index(&init_net, *dst_if_index);
if (!dest_dev) {
if (!src_dev_is_bridge) {
- int i;
-
/*
* If already constructed any interface heirarchies before hitting
* this error condition then Deref all interface heirarchies.
*/
if (valid_if > 0) {
+ int i;
+
for (i = 0; i < valid_if; i++) {
ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
@@ -3902,11 +3902,14 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
/*
* If valid netdev not found, Return 0
*/
+ if (br_dev_src) {
+ dev_put(br_dev_src);
+ }
+
return 0;
}
dest_dev = br_dev_src;
-
}
dest_dev_type = dest_dev->type;
@@ -3945,6 +3948,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
}
}
+ if (br_dev_src && (dest_dev != br_dev_src)) {
+ dev_put(br_dev_src);
+ }
+
dev_put(dest_dev);
return 0;
}
@@ -3972,6 +3979,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
}
+ if (br_dev_src && (dest_dev != br_dev_src)) {
+ dev_put(br_dev_src);
+ }
+
dev_put(dest_dev);
dev_put(mc_br_slave_dev);
return 0;
@@ -3997,6 +4008,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
}
}
+ if (br_dev_src && (dest_dev != br_dev_src)) {
+ dev_put(br_dev_src);
+ }
+
dev_put(dest_dev);
dev_put(mc_br_slave_dev);
return 0;
@@ -4032,6 +4047,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
}
}
+ if (br_dev_src && (dest_dev != br_dev_src)) {
+ dev_put(br_dev_src);
+ }
+
dev_put(dest_dev);
return 0;
}
@@ -4042,8 +4061,15 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
valid_if++;
}
- dev_put(dest_dev);
+ if (dest_dev != br_dev_src) {
+ dev_put(dest_dev);
+ }
}
+
+ if (br_dev_src) {
+ dev_put(br_dev_src);
+ }
+
return total_ii_count;
}
EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed);
--
cgit v1.1

View File

@@ -0,0 +1,33 @@
From 72e3ae508906553e7bc982bf3c0d99bb1cbe9008 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Wed, 20 Nov 2019 16:23:06 -0800
Subject: [qca-nss-ecm] Fix neighbour solicitation send function.
dst_ops->neigh_lookup function pointer is set to the
ip6_neigh_lookup function. This function returns an
error pointer with the ERR_PTR() macro. So, we should
check the return value of this function pointer with
the IS_ERR() macro.
Change-Id: I188a6e53278faaa68f1854524f612efc1f7451fe
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
---
ecm_interface.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ecm_interface.c b/ecm_interface.c
index 3f8554b..36509f0 100644
--- a/ecm_interface.c
+++ b/ecm_interface.c
@@ -1100,7 +1100,7 @@ void ecm_interface_send_neighbour_solicitation(struct net_device *dev, ip_addr_t
#else
neigh = rt6i->dst.ops->neigh_lookup(&rt6i->dst, NULL, &dst_addr);
#endif
- if (neigh == NULL) {
+ if (IS_ERR(neigh)) {
DEBUG_TRACE("Neighbour lookup failure for destination IPv6 address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
dst_release(&rt6i->dst);
return;
--
cgit v1.1

View File

@@ -0,0 +1,260 @@
From 7c0610828b835b2aab96dd50ec841a3a28689112 Mon Sep 17 00:00:00 2001
From: Suman Ghosh <sumaghos@codeaurora.org>
Date: Mon, 16 Mar 2020 15:22:18 +0530
Subject: [qca-nss-ecm] Reference leak during multicast + PPPoE bridge
Signed-off-by: Suman Ghosh <sumaghos@codeaurora.org>
Change-Id: I4472035f1bbb087e637169762ae2648c0fda792a
---
ecm_interface.c | 136 +++++++++++++++++++++++++-------------------------------
1 file changed, 60 insertions(+), 76 deletions(-)
diff --git a/ecm_interface.c b/ecm_interface.c
index 1614336..c0d2357 100644
--- a/ecm_interface.c
+++ b/ecm_interface.c
@@ -3796,6 +3796,25 @@ fail:
}
/*
+ * ecm_interface_hierarchy_delete()
+ * Delete hierarchy of the requested interfaces.
+ */
+static inline void ecm_interface_hierarchy_delete(struct ecm_db_iface_instance *interfaces,
+ uint32_t *interface_first_base,
+ int valid_if)
+{
+ struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
+ struct ecm_db_iface_instance *ifaces;
+ int i;
+
+ for (i = 0; i < valid_if; i++) {
+ ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
+ ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
+ ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
+ }
+}
+
+/*
* ecm_interface_multicast_heirarchy_construct_routed()
* Create destination interface heirarchy for a routed multicast connectiona
*
@@ -3816,7 +3835,6 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
uint32_t *interface_first_base, bool mfc_update,
__be16 *layer4hdr, struct sk_buff *skb)
{
- struct ecm_db_iface_instance *to_list_single[ECM_DB_IFACE_HEIRARCHY_MAX];
struct ecm_db_iface_instance *ifaces;
struct net_device *dest_dev = NULL;
struct net_device *br_dev_src = NULL;
@@ -3829,7 +3847,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
int if_index;
int ii_cnt;
int total_ii_count = 0;
- bool src_dev_is_bridge = false;
+ bool src_dev_is_bridge = false, dest_dev_is_br_dev_src = false;
DEBUG_TRACE("Construct interface heirarchy for dest_addr: " ECM_IP_ADDR_DOT_FMT " src_addr: " ECM_IP_ADDR_DOT_FMT "total destination ifs %d\n",
ECM_IP_ADDR_TO_DOT(packet_dest_addr), ECM_IP_ADDR_TO_DOT(packet_src_addr), max_if);
@@ -3876,6 +3894,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
continue;
}
+ dest_dev_is_br_dev_src = false;
dest_dev = dev_get_by_index(&init_net, *dst_if_index);
if (!dest_dev) {
if (!src_dev_is_bridge) {
@@ -3884,26 +3903,23 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
* this error condition then Deref all interface heirarchies.
*/
if (valid_if > 0) {
- int i;
-
- for (i = 0; i < valid_if; i++) {
- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
- }
+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if);
}
- /*
- * If valid netdev not found, Return 0
- */
- if (br_dev_src) {
- dev_put(br_dev_src);
- }
-
- return 0;
+ goto fail1;
}
dest_dev = br_dev_src;
+
+ /*
+ * In some cases when WAN interface is added to bridge and traffic is downstream,
+ * the bridge device is part of the destination list from MFC, and at the same time
+ * 'src_dev_is_bridge' will be true as well. In such cases we will need to release
+ * the hold on the bridge device separately for dest_dev and br_dev_src.
+ * Setting this flag to true indicates that this is not the case,
+ * and that releasing the hold once is enough
+ */
+ dest_dev_is_br_dev_src = true;
}
dest_dev_type = dest_dev->type;
@@ -3927,7 +3943,6 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
}
if ((if_num < 0) || (if_num > ECM_DB_MULTICAST_IF_MAX)) {
- int i;
DEBUG_WARN("MCS is not ready\n");
/*
@@ -3935,19 +3950,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
* this error condition then Deref all interface heirarchies.
*/
if (valid_if > 0) {
- for (i = 0; i < valid_if; i++) {
- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
- }
+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if);
}
- if (br_dev_src && (dest_dev != br_dev_src)) {
- dev_put(br_dev_src);
- }
-
- dev_put(dest_dev);
- return 0;
+ goto fail2;
}
if (in_dev && !mfc_update) {
@@ -3955,34 +3961,20 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
}
for (br_if = 0; br_if < if_num; br_if++) {
+ int total_if = valid_if + br_if;
+
mc_br_slave_dev = dev_get_by_index(&init_net, mc_dst_if_index[br_if]);
if (!mc_br_slave_dev) {
continue;
}
- if ((valid_if + br_if) > ECM_DB_MULTICAST_IF_MAX) {
- int i;
-
- /*
- * If already constructed any interface heirarchies before hitting
- * this error condition then Deref all interface heirarchies.
- */
- for (i = 0; i < (valid_if + br_if); i++) {
- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
- }
-
- if (br_dev_src && (dest_dev != br_dev_src)) {
- dev_put(br_dev_src);
- }
-
- dev_put(dest_dev);
+ if (total_if > ECM_DB_MULTICAST_IF_MAX) {
+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, total_if);
dev_put(mc_br_slave_dev);
- return 0;
+ goto fail2;
}
- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, valid_if + br_if);
+ ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, total_if);
/*
* Construct a single interface heirarchy of a multicast dev.
*/
@@ -3993,25 +3985,15 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
* If already constructed any interface heirarchies before hitting
* this error condition then Deref all interface heirarchies.
*/
- if ((valid_if + br_if) > 0) {
- int i;
- for (i = 0; i < (valid_if + br_if); i++) {
- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
- }
- }
-
- if (br_dev_src && (dest_dev != br_dev_src)) {
- dev_put(br_dev_src);
+ if (total_if > 0) {
+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, total_if);
}
- dev_put(dest_dev);
dev_put(mc_br_slave_dev);
- return 0;
+ goto fail2;
}
- interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, (valid_if + br_if));
+ interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, total_if);
*interface_first = ii_cnt;
total_ii_count += ii_cnt;
dev_put(mc_br_slave_dev);
@@ -4033,20 +4015,10 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
* this error condition then Deref all interface heirarchies.
*/
if (valid_if > 0) {
- int i;
- for (i = 0; i < valid_if; i++) {
- ifaces = ecm_db_multicast_if_heirarchy_get(interfaces, i);
- ecm_db_multicast_copy_if_heirarchy(to_list_single, ifaces);
- ecm_db_connection_interfaces_deref(to_list_single, interface_first_base[i]);
- }
- }
-
- if (br_dev_src && (dest_dev != br_dev_src)) {
- dev_put(br_dev_src);
+ ecm_interface_hierarchy_delete(interfaces, interface_first_base, valid_if);
}
- dev_put(dest_dev);
- return 0;
+ goto fail2;
}
interface_first = ecm_db_multicast_if_first_get_at_index(interface_first_base, valid_if);
@@ -4055,7 +4027,7 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
valid_if++;
}
- if (dest_dev != br_dev_src) {
+ if (!dest_dev_is_br_dev_src) {
dev_put(dest_dev);
}
}
@@ -4065,6 +4037,18 @@ int32_t ecm_interface_multicast_heirarchy_construct_routed(struct ecm_front_end_
}
return total_ii_count;
+
+fail2:
+ if (!dest_dev_is_br_dev_src) {
+ dev_put(dest_dev);
+ }
+
+fail1:
+ if (br_dev_src) {
+ dev_put(br_dev_src);
+ }
+
+ return 0;
}
EXPORT_SYMBOL(ecm_interface_multicast_heirarchy_construct_routed);
--
cgit v1.1

View File

@@ -0,0 +1,59 @@
From 65a49ebd1bd12b9952dfa214de0a2da43ba2abed Mon Sep 17 00:00:00 2001
From: Bhaskar Valaboju <bhaskarv@codeaurora.org>
Date: Tue, 13 Aug 2019 14:21:03 +0530
Subject: [qca-nss-ecm]: Access global ipv4/ipv6 accelerated count under lock
Flow accelerated count maintained as global variables are accessed
in multiple kernel contexts. These counters are updated under lock,
but read without lock. Read is in kernel thread context (workqueue)
and sometimes it is taking stale entry (0) and doesn't change.
Lock is added to read correct value.
Change-Id: I74cf27fe5097c6ae7dfcc06319762a8a322d79a3
Signed-off-by: Bhaskar Valaboju <bhaskarv@codeaurora.org>
---
frontends/nss/ecm_nss_ipv4.c | 3 +++
frontends/nss/ecm_nss_ipv6.c | 3 +++
2 files changed, 6 insertions(+)
(limited to 'frontends')
diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c
index afd660e..4e66cdf 100644
--- a/frontends/nss/ecm_nss_ipv4.c
+++ b/frontends/nss/ecm_nss_ipv4.c
@@ -2288,10 +2288,13 @@ static void ecm_nss_ipv4_stats_sync_req_work(struct work_struct *work)
int retry = 3;
unsigned long int current_jiffies;
+ spin_lock_bh(&ecm_nss_ipv4_lock);
if (ecm_nss_ipv4_accelerated_count == 0) {
+ spin_unlock_bh(&ecm_nss_ipv4_lock);
DEBUG_TRACE("There is no accelerated IPv4 connection\n");
goto reschedule;
}
+ spin_unlock_bh(&ecm_nss_ipv4_lock);
usleep_range(ECM_NSS_IPV4_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV4_STATS_SYNC_UDELAY);
diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c
index 1f7f51e..55849e7 100644
--- a/frontends/nss/ecm_nss_ipv6.c
+++ b/frontends/nss/ecm_nss_ipv6.c
@@ -1998,10 +1998,13 @@ static void ecm_nss_ipv6_stats_sync_req_work(struct work_struct *work)
int retry = 3;
unsigned long int current_jiffies;
+ spin_lock_bh(&ecm_nss_ipv6_lock);
if (ecm_nss_ipv6_accelerated_count == 0) {
+ spin_unlock_bh(&ecm_nss_ipv6_lock);
DEBUG_TRACE("There is no accelerated IPv6 connection\n");
goto reschedule;
}
+ spin_unlock_bh(&ecm_nss_ipv6_lock);
usleep_range(ECM_NSS_IPV6_STATS_SYNC_UDELAY - 100, ECM_NSS_IPV6_STATS_SYNC_UDELAY);
--
cgit v1.1

View File

@@ -0,0 +1,83 @@
From b96002061178f399c1e58a9ad821e5096a64f788 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Mon, 23 Mar 2020 10:59:39 -0700
Subject: [qca-nss-ecm] Fix IPv6 neighbor solicitation request
Send the solicitation request to the GW address, when
a GW address is found, while establishing the node instance.
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
Change-Id: I2187569bcfd05b0d091cf8c79171ee3c41c39cb9
---
frontends/nss/ecm_nss_ipv6.c | 7 ++++---
frontends/nss/ecm_nss_multicast_ipv6.c | 9 +++++++++
frontends/sfe/ecm_sfe_ipv6.c | 7 ++++---
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c
index c7dd37f..9011e18 100644
--- a/frontends/nss/ecm_nss_ipv6.c
+++ b/frontends/nss/ecm_nss_ipv6.c
@@ -527,13 +527,14 @@ struct ecm_db_node_instance *ecm_nss_ipv6_node_establish_and_ref(struct ecm_fron
struct net_device *master;
master = ecm_interface_get_and_hold_dev_master(dev);
DEBUG_ASSERT(master, "Expected a master\n");
- ecm_interface_send_neighbour_solicitation(master, addr);
+ ecm_interface_send_neighbour_solicitation(master, gw_addr);
dev_put(master);
} else {
- ecm_interface_send_neighbour_solicitation(dev, addr);
+ ecm_interface_send_neighbour_solicitation(dev, gw_addr);
}
- DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
+ DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT " gw: " ECM_IP_ADDR_OCTAL_FMT "\n",
+ ECM_IP_ADDR_TO_OCTAL(addr), ECM_IP_ADDR_TO_OCTAL(gw_addr));
return NULL;
}
done:
diff --git a/frontends/nss/ecm_nss_multicast_ipv6.c b/frontends/nss/ecm_nss_multicast_ipv6.c
index a361eec..38fde95 100644
--- a/frontends/nss/ecm_nss_multicast_ipv6.c
+++ b/frontends/nss/ecm_nss_multicast_ipv6.c
@@ -2558,6 +2558,15 @@ static struct ecm_db_node_instance *ecm_nss_multicast_ipv6_node_establish_and_re
#endif
if (!ecm_interface_mac_addr_get(addr, node_addr, &on_link, gw_addr)) {
DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
+
+ /*
+ * If there is a gw_addr found during the lookup, use that address
+ * for neighbour solicitation request.
+ */
+ if (!ECM_IP_ADDR_IS_NULL(gw_addr)) {
+ ECM_IP_ADDR_COPY(addr, gw_addr);
+ }
+
if (ecm_front_end_is_bridge_port(dev)) {
struct net_device *master;
master = ecm_interface_get_and_hold_dev_master(dev);
diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c
index 3fd5d46..51a9ccb 100644
--- a/frontends/sfe/ecm_sfe_ipv6.c
+++ b/frontends/sfe/ecm_sfe_ipv6.c
@@ -256,13 +256,14 @@ struct ecm_db_node_instance *ecm_sfe_ipv6_node_establish_and_ref(struct ecm_fron
struct net_device *master;
master = ecm_interface_get_and_hold_dev_master(dev);
DEBUG_ASSERT(master, "Expected a master\n");
- ecm_interface_send_neighbour_solicitation(master, addr);
+ ecm_interface_send_neighbour_solicitation(master, gw_addr);
dev_put(master);
} else {
- ecm_interface_send_neighbour_solicitation(dev, addr);
+ ecm_interface_send_neighbour_solicitation(dev, gw_addr);
}
- DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(addr));
+ DEBUG_TRACE("Failed to obtain mac for host " ECM_IP_ADDR_OCTAL_FMT " gw: " ECM_IP_ADDR_OCTAL_FMT "\n",
+ ECM_IP_ADDR_TO_OCTAL(addr), ECM_IP_ADDR_TO_OCTAL(gw_addr));
return NULL;
}
done:
--
cgit v1.1

View File

@@ -0,0 +1,63 @@
From 5b51ae2f1eca61c6f68e40a05333da5a362ff327 Mon Sep 17 00:00:00 2001
From: Murat Sezgin <msezgin@codeaurora.org>
Date: Mon, 13 Apr 2020 09:01:48 -0700
Subject: [qca-nss-ecm] IPv6 solicitation fix with zero gateway address
The ECM function can find a zero gateway address for
a host IP address. In this case, we need to use the
host IP address while sending the solicitation request.
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
Change-Id: I1979834088ddfe1843566f51f64348f79e2df0fc
---
frontends/nss/ecm_nss_ipv6.c | 11 ++++++++++-
frontends/sfe/ecm_sfe_ipv6.c | 11 ++++++++++-
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c
index a05781b..9eb591c 100644
--- a/frontends/nss/ecm_nss_ipv6.c
+++ b/frontends/nss/ecm_nss_ipv6.c
@@ -516,7 +516,16 @@ struct ecm_db_node_instance *ecm_nss_ipv6_node_establish_and_ref(struct ecm_fron
return NULL;
}
- DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr));
+ /*
+ * The found gateway address can be all zeros,
+ * so in this case use the host address.
+ */
+ if (ECM_IP_ADDR_IS_NULL(gw_addr)) {
+ DEBUG_TRACE("GW address is found as zeros, so use host IP\n");
+ ECM_IP_ADDR_COPY(gw_addr, addr);
+ } else {
+ DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr));
+ }
if (ecm_interface_mac_addr_get_no_route(dev, gw_addr, node_addr)) {
DEBUG_TRACE("Found the mac address for gateway\n");
diff --git a/frontends/sfe/ecm_sfe_ipv6.c b/frontends/sfe/ecm_sfe_ipv6.c
index 51a9ccb..e609df7 100644
--- a/frontends/sfe/ecm_sfe_ipv6.c
+++ b/frontends/sfe/ecm_sfe_ipv6.c
@@ -245,7 +245,16 @@ struct ecm_db_node_instance *ecm_sfe_ipv6_node_establish_and_ref(struct ecm_fron
return NULL;
}
- DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr));
+ /*
+ * The found gateway address can be all zeros,
+ * so in this case use the host address.
+ */
+ if (ECM_IP_ADDR_IS_NULL(gw_addr)) {
+ DEBUG_TRACE("GW address is found as zeros, so use host IP\n");
+ ECM_IP_ADDR_COPY(gw_addr, addr);
+ } else {
+ DEBUG_TRACE("Have a gw address " ECM_IP_ADDR_OCTAL_FMT "\n", ECM_IP_ADDR_TO_OCTAL(gw_addr));
+ }
if (ecm_interface_mac_addr_get_no_route(dev, gw_addr, node_addr)) {
DEBUG_TRACE("Found the mac address for gateway\n");
--
cgit v1.1

View File

@@ -0,0 +1,126 @@
From e23eabd570eabde1d1fc803127a97fd101642467 Mon Sep 17 00:00:00 2001
From: Varsha Mishra <varsham@codeaurora.org>
Date: Fri, 12 Jun 2020 01:06:58 +0530
Subject: [qca-nss-ecm] Allow egress on same port when bridge hairpin is
enabled.
When bridge hairpin is enabled, allow egress on same port. Wi-Fi intrabss
frames are getting exceptioned to stack. Bridge gets to make the decision
whether these frames need to be forwarded or dropped.
Signed-off-by: Varsha Mishra <varsham@codeaurora.org>
Change-Id: Ibdd72264d8887330ba0297ed12cbcfc390065bff
---
frontends/nss/ecm_nss_ipv4.c | 28 ++++++++++++++++++++++------
frontends/nss/ecm_nss_ipv6.c | 28 ++++++++++++++++++++++------
2 files changed, 44 insertions(+), 12 deletions(-)
diff --git a/frontends/nss/ecm_nss_ipv4.c b/frontends/nss/ecm_nss_ipv4.c
index 60f799b..51c9ebf 100644
--- a/frontends/nss/ecm_nss_ipv4.c
+++ b/frontends/nss/ecm_nss_ipv4.c
@@ -1756,7 +1756,9 @@ static unsigned int ecm_nss_ipv4_bridge_post_routing_hook(void *priv,
* Case 2:
* For routed packets the skb will have the src mac matching the bridge mac.
* Case 3:
- * If the packet was not local (case 1) or routed (case 2) then we process.
+ * If the packet was not local (case 1) or routed (case 2) then
+ * we process. There is an exception to case 2: when hairpin mode
+ * is enabled, we process.
*/
/*
@@ -1768,14 +1770,28 @@ static unsigned int ecm_nss_ipv4_bridge_post_routing_hook(void *priv,
dev_put(bridge);
return NF_ACCEPT;
}
+
+ /*
+ * This flag needs to be checked in slave port(eth0/ath0)
+ * and not on master interface(br-lan). Hairpin flag can be
+ * enabled/disabled for ports individually.
+ */
if (in == out) {
- DEBUG_TRACE("skb: %p, bridge: %p (%s), port bounce on %p (%s)\n", skb, bridge, bridge->name, out, out->name);
- dev_put(in);
- dev_put(bridge);
- return NF_ACCEPT;
+ if (!br_is_hairpin_enabled(in)) {
+ DEBUG_TRACE("skb: %p, bridge: %p (%s), ignoring"
+ "the packet, hairpin not enabled"
+ "on port %p (%s)\n", skb, bridge,
+ bridge->name, out, out->name);
+ dev_put(in);
+ dev_put(bridge);
+ return NF_ACCEPT;
+ }
+ DEBUG_TRACE("skb: %p, bridge: %p (%s), hairpin enabled on port"
+ "%p (%s)\n", skb, bridge, bridge->name, out, out->name);
}
+
+ /*
+ * Case 2: Routed trafffic would be handled by the INET post routing.
+ */
if (!ecm_mac_addr_equal(skb_eth_hdr->h_source, bridge->dev_addr)) {
- /*
- * Case 2: Routed trafffic would be handled by the INET post routing.
- */
DEBUG_TRACE("skb: %p, Ignoring routed packet to bridge: %p (%s)\n", skb, bridge, bridge->name);
goto skip_ipv4_bridge_flow;
}
diff --git a/frontends/nss/ecm_nss_ipv6.c b/frontends/nss/ecm_nss_ipv6.c
index 6ad425e..160c94c 100644
--- a/frontends/nss/ecm_nss_ipv6.c
+++ b/frontends/nss/ecm_nss_ipv6.c
@@ -1498,7 +1498,9 @@ static unsigned int ecm_nss_ipv6_bridge_post_routing_hook(void *priv,
* Case 2:
* For routed packets the skb will have the src mac matching the bridge mac.
* Case 3:
- * If the packet was not local (case 1) or routed (case 2) then we process.
+ * If the packet was not local (case 1) or routed (case 2) then
+ * we process. There is an exception to case 2: when hairpin mode
+ * is enabled, we process.
*/
/*
@@ -1510,14 +1512,28 @@ static unsigned int ecm_nss_ipv6_bridge_post_routing_hook(void *priv,
dev_put(bridge);
return NF_ACCEPT;
}
+
+ /*
+ * This flag needs to be checked in slave port(eth0/ath0)
+ * and not on master interface(br-lan). Hairpin flag can be
+ * enabled/disabled for ports individually.
+ */
if (in == out) {
- DEBUG_TRACE("skb: %p, bridge: %p (%s), port bounce on %p (%s)\n", skb, bridge, bridge->name, out, out->name);
- dev_put(in);
- dev_put(bridge);
- return NF_ACCEPT;
+ if (!br_is_hairpin_enabled(in)) {
+ DEBUG_TRACE("skb: %p, bridge: %p (%s), ignoring"
+ "the packet, hairpin not enabled"
+ "on port %p (%s)\n", skb, bridge,
+ bridge->name, out, out->name);
+ dev_put(in);
+ dev_put(bridge);
+ return NF_ACCEPT;
+ }
+ DEBUG_TRACE("skb: %p, bridge: %p (%s), hairpin enabled on port"
+ "%p (%s)\n", skb, bridge, bridge->name, out, out->name);
}
+
+ /*
+ * Case 2: Routed trafffic would be handled by the INET post routing.
+ */
if (!ecm_mac_addr_equal(skb_eth_hdr->h_source, bridge->dev_addr)) {
- /*
- * Case 2: Routed trafffic would be handled by the INET post routing.
- */
DEBUG_TRACE("skb: %p, Ignoring routed packet to bridge: %p (%s)\n", skb, bridge, bridge->name);
goto skip_ipv6_bridge_flow;
}
--
cgit v1.1