Index: /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libparser/commands.pm
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libparser/commands.pm	(revision 38166)
+++ /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libparser/commands.pm	(working copy)
@@ -53465,6 +53465,16 @@
                 function_name => "get_q_del_step_size",
                 function_args => [],
         },
+        {
+                obj_type => "ITEM",
+                name => "sessionmaxcount",
+                menu => "root_show_qos",
+                help_string => "show max session count limit",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
+                user_level => "CLI_LEVEL_ENGINEER",
+                function_name => "get_qos_max_session_count",
+                function_args => [],
+        },
 
         {
                 obj_type => "ITEM",
@@ -53535,6 +53545,22 @@
 					optional => "NO",
 			},
 		],
+        },
+        {
+                obj_type => "ITEM",
+                name => "sessionmaxcount",
+                menu => "root_qos",
+                help_string => "set max session count limit",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
+                user_level => "CLI_LEVEL_ENGINEER",
+                function_name => "set_qos_max_session_count",
+                function_args => [
+			{
+					type => "U32",
+					help_string => "set count [max 50000]",
+					optional => "NO",
+			},
+		],
         },
 
 	{
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_classifier.c
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_classifier.c	(revision 38166)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_classifier.c	(working copy)
@@ -61,6 +61,7 @@
 #define MAX_DYN_QUEUE 50000
 #endif
 
+extern uint32_t max_dyn_queue;
 
 uint16_t ports_record[65536];
 
@@ -78,6 +79,7 @@
 unsigned int deq_idx = 0;
 
 int qos_session_cleanup = 0;
+int n_filters = 0;
 
 
 #define QOS_CLASSFIER_DEBUG_FOR_STATIC_POLICY 0
@@ -225,12 +227,13 @@
     }
 
 /* On reaching MAX session queues, we flush the filters and start to delete the queues. Till we delete all queues, we will not be creating any new filter and queue for the sessions and all packets will use 'default' queue */
