Static flow assignment CR 736558
Not supporting 1k/7k connections
Static flow connection implementation was not
supporting 1K and 7K connections, since the input
were always power of 2. Now we have changed it to
support 1K connections. Now the granularity of
configuration is 1K. Hence with this checkin the
configurable numbers would be
1024, 2048, 3072, 4098, 5120m 6144, 7168
Min(IPv4/IPv6): 1024,
Max (IPv4/IPv6): 7168.
Min (IPv4 + IPv6) = 2048
Max (IPv4 + IPv6) = 8192
Change-Id: Iab5355467eb22abbb16bb2c220e859e975138283
Signed-off-by: Vijay Dewangan <vdewanga@codeaurora.org>
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index 595593a..b1d2adf 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -149,13 +149,17 @@
* Error types for ipv4 messages
*/
enum nss_ipv4_error_response_types {
- NSS_IPV4_CR_INVALID_PNODE_ERROR = 1, /**< NSS Error: Invalid interface number */
- NSS_IPV4_CR_MISSING_CONNECTION_RULE_ERROR, /**< NSS Error: Missing connection rule */
- NSS_IPV4_CR_BUFFER_ALLOC_FAIL_ERROR, /**< NSS Error: Buffer allocation failure */
- NSS_IPV4_CR_PPPOE_SESSION_CREATION_ERROR, /**< NSS Error: Unable to create PPPoE session */
- NSS_IPV4_DR_NO_CONNECTION_ENTRY_ERROR, /**< NSS Error: No connection found to delete */
- NSS_IPV4_UNKNOWN_MSG_TYPE, /**< NSS Error: Unknown error */
- NSS_IPV4_LAST /**< NSS IPv4 max error response type */
+ NSS_IPV4_CR_INVALID_PNODE_ERROR = 1, /**< NSS Error: Invalid interface number */
+ NSS_IPV4_CR_MISSING_CONNECTION_RULE_ERROR, /**< NSS Error: Missing connection rule */
+ NSS_IPV4_CR_BUFFER_ALLOC_FAIL_ERROR, /**< NSS Error: Buffer allocation failure */
+ NSS_IPV4_CR_PPPOE_SESSION_CREATION_ERROR, /**< NSS Error: Unable to create PPPoE session */
+ NSS_IPV4_DR_NO_CONNECTION_ENTRY_ERROR, /**< NSS Error: No connection found to delete */
+ NSS_IPV4_CR_CONN_CFG_ALREADY_CONFIGURED_ERROR, /**< NSS Error: Conn cfg already done once */
+ NSS_IPV4_CR_CONN_CFG_NOT_MULTIPLE_OF_QUANTA_ERROR, /**< NSS Error: Conn cfg input is not multiple of quanta */
+ NSS_IPV4_CR_CONN_CFG_EXCEEDS_LIMIT_ERROR, /**< NSS Error: Conn cfg input exceeds max supported connections*/
+ NSS_IPV4_CR_CONN_CFG_MEM_ALLOC_FAIL_ERROR, /**< NSS Error: Conn cfg mem alloc fail at NSS FW */
+ NSS_IPV4_UNKNOWN_MSG_TYPE, /**< NSS Error: Unknown error */
+ NSS_IPV4_LAST /**< NSS IPv4 max error response type */
};
/**
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index 7535e66..b2b97f2 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -186,12 +186,16 @@
* Error types for ipv6 messages
*/
enum nss_ipv6_error_response_types {
- NSS_IPV6_CR_INVALID_PNODE_ERROR = 1, /**< NSS Error: Invalid interface number */
- NSS_IPV6_CR_MISSING_CONNECTION_RULE_ERROR, /**< NSS Error: Missing connection rule */
- NSS_IPV6_CR_BUFFER_ALLOC_FAIL_ERROR, /**< NSS Error: Buffer allocation failure */
- NSS_IPV6_CR_PPPOE_SESSION_CREATION_ERROR, /**< NSS Error: Unable to create PPPoE session */
- NSS_IPV6_DR_NO_CONNECTION_ENTRY_ERROR, /**< NSS Error: No connection found to delete */
- NSS_IPV6_UNKNOWN_MSG_TYPE, /**< NSS Error: Unknown error */
+ NSS_IPV6_CR_INVALID_PNODE_ERROR = 1, /**< NSS Error: Invalid interface number */
+ NSS_IPV6_CR_MISSING_CONNECTION_RULE_ERROR, /**< NSS Error: Missing connection rule */
+ NSS_IPV6_CR_BUFFER_ALLOC_FAIL_ERROR, /**< NSS Error: Buffer allocation failure */
+ NSS_IPV6_CR_PPPOE_SESSION_CREATION_ERROR, /**< NSS Error: Unable to create PPPoE session */
+ NSS_IPV6_DR_NO_CONNECTION_ENTRY_ERROR, /**< NSS Error: No connection found to delete */
+ NSS_IPV6_CR_CONN_CFG_ALREADY_CONFIGURED_ERROR, /**< NSS Error: Conn cfg already done once */
+ NSS_IPV6_CR_CONN_CFG_NOT_MULTIPLE_OF_QUANTA_ERROR, /**< NSS Error: Conn cfg input is not multiple of quanta */
+ NSS_IPV6_CR_CONN_CFG_EXCEEDS_LIMIT_ERROR, /**< NSS Error: Conn cfg input exceeds max supported connections*/
+ NSS_IPV6_CR_CONN_CFG_MEM_ALLOC_FAIL_ERROR, /**< NSS Error: Conn cfg mem alloc fail at NSS FW */
+ NSS_IPV6_UNKNOWN_MSG_TYPE, /**< NSS Error: Unknown error */
};
/**
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index 1251ce8..3428f6f 100755
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -22,8 +22,11 @@
#ifndef __NSS_HLOS_IF_H
#define __NSS_HLOS_IF_H
-#define MIN_NUM_CONN 256 /**< MIN Connection shared between IPv4 and IPv6 */
-#define MAX_TOTAL_NUM_CONN_IPV4_IPV6 8196 /**< MAX Connection shared between IPv4 and IPv6 */
+#define NSS_MIN_NUM_CONN 256 /**< MIN Connection shared between IPv4 and IPv6 */
+#define NSS_DEFAULT_NUM_CONN 1024 /**< Default number of connections for each IPV4 and IPV6 */
+#define NSS_NUM_CONN_QUANTA_MASK (1024 - 1) /**< Quanta of number of connections 1024 */
+#define NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6 8196 /**< MAX Connection shared between IPv4 and IPv6 */
+#define NSS_CONN_CFG_TIMEOUT 6000 /**< 6 sec timeout for connection cfg message */
/*
* Variables used for sysctl updates.
@@ -31,6 +34,22 @@
extern int nss_ipv4_conn_cfg;
extern int nss_ipv6_conn_cfg;
+enum {
+ SUCCESS = 0,
+ FAILURE = 1,
+};
+
+/*
+ * Private data structure for configuring ipv4/6 connections
+ */
+struct nss_conn_cfg_pvt {
+ struct semaphore sem; /* Semaphore structure */
+ struct completion complete; /* completion structure */
+ int current_value; /* valid entry */
+ int response; /* Response from FW */
+};
+
+
/*
* Request/Response types
*/
diff --git a/nss_ipv4.c b/nss_ipv4.c
index 68d28b9..d7699d8 100644
--- a/nss_ipv4.c
+++ b/nss_ipv4.c
@@ -22,11 +22,13 @@
#include <linux/ppp_channel.h>
#include "nss_tx_rx_common.h"
+
extern void nss_rx_metadata_ipv4_rule_establish(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_rule_establish *nire);
extern void nss_rx_metadata_ipv4_create_response(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim);
extern void nss_rx_ipv4_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs);
-int nss_ipv4_conn_cfg __read_mostly = 4096;
+int nss_ipv4_conn_cfg __read_mostly = NSS_DEFAULT_NUM_CONN;
+static struct nss_conn_cfg_pvt i4cfgp;
/*
* nss_ipv4_driver_conn_sync_update()
@@ -305,17 +307,29 @@
/*
* nss_ipv4_conn_cfg_callback()
- * call back function for the ipv6 connection configuration handler
+ * call back function for the ipv4 connection configuration handler
*/
static void nss_ipv4_conn_cfg_callback(void *app_data, struct nss_if_msg *nim)
{
if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
nss_warning("IPv4 connection configuration failed with error: %d\n", nim->cm.error);
+ /*
+ * Error, hence we are not updating the nss_ipv4_conn_cfg
+ * Restore the current_value to its previous state
+ */
+ i4cfgp.response = FAILURE;
+ complete(&i4cfgp.complete);
return;
}
+ /*
+ * Sucess at NSS FW, hence updating nss_ipv4_conn_cfg, with the valid value
+ * saved at the sysctl handler.
+ */
nss_info("IPv4 connection configuration success: %d\n", nim->cm.error);
+ i4cfgp.response = SUCCESS;
+ complete(&i4cfgp.complete);
}
/*
@@ -329,40 +343,54 @@
struct nss_ipv4_msg nim;
struct nss_ipv4_rule_conn_cfg_msg *nirccm;
nss_tx_status_t nss_tx_status;
- int ret = 1;
- uint32_t sum_of_conn = nss_ipv4_conn_cfg + nss_ipv6_conn_cfg;
+ int ret = FAILURE;
+ uint32_t sum_of_conn;
/*
- * The input should be power of 2.
- * Input for ipv4 and ipv6 sum togther should not exceed 8k
- * Min. value should be at leat 256 connections. This is the
+ * Acquiring semaphore
+ */
+ down(&i4cfgp.sem);
+
+ /*
+ * Take snap shot of current value
+ */
+ i4cfgp.current_value = nss_ipv4_conn_cfg;
+
+ /*
+ * Write the variable with user input
+ */
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ if (ret || (!write)) {
+ up(&i4cfgp.sem);
+ return ret;
+ }
+
+ /*
+ * The input should be multiple of 1024.
+ * Input for ipv4 and ipv6 sum together should not exceed 8k
+ * Min. value should be at least 256 connections. This is the
* minimum connections we will support for each of them.
*/
- if ((nss_ipv4_conn_cfg & (nss_ipv4_conn_cfg - 1)) ||
- (sum_of_conn > MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
- (nss_ipv4_conn_cfg < MIN_NUM_CONN)) {
+ sum_of_conn = nss_ipv4_conn_cfg + nss_ipv6_conn_cfg;
+ if ((nss_ipv4_conn_cfg & NSS_NUM_CONN_QUANTA_MASK) ||
+ (sum_of_conn > NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
+ (nss_ipv4_conn_cfg < NSS_MIN_NUM_CONN)) {
nss_warning("%p: input supported connections (%d) does not adhere\
- specifications\n1) not power of 2,\n2) is less than \
+ specifications\n1) not multiple of 1024,\n2) is less than \
min val: %d, OR\n IPv4/6 total exceeds %d\n",
nss_ctx,
nss_ipv4_conn_cfg,
- MIN_NUM_CONN,
- MAX_TOTAL_NUM_CONN_IPV4_IPV6);
- return ret;
+ NSS_MIN_NUM_CONN,
+ NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ nss_ipv4_conn_cfg = i4cfgp.current_value;
+ up(&i4cfgp.sem);
+ return FAILURE;
}
- ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
-
- if (ret) {
- return ret;
- }
-
- if ((!write)) {
- nss_warning("%p: IPv4 supported connections write failed: %d\n", nss_ctx, nss_ipv4_conn_cfg);
- return ret;
- }
-
-
nss_info("%p: IPv4 supported connections: %d\n", nss_ctx, nss_ipv4_conn_cfg);
nss_cmn_msg_init(&nim.cm, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_CONN_CFG_RULE_MSG,
@@ -376,16 +404,55 @@
nss_warning("%p: nss_tx error setting IPv4 Connections: %d\n",
nss_ctx,
nss_ipv4_conn_cfg);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ nss_ipv4_conn_cfg = i4cfgp.current_value;
+ up(&i4cfgp.sem);
+ return FAILURE;
}
- return ret;
+
+ /*
+ * Blocking call, wait till we get ACK for this msg.
+ */
+ ret = wait_for_completion_timeout(&i4cfgp.complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
+ if (ret == 0) {
+ nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ nss_ipv4_conn_cfg = i4cfgp.current_value;
+ up(&i4cfgp.sem);
+ return FAILURE;
+ }
+
+ /*
+ * ACK/NACK received from NSS FW
+ * If ACK: Callback function will update nss_ipv4_conn_cfg with
+ * i4cfgp.num_conn_valid, which holds the user input
+ */
+ if (FAILURE == i4cfgp.response) {
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ nss_ipv4_conn_cfg = i4cfgp.current_value;
+ up(&i4cfgp.sem);
+ return FAILURE;
+ }
+
+ up(&i4cfgp.sem);
+ return SUCCESS;
}
static ctl_table nss_ipv4_table[] = {
{
- .procname = "ipv4_conn",
- .data = &nss_ipv4_conn_cfg,
- .maxlen = sizeof(int),
- .mode = 0644,
+ .procname = "ipv4_conn",
+ .data = &nss_ipv4_conn_cfg,
+ .maxlen = sizeof(int),
+ .mode = 0644,
.proc_handler = &nss_ipv4_conn_cfg_handler,
},
{ }
@@ -393,9 +460,9 @@
static ctl_table nss_ipv4_dir[] = {
{
- .procname = "ipv4cfg",
- .mode = 0555,
- .child = nss_ipv4_table,
+ .procname = "ipv4cfg",
+ .mode = 0555,
+ .child = nss_ipv4_table,
},
{ }
};
@@ -431,6 +498,9 @@
* Register sysctl table.
*/
nss_ipv4_header = register_sysctl_table(nss_ipv4_root);
+ sema_init(&i4cfgp.sem, 1);
+ init_completion(&i4cfgp.complete);
+ i4cfgp.current_value = nss_ipv4_conn_cfg;
}
/*
diff --git a/nss_ipv6.c b/nss_ipv6.c
index 3b51486..93ba169 100644
--- a/nss_ipv6.c
+++ b/nss_ipv6.c
@@ -25,7 +25,8 @@
extern void nss_rx_metadata_ipv6_create_response(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *nim);
extern void nss_rx_ipv6_sync(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync *nirs);
-int nss_ipv6_conn_cfg __read_mostly = 4096;
+int nss_ipv6_conn_cfg __read_mostly = NSS_DEFAULT_NUM_CONN;
+static struct nss_conn_cfg_pvt i6cfgp;
/*
* nss_ipv6_driver_conn_sync_update()
@@ -309,11 +310,22 @@
static void nss_ipv6_conn_cfg_callback(void *app_data, struct nss_if_msg *nim)
{
if (nim->cm.response != NSS_CMN_RESPONSE_ACK) {
- nss_warning("IPv6 connection configuration failed with error: %d\n", nim->cm.error);
+ /*
+ * Error, hence we are not updating the nss_ipv4_conn_cfg
+ * Restore the current_value to its previous state
+ */
+ i6cfgp.response = FAILURE;
+ complete(&i6cfgp.complete);
return;
}
+ /*
+ * Sucess at NSS FW, hence updating nss_ipv4_conn_cfg, with the valid value
+ * saved at the sysctl handler.
+ */
nss_info("IPv6 connection configuration success: %d\n", nim->cm.error);
+ i6cfgp.response = SUCCESS;
+ complete(&i6cfgp.complete);
}
@@ -328,8 +340,24 @@
struct nss_ipv6_msg nim;
struct nss_ipv6_rule_conn_cfg_msg *nirccm;
nss_tx_status_t nss_tx_status;
- int ret = 1;
- uint32_t sum_of_conn = nss_ipv4_conn_cfg + nss_ipv6_conn_cfg;
+ int ret = FAILURE;
+ uint32_t sum_of_conn;
+
+ /*
+ * Acquiring semaphore
+ */
+ down(&i6cfgp.sem);
+
+ /*
+ * Take a snapshot of the current value
+ */
+ i6cfgp.current_value = nss_ipv6_conn_cfg;
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ if (ret || (!write)) {
+ up(&i6cfgp.sem);
+ return ret;
+ }
/*
* Specifications for input
@@ -338,29 +366,26 @@
* 3) Min. value should be at leat 256 connections. This is the
* minimum connections we will support for each of them.
*/
- if ((nss_ipv6_conn_cfg & (nss_ipv6_conn_cfg - 1)) ||
- (sum_of_conn > MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
- (nss_ipv6_conn_cfg < MIN_NUM_CONN)) {
+ sum_of_conn = nss_ipv4_conn_cfg + nss_ipv6_conn_cfg;
+ if ((nss_ipv6_conn_cfg & NSS_NUM_CONN_QUANTA_MASK) ||
+ (sum_of_conn > NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6) ||
+ (nss_ipv6_conn_cfg < NSS_MIN_NUM_CONN)) {
nss_warning("%p: input supported connections (%d) does not adhere\
specifications\n1) not power of 2,\n2) is less than \
min val: %d, OR\n IPv4/6 total exceeds %d\n",
nss_ctx,
nss_ipv6_conn_cfg,
- MIN_NUM_CONN,
- MAX_TOTAL_NUM_CONN_IPV4_IPV6);
- return ret;
+ NSS_MIN_NUM_CONN,
+ NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ nss_ipv6_conn_cfg = i6cfgp.current_value;
+ up(&i6cfgp.sem);
+ return FAILURE;
}
- ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
-
- if (ret) {
- return ret;
- }
-
- if (!write) {
- nss_warning("%p: IPv6 supported connections write failed: %d\n", nss_ctx, nss_ipv6_conn_cfg);
- return ret;
- }
nss_info("%p: IPv6 supported connections: %d\n", nss_ctx, nss_ipv6_conn_cfg);
@@ -375,16 +400,54 @@
nss_warning("%p: nss_tx error setting IPv6 Connections: %d\n",
nss_ctx,
nss_ipv6_conn_cfg);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ nss_ipv6_conn_cfg = i6cfgp.current_value;
+ up(&i6cfgp.sem);
+ return FAILURE;
}
- return ret;
+
+ /*
+ * Blocking call, wait till we get ACK for this msg.
+ */
+ ret = wait_for_completion_timeout(&i6cfgp.complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
+ if (ret == 0) {
+ nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
+
+ /*
+ * Restore the current_value to its previous state
+ */
+ nss_ipv6_conn_cfg = i6cfgp.current_value;
+ up(&i6cfgp.sem);
+ return FAILURE;
+ }
+
+ /*
+ * ACK/NACK received from NSS FW
+ * If ACK: Callback function will update nss_ipv4_conn_cfg with
+ * i6cfgp.num_conn_valid, which holds the user input
+ */
+ if (FAILURE == i6cfgp.response) {
+ /*
+ * Restore the current_value to its previous state
+ */
+ nss_ipv6_conn_cfg = i6cfgp.current_value;
+ up(&i6cfgp.sem);
+ return FAILURE;
+ }
+
+ up(&i6cfgp.sem);
+ return SUCCESS;
}
static ctl_table nss_ipv6_table[] = {
{
- .procname = "ipv6_conn",
- .data = &nss_ipv6_conn_cfg,
- .maxlen = sizeof(int),
- .mode = 0644,
+ .procname = "ipv6_conn",
+ .data = &nss_ipv6_conn_cfg,
+ .maxlen = sizeof(int),
+ .mode = 0644,
.proc_handler = &nss_ipv6_conn_cfg_handler,
},
{ }
@@ -392,9 +455,9 @@
static ctl_table nss_ipv6_dir[] = {
{
- .procname = "ipv6cfg",
- .mode = 0555,
- .child = nss_ipv6_table,
+ .procname = "ipv6cfg",
+ .mode = 0555,
+ .child = nss_ipv6_table,
},
{ }
};
@@ -429,6 +492,9 @@
* Register sysctl table.
*/
nss_ipv6_header = register_sysctl_table(nss_ipv6_root);
+ sema_init(&i6cfgp.sem, 1);
+ init_completion(&i6cfgp.complete);
+ i6cfgp.current_value = nss_ipv6_conn_cfg;
}
/*