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 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/click/lib/libparser/commands.pm	(working copy)
@@ -53417,34 +53417,44 @@
         },
         {
                 obj_type => "ITEM",
-                name => "session_q_count",
+                name => "session_count",
                 menu => "root_show_qos",
                 cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
-                user_level => "CLI_LEVEL_ENGINEER",
-                help_string => "Show current Queue count for sessions",
+                user_level => "CLI_LEVEL_ENABLE",
+                help_string => "Show current session count",
                 function_name => "show_current_queue_count_for_sessions",
                 function_args => [],
         },
         {
                 obj_type => "ITEM",
-                name => "display_queues_for_session",
+                name => "session_queues",
                 menu => "root_show_qos",
                 cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
                 user_level => "CLI_LEVEL_ENGINEER",
-                help_string => "Show Queues for QoS Session",
+                help_string => "Show Session Queues",
                 function_name => "show_session_qos_queue_root_kern",
                 function_args => [],
         },
         {
                 obj_type => "ITEM",
-                name => "display_filters_for_session",
+                name => "session_filters",
                 menu => "root_show_qos",
                 cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
                 user_level => "CLI_LEVEL_ENGINEER",
-                help_string => "Show filters for QoS Session",
+                help_string => "Show Session filters",
                 function_name => "show_session_qos_filter_kern",
                 function_args => [],
         },