-    if (current_dyn_q_count >= MAX_DYN_QUEUE) {
-	fastlog_syslog(LOG_DEBUG, "QoS sessions reached maximum limit : %u. Recycling old sessions\n", MAX_DYN_QUEUE);
+    if (current_dyn_q_count >= max_dyn_queue) {
+	fastlog_syslog(LOG_DEBUG, "QoS sessions reached maximum limit : %u. Recycling old sessions\n", max_dyn_queue);
         if (qos_session_cleanup == 0) {
-            qos_session_cleanup = 1;
             mtx_lock (&qos_filter_lock);
+            qos_session_cleanup = 1;
             qos_filter_clear_all_dyn (NULL);
+            n_filters = 0;
             mtx_unlock (&qos_filter_lock);
         }
         mtx_unlock (&qos_session_lock);
@@ -1072,6 +1075,10 @@
 	}
 
 	mtx_lock (&qos_filter_lock);
+	if (qos_session_cleanup) {
+	    mtx_unlock (&qos_filter_lock);
+	    goto ADD_FLTR_ERROR;
+	}
 
 	qs = &qos_filter_share;
 
@@ -1107,7 +1114,7 @@
         /*
         * Find an empty one.
 	*/
-	for(i=0; i < QOS_MAX_FLTR_NUM; i++) {
+	for(i = n_filters; i < QOS_MAX_FLTR_NUM; i++) {
 		pfltr = &qs->a_fltrs[i];
 
 		if(!pfltr->used) {
@@ -1136,12 +1143,14 @@
 	}
 
 	pfltr->used = 1;
-
+	++n_filters;
 	mtx_unlock (&qos_filter_lock);
 	return QOS_SUCCESS;
 
 ADD_FLTR_ERROR:
-	qos_queue_free(&qos_filter->qosq_info);
+	if (qos_session_status != SESSION_ENABLE) {
+	    qos_queue_free(&qos_filter->qosq_info);
+	}
 	return QOS_FAILURE;
 }
 
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_dynamic.h
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_dynamic.h	(revision 38166)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_dynamic.h	(working copy)
@@ -30,6 +30,8 @@
 extern struct mtx qos_session_lock;
 extern struct mtx qos_filter_lock;
 
+extern uint32_t max_dyn_queue;
+
 typedef struct dyn_qos_session_lookup {
     struct dyn_qos_session_lookup *dyn_qos_session_lookup_node[N_CHILDREN];
     qos_queue_root_t *qos_session_q_save;
@@ -62,3 +64,5 @@
 int set_q_del_step_size (void *pcb, uint32_t count);
 int get_q_del_step_size (void *pcb);
 int qos_session_init (void);
+int set_qos_max_session_count (void *pcb, uint32_t count);
+int get_qos_max_session_count (void *pcb);
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_dynamic.c
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_dynamic.c	(revision 38166)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_dynamic.c	(working copy)
@@ -28,6 +28,10 @@
 
 #define TUPLE_LEN 12 /* src ip + src port + dest ip + dst port */
 
+#ifndef MAX_DYN_QUEUE
+#define MAX_DYN_QUEUE 50000
+#endif
+
 struct mtx qos_session_lock;
 struct mtx qos_filter_lock;
 
@@ -35,6 +39,7 @@
 
 uint32_t repeat_segment_num = 50;
 uint32_t q_del_step_size = 50;
+uint32_t max_dyn_queue = MAX_DYN_QUEUE;
 
 struct dyn_session_qos_conf_head dyn_session_qos_conf_head = STAILQ_HEAD_INITIALIZER(dyn_session_qos_conf_head);
 
@@ -406,8 +411,8 @@
 }
 
 int set_tuple_count (void *pcb, uint32_t count) {
-    if (count < 50 || count > 1024) {
-        app_printf(pcb, "ERROR : count should be between 50 to 1024.\n");
+    if (count < 1 || count > 1024) {
+        app_printf(pcb, "ERROR : count should be between 1 to 1024.\n");
         return (QOS_USERLAND_FAILURE);
     }
     repeat_segment_num = count;
@@ -419,13 +424,14 @@
 }
 
 int set_q_del_step_size (void *pcb, uint32_t count) {
-    if (count <= 0 || count > 1024) {
+    if (count < 1 || count > 1024) {
         app_printf(pcb, "ERROR : count should be between 1 to 1024.\n");
         return (QOS_USERLAND_FAILURE);
     }
     q_del_step_size = count;
     return QOS_SUCCESS;
 }
+
 int get_q_del_step_size (void *pcb) {
     app_printf(pcb, "count : %u\n", q_del_step_size);
     return QOS_SUCCESS;
@@ -436,3 +442,17 @@
     mtx_init(&qos_filter_lock, "qos filter lock", NULL, MTX_DEF | MTX_NOWITNESS);
     return QOS_SUCCESS;
 }
+
+int set_qos_max_session_count (void *pcb, uint32_t count) {
+    if (count > MAX_DYN_QUEUE) {
+        app_printf(pcb, "ERROR : count can not be set more then %d\n", MAX_DYN_QUEUE);
+        return (QOS_USERLAND_FAILURE);
+    }
+    max_dyn_queue = count;
+    return QOS_SUCCESS;
+}
+
+int get_qos_max_session_count (void *pcb) {
+    app_printf(pcb, "count : %u\n", max_dyn_queue);
+    return QOS_SUCCESS;
+}
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_scheduler.c
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_scheduler.c	(revision 38166)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_scheduler.c	(working copy)
@@ -748,18 +748,23 @@
 		}
 	}
 
-	/* Check duplicated queue name */
         mtx_lock (&qos_session_lock);
-	STAILQ_FOREACH(pQoSQRootSave, &qos_queue_root_head, list_entry) {
+	if (qos_session_cleanup) {
+	    mtx_unlock (&qos_session_lock);
+	    return(QOS_USERLAND_FAILURE);
+	}
+
+	/* Check duplicated queue name */
+        if (!qos_session_status) {
+	    STAILQ_FOREACH(pQoSQRootSave, &qos_queue_root_head, list_entry) {
 		if (strcmp(pQoSQRootSave->sQName, pQoSQRoot->sQName) == 0) {
 			app_printf(pcb, "ERROR: root queue %s has been configured\n",pQoSQRoot->sQName);
 			fastlog_syslog(LOG_DEBUG, "ERROR: root queue %s has been configured\n",pQoSQRoot->sQName);
                         mtx_unlock (&qos_session_lock);
 			return(QOS_USERLAND_FAILURE);
 		}
-	}
+	    }
 
-        if (!qos_session_status) {
 	    STAILQ_FOREACH(pQoSQSub, &qos_queue_sub_head, list_entry) {
 		if (strcmp(pQoSQSub->sQName, pQoSQRoot->sQName) == 0) {
 			app_printf(pcb, "ERROR: sub queue %s has been configured\n",pQoSQRoot->sQName);
@@ -821,7 +826,9 @@
 	s = splimp();
 
 	/* Add the class */
-	iErrCode = altq_add_queue(pALTQConf);
+        mtx_lock (&qos_session_lock);
+        iErrCode = altq_add_queue(pALTQConf);
+        mtx_unlock (&qos_session_lock);
 
 	if (iErrCode != 0) {
 		if (EMFILE == iErrCode) {
@@ -917,7 +924,6 @@
 	STAILQ_REMOVE(&qos_queue_root_head, pQoSQRoot, qos_queue_root, list_entry);
 	free(pQoSQRoot, M_QOS);
         --current_dyn_q_count;
-        mtx_unlock (&qos_session_lock);
 
 	/* Security */
 	s = splimp();
@@ -927,6 +933,7 @@
 	if (!iErrCode) {iErrCode = iErrCode1;}
 
 	splx(s);
+	mtx_unlock (&qos_session_lock);
 	return(iErrCode);
 }
 
