[qca-nss-ecm] Add destroy re-try feature.
When a destroy request fails to sent to the acceleration
engine for some reason, that connection was being removed
from the ECM's database but the accel engine still keeps
that connection since it doesn't receive that request.
With this commit, if a destroy request fails, the defunct
timer is reset to a smaller timeout value and the defunct
callback is called again after the timeout expires.
Change-Id: I2e42a61234eaa53267aa0a987c417f0926f4d80c
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
diff --git a/ecm_db.c b/ecm_db.c
index 6ba6221..139b63f 100644
--- a/ecm_db.c
+++ b/ecm_db.c
@@ -1126,14 +1126,31 @@
*/
void ecm_db_connection_make_defunct(struct ecm_db_connection_instance *ci)
{
+ struct ecm_front_end_connection_instance *feci;
+ ecm_front_end_acceleration_mode_t accel_mode;
+
DEBUG_CHECK_MAGIC(ci, ECM_DB_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", ci);
if (ci->defunct) {
ci->defunct(ci->feci);
}
- if (ecm_db_timer_group_entry_remove(&ci->defunct_timer)) {
- ecm_db_connection_deref(ci);
+ feci = ecm_db_connection_front_end_get_and_ref(ci);
+ accel_mode = feci->accel_state_get(feci);
+ feci->deref(feci);
+
+ /*
+ * It is possible that the defunct process fails and re-try is in progress.
+ * In that case, the connection's defunct timer is reset to defunct re-try
+ * timeout value and the connection waits for the next defunct call. So, we
+ * should remove the timer from the timer group, if the re-acceleration for this
+ * connection is not possible which means "decel pending" or one of the
+ * "accel fail" modes. Otherwise, the timer will be removed and re-try will not happen.
+ */
+ if (ECM_FRONT_END_ACCELERATION_NOT_POSSIBLE(accel_mode)) {
+ if (ecm_db_timer_group_entry_remove(&ci->defunct_timer)) {
+ ecm_db_connection_deref(ci);
+ }
}
}
EXPORT_SYMBOL(ecm_db_connection_make_defunct);
@@ -12455,6 +12472,12 @@
ecm_db_timer_groups[ECM_DB_TIMER_GROUPS_CONNECTION_SIP_TIMEOUT].tg = ECM_DB_TIMER_GROUPS_CONNECTION_SIP_TIMEOUT;
/*
+ * Defunct re-try timeout (5 seconds)
+ */
+ ecm_db_timer_groups[ECM_DB_TIMER_GROUPS_CONNECTION_DEFUNCT_RETRY_TIMEOUT].time = ECM_DB_CONNECTION_DEFUNCT_RETRY_TIMEOUT;
+ ecm_db_timer_groups[ECM_DB_TIMER_GROUPS_CONNECTION_DEFUNCT_RETRY_TIMEOUT].tg = ECM_DB_TIMER_GROUPS_CONNECTION_DEFUNCT_RETRY_TIMEOUT;
+
+ /*
* Reset connection by protocol counters
*/
memset(ecm_db_connection_count_by_protocol, 0, sizeof(ecm_db_connection_count_by_protocol));
diff --git a/ecm_db_types.h b/ecm_db_types.h
index 1ad4ff1..cbe3b69 100644
--- a/ecm_db_types.h
+++ b/ecm_db_types.h
@@ -105,6 +105,7 @@
#define ECM_DB_CONNECTION_SDP_TIMEOUT 120
#define ECM_DB_CONNECTION_SIP_TIMEOUT 28800
#define ECM_DB_CONNECTION_BITTORRENT_TIMEOUT 120
+#define ECM_DB_CONNECTION_DEFUNCT_RETRY_TIMEOUT 5
/*
* Timer groups.
@@ -135,6 +136,7 @@
ECM_DB_TIMER_GROUPS_CONNECTION_SIP_TIMEOUT, /* SIP timeout */
ECM_DB_TIMER_GROUPS_CONNECTION_IGMP_TIMEOUT, /* IGMP timeout */
ECM_DB_TIMER_GROUPS_CONNECTION_BITTORRENT_TIMEOUT, /* Bittorrent connections timeout */
+ ECM_DB_TIMER_GROUPS_CONNECTION_DEFUNCT_RETRY_TIMEOUT, /* Defunct retry timeout */
ECM_DB_TIMER_GROUPS_MAX /* Always the last one */
};
typedef enum ecm_db_timer_groups ecm_db_timer_group_t;
diff --git a/frontends/ecm_front_end_common.c b/frontends/ecm_front_end_common.c
index fe2e5e5..6ed9d4b 100644
--- a/frontends/ecm_front_end_common.c
+++ b/frontends/ecm_front_end_common.c
@@ -80,4 +80,38 @@
}
#endif
+/*
+ * ecm_front_end_destroy_failure_handle()
+ * Destroy request failure handler.
+ */
+void ecm_front_end_destroy_failure_handle(struct ecm_front_end_connection_instance *feci)
+{
+ spin_lock_bh(&feci->lock);
+ feci->stats.driver_fail_total++;
+ feci->stats.driver_fail++;
+ if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
+ /*
+ * Reached to the driver failure limit. ECM no longer allows
+ * re-trying deceleration.
+ */
+ feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
+ spin_unlock_bh(&feci->lock);
+ DEBUG_WARN("%p: Decel failed - driver fail limit\n", feci);
+ return;
+ }
+ /*
+ * Destroy request failed. The accelerated connection couldn't be destroyed
+ * in the acceleration engine. Revert back the accel_mode, unset the is_defunct
+ * flag just in case this request has come through the defunct process.
+ */
+ feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_ACCEL;
+ feci->is_defunct = false;
+ spin_unlock_bh(&feci->lock);
+
+ /*
+ * Reset the defunct timer to a smaller timeout value so that the connection will be
+ * tried to be defuncted again, when the timeout expires (its value is 5 seconds).
+ */
+ ecm_db_connection_defunct_timer_reset(feci->ci, ECM_DB_TIMER_GROUPS_CONNECTION_DEFUNCT_RETRY_TIMEOUT);
+}
diff --git a/frontends/include/ecm_front_end_common.h b/frontends/include/ecm_front_end_common.h
index 8a9ed93..ca3a35a 100644
--- a/frontends/include/ecm_front_end_common.h
+++ b/frontends/include/ecm_front_end_common.h
@@ -171,3 +171,4 @@
extern void ecm_front_end_bond_notifier_stop(int num);
extern int ecm_front_end_bond_notifier_init(struct dentry *dentry);
extern void ecm_front_end_bond_notifier_exit(void);
+extern void ecm_front_end_destroy_failure_handle(struct ecm_front_end_connection_instance *feci);
diff --git a/frontends/nss/ecm_nss_non_ported_ipv4.c b/frontends/nss/ecm_nss_non_ported_ipv4.c
index 0586594..6e1eee0 100644
--- a/frontends/nss/ecm_nss_non_ported_ipv4.c
+++ b/frontends/nss/ecm_nss_non_ported_ipv4.c
@@ -74,6 +74,7 @@
#include "ecm_tracker.h"
#include "ecm_classifier.h"
#include "ecm_front_end_types.h"
+#include "ecm_front_end_common.h"
#include "ecm_tracker_datagram.h"
#include "ecm_tracker_udp.h"
#include "ecm_tracker_tcp.h"
@@ -1456,14 +1457,7 @@
/*
* TX failed
*/
- spin_lock_bh(&feci->lock);
- feci->stats.driver_fail_total++;
- feci->stats.driver_fail++;
- if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
- DEBUG_WARN("%p: Decel failed - driver fail limit\n", nnpci);
- feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
- }
- spin_unlock_bh(&feci->lock);
+ ecm_front_end_destroy_failure_handle(feci);
/*
* Could not send the request, decrement the decel pending counter
diff --git a/frontends/nss/ecm_nss_non_ported_ipv6.c b/frontends/nss/ecm_nss_non_ported_ipv6.c
index c5efaaf..3e91a62 100644
--- a/frontends/nss/ecm_nss_non_ported_ipv6.c
+++ b/frontends/nss/ecm_nss_non_ported_ipv6.c
@@ -75,6 +75,7 @@
#include "ecm_tracker.h"
#include "ecm_classifier.h"
#include "ecm_front_end_types.h"
+#include "ecm_front_end_common.h"
#include "ecm_tracker_datagram.h"
#include "ecm_tracker_udp.h"
#include "ecm_tracker_tcp.h"
@@ -1274,14 +1275,7 @@
/*
* TX failed
*/
- spin_lock_bh(&feci->lock);
- feci->stats.driver_fail_total++;
- feci->stats.driver_fail++;
- if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
- DEBUG_WARN("%p: Decel failed - driver fail limit\n", nnpci);
- feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
- }
- spin_unlock_bh(&feci->lock);
+ ecm_front_end_destroy_failure_handle(feci);
/*
* Could not send the request, decrement the decel pending counter
diff --git a/frontends/nss/ecm_nss_ported_ipv4.c b/frontends/nss/ecm_nss_ported_ipv4.c
index 71d87e9..44f24ee 100644
--- a/frontends/nss/ecm_nss_ported_ipv4.c
+++ b/frontends/nss/ecm_nss_ported_ipv4.c
@@ -1487,14 +1487,7 @@
/*
* TX failed
*/
- spin_lock_bh(&feci->lock);
- feci->stats.driver_fail_total++;
- feci->stats.driver_fail++;
- if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
- DEBUG_WARN("%p: Decel failed - driver fail limit\n", npci);
- feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
- }
- spin_unlock_bh(&feci->lock);
+ ecm_front_end_destroy_failure_handle(feci);
/*
* Could not send the request, decrement the decel pending counter
diff --git a/frontends/nss/ecm_nss_ported_ipv6.c b/frontends/nss/ecm_nss_ported_ipv6.c
index 1bb31f0..08641cb 100644
--- a/frontends/nss/ecm_nss_ported_ipv6.c
+++ b/frontends/nss/ecm_nss_ported_ipv6.c
@@ -1377,14 +1377,7 @@
/*
* TX failed
*/
- spin_lock_bh(&feci->lock);
- feci->stats.driver_fail_total++;
- feci->stats.driver_fail++;
- if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
- DEBUG_WARN("%p: Decel failed - driver fail limit\n", npci);
- feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
- }
- spin_unlock_bh(&feci->lock);
+ ecm_front_end_destroy_failure_handle(feci);
/*
* Could not send the request, decrement the decel pending counter
diff --git a/frontends/sfe/ecm_sfe_non_ported_ipv4.c b/frontends/sfe/ecm_sfe_non_ported_ipv4.c
index 7008b7a..4160bd4 100644
--- a/frontends/sfe/ecm_sfe_non_ported_ipv4.c
+++ b/frontends/sfe/ecm_sfe_non_ported_ipv4.c
@@ -74,6 +74,7 @@
#include "ecm_tracker.h"
#include "ecm_classifier.h"
#include "ecm_front_end_types.h"
+#include "ecm_front_end_common.h"
#include "ecm_tracker_datagram.h"
#include "ecm_tracker_udp.h"
#include "ecm_tracker_tcp.h"
@@ -1354,14 +1355,7 @@
/*
* TX failed
*/
- spin_lock_bh(&feci->lock);
- feci->stats.driver_fail_total++;
- feci->stats.driver_fail++;
- if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
- DEBUG_WARN("%p: Decel failed - driver fail limit\n", nnpci);
- feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
- }
- spin_unlock_bh(&feci->lock);
+ ecm_front_end_destroy_failure_handle(feci);
/*
* Could not send the request, decrement the decel pending counter
diff --git a/frontends/sfe/ecm_sfe_non_ported_ipv6.c b/frontends/sfe/ecm_sfe_non_ported_ipv6.c
index 89ab791..c0e082f 100644
--- a/frontends/sfe/ecm_sfe_non_ported_ipv6.c
+++ b/frontends/sfe/ecm_sfe_non_ported_ipv6.c
@@ -75,6 +75,7 @@
#include "ecm_tracker.h"
#include "ecm_classifier.h"
#include "ecm_front_end_types.h"
+#include "ecm_front_end_common.h"
#include "ecm_tracker_datagram.h"
#include "ecm_tracker_udp.h"
#include "ecm_tracker_tcp.h"
@@ -1245,14 +1246,7 @@
/*
* TX failed
*/
- spin_lock_bh(&feci->lock);
- feci->stats.driver_fail_total++;
- feci->stats.driver_fail++;
- if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
- DEBUG_WARN("%p: Decel failed - driver fail limit\n", nnpci);
- feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
- }
- spin_unlock_bh(&feci->lock);
+ ecm_front_end_destroy_failure_handle(feci);
/*
* Could not send the request, decrement the decel pending counter
diff --git a/frontends/sfe/ecm_sfe_ported_ipv4.c b/frontends/sfe/ecm_sfe_ported_ipv4.c
index 7356ed4..896747b 100644
--- a/frontends/sfe/ecm_sfe_ported_ipv4.c
+++ b/frontends/sfe/ecm_sfe_ported_ipv4.c
@@ -1395,14 +1395,7 @@
/*
* TX failed
*/
- spin_lock_bh(&feci->lock);
- feci->stats.driver_fail_total++;
- feci->stats.driver_fail++;
- if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
- DEBUG_WARN("%p: Decel failed - driver fail limit\n", npci);
- feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
- }
- spin_unlock_bh(&feci->lock);
+ ecm_front_end_destroy_failure_handle(feci);
/*
* Could not send the request, decrement the decel pending counter
diff --git a/frontends/sfe/ecm_sfe_ported_ipv6.c b/frontends/sfe/ecm_sfe_ported_ipv6.c
index aab8267..ae9a9f8 100644
--- a/frontends/sfe/ecm_sfe_ported_ipv6.c
+++ b/frontends/sfe/ecm_sfe_ported_ipv6.c
@@ -1338,14 +1338,7 @@
/*
* TX failed
*/
- spin_lock_bh(&feci->lock);
- feci->stats.driver_fail_total++;
- feci->stats.driver_fail++;
- if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) {
- DEBUG_WARN("%p: Decel failed - driver fail limit\n", npci);
- feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER;
- }
- spin_unlock_bh(&feci->lock);
+ ecm_front_end_destroy_failure_handle(feci);
/*
* Could not send the request, decrement the decel pending counter