+        {
+                obj_type => "ITEM",
+                name => "sessionpacketcount",
+                menu => "root_show_qos",
+                help_string => "show packet match count to create Session",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
+		user_level => "CLI_LEVEL_ENGINEER",
+                function_name => "get_tuple_count",
+                function_args => [],
+        },
 
         {
                 obj_type => "ITEM",
@@ -53464,7 +53474,7 @@
         },
         {
                 obj_type => "ITEM",
-                name => "session_on",
+                name => "sessionon",
                 menu => "root_qos",
                 help_string => "Activate QoS Session",
                 cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
@@ -53475,7 +53485,7 @@
 
         {
                 obj_type => "ITEM",
-                name => "session_off",
+                name => "sessionoff",
                 menu => "root_qos",
                 help_string => "Deactivate QoS Session",
                 cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
@@ -53484,6 +53494,23 @@
                 function_args => [],
         },
 
+        {
+                obj_type => "ITEM",
+                name => "sessionpacketcount",
+                menu => "root_qos",
+                help_string => "set packet match count to create Session",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL|CMD_KERN_API",
+		user_level => "CLI_LEVEL_ENGINEER",
+                function_name => "set_tuple_count",
+		function_args => [
+			{
+					type => "U32",
+					help_string => "count [50 to 1024]",
+					optional => "NO",
+			},
+		],
+        },
+
 	{
 		obj_type => "ITEM",
 		name => "sub",
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/altq_cbq.h
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/altq_cbq.h	(revision 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/altq_cbq.h	(working copy)
@@ -90,7 +90,11 @@
 
 #ifdef _KERNEL
 
-#define	CBQ_MAX_CLASSES	100000
+#ifndef MAX_DYN_QUEUE
+#define MAX_DYN_QUEUE 50000
+#endif
+
+#define	CBQ_MAX_CLASSES	(MAX_DYN_QUEUE + 100)
 
 /*
  * Define State structures.
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_classifier.h
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_classifier.h	(revision 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_classifier.h	(working copy)
@@ -31,11 +31,15 @@
 #define QOS_FLTR_NLEN 32
 
 /*
- * maximum filter number
+ * maximum filter number. It is recommended not to create QoS filters when 'QoS Session' feature is enabled.
  */
-//#define QOS_MAX_FLTR_NUM 1024
-//
-#define QOS_MAX_FLTR_NUM 100000
+
+
+#ifndef MAX_DYN_QUEUE
+#define MAX_DYN_QUEUE 50000
+#endif
+
+#define QOS_MAX_FLTR_NUM (MAX_DYN_QUEUE + 100)
 
 
 /*
@@ -218,6 +222,7 @@
 int qos_dyn_del(clickrule_5tuple_t *tp, struct qos_queue_info *qqi);
 int qos_filter_dyn_clear_interface(struct qos_queue_info *qqi);
 int qos_filter_clear_all(void *pcb);
+int qos_filter_clear_all_dyn(void *pcb);
 int qos_filter_clear_interface(void *pcb, struct ifnet *ifp, uint8_t dir);
 
 #define qos_printf(fmt, arg...)
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 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_classifier.c	(working copy)
@@ -57,13 +57,15 @@
 #include <click/app/fastlog/fastlog.h>
 #include <click/app/qos/qos_dynamic.h>
 
-/* MAX 100000 queues are supported. However if 'qos session' feature is enabled,
-    then administrator can only configure upto 1000 static queues/filter(using CLI or UI) and rest reserved
-    for 'qos session' feature which envolves creating queues/filters dynamically */
+#ifndef MAX_DYN_QUEUE
+#define MAX_DYN_QUEUE 50000
+#endif
+
+#define Q_DEL_STEP_SIZE 50
 
-#define MAX_DYN_QUEUE 99000
+uint16_t ports_record[65536];
 
-static void delete_queue_filter (unsigned int count);
+static void delete_dyn_queues (void);
 static int qos_filter_add_table(qos_filter_share_t *qs, qos_filter_t *pfltr);
 static int qos_filter_del_table(qos_filter_share_t *qs, qos_filter_t *pfltr);
 static int qos_filter_rebuild(struct ifnet *ifp, int dir);
@@ -76,6 +78,7 @@
 unsigned int enq_idx = 0;
 unsigned int deq_idx = 0;
 char q_dynamic_list[MAX_DYN_QUEUE][32];
+int qos_session_cleanup = 0;
 
 
 #define QOS_CLASSFIER_DEBUG_FOR_STATIC_POLICY 0
@@ -136,6 +139,7 @@
 qos_filter_share_t qos_filter_share;
 extern uint32_t **clickrule_notfound;
 extern int qos_session_status;
+extern uint32_t repeat_segment_num;
 
 /******************************************************************************
  * Return the current valid class poniter.
@@ -210,7 +214,14 @@
     char ip_str[20];
     uint32_t smask = -1;
     uint32_t dmask = -1;
+    int count = 0;
     
+    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);
+        qos_session_cleanup = 1;
+        qos_filter_clear_all_dyn (NULL);
+        return;
+    }
 
     if (sip) {
         sprintf (ip_str, "%u", sip);
@@ -218,11 +229,11 @@
         sprintf (ip_str, "%u", dip);
     }
 
-    sprintf (q_name, "%s%s_%u_%u_%s", DYNAMIC_QUEUE_PREFIX, ip_str, sport, dport, sDir);
-    sprintf (f_name, "%s%s_%u_%u_%s", DYNAMIC_FILTER_PREFIX, ip_str, sport, dport, sDir);
+    sprintf (q_name, "%s%s%u%u%c", DYNAMIC_QUEUE_PREFIX, ip_str, sport, dport, sDir[0]);
+    sprintf (f_name, "%s%s%u%u%c", DYNAMIC_FILTER_PREFIX, ip_str, sport, dport, sDir[0]);
 
-    strcpy(pQoSQRoot->sQName, q_name);
-    strcpy(pALTConf->qname, q_name);
+    strncpy(pQoSQRoot->sQName, q_name, 32);
+    strncpy(pALTConf->qname, q_name, 32);
 
     qos_queue_root_kern (NULL, pQoSQRoot, sizeof(qos_queue_root_t), pALTConf, sizeof(struct altq_conf));
 
@@ -235,37 +246,37 @@
         
     qos_filter_kern(NULL, f_name, q_name, sip, smask, sport, dip, dmask, dport, "any", 1);
 
-    if (enq_idx == MAX_DYN_QUEUE)
+    if (enq_idx == MAX_DYN_QUEUE) {
         enq_idx = 0;
-    sprintf (q_dynamic_list[enq_idx++], "%s", q_name);
-    ++current_dyn_q_count;
-    if (current_dyn_q_count % 1000 == 0)
-	    fastlog_syslog(LOG_DEBUG, "Current QoS Session queues : %u\n", current_dyn_q_count);
-
-/*
-If current Queue utilization is 100% then delete 30% of the queue(and corresponding filter)
-*/
-    if (current_dyn_q_count >= MAX_DYN_QUEUE) {
-	    fastlog_syslog(LOG_DEBUG, "QoS session queues reached maximum limit : %u. Deleting old %u queues.\n", MAX_DYN_QUEUE, MAX_DYN_QUEUE * 0.3);
-        delete_queue_filter(0.3 * MAX_DYN_QUEUE);
     }
+    sprintf (q_dynamic_list[enq_idx], "%s", q_name);
+    ++enq_idx;
+    ++current_dyn_q_count;
 }
 
-void delete_queue_filter (unsigned int count) {
-    char q_name[32];
-    char f_name[32];
 
-    while(count--) {
-        if (deq_idx == MAX_DYN_QUEUE) 
+static void delete_dyn_queues () {
+    int count;
+
+    count = (current_dyn_q_count >= Q_DEL_STEP_SIZE) ? Q_DEL_STEP_SIZE : current_dyn_q_count;
+
+    while(count) {
+        if (deq_idx == MAX_DYN_QUEUE) {
             deq_idx = 0;
-        strcpy (q_name, q_dynamic_list[deq_idx++]);
-        strcpy (f_name, q_name);
-        f_name[0] = 'f';
-        no_qos_filter_kern (NULL, f_name);
-        no_qos_queue_root_kern (NULL, q_name);
+        }
+        no_qos_queue_root_sess_kern (q_dynamic_list[deq_idx]);
+        bzero(q_dynamic_list[deq_idx], 32);
+        ++deq_idx;
         --current_dyn_q_count;
+        --count;
+    }
+
+    if (current_dyn_q_count <= 0) {
+        qos_session_cleanup = 0;
     }
 }
+
+
 /******************************************************************************
  *  Get a proper class for the outbound or inbound packets
  *
@@ -301,6 +312,9 @@
 	int src_ip_index;
 	int dst_ip_index;
 
+    qos_queue_root_t local_qos_q_conf;
+    struct altq_conf local_altq_conf;
+
 
 	m = *mp;
 	if(NULL == ifp || NULL == m || NULL == pktattr) {
@@ -531,58 +545,74 @@
 
 label:
         if (qos_session_status == SESSION_ENABLE) {
-	    if (QOSD_OUTPUT == direction) {
-		rorder = (uint8_t *) o_net_order;
-                sDir = "OUT";
-                *((uint8_t *)&src_port_qos + 0) = rtuple[rorder[4]];
-                *((uint8_t *)&src_port_qos + 1) = rtuple[rorder[3]];
-
-                *((uint8_t *)&dst_port_qos + 0) = rtuple[rorder[2]];
-                *((uint8_t *)&dst_port_qos + 1) = rtuple[rorder[1]];
-            } else {
-		rorder = (uint8_t *) i_net_order;
-                sDir = "IN";
-                *((uint8_t *)&src_port_qos + 0) = rtuple[rorder[2]];
-                *((uint8_t *)&src_port_qos + 1) = rtuple[rorder[1]];
-
-                *((uint8_t *)&dst_port_qos + 0) = rtuple[rorder[4]];
-                *((uint8_t *)&dst_port_qos + 1) = rtuple[rorder[3]];
+            if (qos_session_cleanup) {
+                delete_dyn_queues();
             }
+            else {
+	        if (QOSD_OUTPUT == direction) {
+		    rorder = (uint8_t *) o_net_order;
+                    sDir = "OUT";
+                    *((uint8_t *)&src_port_qos + 0) = rtuple[rorder[4]];
+                    *((uint8_t *)&src_port_qos + 1) = rtuple[rorder[3]];
+
+                    *((uint8_t *)&dst_port_qos + 0) = rtuple[rorder[2]];
+                    *((uint8_t *)&dst_port_qos + 1) = rtuple[rorder[1]];
+                } else {
+		    rorder = (uint8_t *) i_net_order;
+                    sDir = "IN";
+                    *((uint8_t *)&src_port_qos + 0) = rtuple[rorder[2]];
+                    *((uint8_t *)&src_port_qos + 1) = rtuple[rorder[1]];
 
-            src_ip_index = 5;
-            dst_ip_index = 9;
+                    *((uint8_t *)&dst_port_qos + 0) = rtuple[rorder[4]];
+                    *((uint8_t *)&dst_port_qos + 1) = rtuple[rorder[3]];
+                }
 
+                src_ip_index = 5;
+                dst_ip_index = 9;
+
+
+                for (i = 0; i < 4; i++) {
+                    *((uint8_t *)&src_ip_qos + i) = rtuple[rorder[i+src_ip_index]];
+                }
+                for (i = 0; i < 4; i++) {
+                    *((uint8_t *)&dst_ip_qos + i) = rtuple[rorder[i+dst_ip_index]];
+                }
 
-            for (i = 0; i < 4; i++) {
-                *((uint8_t *)&src_ip_qos + i) = rtuple[rorder[i+src_ip_index]];
-            }
-            for (i = 0; i < 4; i++) {
-                *((uint8_t *)&dst_ip_qos + i) = rtuple[rorder[i+dst_ip_index]];
-            }
 #if 0
 	fastlog_syslog(LOG_DEBUG, "TO CHECK ..src ip : %u, src_port : %u, dst_ip : %u, dst_port : %u, dir : %d\n",src_ip_qos, src_port_qos, dst_ip_qos, dst_port_qos, direction);
 #endif
 
-            temp = qos_session_lookup(src_ip_qos, src_port_qos, dst_ip_qos, dst_port_qos, direction);
+                temp = qos_session_lookup(src_ip_qos, src_port_qos, dst_ip_qos, dst_port_qos, direction);
 
-            if (temp && !strcmp(temp->qos_session_altq_conf_save->ifname, ifp->if_xname) 
-                && !strcmp(temp->qos_session_q_save->sDir, sDir))    {
+                if (temp && !strcmp(temp->qos_session_altq_conf_save->ifname, ifp->if_xname) 
+                    && !strcmp(temp->qos_session_q_save->sDir, sDir))    {
 
-                if (!temp->is_sip_match) {
-                    src_ip_qos = 0;
-                }
-                if (!src_ip_qos && !temp->is_sport_match) {
-                    src_port_qos = 0;
-                }
-                if (!temp->is_dip_match) {
-                    dst_ip_qos = 0;
-                }
-                if (!dst_ip_qos && !temp->is_dport_match) {
-                    dst_port_qos = 0;
-                }
+                    ++ports_record[src_port_qos];
 
-                create_queue_filter(src_ip_qos, src_port_qos, dst_ip_qos, dst_port_qos, sDir, temp->qos_session_q_save,
-                    temp->qos_session_altq_conf_save);
+                    if (ports_record[src_port_qos] >= repeat_segment_num){
+                        ports_record[src_port_qos] = 0;
+
+                        if (!temp->is_sip_match) {
+                            src_ip_qos = 0;
+                        }
+                        if (!src_ip_qos && !temp->is_sport_match) {
+                            src_port_qos = 0;
+                        }
+                        if (!temp->is_dip_match) {
+                            dst_ip_qos = 0;
+                        }
+                        if (!dst_ip_qos && !temp->is_dport_match) {
+                            dst_port_qos = 0;
+                        }
+
+                        bzero (&local_qos_q_conf, sizeof (qos_queue_root_t));
+                        bzero (&local_altq_conf, sizeof (struct altq_conf));
+               
+                        memmove (&local_qos_q_conf, temp->qos_session_q_save, sizeof (qos_queue_root_t));
+                        memmove (&local_altq_conf, temp->qos_session_altq_conf_save, sizeof (struct altq_conf));
+                        create_queue_filter(src_ip_qos, src_port_qos, dst_ip_qos, dst_port_qos, sDir, &local_qos_q_conf, &local_altq_conf);
+                    }
+                }
             }
         }
 
@@ -869,6 +899,40 @@
 
 	return QOS_SUCCESS;
 }
+
+/******************************************************************************
+ *  Clear all qos filters. This function is optimized for QoS session cleanup
+ *
+ *  return: QOS_SUCCESS, success; QOS_FAILURE,failure.
+ ******************************************************************************/
+int qos_filter_clear_all_dyn(void *pcb)
+{
+	qos_filter_share_t *qs;
+	qos_filter_ifnode_t *ifn_p;
+	qos_filter_t *pfltr;
+	int i;
+	int s = 0;
+
+	qs = &qos_filter_share;
+
+	for(i=0; i < QOS_MAX_INTERFACE; i++) {
+		ifn_p = &(qs->ifnodes[i]);
+
+		if(!ifn_p->initiation) {
+			continue;
+		}
+
+		/* Security */
+		s = splimp();
+		clickrule_clear(&ifn_p->if_o_table);
+		clickrule_clear(&ifn_p->if_i_table);
+		splx(s);
+	}
+	
+        qos_filter_init();
+
+	return QOS_SUCCESS;
+}
 
 
 /******************************************************************************
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 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_dynamic.h	(working copy)
@@ -25,6 +25,7 @@
 
 extern struct dyn_session_qos_conf_head dyn_session_qos_conf_head;
 extern int qos_session_status;
+extern uint32_t repeat_segment_num;
 
 
 typedef struct dyn_qos_session_lookup {
@@ -54,3 +55,5 @@
 static int qos_session_config_count(void);
 int enable_session (void *pcb);
 int disable_session (void *pcb);
+int set_tuple_count (void *pcb, uint32_t count);
+int get_tuple_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 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_dynamic.c	(working copy)
@@ -30,6 +30,8 @@
 
 int qos_session_status = SESSION_DISABLE;
 
+uint32_t repeat_segment_num = 50;
+
 struct dyn_session_qos_conf_head dyn_session_qos_conf_head = STAILQ_HEAD_INITIALIZER(dyn_session_qos_conf_head);
 
 dyn_qos_session_lookup_t *dyn_qos_session_lookup_root = NULL;
@@ -123,10 +125,10 @@
     current->is_leaf = 1;
 
     current->qos_session_q_save = (qos_queue_root_t *) malloc(sizeof(qos_queue_root_t), M_QOS, M_NOWAIT | M_ZERO);
-    memcpy(current->qos_session_q_save, pQoSQRoot, sizeof(qos_queue_root_t));
+    memmove(current->qos_session_q_save, pQoSQRoot, sizeof(qos_queue_root_t));
 
     current->qos_session_altq_conf_save = (struct altq_conf *) malloc(sizeof(struct altq_conf), M_QOS, M_NOWAIT | M_ZERO);
-    memcpy(current->qos_session_altq_conf_save, pALTQConf, sizeof(struct altq_conf));
+    memmove(current->qos_session_altq_conf_save, pALTQConf, sizeof(struct altq_conf));
 
     return (QOS_SUCCESS);
 }
@@ -185,9 +187,9 @@
 int show_qos_session_config(void *pcb, char *name) {
 
     if (qos_session_status == SESSION_ENABLE) 
-        app_printf(pcb, "qos session_on\n");
+        app_printf(pcb, "qos sessionon\n");
     else
-        app_printf(pcb, "qos session_off\n");
+        app_printf(pcb, "qos sessionoff\n");
 
     dyn_session_qos_conf_t *dyn_qos_conf_run = NULL;
 
@@ -412,3 +414,16 @@
     fastlog_syslog(LOG_DEBUG, "disable syslog %d\n", qos_session_status);
     return QOS_SUCCESS;
 }
+
+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");
+        return (QOS_USERLAND_FAILURE);
+    }
+    repeat_segment_num = count;
+    return QOS_SUCCESS;
+}
+int get_tuple_count (void *pcb) {
+    app_printf(pcb, "count : %u\n", repeat_segment_num);
+    return QOS_SUCCESS;
+}
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_scheduler.h
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_scheduler.h	(revision 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_scheduler.h	(working copy)
@@ -42,9 +42,9 @@
 
 #define QOS_BORROW_DEFAULT	QOS_UNBORROW
 
-/* QoS queue size limit */
+/* QoS queue size limit. It is recommend not to create Queues (except 'default queues') when 'QoS Session' feature is enabled. */
 
-#define QOS_DEFAULT_QLIMIT	100000
+#define QOS_DEFAULT_QLIMIT (MAX_DYN_QUEUE + 100)
 
 /*************************************************************************
  * STRUCTURE DEFINITIONS
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 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_scheduler.c	(working copy)
@@ -62,6 +62,7 @@
 
 #include <click/app/qos/qos_http.h>
 
+extern int qos_session_status;
 
 /* QoS qid generator */
 static uint32_t qos_index = 0;
@@ -169,13 +170,14 @@
 		return(QOS_FAILURE);
 	}
 
+	if (!qos_session_status) {
 	/* Referrence count */
-	if (NULL == pQoSQSubFirst) {
+	    if (NULL == pQoSQSubFirst) {
 		pQoSQRoot->ref_cnt++;
-	} else {
+	    } else {
 		pQoSQSubFirst->ref_cnt++;
+	    }
 	}
-
 	return(QOS_SUCCESS);
 }
 
@@ -227,11 +229,13 @@
 	}
 
 	/* Referrence count */
-	if (NULL == pQoSQSubFirst) {
+	if (!qos_session_status) {
+	    if (NULL == pQoSQSubFirst) {
 		pQoSQRoot->ref_cnt--;
-	} else {
+	    } else {
 		pQoSQSubFirst->ref_cnt--;
-	}
+	    }
+        }
 
 	return(QOS_SUCCESS);
 }
@@ -688,9 +692,9 @@
 	}
 
 	/* Set the global maximun number */
-	if (qos_queue_count() >= QOS_MAXQ) {
-		app_printf(pcb, "ERROR: too many queues configured (maximum %d)\n", QOS_MAXQ);
-		return(QOS_USERLAND_FAILURE);
+        if (qos_queue_count() >= QOS_MAXQ) {
+	        app_printf(pcb, "ERROR: too many queues configured (maximum %d)\n", QOS_MAXQ);
+	        return(QOS_USERLAND_FAILURE);
 	}
 
 	pQoSQRoot = (qos_queue_root_t *)pRoot;
@@ -763,22 +767,21 @@
 
 	pALTQConf->qid = ++qos_index;
 
-//TODO disable bandwidth check only if "session"(dynamic) qos is enabled
-#if 0
+        if (!qos_session_status) {
 	/* Check bandwidth */
-	nBandCheck = pALTQConf->bandwidth;
-	STAILQ_FOREACH(pQoSQRootSave, &qos_queue_root_head, list_entry) {
+	    nBandCheck = pALTQConf->bandwidth;
+	    STAILQ_FOREACH(pQoSQRootSave, &qos_queue_root_head, list_entry) {
 		if ((strcmp(pQoSQRootSave->sHwIf, pQoSIfConf->sHwIf) == 0) &&
 				(pQoSQRootSave->iDir == pQoSIfConf->iDir)) {
 			nBandCheck += pQoSQRootSave->nBand;
 		}
-	}
-	if (nBandCheck > pQoSIfConf->nBand || nBandCheck < pALTQConf->bandwidth) {
+	    }
+	    if (nBandCheck > pQoSIfConf->nBand || nBandCheck < pALTQConf->bandwidth) {
 		app_printf(pcb, "ERROR: total bandwidth of %s root queues is greater than interface bandwidth\n", pQoSQRoot->sDir);
 		--qos_index;
 		return(QOS_USERLAND_FAILURE);
-	}
-#endif
+	    }
+        }
 
 	/* Save user configuration */
 	pQoSQRootSave = malloc(sizeof(qos_queue_root_t), M_QOS, M_NOWAIT | M_ZERO);
@@ -820,6 +823,69 @@
 	return(iErrCode);
 }
 
+
+/* delete dynamically created queues */
+int no_qos_queue_root_sess_kern(char *sQueue)
+{
+	qos_queue_sub_t *pQoSQSub = NULL;
+	qos_queue_root_t *pQoSQRoot = NULL;
+	struct altq_conf confALTQ;
+	qos_queue_info_t infoQoSQueue;
+	int iErrCode = 0, iErrCode1 = 0;
+	int s = 0;
+
+
+	bzero(&confALTQ, sizeof(confALTQ));
+	bzero(&infoQoSQueue, sizeof(infoQoSQueue));
+
+	confALTQ.scheduler = ALTQT_CBQ;
+
+	STAILQ_FOREACH(pQoSQRoot, &qos_queue_root_head, list_entry) {
+		if (strcmp(sQueue, pQoSQRoot->sQName) == 0) {
+
+			confALTQ.qid = pQoSQRoot->iQID;
+			strcpy(confALTQ.ifname, pQoSQRoot->sHwIf);
+			confALTQ.direction = pQoSQRoot->iDir;
+			break;
+		}
+	}
+
+	if (pQoSQRoot == NULL) {
+		fastlog_syslog(LOG_DEBUG, "ERROR: can not find the root queue\n");
+		return(QOS_USERLAND_FAILURE);
+	}
+
+	/* Get discipline */
+	confALTQ.altq_disc = altq_lookup(confALTQ.ifname, confALTQ.direction, ALTQT_CBQ);
+	if (confALTQ.altq_disc == NULL) {
+		fastlog_syslog(LOG_DEBUG, "ERROR: can not find the QoS interface\n");
+		return(QOS_USERLAND_FAILURE);
+	}
+
+	/* Prepare clearing dynamic filters */
+	infoQoSQueue.ifp = ifunit(confALTQ.ifname);
+	if (infoQoSQueue.ifp == NULL) {
+		fastlog_syslog(LOG_DEBUG, "ERROR: can not find the QoS interface\n");
+		return(QOS_USERLAND_FAILURE);
+	}
+	infoQoSQueue.direction = confALTQ.direction;
+
+	/* Free memory */
+	STAILQ_REMOVE(&qos_queue_root_head, pQoSQRoot, qos_queue_root, list_entry);
+	free(pQoSQRoot, M_QOS);
+
+	/* Security */
+	s = splimp();
+
+	/* Remove queue */
+	iErrCode1 = altq_remove_queue(&confALTQ);
+	if (!iErrCode) {iErrCode = iErrCode1;}
+
+	splx(s);
+	return(iErrCode);
+}
+
+
 /* CLI: no qos queue root ... */
 int no_qos_queue_root_kern(void *pcb, char *sQueue)
 {
@@ -854,10 +920,12 @@
 	/* Check reference count and Get necessary fields */
 	STAILQ_FOREACH(pQoSQRoot, &qos_queue_root_head, list_entry) {
 		if (strcmp(sQueue, pQoSQRoot->sQName) == 0) {
-			if (pQoSQRoot->ref_cnt > 0) {
+	                if (!qos_session_status) {
+			    if (pQoSQRoot->ref_cnt > 0) {
 				app_printf(pcb, "ERROR: please delete QoS filters on the queue firstly\n");
 				return(QOS_USERLAND_FAILURE);
-			}
+			    }
+                        }
 
 			confALTQ.qid = pQoSQRoot->iQID;
 			strcpy(confALTQ.ifname, pQoSQRoot->sHwIf);
@@ -1079,21 +1147,20 @@
 	/* QoS queue ID */
 	pALTQConf->qid = ++qos_index;
 
-//TODO disable bandwidth check only if "session"(dynamic) qos is enabled
-#if 0
+	if (!qos_session_status) {
 	/* Check bandwidth */
-	nBandCheck = pALTQConf->bandwidth;
-	STAILQ_FOREACH(pQoSQSubSave, &qos_queue_sub_head, list_entry) {
+	    nBandCheck = pALTQConf->bandwidth;
+	    STAILQ_FOREACH(pQoSQSubSave, &qos_queue_sub_head, list_entry) {
 		if ((strcmp(pQoSQSubSave->sParent, pQoSQSub->sParent) == 0)) {
 			nBandCheck += pQoSQSubSave->nBand;
 		}
-	}
-	if (nBandCheck > nParentBand  || nBandCheck < pALTQConf->bandwidth) {
+	    }
+	    if (nBandCheck > nParentBand  || nBandCheck < pALTQConf->bandwidth) {
 		app_printf(pcb, "ERROR: total bandwidth of sub queues is greater than parent bandwidth\n");
 		--qos_index;
 		return(QOS_USERLAND_FAILURE);
+	    }
 	}
-#endif
 
 	/* Save user configuration */
 	pQoSQSubSave = malloc(sizeof(qos_queue_sub_t), M_QOS, M_NOWAIT | M_ZERO);
@@ -1177,13 +1244,14 @@
 			if (strcmp(pParent, pQoSQSub->sQName) == 0) {
 				if (NULL == pQoSQSubFirst) {
 					pQoSQSubFirst = pQoSQSub;
-
-					if (pQoSQSub->ref_cnt > 0) {
+	                                if (!qos_session_status) {
+					    if (pQoSQSub->ref_cnt > 0) {
 						app_printf(pcb, "ERROR: please delete QoS filters on the queue firstly\n");
 						return(QOS_USERLAND_FAILURE);
-					} else {
+					    } else {
 						confALTQ.qid = pQoSQSub->iQID;
-					}
+					    }
+                                        }
 				}
 
 				pParent = pQoSQSub->sParent;
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_subr.c
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_subr.c	(revision 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_subr.c	(working copy)
@@ -371,9 +371,10 @@
 int clear_qos_all_kern(void *pcb)
 {
 
-    delete_qos_session_config (pcb, QOS_NAME_FOR_ALL);
-    /* bug 14949, qiuzj, http qos */
-    clear_qos_http_url(pcb);
+	delete_qos_session_config (pcb, QOS_NAME_FOR_ALL);
+	disable_session (pcb);
+	/* bug 14949, qiuzj, http qos */
+	clear_qos_http_url(pcb);
     
 	qos_filter_clear_all(pcb);
 	qos_interface_clear_all(pcb);
@@ -911,10 +912,12 @@
 
     /* QoS session command format */
     char qos_session_conf_cmd[] = "qos session xxxxxx xxx.xxx.xxx.xxx xxxxx xxx.xxx.xxx.xxx xxxxx xxxxxxx xxx";
-    char qos_session_status_cmd[] = "qos session_xxx";
+    char qos_session_status_cmd[] = "qos sessionxxx";
+    char qos_session_tuple_count_cmd[] = "qos set_tuple_count xxxx";
 
     len = (sizeof (qos_session_conf_cmd) + QOS_SNAME_MAX + 1) * MAX_QOS_SESSION_CONFIG;
     len += sizeof (qos_session_status_cmd) + 1;
+    len += sizeof (qos_session_tuple_count_cmd) + 1;
 
     MALLOC(buffer, char *, len, M_TEMP, M_NOWAIT);
 
@@ -927,9 +930,11 @@
     cur = buffer;
 
     if (qos_session_status == SESSION_ENABLE)
-        cur += sprintf (cur, "qos session_on\n");
+        cur += sprintf (cur, "qos sessionon\n");
     else
-        cur += sprintf (cur, "qos session_off\n");
+        cur += sprintf (cur, "qos sessionoff\n");
+
+    cur += sprintf (cur, "qos set_tuple_count %u\n", repeat_segment_num);
 
     STAILQ_FOREACH(dyn_qos_conf_run, &dyn_session_qos_conf_head, list_entry) {
         cur += sprintf (cur, "qos session \"%s\" %s %u.%u.%u.%u %u %u.%u.%u.%u %u %s %s\n",
Index: /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_var.h
===================================================================
--- /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_var.h	(revision 38090)
+++ /branches/rel_apv_10_4_0_112_gail/usr/src/sys/click/app/qos/qos_var.h	(working copy)
@@ -45,7 +45,11 @@
 #define QOS_MAXPRIO		8
 
 /* QoS maximum queue */
-#define QOS_MAXQ		100000
+#ifndef MAX_DYN_QUEUE
+#define MAX_DYN_QUEUE 50000
+#endif
+
+#define QOS_MAXQ (MAX_DYN_QUEUE + 100)
 
 /* QoS interface maximum number */
 #define MAX_VLAN 4094
